Migration guide from 2.x to 3.x
Check out the @lingui/codemods package for semi-automatic migration of your codebase.
Backward incompatible changes
Minimal required versions are:
- Node.js: 10.x
- React: 16.8
- Babel: 7
@lingui/react
-
<I18n>
render-prop component was removed in favor ofuseLingui
hook. -
In
I18nProvider
,defaultRender
prop was renamed todefaultComponent
, and now only accepts Custom Components -
In
Trans
,defaults
prop was renamed tomessage
anddescription
tocomment
. -
In
Trans
,render
prop only accepts render-prop function which is used to render translation. -
In
Trans
, new propcomponent
accepts React component which is used to render translation. -
In
Trans
,components
is now an object, not an array. When using the low level API, it allows to name the component placeholders:<Trans id="Read <a>the docs</a>!" components={{ a: <a href="/docs" /> }} />
-
NumberFormat
andDateFormat
components were removed. Importi18n
from@lingui/core
package and usei18n.date()
andi18n.number()
instead.
Removed I18nProvider
declarative API
LinguiJS started as a React library. After @lingui/core
package was introduced, there were two ways how to switch active locales and manage catalogs in React: either using I18nProvider
declarative API or using setupI18n
imperative API.
In the same spirit as @apollo/react
and react-redux
, the I18nProvider
is simplified and accepts i18n
manager, which must be created manually:
import { I18nProvider } from '@lingui/react'
import { i18n } from "@lingui/core"
+ import { en } from 'make-plural/plurals'
import { messages } from './locale/en/messages.js'
+ i18n.loadLocaleData('en', { plurals: en })
+ i18n.load('en', messages)
+ i18n.activate('en')
function App() {
return (
- <I18nProvider locale="en" catalogs={{ en: catalogEn }}>
+ <I18nProvider i18n={i18n}>
<App />
</I18nProvider>
)
}
@lingui/core
-
Package now exports default
i18n
instance. It's recommended to use it unless you need customized instance.+ import { i18n } from "@lingui/core"
- import { setupI18n } from "@lingui/core"
- const i18n = setupI18n()
i18n.activate('en')NoteIf you decide to use custom
i18n
instance, you also need to setruntimeConfigModule
. Macros automatically importi18n
instance and must be aware of correct import path. -
i18n.t
,i18n.plural
,i18n.select
andi18n.selectOrdinal
methods were removed in favor of macros. -
i18n.use
was removed. Using two locales at the same time isn't common use-case and can be solved in user land by having two instances ofi18n
object. -
Signature of
i18n._
method has changed. The third parameter now accepts default message inmessage
prop, instead ofdefaults
:- i18n._('Welcome / Greetings', { name: 'Joe' }, { defaults: "Hello {name}" })
+ i18n._('Welcome / Greetings', { name: 'Joe' }, { message: "Hello {name}" }) -
i18n._
also accepts a message descriptor as a first parameter:i18n._({
id: string,
message?: string,
comment?: string
})
i18n.load
loads a catalog for a single locale
i18n
manager is the single source of truth and there's no need to keep all catalogs loaded outside this object. To make loading easier, i18n.load
now accepts catalog for a single locale or multiple catalogs at once.
import { i18n } from "@lingui/core"
import catalogEn from './locale/en/messages.js'
- i18n.load({ en: catalogEn })
+ i18n.load('en', catalogEn.messages)
You can still use i18n.load
to load all catalogs at once:
// i18n.js
import { i18n } from "@lingui/core";
import catalogEn from "./locale/en/messages.js";
import catalogFr from "./locale/fr/messages.js";
i18n.load({
en: catalogEn.messages,
fr: catalogFr.messages,
});
@lingui/macro
-
plural
,select
andselectOrdinal
accepts value as a first parameter:- plural({ value, one: "# book", other: "# books" })
+ plural(value, { one: "# book", other: "# books" })
@lingui/cli
- command
lingui init
was removed - command
lingui add-locale
was removed
Whitespace
Whitespace handling in plugins had few bugs. By fixing them, there might be few backward incompatible changes. It's advised to run extract
and inspect changes in catalogs (if any).
- Spaces before
{variables}
in JSX aren't preserved. This is how React handles whitespaces in JSX. Leading whitespace is always removed:
<Trans>
"
{variable}
"
</Trans>
// Becomes: "{variable}"
- Forced newlines are preserved. Sometimes it's useful to keep newlines in JSX. If that's your case, you need to force it in the same was as spaces are forced before variables or elements:
<Trans>
1. Item{"\n"}
2. Item
</Trans>
// Becomes: 1. Item\n2. Item
Plugins/Presets
Plugins are replaced with macros. Presets are removed completely because they aren't needed anymore.
- Uninstall plugins/presets, remove them from Babel config and replace them with
macros
:
- npm
- Yarn
- pnpm
npm uninstall @lingui/babel-preset-react
npm install --dev @lingui/macro babel-plugin-macros
yarn remove @lingui/babel-preset-react
yarn add --dev @lingui/macro babel-plugin-macros
pnpm remove @lingui/babel-preset-react
pnpm add --dev @lingui/macro babel-plugin-macros
{
"presets": [
- "@lingui/babel-preset-react"
],
"plugins": [
+ "macros",
]
}
-
Import
Trans
,Plural
,Select
andSelectOrdinal
from@lingui/macro
:- import { Trans } from "@lingui/react"
+ import { Trans } from "@lingui/macro"NoteIf you used
Trans
component without children, then keep the import from@lingui/react
:import { Trans } from "@lingui/react";
const CustomID = () => <Trans id="msg.id" />;
const DynamicID = () => <Trans id={msgId} />; -
i18n.t
,i18n.plural
,i18n.select
andi18n.selectOrdinal
methods are removed and replaced with macros.
These macros automatically binds message to default i18n
object:
import { i18n } from "@lingui/core"
+ import { t } from "@lingui/macro"
- i18n.t`Hello World`
+ t`Hello World`
New features
i18n.load
i18n.load
can now accept one catalog for specific locale. Useful for incremental loading of catalogs.
import { i18n } from "@lingui/core";
// Lingui v2 and v3
i18n.load({
en: require("./locale/en/messages"),
cs: require("./locale/cs/messages"),
});
// Lingui v3 only
i18n.load("en", require("./locale/en/messages"));
i18n.load("cs", require("./locale/cs/messages"));
i18n.on('change', callback)
Event change
is fired anytime new catalogs are loaded or when locale is activated.
Native TypeScript support
Lingui now supports TypeScript out of the box, don't forget to remove the @types/lingui
packages from your project.