Describe the bug
This is an issue I encountered while migrating from the 3.0.0-5 version to 3.0.0-11. I probably have to use make-plural somewhere in my app, but I don't know where because the migration docs didn't mention it.
To Reproduce
Steps to reproduce the behavior, possibly with minimal code sample, e.g:
import { plural } from '@lingui/macro'
import { useLingui } from '@lingui/react'
export default function App() {
const { i18n } = useLingui()
return (
<span>
{i18n._(plural(1, {
one: 'I have # friend',
other: 'I have # friends',
}))}
</span>
)
}

Expected behavior
I should either expect the code to work out-of-the-box, or to have the migration docs to point out what the developer is supposed to do to have plurals working.
Hey @lucasecdb, one minor issue is that you don't have to use i18n to wrap output of macro. Macro already returns i18n._ call under the hood. This example should be enough:
import { plural } from '@lingui/macro'
export default function App() {
return (
<span>
{plural(1, {
one: 'I have # friend',
other: 'I have # friends',
})}
</span>
)
}
Regarding plurals: Do you load localeData manually? https://js-lingui-git-next.lingui-js.now.sh/releases/migration-3.html#removed-i18nprovider-declarative-api
import { plural } from '@lingui/macro'
+ import { i18n } from "@lingui/core"
+ import { en } from 'make-plural/plurals'
+ i18n.loadLocaleData('en', { plurals: en })
export default function App() {
return (
<span>
{plural(1, {
one: 'I have # friend',
other: 'I have # friends',
})}
</span>
)
}
You're right, it's missing in migration docs.
one minor issue is that you don't have to use
i18nto wrap output of macro. Macro already returnsi18n._call under the hood
@tricoder42 oh, that's sweet! thanks :-)
Regarding plurals: Do you load
localeDatamanually?
yeah, I searched the typings on the i18n instance to see which method I should use to load the locale data. I didn't know about the make-plural/plurals entrypoint, that's nice.
I think I can help create a little section in the docs regarding the change to how to load locale data if you can add help me on the motivation for this change (I have a hunch it's about bundlesize).
I think I can help create a little section in the docs regarding the change to how to load locale data if you can add help me on the motivation for this change (I have a hunch it's about bundlesize).
That would be awesome! Thanks a lot 馃憤
@tricoder42 I have the same issue with plurals is not a function, but when
I added localeData manually but the error still persists, like in this demo https://github.com/lingui/js-lingui/pull/704
Another issue where I described the problem thoroughly https://github.com/lingui/js-lingui/issues/705
import {i18n} from '@lingui/core';
import { en, ru } from 'make-plural/plurals'
i18n.loadLocaleData('en', { plurals: en })
i18n.loadLocaleData('ru', { plurals: ru })
@tienpham94 you can try to import via one of the follows:
import * as plurals from 'make-plural/plurals'
const plurals: Record<string, Function> = require('make-plural/plurals');
And apply as:
let locale = "en"
let messages = {}; // preload somewhere
i18n.loadLocaleData(locale, { plurals: plurals[locale] })
i18n.load(locale, messages);
Making sure that loadLocaleData is called before load is called the first time for a locale fixed the issue for me.
Instead of using make-plural, I used the browser's own Intl implementation like this:
const pluralsOrdinal = new Intl.PluralRules(locale, { type: "ordinal" })
const pluralsCardinal = new Intl.PluralRules(locale, { type: "cardinal" })
i18n.loadLocaleData(locale, {
plurals(count: number, ordinal: boolean) {
return (ordinal ? pluralsOrdinal : pluralsCardinal).select(count)
},
})
This should be fixed in 3.0.0-18 which prevents rendering before messages are loaded.
This still isn't working for me in 3.0.1
import { setupI18n } from '@lingui/core'
import * as plurals from 'make-plural/plurals'
import en from './locales/en/messages'
import es from './locales/es/messages'
export const i18n = setupI18n()
i18n.loadLocaleData('en', { plurals: plurals.en })
i18n.loadLocaleData('es', { plurals: plurals.es })
i18n.load('en', en.messages)
i18n.load('es', es.messages)
TypeError: plurals is not a function
plural
http://app-dev.greenlightready.com/static/js/0.chunk.js:596:43
ctx
http://app-dev.greenlightready.com/static/js/0.chunk.js:645:37
(anonymous function)
http://app-dev.greenlightready.com/static/js/0.chunk.js:684:21
formatMessage
http://app-dev.greenlightready.com/static/js/0.chunk.js:666:22
(anonymous function)
http://app-dev.greenlightready.com/static/js/0.chunk.js:690:18
I18n._
http://app-dev.greenlightready.com/static/js/0.chunk.js:982:82
WelcomePage.render
src/pages/welcome/WelcomePage.tsx:115
112 | <p>
113 | <Trans id="WelcomePage.welcome">
114 | Hi {user.firstName}! You've been added
> 115 | by {plural(this.totalLocations(), { one: 'location', other: 'locations' })}
| ^ 116 | to Greenlight's secure COVID-19 monitoring platform.
117 | </Trans>
118 | </p>
i18n.loadLocaleData('en', { plurals: plurals.en })
i18n.loadLocaleData('es', { plurals: plurals.es })
Don't use setupI18n if you're not editing more interanlly i18n configuration. It's recommended to use the i18n instance from lingui/core
I've tried your changes on create-react-app example on Lingui project.
import { i18n } from "@lingui/core";
import * as plurals from 'make-plural/plurals'
export const locales = {
en: "English",
cs: "膶esky",
};
export const defaultLocale = "en";
i18n.loadLocaleData('en', { plurals: plurals.en })
i18n.loadLocaleData('cs', { plurals: plurals.es })
And works perfect, can you install make-plural to try if that's the problem, anyways on the new version we're realisng a better message for this case
"Don't use setupI18n"
That was all that needed to change! Thanks.
Most helpful comment
Making sure that
loadLocaleDatais called beforeloadis called the first time for a locale fixed the issue for me.Instead of using
make-plural, I used the browser's own Intl implementation like this: