Js dates are internationalized, wheels are flying, and ECMAScript is introducing native Intl objects. This leads directly to the abandonment of moment.js and the evolution to Luxen.js. International date library (day.js) using JS native API began to emerge, and quickly seized relevant market share with the attitude of “small and exquisite, really sweet to be built late”, leading a wave of international library iteration trend. React front-end internationalization solutions are also evolving, such as React-18Next, react-Intl-Universal, lingui.js, React-Intl (format.js), FBT, Kiwi, and more. With the exception of the first two brothers who remain friendly to native JS, the rest have moved towards workflow. This paper introduces the basic concepts and processes of react internationalization workflow from three aspects: traditional front-end internationalization pain points, workflow solutions, and the comparison between Lingui.js and Form.js (React-intl), and why lingui.js is recommended.
Traditional front-end internationalization pain points:
The author used react-Intl-universal. It works well to start with some samples, and copy can be loaded on demand with a few modifications according to the official example. But as you go along, something’s wrong. Json copywriting often needs to be managed centrally, one language for one JSON file. Here’s how it works: Every time you add a component, you have to go carefully to the Locales directory to modify the corresponding JSON file. And the naming has to be a little bit regular. Accidentally name conflict, accidentally omitted. Internationalization copywriting is usually maintained by the code writers themselves. The frequency of component addition and modification is high, and the translation collaboration is difficult.
If you want to publish internationalized resources to CDN, json format is preferred. However, it is troublesome to maintain JSON copywriting in a centralized way. First of all, I want to have a JS support, import, export, according to the component management copywriting, the name is not easy to conflict, isn’t it? Hence the react-18Next and React-INTl (version 5). At a glance, you can split up different internationalization documents by component.
In this way, due to the use of JS, if the international copywriting needs to be dynamically loaded, it will usually be divided into chunks and packed into chunks. Using JS, document management is clearer, names are not easy to conflict, but the synchronization problem caused by forgetting can not be solved, the work process is still unchanged, team collaboration is still difficult. The disadvantages of this cottage internationalization are summarized as follows:
- Maintenance of international copywriting is tedious and difficult, and development is troublesome
- There is no way to know if there is any unsynchronized copy in the project,
- Internationalization involves many people and teamwork is difficult. Because of this, many libraries have proposed the whole process solution of internationalization.
React International workflow solution
The current react internationalization workflow solution is basically similar with minor differences. The core steps are extracted, translated, and merged through commands. Using form.js as an example, an internationalized workflow solution typically consists of the following steps:
Extraction: The defaultMessage in the component or code is aggregated by command into a JSON or Po file with instructions for translation. Message upload: This step uploads the intermediate copy that needs to be translated to the translation provider (or translation team). Translation download: The translation provider (or translation team) submits the results of the translation to the code team. Compile merge: The code team uses the command, which compiles and merges translated messages and submits them back to the code base.
If this abstraction seems too abstract and unintuitive, since lingui.js and form.js are basically the same internationalization process, take lingui.js and json as an example:
Kiwi and FBT have similar internationalization workflows. Some additional tools are available in the IDE, or in translation. Take kiwi official documents internationalization full-process solution as an example:
FBT and KIwi scheme, a bit complex, difficult to get started, more configuration, more pits. Lingui.js or form.js is recommended.
Compare lingui.js with form. js(react-intl)
This Comparison content comes from Comparison with React-intl official document, which retains the original taste. The plural content is basically the same, so it is omitted, and the rest are only modified a little
React – INTL is easily the most popular and widely used I18N library for React. Lingui.js is very similar in many ways: both library pairs (ICU- message format for messages) use the same syntax, and they also have very similar apis.
Here is an example of react-intl:
<FormattedMessage
id="welcome"
defaultMessage={`Hello {name}, you have {unreadCount, number} {unreadCount, plural, one {message} other {messages} }`}
values={{name: <b>{name}</b>, unreadCount}}
/>
Copy the code
Lingui.js’s underlying API, not much different:
<Trans
id="welcome"
defaults={`Hello {name}, you have {unreadCount, number} {unreadCount, plural, one {message} other {messages} }`}
values={{name: <b>{name}</b>, unreadCount}}
/>
Copy the code
Doesn’t look like much of an API why does Lingui have to create another wheel?
- Translation with rich text markup
Suppose we have the following code:
<p>Read the <a href="/docs>documentation</a>.</p>
Copy the code
In react-intl, it translates to:
<FormattedMessage
id='msg.docs'
defaultMessage='Read the <link>documentation</link>.'
values={{
link: (. chunks) = > <a href="/docs">{chunks}</a>}} / >Copy the code
Lingui.js extends the tagged ICU message format, and the above example would be translated as:
<Trans
id='msg.docs'
defaults='Read the <0>documentation</0>.'
components={[
<a href="/docs" />]} / >Copy the code
After the message is extracted, the translator gets the information: Readthe<0>documentation</0>.
- Component-based message syntax macros
Lingui.js provides the @lingui/macro macro that automatically generates message syntax. Let’s review the above example
<p>
Read the <a href="/docs>documentation</a>.
</p>
Copy the code
The only thing we need to do is wrap it in a macro:
<p>
<Trans id="msg.docs">Read the <a href="/docs>documentation</a>.</Trans>
</p>
Copy the code
This macro parses the macro node and automatically generates its defaults and props for the component.
This is useful when adding i18N nationalization to an existing project, and all we need is to wrap the information in macros. Let’s compare the following react-intL to see the difference:
<p>
<FormattedMessage
id='msg.docs'
defaultMessage='Read the <link>documentation</link>.'
values={{
link: (. chunks) = > <a href="/docs">{chunks}</a>}} / >
</p>
Copy the code
It is worth mentioning that the message ID is completely optional. Lingui.js is unprofessional in this case and works perfectly with messages as ids
<p>
<Trans>Read the <a href="/docs>documentation</a>.</Trans>
</p>
Copy the code
The message ID is Readthe<0>documentation</0>. Instead of msg.id. Both solutions have pros and cons, and Lingui allows you to choose the solution that works best for you.
- Text attributes
Components cannot be used in certain contexts, such as translation text properties. React-intl provides JS methods that return pure strings (e.g. FormatMessage), while lingui.js provides the core library for such translations. It also provides macros for these use cases!
Here’s an example:
<a title={i18n._(t`The title of ${name}`)}>{name}</a>
<img alt={i18n._(plural({ value: count.one: "flag", other: "flags"}}))src="..." />
Copy the code
Custom ids are also supported
<a title={i18n._(t("link.title")`The title of ${name}`}>{name}</a>
<img alt={i18n._(plural("img.alt", { value: count.one: "flag", other: "flags"}}))src="..." />
Copy the code
- Extended message directory
Suppose our application has been internationalized, and now we want to send messages to the translator. React-intl comes with the Babel plug-in, which can extract messages from a single file, but it’s up to you to merge them into a file and send them to the translator. Lingui.js provides a convenient CLI to extract messages and merge them with any existing translations.
- Message to compile
The largest and slowest part of the I18N library is the message parsing and formatter. Lingui.js compiles messages from message format syntax into JS functions (such as components, variables, etc.) that accept interpolation only. This will make the final package smaller and make the library faster. Compiled directories are also bundled with locale data, such as complex numbers, so you don’t have to load them manually.
- The lack of lingui. Js
React IntL has been around for a while, and it’s definitely more popular and more used, with a lot of production sites running it. The community is larger, and it’s much easier to find help on StackOverflow and other sites.
Lingui.js is a very new library and the community is currently small. It has not been tested in many production sites. On the other hand, lingui.js’s test suite is very large, and all the examples are integrated into the integrated test suite to make sure everything works. Last but not least, lingui.js has been actively maintained. Bugs are fixed regularly and new features are constantly being introduced. Work is currently under way to split the Webpack code so that only messages related to the code in the block are loaded.
- conclusion
Both libraries use the same message format syntax and have the same API
lingui.js
- Support for rich text messages
- Provides macros to simplify writing messages using message format syntax
- Provides a CLI for extracting and compiling messages
- Very small (< 5KB Gzip) and fast
- Also works with native JS
- Actively maintain
react-intl
- React is the most popular and used i18n lib
- Used in many production sites (stability)
- There are many online resources
conclusion
The author has made a practical attempt to the above schemes. Finally, a simple comparison is made in terms of process mode, document-friendly, active community, and ease of use, as shown in the following table. The Babel /macros used by Ling.js allows macros to provide richer information to the translation team, while generating less code, shielding translator-only information at compile time. It also provides rich tools for language detection. In terms of document loading on demand, it also provides flexible API, which can be compatible with MULTIPLE distribution methods of JSON and JS with a little modification. Lingui.js is a very useful solution for the React front-end internationalization workflow.