Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Country-coded language codes breaks plurals when using po-gettext format #1130

Closed
Tracked by #1128
cvincent-atmanco opened this issue Sep 7, 2021 · 1 comment · Fixed by #1131
Closed
Tracked by #1128

Comments

@cvincent-atmanco
Copy link

We are currently in the process of converting the localization of our application from 2-letter ISO Codes to 4-letter ISO Codes, and we use lingui for localizing all of our front-end applications.
We renamed all of PO files (messages.en.po -> messages.en-CA.po), and changed our lingui.config.ts locales from en to en-CA.

For the PO files content, following the GNU Documents, the Language header can be in the following format;

‘ll_CC’, where ‘ll’ is an ISO 639 two-letter language code (lowercase) and ‘CC’ is an ISO 3166 two-letter country code (uppercase).

So we changed the Language header from en to en_CA.

Describe the bug
After changing the Language header in the PO files, the plurals couldn't be parsed correctly by @lingui/loader. We got the following error message:
Multiple translations for item with key KEY in language en_CA, but no plural cases were found. This prohibits the translation of .po plurals into ICU plurals. Pluralization will not work for this key.

We pinpointed the error to the getPluralCases(lang) called by convertPluralsToICU(items, lang) method in packages/cli/src/api/formats/po-gettext.ts. It seems like it's using the language from the PO file header as-is, and node-gettext/lib/plurals doesn't have any country-coded language code. Therefore, no plural cases are ever found.

I was able to "fix" this issue by adding these couple of lines at the beginning of getPluralCases(lang):

const getPluralCases = (lang: string): string[] | undefined => {
>  if (lang.includes("_")) {
>    lang = lang.split("_")[0];
>  }

  const gettextPluralsInfo = gettextPlurals[lang]

  return gettextPluralsInfo?.examples.map((pluralCase) =>
    pluralsCldr(lang, pluralCase.sample)
  )
}

But I am curious if it's a configuration issue on our side. I couldn't find anything in the docs explaining how to handle such a use-case (country-coded language codes + po-gettext format + plurals), but maybe there's an undocumented way of doing it?

To Reproduce
Using a PO file with a country-coded language code such as:

msgid ""
msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Language: en_CA\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"

msgid "test_key"
msgid_plural "test_key_plural"
msgstr[0] "# item"
msgstr[1] "# items"

and a country-coded language code in your lingui.config.ts, such as:

module.exports = {
    locales: ["en-CA"],
    sourceLocale: "en-CA",
    fallbackLocales: {
        default: "en-CA"
    },
    catalogs: [
        {
            path: "<rootDir>/src/locales/messages.{locale}",
            include: "<rootDir>/src",
            exclude: ["**/node_modules/**"]
        }
    ],
    format: "po-gettext",
    compileNamespace: "cjs",
};

You can simply run lingui compile and it should reproduce the error.

Expected behavior
It should find the correct plural cases for country-coded language codes, such as "en-CA" or "fr-CA".

  • jsLingui version 3.10.4
  • Babel version 7.12.9
@semoal
Copy link
Contributor

semoal commented Sep 7, 2021

This is a good pick mate, going to fix it right now. node-gettext only offer plurals for 2-letter iso locales, so you're solution is perfectly valid

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants