如何使用 Android 数量字符串(复数)

我试图使用参考资料中的 GetQuantityString方法来检索基于 Android Developer 指南 数量字符串(复数)数量字符串(复数)

我得到的错误是

错误: (604)在非位置格式中指定的多个替换; 您的意思是添加 format = “ false”属性吗?
错误: (604)在预期的位置找到标记

当我设置复数如下

<plurals name="productCount">
<item quantity="one" formatted="true">%1$d of %2$d product</item>
<item quantity="other" formatted="true">%1$d of %2$d products</item>
</plurals>

然后试着读下面的内容 SetText (getResources () . getQuantityString (R.multials.productCount,position,size)) ;

一种变通方法是将字符串分解为只对字符串的最后一部分使用复数,并将两部分连接起来。但如果可能的话,我尽量避免这样做。

46127 次浏览

您不需要为这些项目中的任何一个设置“格式化”属性。在使用数量字符串时,只有三种可能性:

  1. 资源字符串是纯文本,不包含任何参数
  2. 资源字符串只包含一个参数(很可能是数量) ; 使用 %d或任何您需要的格式
  3. 资源字符串包含多个参数; 所有参数都必须根据它们的位置显式访问,例如 %1$d

对于 getQuantityString方法,有两个重载: 一个只包含资源 id 和数量,另一个包含额外的 Object... formatArgs参数。

对于情况1. ,可以使用 getQuantityString(@PluralsRes int id, int quantity)方法。

对于所有其他情况,例如,如果你有 任何参数,你需要 getQuantityString(@PluralsRes int id, int quantity, Object... formatArgs)过载。注意: 所有参数必须出现在参数数组中。这意味着,如果资源字符串显示了数量,那么数量变量将被传递给函数 两次

这是因为在解析资源字符串的位置参数时,不考虑方法本身的 quantity参数。

如果这些是你的资源,

<resources>
<plurals name="test0">
<item quantity="one">Test ok</item>
<item quantity="other">Tests ok</item>
</plurals>
<plurals name="test1">
<item quantity="one">%d test ok</item>
<item quantity="other">%d tests ok</item>
</plurals>
<plurals name="test2">
<item quantity="one">%2$s: %1$d test ok</item>
<item quantity="other">%2$s: %1$d tests ok</item>
</plurals>
<plurals name="test3">
<item quantity="one">%3$s: %1$d test out of %2$d ok</item>
<item quantity="other">%3$s: %1$d tests out of %2$d ok</item>
</plurals>
</resources>

那么对 getQuantityString的适当呼叫是:

int success = 1;
int total = 10;
String group = "Group name";


getResources().getQuantityString(R.plurals.test0, success)
// Test ok
getResources().getQuantityString(R.plurals.test1, success, success)
// 1 test ok
getResources().getQuantityString(R.plurals.test2, success, success, group)
// Group name: 1 test ok
getResources().getQuantityString(R.plurals.test3, success, success, total, group)
// Group name: 1 test out of 10 ok


success = 5;
getResources().getQuantityString(R.plurals.test0, success)
// Tests ok
getResources().getQuantityString(R.plurals.test1, success, success)
// 5 tests ok
getResources().getQuantityString(R.plurals.test2, success, success, group)
// Group name: 5 tests ok
getResources().getQuantityString(R.plurals.test3, success, success, total, group)
// Group name: 5 tests out of 10 ok

数量类: 理解 quantity参数

如上所述,关键是要理解 getQuantityStringquantity参数不能用来替换诸如 %d%1$d之类的占位符。相反,它用于结合资源文件的区域设置,从 plurals本身确定适当的 item

但是要注意,这种映射比属性的名称及其可能的值(zeroonetwofewmanyother)更不直接。例如,提供一个额外的 <item quantity="zero">将不起作用(至少在英语中不起作用),即使 quantity参数的值为0。

原因是 plurals在 Android 中的工作方式是由 数量类别的概念决定的。数量类是在给定语言中具有相同语法规则的一组数量值。这意味着

  • 使用哪些数量类别,以及
  • 映射到它们的数值

取决于各个资源文件所用的区域设置。

重要的是要明白,这两个问题都只是由 语法上的必要性决定的。下面是一些例子:

  • 在汉语或韩语中,只使用 other,因为在这些语言中,句子不会因为给定的数量而在语法上有所不同。
  • 在英语中,有两个类: one表示字面值1,other表示包括0在内的所有其他值。
  • 在爱尔兰语中,1被映射到 one,2被映射到 two,3-6是 few,7-10是 many,0和11 + 是 other
  • 在斯洛文尼亚语中,值1 还有中的所有值 结束都映射到 one(1,101,3001,...)。2和以02结尾的值映射到 two(2,302,1002,...)。以03或04结尾的值映射到 few(3,4,6004,...)。其他的都是 other(0,11,48,312,...)。
  • 在波兰语中,5-19和以05-19结尾的值映射到 many(5,12,216,4711,...)。以2、3或4结尾的值(包括2-4本身)映射到 few(3、42、103、12035374,...)。然而,这尊重12、13和14是这条规则的例外,因为它们映射到 many。(旁注: 是的,从语法上讲,5是 很多,而12035374是 很少。)
  • 亚美尼亚语与英语类似,只是值0也映射到 one,因为这是他们的语法工作方式。从这个例子中可以看出,数量类 one甚至不一定只表示一个左右的数字。

正如您所看到的,确定正确的数量类可能会变得相当复杂。这就是为什么 getQuantityString已经根据 quantity参数和资源文件的区域设置为您做了这些。Android (大多数)所遵循的规则在 Unicode 通用区域资料库语言复数规则中定义。这也是数量类名称的来源。

所有这一切意味着,翻译任何数量字符串所需的数量类集可以因语言而异(汉语只需要 other,英语需要 oneother,爱尔兰语只需要 zero,等等)。然而,在一种语言中,所有 plurals都应该有相同数量的项目,涵盖该特定语言所需的所有数量类。

结论

getQuantityString的呼叫可以这样理解:

int success = 5;
int total = 10;
String group = "Group name";


getResources().getQuantityString(R.plurals.test3, success, success, total, group)
//                               \_____________/  \_____/  \___________________/
//                                      |            |               |
//         id: used to get the plurals resource      |               |
//   quantity: used to determine the appropriate quantity class      |
// formatArgs: used to positionally replace the placeholders %1, %2 and %3

quantity参数的值“5”将意味着所使用的 item将是来自中文、韩文、英文、斯洛文尼亚文和亚美尼亚文资源文件的数量类 other,爱尔兰文是 few,波兰文是 many


我还要简要提到两个特例:

非整数量

基本上,所选择的类再次依赖于特定于语言的规则。它既不是通用的如何选择一个类,也不能保证任何需要覆盖整数的所有规则的类也可以用于任何非整数。下面是一些例子:

  • 对于英语,任何带小数的值总是映射到 other
  • 对于斯洛文尼亚语,任何带小数的值总是映射到 few
  • 对于 Irish,选择取决于整数部分。
  • 对于波兰语,与整数的复杂规则不同,非整数总是像英语一样映射到 other

注: 根据 语言复数规则应该是这样的。唉,Android 目前还没有现成的 floatdouble方法。

一个字符串中的多个量

如果您的显示文本有多个数量,例如 %d match(es) found in %d file(s).,将其拆分为 单独的资源:

  1. %d match(es)(plurals项目)
  2. %d file(s)(plurals项目)
  3. %1$s found in %2$s.(普通参数化 strings项)

然后,您可以对1和2调用适当的 getQuantityString,然后对第三个 getString调用适当的 getString,前两个容易本地化的字符串作为 formatArgs

原因是允许翻译人员在第三个资源中切换参数顺序,如果语言需要的话。例如,如果一种假设语言中唯一有效的语法是 In %d file(s) it found %d match(es).,那么翻译人员可以像往常一样翻译复数,然后将第三个资源翻译为 In %2$s it found %1$s.来解释交换顺序。