可靠计算.NET中覆盖特定于文化的资源

时间:2017-03-04 17:02:44

标签: c# .net cultureinfo resx resourcemanager

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

我有一个使用资源(resx)进行翻译的应用程序。我有标准Strings.resx文件包含所有字符串,Strings.xx-XX.resx文件覆盖特定xx-XX文化中的文件。初始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,他&#39 ;我将从es-ES的.NET获得回退,但这对我们的计算不起作用。我可以将tryParents中的GetResourceSet()布尔值切换为true,但是我始终会在原始en-US中声明的Strings字符串中获得回退文件,所以我们总是有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-ES对于es-UY用户来说完全没问题,但是en-USzh-CN不好。另一方面,对于en-US用户,en-GB完全没问题。

也许我可以某种方式将ResourceSettryParents设置进​​行比较并比较哪些字符串不同?但是,它需要进行参考比较,因为一些字符串可能在两种不同的语言中具有相同的翻译。它甚至可能吗?

欢迎任何建议。

1 个答案:

答案 0 :(得分: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%完成翻译,我们必须至少有一个翻译资源,其表示形式与原始默认字符串不同,否则无法说明这是否是预期的翻译资源集,或者是否从US
  3. 我对此解决方案非常满意。