【问题标题】:Building C# application with localization-aware language keys使用本地化感知语言键构建 C# 应用程序
【发布时间】:2021-10-06 21:07:22
【问题描述】:

简介

我正在寻找更多定制的解决方案来翻译我的应用程序。我将在获得条目后使用HumanizerSmart.Format。问题是首先要定义键来获取它们。

要求

要求是:

  1. 语言键必须在代码中定义,最好在使用它们的地方附近
  2. 语言键必须包含默认英语值
  3. 必须在构建应用套件后列出所有语言键(XML、CSV、JSON 等)
  4. 语言条目必须从外部源(如 JSON 文件)提供,无需任何类型的重新编译
  5. 该应用程序可能包含多个可执行文件、共享库等。所有这些都以 C# 应用程序的形式出现

废弃的解决方案

首先,我丢弃的东西:

  • 内置 C# Resources.dll;它们违反了 (1) 和 (4)
  • 带有密钥的外部文件。违规 (1)

我处理问题的想法

现在,我对解决方案的想法看起来是这样(并且受到 C++ GetText 的启发)

有一个包含键的模板类:

private sealed class Module1Keys : LocalizationKeys<Module1Keys>
{
    public static readonly LocalizationKey HelloWorld = DefineKey("/foo", "Hello World!");
    public static readonly LocalizationKey HelloWorld2 = DefineKey("/bar", "Hello World2!");
}

LocalizationKeys 类包含一个静态方法,该方法实际上将在简单集合中注册键

public abstract class LocalizationKeys<T> where T : LocalizationKeys<T>
{
    protected static LocalizationKey DefineKey(string path, string english)
    {
        var ret = new LocalizationKey(typeof(T), path, english);
        // Following registers localization key in runtime:
        Localization.Instance.RegisterLocalizableKey(ret);

        return ret;
    }
}

问题

在这种方法中唯一需要处理的事情在构建过程中列出可本地化的键...这是我碰壁的地方。在运行时列出它们很容易,但我无法构建时间运行代码(特别是它可能构建为共享库)。

也许我自己想多了,有更好、更干净的解决方案 - 我不需要坚持这个解决方案,但谷歌搜索并没有产生更好的结果......

【问题讨论】:

  • @MickyD 不,我不想使用明确的GetText - 如果您有任何更好的想法仍然满足#3 和#4,我会很乐意接受。不幸的是,我不能放弃其中任何一个。
  • @MickyD 为什么要投票赞成?在最后一段中有明确说明的问题要解决。我在说明问题后展示了我的原始研究,所以如果你认为有更好的解决方案,我很乐意回顾
  • @MickyD 编写的代码是部分解决方案,我包括在内以展示我的研究。我无法在构建时列出键(这是#3 直接要求的)我正在寻求解决这个问题。
  • 哦,你的意思是 second 最后一段。收回。对不起那个好先生:)

标签: c# design-patterns build localization


【解决方案1】:

成功了。在GetText 次我们不得不求助于手动解析代码。

...但是现在,有了 CSharp,我们有了一个带有 CodeAnalysis API 的 Roslyn。

解决方案

连接包含Microsoft.CodeAnalysis NuGet 的自定义控制台构建工具,代码如下:

var model = compilation.GetSemanticModel(tree);
var methods = root.DescendantNodes().OfType<InvocationExpressionSyntax>();

foreach(var method in methods)
{
    if(model.GetSymbolInfo(method).Symbol is IMethodSymbol symbol &&
        symbol.ContainingNamespace.Name == "MyProject" &&
        symbol.ContainingType.Name == "LocalizationKeys" &&
        symbol.Name == "DefineKey")
    {
        var key = method.ArgumentList.Arguments.FirstOrDefault();
        var eng = method.ArgumentList.Arguments.Skip(1).FirstOrDefault();

        if(key.Expression is LiteralExpressionSyntax literalKey &&
            eng.Expression is LiteralExpressionSyntax literalEng)
        {
            // "/foo" -> "Hello World!"
            // "/bar" -> "Hello World2!"
            Console.WriteLine(literalKey + " -> " + literalEng);
        }
        else
        {
            // Bonus: detect violation of key definition rule. It is not a literal!
        }
    }
}

将此控制台工具编译为可执行文件并将其添加为构建后步骤。利润。

【讨论】:

    猜你喜欢
    • 2016-10-14
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-08
    • 1970-01-01
    相关资源
    最近更新 更多