Seamless internationalization in Javascript and React
js-lingui
There's ongoing campaign on Indiegogo to raise funds for this project. If you want to support it, please consider donation or share it with your friend.
Type-checked and intuitive way to internationalize applications in Javascript and React.
Internationalization is the design and development of a product, application or document content that enables easy localization for target audiences that vary in culture, region, or language.
Key features
⚠️ Warning: Latest stable version of jsLingui requires Babel 6. Babel 7 will be
supported from the next major version (3.x) after it's released.
- Small and fast - about 6kb gzipped
- Babel plugin for convenient, type-checked way of writing ICU MessageFormat (recommended, but not required)
- CLI for extracting and compiling message catalogs
- Built on standard ICU MessageFormat (is able to replace [react-intl][ReactIntl] completely)
- Variable interpolation
- Components inside translations (e.g:
Read <Link to="...">documentation</Link>.
) - Plurals, Ordinals and Categories (i.e. Select)
- Number and Date formats (from Intl)
- Works with manual and generated message IDs
- Works with in any JS environment, while integration packages brings better developer experience in target environments (e.g:
lingui-react
for React) - High quality build (high test coverage, follows semver, deprecation warnings for breaking changes and migration guides for major releases)
See the [tutorial for React][TutorialReact]
Intuitive way of writing messages
No matter what i18n library you use, there is always an underlying message
format that handles variable interpolation, plurals and date/number formatting.
js-lingui
isn't reinventing the wheel, but rather uses standardized
ICU MessageFormat which is supported in many platforms (the same format
that [react-intl][ReactIntl] uses).
js-lingui
goes one step further and allows you to write messages in a way
so intuitive that you'll forget there's an underlying i18n library.
Compare following examples of low-level API and convenient functions/components:
Instead of:
i18n._(
'Hello, my name is {name}',
{ name }
)
… you simply write:
i18n.t`Hello, my name is ${name}`
Complex plural rules:
i18n._(
`{numBooks, plural,
one {{name} has # book}
other {{name} has # books}}`,
{ name, numBooks }
)
… becomes readable and type-checked:
i18n.plural({
value: numBooks,
one: `${name} # book`,
other: `${name} # books`
})
The same message in React:
<Trans id="msg.simple" defaults="Hello {name}" values={{ name }} />
… becomes:
<Trans id="msg.simple">Hello {name}</Trans>
Components inside translations:
<Trans
id="msg.link"
defaults="Read the <0>documentation</0>."
components={[<Link to="/docs" />]}
/>
… works seamlessly:
<Trans id="msg.link">
Read the <Link to="/docs">documentation</Link>.
</Trans>
Messages with plurals:
<Trans
id="msg.plural"
defaults="{numBooks, plural, one{{name} has # book} other{{name} has # books}}"
values={{ numBooks }}
/>
… are type-checked and errorproof:
<Plural
id="msg.plural"
value={numBooks}
one={<Trans>{name} has # book</Trans>}
other={<Trans>{name} has # books</Trans>}
/>
Note: In examples above, the first example is low-level API which you can use
when babel plugin isn't available (e.g. in Create React Apps). However, you'll
miss another layer of validation and type-checking for messages.
Message IDs are optional.
Without them it's even easier, default messages become message ids:
const Pitch = () => (
<div>
// Variable Interpolation
<Trans>Hello {name}</Trans>
// Seamless translations with components
<Trans>
Read the <Link to="/docs">documentation</Link>.
</Trans>
// Plurals
<Plural
value={numBooks}
one={{name} has # book}
other={{name} has # books}
/>
</div>
)
Batteries included - CLI for working with message catalogs
js-lingui
ships with easy CLI for extracting, merging and compiling of
message catalogs.
All messages from the source files can be extracted with one command:
lingui extract
Extracting messages from source files…
Collecting all messages…
Writing message catalogues…
Messages extracted!
Catalog statistics:
┌──────────┬─────────────┬─────────┐
│ Language │ Total count │ Missing │
├──────────┼─────────────┼─────────┤
│ cs │ 42 │ 34 │
│ en │ 42 │ 42 │
│ fr │ 42 │ 42 │
└──────────┴─────────────┴─────────┘
(use "lingui add-locale <language>" to add more locales)
(use "lingui extract" to update catalogs with new messages)
(use "lingui compile" to compile catalogs for production)
If you run this command second time, it'll merge translations from existing
catalog with new messages.
Works with manual and generated message IDs
js-lingui
doesn't force you to use generated message IDs either. If you prefer
setting your IDs manually, just pass id
prop. Generated message will be used
as a default one:
<Plural
id="msg.plural"
value={numBooks}
one={{name} has # book}
other={{name} has # books}
/>
Works anywhere
Core library @lingui/core
works in any JS environment. Integration libraries
like @lingui/react
only brings better performance for target environments.