i18next / i18next-icu

i18nFormat plugin to use ICU format with i18next
MIT License
81 stars 17 forks source link

ICU pluralisation in Android React Native app breaks if label has # #47

Open catarinamateus opened 2 years ago

catarinamateus commented 2 years ago

Which package?

"react-native": "0.61.2", "i18next": "17.2.0", "i18next-icu": "2.0.3", "intl-messageformat": "9.4.6",

"@formatjs/intl-getcanonicallocales": "1.8.0", "@formatjs/intl-locale": "2.4.41", "@formatjs/intl-pluralrules": "4.2.0",

Describe the bug

When I use plural labels in my JSON and they include '#' following ICU format, these label are broken in my app without throwing any error.

To Reproduce

import i18n, { InitOptions } from 'i18next';
import ICU from 'i18next-icu';
import { initReactI18next } from 'react-i18next';
import '@formatjs/intl-getcanonicallocales/polyfill'
import '@formatjs/intl-locale/polyfill'
import '@formatjs/intl-pluralrules/polyfill'
import '@formatjs/intl-pluralrules/locale-data/en'

//On my app init
 i18n.use(languageDetector(cfg))
        .use(ICU)
        .use(initReactI18next)
        .init({
              fallbackLng: 'en',
               debug: true,
               nsSeparator: ':',
               keySeparator: '.',
               interpolation: {
                  escapeValue: false,
                  formatSeparator: ',',
                },
              react: {
                  wait: true,
                  useSuspense: false,
               },
            resources: {
                en: {
                     error: '{count, plural, one {Recording canceled.} other {Canceled # recordings.}}',
                     success: '{count, plural, one {Recording canceled.} other {Canceled recordings.}}',
                },
            },
        });

//Testing labels

i18n.t('error', {count : 1})
i18n.t('success', {count : 1})

//OUTPUT:  
// Recording canceled.
// Recording canceled.

i18n.('error', {count : 9})
i18n.t('success', {count : 9})

//OUTPUT: 
// {count, plural, one {Recording canceled.} other {Canceled # recordings.}} ---> EXPECTED OUTPUT: Canceled 9 recordings.
// Canceled recordings.

Smartphone (please complete the following information):

Android emulator pixel 30 api 30

adrai commented 2 years ago

It looks like your icu syntax is wrong... there is a missing } at the end.

Here a fixed example: https://codesandbox.io/s/react-i18next-example-forked-f3txn?file=/src/i18n.js:708-709

catarinamateus commented 2 years ago

hi @adrai , it was a typo mistake, syntax is correct in our code. I forgot to mention that this is working fine in iOS and Web (all share same source code), as it is working in your codesandbox, this only fails for android devices :(

adrai commented 2 years ago

Sorry, I'm not able to help... no mobile dev environment... but if it works for ios and web, there might be an issue with the android emolator... and i18next-icu is not the root cause. 🤷‍♂️ Does it work on a real android device at least?

catarinamateus commented 2 years ago

Hi @adrai,

Thanks for the quick response.

It just doesn't work in Android (emulator or real device) when using plurals and we include the #, but it works if using {count} , I can't find anywhere the reason why. Could you come up with any reason why would this happen?

Basically what I found is that intl-messageformat (formatJS) that is being used in your lib, needs Intl support, what it doesn't come out of the box for Android apps built in react-native. For that reason I added the polyfills provided by formatJs to cover pluralisation in Android. I asked them if they knew if could be missing any script in their lib but they indicated it should be an i18next issue.

I'll try to dig a little bit more and give you updates if anything comes up!

adrai commented 2 years ago

Sorry, I'm not a mobile developer... Did you install intl-messageformat? npm install intl-messageformat