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

16 asp.net localization

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

或者我不得不在我看来有逻辑来看它是单数还是复数?

Mar*_*ski 35

JasonTrue写道:

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

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

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

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

a: Number of cars: %d
Run Code Online (Sandbox Code Playgroud)

这意味着名词"car"的形式不依赖于数字,0与任何其他数字一样自然.

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

b: You have 1 car.    
c: You have %d cars.
Run Code Online (Sandbox Code Playgroud)

永远不要将这些单位分成更小的片段,如

d: You have
e: car(s)
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

  • 很好的答案!幽默的加分! (4认同)
  • 在阿拉伯语中,有3种形式:单数,双数和复数 (3认同)

Sco*_*pey 5

我一直在研究图书馆,以协助应用程序的国际化.它被称为SmartFormat,在GitHub上是开源的.

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

例如:

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

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

它还涉及可能的性别特定格式,列表等等.


nmd*_*mdr 0

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

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

开发一个具有以下逻辑的类:

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";
}
Run Code Online (Sandbox Code Playgroud)