Add support for translation attributes.

This commit is contained in:
Matthias Mailänder
2022-10-25 21:31:36 +02:00
committed by Gustas
parent 760a1245c5
commit e251377f7c
3 changed files with 84 additions and 51 deletions

View File

@@ -7,7 +7,7 @@
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" /> <PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Linguini.Bundle" Version="0.3.1" /> <PackageReference Include="Linguini.Bundle" Version="0.3.2" />
<PackageReference Include="OpenRA-Eluant" Version="1.0.18" /> <PackageReference Include="OpenRA-Eluant" Version="1.0.18" />
<PackageReference Include="Mono.NAT" Version="3.0.3" /> <PackageReference Include="Mono.NAT" Version="3.0.3" />
<PackageReference Include="SharpZipLib" Version="1.3.3" /> <PackageReference Include="SharpZipLib" Version="1.3.3" />

View File

@@ -101,7 +101,7 @@ namespace OpenRA
foreach (var (k, v) in arguments) foreach (var (k, v) in arguments)
fluentArguments.Add(k, v.ToFluentType()); fluentArguments.Add(k, v.ToFluentType());
var result = bundle.TryGetAttrMsg(key, fluentArguments, out var errors, out value); var result = bundle.TryGetAttrMessage(key, fluentArguments, out var errors, out value);
foreach (var error in errors) foreach (var error in errors)
Log.Write("debug", $"Translation of {key}: {error}"); Log.Write("debug", $"Translation of {key}: {error}");
@@ -118,7 +118,7 @@ namespace OpenRA
public bool HasMessage(string key) public bool HasMessage(string key)
{ {
return bundle.HasMessage(key); return bundle.HasAttrMessage(key);
} }
// Adapted from Fluent.Net.SimpleExample.TranslationService by Mark Weaver // Adapted from Fluent.Net.SimpleExample.TranslationService by Mark Weaver

View File

@@ -62,54 +62,31 @@ namespace OpenRA.Mods.Common.Lint
foreach (var entry in result.Entries) foreach (var entry in result.Entries)
{ {
// Don't flag definitions referenced (only) within the .ftl definitions as unused // Don't flag definitions referenced (only) within the .ftl definitions as unused
var isReusableTerm = entry.GetType() == typeof(AstTerm); if (entry.GetType() == typeof(AstTerm))
var key = entry.GetId(); continue;
if (!referencedKeys.Contains(key) && !isReusableTerm)
emitWarning($"Unused key `{key}` in {file}.");
variableReferences.Clear(); variableReferences.Clear();
var key = entry.GetId();
if (entry is AstMessage message) if (entry is AstMessage message)
{ {
var node = message.Value; var hasAttributes = message.Attributes.Count > 0;
foreach (var element in node.Elements)
{
if (element is Placeable placeable)
{
var expression = placeable.Expression;
if (expression is IInlineExpression inlineExpression)
{
if (inlineExpression is VariableReference variableReference)
CheckVariableReference(variableReference.Id.Name.ToString(), entry, emitWarning, file);
}
if (expression is SelectExpression selectExpression) if (!hasAttributes)
{ {
foreach (var variant in selectExpression.Variants) CheckUnusedKey(key, null, emitWarning, file);
{ CheckMessageValue(message.Value, key, null, emitWarning, file);
foreach (var variantElement in variant.Value.Elements) CheckMissingVariable(key, null, emitError, file);
{
if (variantElement is Placeable variantPlaceable)
{
var variantExpression = variantPlaceable.Expression;
if (variantExpression is IInlineExpression variantInlineExpression)
{
if (variantInlineExpression is VariableReference variantVariableReference)
CheckVariableReference(variantVariableReference.Id.Name.ToString(), entry, emitWarning, file);
}
}
}
}
}
}
} }
else
if (referencedVariablesPerKey.ContainsKey(entry.GetId()))
{ {
var referencedVariables = referencedVariablesPerKey[entry.GetId()]; foreach (var attribute in message.Attributes)
foreach (var referencedVariable in referencedVariables)
{ {
if (!variableReferences.Contains(referencedVariable)) var attrName = attribute.Id.Name.ToString();
emitError($"Missing variable `{referencedVariable}` for key `{entry.GetId()}` in {file}.");
CheckUnusedKey(key, attrName, emitWarning, file);
CheckMessageValue(attribute.Value, key, attrName, emitWarning, file);
CheckMissingVariable(key, attrName, emitError, file);
} }
} }
} }
@@ -118,18 +95,74 @@ namespace OpenRA.Mods.Common.Lint
} }
} }
void CheckVariableReference(string element, IEntry entry, Action<string> emitWarning, string file) void CheckUnusedKey(string key, string attribute, Action<string> emitWarning, string file)
{ {
variableReferences.Add(element); var isAttribute = !string.IsNullOrEmpty(attribute);
var keyWithAtrr = isAttribute ? $"{key}.{attribute}" : key;
if (referencedVariablesPerKey.ContainsKey(entry.GetId())) if (!referencedKeys.Contains(keyWithAtrr))
emitWarning(isAttribute ?
$"Unused attribute `{attribute}` of key `{key}` in {file}." :
$"Unused key `{key}` in {file}.");
}
void CheckMessageValue(Pattern node, string key, string attribute, Action<string> emitWarning, string file)
{
foreach (var element in node.Elements)
{ {
var referencedVariables = referencedVariablesPerKey[entry.GetId()]; if (element is Placeable placeable)
if (!referencedVariables.Contains(element)) {
emitWarning($"Unused variable `{element}` for key `{entry.GetId()}` in {file}."); var expression = placeable.Expression;
if (expression is IInlineExpression inlineExpression)
if (inlineExpression is VariableReference variableReference)
CheckVariableReference(variableReference.Id.Name.ToString(), key, attribute, emitWarning, file);
if (expression is SelectExpression selectExpression)
{
foreach (var variant in selectExpression.Variants)
{
foreach (var variantElement in variant.Value.Elements)
{
if (variantElement is Placeable variantPlaceable)
{
var variantExpression = variantPlaceable.Expression;
if (variantExpression is IInlineExpression variantInlineExpression)
if (variantInlineExpression is VariableReference variantVariableReference)
CheckVariableReference(variantVariableReference.Id.Name.ToString(), key, attribute, emitWarning, file);
}
}
}
}
}
} }
else }
emitWarning($"Unused variable `{element}` for key `{entry.GetId()}` in {file}.");
void CheckMissingVariable(string key, string attribute, Action<string> emitError, string file)
{
var isAttribute = !string.IsNullOrEmpty(attribute);
var keyWithAtrr = isAttribute ? $"{key}.{attribute}" : key;
if (!referencedVariablesPerKey.ContainsKey(keyWithAtrr))
return;
foreach (var referencedVariable in referencedVariablesPerKey[keyWithAtrr])
if (!variableReferences.Contains(referencedVariable))
emitError(isAttribute ?
$"Missing variable `{referencedVariable}` for attribute `{attribute}` of key `{key}` in {file}." :
$"Missing variable `{referencedVariable}` for key `{key}` in {file}.");
}
void CheckVariableReference(string varName, string key, string attribute, Action<string> emitWarning, string file)
{
var isAttribute = !string.IsNullOrEmpty(attribute);
var keyWithAtrr = isAttribute ? $"{key}.{attribute}" : key;
variableReferences.Add(varName);
if (!referencedVariablesPerKey.ContainsKey(keyWithAtrr) || !referencedVariablesPerKey[keyWithAtrr].Contains(varName))
emitWarning(isAttribute ?
$"Unused variable `{varName}` for attribute `{attribute}` of key `{key}` in {file}." :
$"Unused variable `{varName}` for key `{key}` in {file}.");
} }
} }
} }