具有单数和复数的ASP.NET本地化

时间:2008-12-17 22:57:47

标签: asp.net localization

我可以使用ASP.NET资源/本地化翻译字符串以简单的方式依赖于一个或其他(英语语法),就像我在我的翻译中传递数字1,它返回“你有一辆车”或0 ,2及更高,“你有%n辆汽车”?

或者我被迫在我看来有逻辑,看它是单数还是复数?

7 个答案:

答案 0 :(得分:34)

JasonTrue写道:

  

据我所知,没有一种语言需要比单数/复数更复杂的语言

这种语言确实存在。例如,在我的母语波兰语中,有三种形式:1表示,2-4表示零,数字表示大于4.然后,当你达到20时,21,22-24和25+的表格再次不同(与数字0-9相同的语法形式。是的,“你有0件事”听起来很尴尬,因为你不太可能在现实生活中看到它。

作为本地化专家,我会推荐以下内容:

如果可能,请使用将数字放在最后的表格:

a: Number of cars: %d

这意味着名词“car”的形式不依赖于数字,0和任何其他数字一样自然。

如果上述内容不可接受,至少总是将完整的句子作为可翻译的资源。也就是说,请使用

b: You have 1 car.    
c: You have %d cars.

从不将此类单位拆分为较小的片段,例如

d: You have
e: car(s)

(然后在其他地方你有一个不可本地化的资源,例如%s %d %s

不同的是,虽然我不能直接翻译(c),因为名词的形式会改变,我可以看到问题我可以将句子改为形式(a)的翻译。

另一方面,当我面对(d)和(e)片段时,无法确保得到的句子是否具有语法性。再次:使用片段保证在某些语言中,翻译将是从语法上的尴尬到彻底破坏的任何内容。

这适用于全面,而不仅仅是数字。例如,诸如%s was deleted之类的片段也是不可翻译的,因为动词的形式将取决于名词的性别,这在此处不可用。我能为波兰语做的最好的事情相当于Deleted: %s,但只有%s占位符包含在可翻译资源中我才能做到。如果我所有的都被“删除”而没有指向名词的线索,我只能大声咒骂我的狗,最后我还是要产生垃圾语法。

答案 1 :(得分:5)

我一直在图书馆工作,以协助应用程序的国际化。它名为 SmartFormat ,在GitHub上是开源的。

它包含"语法数字"许多语言的规则,根据语言环境确定正确的单数/复数形式。翻译具有依赖于数量的单词的短语时,指定多个表单,格式化程序根据这些规则选择正确的表单。

例如:

var message = "There {0:is:are} {0} {0:item:items} remaining.";
var output = Smart.Format(culture, message, items.Count);

它与String.Format(...)具有非常相似的语法,但有许多强大的功能,可以轻松创建自然和语法正确的消息。

它还处理可能的特定于性别的格式,列表等等。

答案 2 :(得分:2)

moodforaday写道:

这适用于全面,而不仅仅是数字。例如,诸如“%s被删除”的片段也是不可翻译的,因为动词的形式将取决于名词的性别,这在此不可用。我能为波兰语做的最好的事情相当于“已删除:%s”,但只有%s占位符包含在可翻译资源中时我才能这样做。如果我所有的都被“删除”而没有指向名词的线索,我只能大声咒骂我的狗,最后我还是要产生垃圾语法。

我想在这里提出的观点是,永远不要包含名词作为参数。许多欧洲语言基于其性别修改名词,而对于德语,则无论是主语,宾语还是间接宾语。只需使用单独的消息。 而不是“%s被删除。”,为每种类型使用单独的翻译字符串: “该交易已被删除。” “该用户已被删除。”等

这样,每个字符串都可以正确翻译。

可以在此处找到处理不同语言的复数形式的解决方案: http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html

虽然您不能在商业应用程序中使用上述软件(它在GPL中涵盖),但您可以使用相同的概念。它们的复数形式表达式完全适合.NET中的lambda表达式。包含大量语言的复数形式表达式数量有限。您可以将特定语言映射到lambda表达式,该表达式根据语言计算要使用的复数形式。然后,在.NET resx文件中查找相应的复数形式。

答案 3 :(得分:1)

AFAIK,没有任何内置的框架可以做到这一点..

以下是该问题的一个通用解决方案的示例:

http://dotnetperls.com/plural

答案 4 :(得分:1)

anvilis写道:

  

我想在这里提出的观点是,永远不要包含名词作为参数。许多欧洲语言基于其性别修改名词,而对于德语,则无论是主语,宾语还是间接宾语。只需使用单独的消息。而不是“%s被删除。”,为每种类型使用单独的翻译字符串:“事务被删除。” “该用户已被删除。”等

我一直很好奇正确的方式是什么,使得类似于上面的内容,但是包括不能作为翻译的一部分包含的字符串,例如“%s说:”或“ %s写道:“(现在可以在Facebook上看到)。在这种情况下,%s很可能是用户名,动词取决于用户的性别,例如。

(很抱歉将此作为答案而非使用评论 - 我找不到评论链接)

答案 5 :(得分:0)

没有内置任何东西,我们最终编写了这样的代码: 另一种解决方案可以是:

  

在资源文件字符串中使用{CAR}等占位符   为“car”维护单数和复数单词的单独资源条目:     CAR_SINGULAR汽车
    CAR_PLURAL汽车

     

用这个逻辑开发一个类:

class MyResource
 {

    private List<string> literals = new List<string>();
    public MyResource() { literals.Add("{CAR}") }
    public static string GetLocalizedString(string key,bool isPlural)
    {
       string val = rm.GetString(key);
       if(isPlural)
       {
          val = ReplaceLiteralWithPlural(val);
       }
       else
       {
          val = ReplaceLiteralWithSingular(val);   
       }     
    }  
}

string ReplaceLiteralWithPlural(string val)
{
   StringBuilder text = new StringBuilder(val)
   foreach(string literal in literals)
   {
      text = text.Replace(literal,GetPluralKey(literal));
   }
}

string GetPluralKey(string literal)
{
  return literal + "_PLURAL";
}

答案 6 :(得分:-1)

逻辑不需要在您的视图中,但它肯定不在DotNet框架的资源模型中。你的是一个足够简单的案例,你可以通过为单数创建一个简单的格式字符串,以及为复数创建一个简单的格式字符串。 “你有一辆车。”/“你有{0}辆汽车。”然后,您需要编写一个区分复数和单数情况的方法。

据我所知,没有一种语言需要比单数/复数更复杂的语言,但可能有一些语言表达相当于“你有0辆车”听起来不对。还有许多语言在单数和复数之间没有区别,但这只需要在资源字符串中有一点重复。 (编辑添加:性别,有时结尾会根据许多语言中的单位数量而变化,但只要您区分单数和复数句子而不仅仅是单词,这应该没问题。)

微软大多放弃了语义上的聪明本地化,因为很难将多元化之类的内容概括为30多种语言。这就是为什么你会在大多数应用程序中看到数字量的无聊呈现,这些应用程序被翻译成多种语言,沿着“Cars:{0}”。这听起来很蹩脚,但令人惊讶的是,在我最后一次检查时,可用性研究在大多数情况下并不支持冗长的自然语言表达。