Migration guide from 0.x to 1.x¶
Even though only a few projects use LinguiJS at the moment, the purpose of this guide is to setup a high-quality migration path for future major versions.
Newline normalization in Babel plugins¶
Formatting of the source code shouldn’t affect generated messages. Both Babel plugins will normalize newlines inside translations.
In Javascript, multiple spaces before and after newline are replaced with single space, while newlines are removed completely:
i18n.t`
This message is wrapped
on multiple
lines
`
// babel-plugin-lingui-transform-js 0.x
"This message is wrapped\n on multiple\n lines"
// babel-plugin-lingui-transform-js 1.x
"This message is wrapped on multiple lines"
Newline normalization in React follows JSX conventions: newlines between text are replaced with single space, but newlines between components or between text and a component are removed and no space is added:
<Trans>
This message is wrapped
on <em>multiple</em>
<strong>lines</strong>
</Trans>
// babel-plugin-lingui-transform-react 0.x
"This message is wrapped\n on <em>multiple<em>\n <0>lines</0>"
// babel-plugin-lingui-transform-react 1.x
"This message is wrapped on <0>multiple<0><1>lines</1>"
As weird as it is, this is consistent with how JSX works. If you need to force
a space at the end of a line, add {" "}
:
<Trans>
This message is wrapped
on <em>multiple</em>{" "}
<strong>lines</strong>
</Trans>
// This will result in:
"This message is wrapped on <0>multiple<0> <1>lines</1>"
This change won’t break the code, but it’s necessary to update message catalogs.
Javascript API (lingui-i18n
)¶
I18n constructor replaced with factory function¶
I18n
constructor has been replaced with the setupI18n
factory function:
import { setupI18n } from 'lingui-i18n'
// lingui-i18n 0.x
const i18n = new I18n(
language: string,
messages: {[language: string]: Messages}
)
// lingui-i18n 1.x
const i18n = setupI18n({
language: string,
catalogs?: {
{[language: string]}: {
messages: Messages
}
},
development?: Development
})
messages
were also replaced with catalogs
, more info
below.
lingui-i18n
still exports the default instance of I18n
class, but as
a named export:
// lingui-i18n 0.x
// also works in lingui-i18n 1.x, but deprecated
import i18n from 'lingui-i18n'
// lingui-i18n 1.1
import { i18n } from 'lingui-i18n'
Explicit development mode¶
The biggest change in this first major release is support for compiled message catalogs. Most i18n libraries parse and compile messages on the fly, which makes them heavy and slow. The compiler is still useful in development, but now it has to be enabled manually:
import { setupI18n } from 'lingui-i18n'
const dev = process.env.NODE_ENV !== 'production'
// this import is required in development only
? require('lingui-i18n/dev')
: null
const i18n = setupI18n({
language: 'en',
development: dev
})
Development data includes compiler and plural rules for all languages. Both
are very large and unnecessary in production, because lingui-i18n
supports loading of compiled message catalogs.
Messages replaced with catalogs¶
Plural rules are removed from library completely, because compiled message
catalogs contain language-specific data, including plural rules. messages
were replaced with catalogs
to simplify loading all required data:
In previous version, loading of messages looked like this (lingui-i18n 1.x
):
// lingui-i18n 0.x
type Messages = {
[messageId: string]: string
}
type AllMessages = {
[language: string]: Messages
}
// setupI18n({ messages: AllMessages })
const i18n = setupI18n({
messages: {
en: {
msg: 'Hello'
}
}
})
// i18n.load(messages: AllMessages)
i18n.load({
en: {
msg: 'Hello'
}
})
Now it looks like this (lingui-i18n 1.x
):
type Messages = {
// support both static and compiled messages
[messageId: string]: string | Function
}
type Catalog = {
messages: Messages,
languageData: {
// required in production
plurals: Function
}
}
type Catalogs = {
[language: string]: Catalog
}
// setupI18n({ catalogs: Catalogs })
const i18n = setupI18n({
catalogs: {
en: {
messages: {
msg: 'Hello'
}
}
}
})
// i18n.load(catalogs: Catalogs)
i18n.load({
en: {
messages: {
msg: 'Hello'
}
}
})
More about [loading message catalogs]().
React API (lingui-react
)¶
Changes in React API reflect changes in underlying core lingui-i18n
.
InjectI18n
was removed and replaced with withI18n
decorator. Loading
InjectI18n
in recent versions of lingui-react@<1.0.0
would raise a
deprecation warning in console.
Development data must be loaded explicitly. It works in the same way as in
lingui-i18n
:
import { I18nProvider } from 'lingui-react'
const dev = process.env.NODE_ENV !== 'production'
// this import is required in development only
? require('lingui-i18n/dev')
: null
const App = () => {
<I18nProvider language="en" development={dev}>
<Content />
</I18nProvider>
}
Also, messages were replaced with catalogs:
import { I18nProvider } from 'lingui-react'
const dev = process.env.NODE_ENV !== 'production'
// this import is required in development only
? require('lingui-i18n/dev')
: null
const catalog = {
messages: {
msg: "Hello"
}
}
const App = () => {
<I18nProvider language="en" catalogs={{ en: catalog }} development={dev}>
<Content />
</I18nProvider>
}
CLI (lingui-cli)¶
lingui export
command now creates a more complex message catalog, which contains
not only translations, but also default messages (if any) and locations from where
the strings were extracted.
Running lingui export
will generate the new-style catalog while merging translations
from the old one. This process is completely seamless. However, any external
tool must be updates to accept the new-style catalogs.