Js-lingui: [next]: Describe how to load localeData in migration docs

Created on 26 Apr 2020  路  10Comments  路  Source: lingui/js-lingui

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>
  )
}

image

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.

accepted 馃悶bug 馃摉 documentation

Most helpful comment

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)
    },
})

All 10 comments

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 i18n to wrap output of macro. Macro already returns i18n._ call under the hood

@tricoder42 oh, that's sweet! thanks :-)

Regarding plurals: Do you load localeData manually?

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.

Was this page helpful?
0 / 5 - 0 ratings