Search code examples
reactjslocalizationtranslationicureact-intl

Why my nested plural ICU message does not work in react-intl FormattedMessage?


I'm using react-intl and its <FormattedMessage /> tag.

I want to have a structured message that will pick the correct plural variant based on provided values to allow translators to work with rules of their language, i.e., if they have a different variant for "one", "two", "many", items, etc. I did not want to have it hardcoded inside of the application business logic via switch statements that would use just English rules for "zero", "one", and "other".

<FormattedMessage id="myMessage" values={{applesCount: 4, orangesCount: 0, pearsCount: 1}} /> should produce I have some apples and some pears from the following source.

For some reasons, it returns I have some apples, some pears, and some oranges

{applesCount, plural, 
    zero {{pearsCount, plural, 
        zero {{orangesCount, plural, 
            zero {I have no fruit}
            other {I have some oranges}
        }}
        other {{orangesCount, plural, 
            zero {I have some pears}
            other {I have some pears and some oranges}
        }}
    }}
    other {{pearsCount, plural, 
        zero {{orangesCount, plural, 
            zero {I have some apples}
            other {I have some apples and some oranges}
        }}
        other {{orangesCount, plural, 
            zero {I have some apples and some pears}
            other {I have some apples, some pears, and some oranges}
        }}
    }}
}

I tested it via https://format-message.github.io/icu-message-format-for-translators/editor.html

Also, I have this codesandbox where you can tinker with it: https://codesandbox.io/s/react-intl-formattedmessage-using-plural-x8ki5

For reference, I checked http://userguide.icu-project.org/formatparse/messages and https://formatjs.io/guides/message-syntax/ and would expect that my message structure is supported.

Can you help me detect what is wrong or how should I change it to get it working?


Solution

  • The issue is:

    English as a language doesn't have grammar specialized specifically for zero number of items.

    It is mainly singular or plural (on in some rare residual cases dual).

    The syntax which you are using is specifically for those languages where grammar is specialized specifically for zero number of items. (Examples are Arabic and Latvian)

    Read Here: https://formatjs.io/guides/message-syntax/#plural-format.
    Also, this article on wikipedia explains the same

    So, the approach won't work for English. Instead you need to use =0 (=value syntax) for matching quantity to zero for the solution to work.

    {applesCount, plural, 
        =0 {{pearsCount, plural, 
            =0 {{orangesCount, plural, 
                =0 {I have no fruit}
                other {I have some oranges}
            }}
            other {{orangesCount, plural, 
                =0 {I have some pears}
                other {I have some pears and some oranges}
            }}
        }}
        other {{pearsCount, plural, 
            =0 {{orangesCount, plural, 
                =0 {I have some apples}
                other {I have some apples and some oranges}
            }}
            other {{orangesCount, plural, 
                =0 {I have some apples and some pears}
                other {I have some apples, some pears, and some oranges}
            }}
        }}
    }
    

    Similarly, for 1 number, one won't work for English. You have to use =value syntax (=1).
    Tried this on sandbox and works fine.

    Hope it helps. Revert for any doubts.