我正在尝试使用资源中的getQuantityString方法根据Android开发人员指南检索数量字符串(复数)数量字符串(复数)
我得到的错误是
错误:(604) 以非位置格式指定了多个替换;您的意思是添加 formatted="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>
并尝试按如下所示阅读
productIndexCountText.setText(getResources().getQuantityString(R.plurals.productCount, position, size));
一种解决方法是将字符串分解为仅对字符串的最后一部分使用复数,并将这两个部分连接起来。但如果可能的话,我尽量避免这样做。
您无需为其中任何项设置"格式化"属性。使用数量字符串时,只有三种可能性:
- 资源字符串是纯文本,不包含任何参数
- 资源字符串仅包含一个参数(很可能是数量);请使用
%d
或您需要的任何格式 - 资源字符串包含多个参数;所有参数都必须按其位置显式访问,例如
%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
参数如上所述,关键是要了解getQuantityString
的quantity
参数不用于替换占位符,如%d
或%1$d
。相反,它用于结合资源文件的区域设置,从plurals
本身确定适当的item
。
但请注意,这是一个比属性名称及其可能的值(zero
、one
、two
、few
、many
、other
)可能暗示的更直接的映射。例如,即使quantity
参数的值为 0,提供额外的<item quantity="zero">
也不起作用(至少在英语中不起作用)。
原因是plurals
在 Android 中的工作方式是通过数量类的概念。数量类是一组在给定语言中具有相同语法规则的数量值。这关键意味着
- 使用哪些数量类别,以及
- 映射到它们的数值
取决于相应资源文件所针对的区域设置。
重要的是要明白,这两个问题都是由语法必要性决定的。以下是一些示例:
- 在中文或韩语中,只使用
other
,因为在这些语言中,句子在语法上不会根据给定的数量而有所不同。 - 在英语中,有两个类:
one
表示文本值 1,other
表示所有其他值(包括 0)。 - 在爱尔兰语中,1映射到
one
,2映射到two
,3-6是few
,7-10是many
,0和11+是other
。 - 在斯洛文尼亚语中,值 1和所有以01 结尾的值映射到
one
(1, 101, 3001, ...)。 2 和以 02 结尾的值映射到two
(2, 302, 1002, ...)。 3、4 和以 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
,英语需要one
和other
,爱尔兰语需要除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
。 - 对于爱尔兰语,选择取决于整数部分。
- 对于波兰语,与整数的复杂规则相反,非整数总是像英语一样映射到
other
。
注意:根据语言复数规则,这是应该的。唉,Android目前没有现成的float
或double
方法。
一个字符串中的多个数量
如果您的显示文本有多个数量,例如%d match(es) found in %d file(s).
,将其拆分为三个单独的资源:
%d match(es)
(plurals
项)%d file(s)
(plurals
项)%1$s found in %2$s.
(普通参数化strings
项)
然后,您可以对 1 和 2 的getQuantityString
进行适当的调用,然后对第三个进行另一次getString
调用,前两个易于本地化的字符串作为formatArgs
。
原因是允许翻译人员在语言需要时切换第三个资源中的参数顺序。 例如,如果假设语言中唯一有效的语法是In %d file(s) it found %d match(es).
,则翻译者可以像往常一样翻译复数形式,然后将第三个资源翻译为In %2$s it found %1$s.
以解释交换的顺序。