【问题标题】:Reliable calculation of overriden culture-specific resources in .NET在 .NET 中可靠地计算覆盖的文化特定资源
【发布时间】:2017-03-04 17:02:44
【问题描述】:

从标题可能有点难以猜出我的意思,所以让我详细说明一下。

我有一个使用资源 (resx) 进行翻译的应用程序。我有包含所有字符串的标准 Strings.resx 文件,以及在特定 xx-XX 文化中覆盖它们的 Strings.xx-XX.resx 文件。初始 Strings.resx 文件具有 X 字符串数,其中特定于文化的 Strings.xx-XX.resx 文件可能少于或等于 X 字符串数。

我正在尝试编写一个函数,该函数能够可靠地计算该语言中有多少字符串被覆盖,与初始数字相比,这可以给我一个不错的整体翻译百分比。

例如,我们总共有 10 个字符串,es-ES 文化中有 6 个字符串。当es-ES用户启动应用程序时,他会收到es-ES翻译完成60%的消息。

到目前为止,我设法编写了这样的代码:

ushort defaultResourceSetCount = 0;
ResourceSet defaultResourceSet = Strings.ResourceManager.GetResourceSet(CultureInfo.GetCultureInfo("en-US"), true, true);
if (defaultResourceSet != null) {
    defaultResourceSetCount = (ushort) defaultResourceSet.Cast<object>().Count();
}

ushort currentResourceSetCount = 0;
ResourceSet currentResourceSet = Strings.ResourceManager.GetResourceSet(CultureInfo.CurrentCulture, true, false);
if (currentResourceSet != null) {
    currentResourceSetCount = (ushort) currentResourceSet.Cast<object>().Count();
}

if (currentResourceSetCount < defaultResourceSetCount) {
    // This is our percentage that we want to calculate and show to user
    float translationCompleteness = currentResourceSetCount / (float) defaultResourceSetCount;
}

上面的代码有效,但有很多我想解决的方言限制。它基本上仅适用于在特定文化中具有特定文化的非常通用的情况,例如 es-ESStrings 文件在该特定文化中 - 如果用户使用其他东西,例如 es-UY,他将从 .NET 获得回退es-ES,但这不适用于我们的计算。我可以将 GetResourceSet() 中的 tryParents boolean 切换为 true,但是我总是会在原始 en-US 文件中声明的 en-US 字符串的形式上得到回退,所以我们总是有 100% 的翻译进度,即使用户选择了完全不同的文化。

所以基本上,以我们在Strings.resx 中的 10 个资源和Strings.es-ES.resx 中的 6 个资源的示例,应该发生以下事情:

  • 使用en-US 文化时,我们获得了 100% 的完成度。
  • 使用 en-GB 文化时,我们获得了 100% 的完成度,因为它回退到 en-US,我们已经涵盖了这一点。
  • 使用es-ES 文化时,我们完成了 60%。
  • 当使用es-UY 文化时,我们获得了 60% 的完成率,因为 .NET 将es 视为一个后备,然后将es-ES 视为一个后备。请注意,我们没有声明 es,而是声明了 es-ES
  • 使用 zh-CN 时,我们的完成率为 0%,即使最深的后备是我们已经涵盖的 en-US

我想以最好的方式解决这个问题,但我不太确定那种最好的方式 - 我认为简单地获取资源数量就可以了,但确实如此,但是不适用于方言,尝试所有父母也不起作用,因为它总是会导致en-US。另一方面,我想假设任何比Strings.resx 更好的后备都可以被视为已翻译,因为es-ESes-UY 用户完全没问题,但en-USzh-CN 不利。另一方面,en-US 对于en-GB 用户来说完全没问题。

也许我可以以某种方式比较ResourceSets 和tryParents 设置并比较哪些字符串不同?不过,这需要进行参考比较,因为某些字符串完全有可能在两种不同的语言中具有相同的翻译。有没有可能?

欢迎提出任何建议。

【问题讨论】:

  • 假设 en-US 是您的原始字符串并且是 100% 的情况:我采取了一种策略来比较跨文化字符串的值以及它们的长度是否非零且没有键诸如“TODO”“REVIEW”“NOT DONE”之类的词我将它们与原始的 en-US 进行比较。如果它们不同且非零,那么它们可能已完成。如果它们与 en-US 的值相同,则它们“未完成”。这是因为它们都以每个资源文件中的 en-US 值开始。我还比较了字节数和长度,以量化明显的古怪或公然的屏幕调整大小问题。
  • @SqlSurfer 这很好,但我假设您比较实际的字符串值表示?在这种情况下,很遗憾它对我不起作用,因为我实际上包含许多字符串,仅用于 RTL 语言案例的翻译,而且它们在 90% 的语言中完全相同,所以类似于 "{0} V {1}”存在于所有语言中,除了希伯来语,它是“{1} V{0}”或类似的。

标签: c# .net cultureinfo resx resourcemanager


【解决方案1】:

这是我在这个问题上想出的最好的:

if (CultureInfo.CurrentCulture.TwoLetterISOLanguageName.Equals("en")) {
    return;
}

ResourceSet defaultResourceSet = Strings.ResourceManager.GetResourceSet(CultureInfo.GetCultureInfo("en-US"), true, true);
if (defaultResourceSet == null) {
    return;
}

HashSet<DictionaryEntry> defaultStringObjects = new HashSet<DictionaryEntry>(defaultResourceSet.Cast<DictionaryEntry>());
if (defaultStringObjects.Count == 0) {
    return;
}

ResourceSet currentResourceSet = Strings.ResourceManager.GetResourceSet(CultureInfo.CurrentCulture, true, true);
if (currentResourceSet == null) {
    return;
}

HashSet<DictionaryEntry> currentStringObjects = new HashSet<DictionaryEntry>(currentResourceSet.Cast<DictionaryEntry>());
if (currentStringObjects.Count >= defaultStringObjects.Count) {
    // Either we have 100% finished translation, or we're missing it entirely and using en-US
    HashSet<DictionaryEntry> testStringObjects = new HashSet<DictionaryEntry>(currentStringObjects);
    testStringObjects.ExceptWith(defaultStringObjects);

    // If we got 0 as final result, this is the missing language
    // Otherwise it's just a small amount of strings that happen to be the same
    if (testStringObjects.Count == 0) {
        currentStringObjects = testStringObjects;
    }
}

if (currentStringObjects.Count < defaultStringObjects.Count) {
    float translationCompleteness = currentStringObjects.Count / (float) defaultStringObjects.Count;
    Console.WriteLine("Do something with translation completeness: " + translationCompleteness);
}

它只需要两个相当不错的假设:

  1. 当前文化资源集的资源不能超过我们的默认 (en-US) 文化,仅在进行翻译时总是如此。
  2. 如果我们有 100% 完成翻译,我们必须至少有 1 个翻译资源的表示形式与原始默认字符串不同,否则无法说明这是有意翻译的资源集,还是从 en- 中提取的默认资源集美国。

我对这个解决方案非常满意。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多