在法语中,复数系统将 0 视为 "other" 而不是 "one"

In French, plural system treats 0 as "other" instead of "one"

res/values/strings.xml中,我有

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <plurals name="days_amount">
        <item quantity="one">%d day EN</item>
        <item quantity="other">%d days EN</item>
</plurals>
</resources>

res/values-fr/strings.xml中,我有

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <plurals name="days_amount">
        <item quantity="one">%d jour FR</item>
        <item quantity="other">%d jours FR</item>
    </plurals>
</resources>

使用英语语言环境 res.getQuantityString(R.plurals.days_amount, 0, 0) 返回:

"0 days"

这符合英语规则(即零数量 <=> 多个数量)。


但是对于法语语言环境,它返回:

"0 jours"

根据法国规则这是不合适的(又名零数量 <=> 单数)。

它应该返回 "O jour"

法国规则:http://www.unicode.org/cldr/charts/25/supplemental/language_plural_rules.html#fr


所以,这是一个错误,还是我做错了什么?

你做错了什么。它完全按照您的指示去做。

您的规则规定当值为 other 时,使用 "days" 或 "jours"。然后您传入值 0,即 other,因此它会根据要求使用 "days" 和 "jours"。

您可以尝试为数量 "zero" 设置第三个值,它具有特定于语言的规则。

我认为你的代码是正确的。原因如下:

  1. Android documentation contains the text zero, one, two, few, many, and other, which exactly matches the wording of the Unicode language plural rules。这表明 Android 使用了它们。
  2. 这些复数规则规定 0 本书 的法语案例由 one 案例处理。

由于 Android 文档没有明确提及 Unicode 语言的复数规则,您应该要求 Android 支持人员进行澄清。

在这样做之前,您应该咨询 this other question,法国的规则显然行之有效。

确实,您的担心是对的,在法语中,金额 0 应被视为“one”而不是“other”。问题出在某些 Android API 中:API <= 16

因此,如果您仍想支持 API 16,只需为零金额添加一个额外的字符串键。假设您有:

<plurals name="label_message_reminder_text">
        <item quantity="other">Vous avez %1$s nouveaux messages</item>
        <item quantity="one">Vous avez %1$s nouveau message</item>
</plurals>

只需添加一个额外的字符串:

<string name="label_message_reminder_text_zero">Vous avez %1$s nouveau message</string>

然后在检索复数时可以这样做:

String newMessagesText = getMyString(context, resourceId, amount);
messageTextView.setText(String.format(newMessagesText, amount));

你可以有一个方法来执行 getMyString():

public String getMyString(Context context, int resourceId, int amount){

  if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {    
     if(amount == 0) {
        switch (resourceId) {
           case R.plurals.label_message_reminder_text:
              return context.getResources().getString(R.string.label_message_reminder_text_zero);
        }
     }
  }

  return context.getResources().getQuantityString(resourceId, amount);

}