preface
Recently set up a project, from 0 to do, need to do multi-language internationalization, did today, basically achieved the desired effect, the first time to find gold do not spray, here simply share:
background
Internationalization scheme
- Overview of internationalization Solutions
- Front-end internationalization detailed explanation, examples
- Internationalize resource file management
- Collaboration between projects and between developers and translators
- Appendix of internationalization Specification
- Further reading
Overview of internationalization Solutions
Internationalization is a seemingly simple but actually very complex field. When you actually do internationalization work, you will find that it often involves many contents:
- Front-end internationalization
- Server-side internationalization
- Internationalize resource file management
- How do projects and developers and translators collaborate
Moreover, internationalization scenarios are often tied to specific technology stacks.
This internationalization solution is only for React technology stack and does not involve server-side internationalization content.
Front-end internationalization detailed explanation, examples
The core steps of internationalization are two:
- Create a resource file and store it in key-value mode
- Load the resource file and replace the contents of the key on the page with the associated value
Some exploring
I didn’t really explore it, but I googled it and found a mature library on GitHub: React-i18Next
react-intl
react-intl-universa
How to use it
react-i18next
The installation
npm install i18next react-i18next --saveCopy the code
The introduction of the App. Js
import i18n from 'i18next';
import { useTranslation, initReactI18next } from 'react-i18next';
Copy the code
Initialize the
const lng = 'en';
i18n
.use(initReactI18next) // passes i18n down to react-i18next
.init({
resources: {
en: {
translation: {
Welcome: 'Welcome to React',
},
},
zh: {
translation: {
Welcome: 'Welcome to React',
},
},
},
lng: lng,
fallbackLng: lng,
interpolation: {
escapeValue: false,}});Copy the code
Actual results
function App() {
const { t } = useTranslation();
return (
<div className="App">
<p>{t('Welcome')}</p>
</div>
);
}
export default App;
Copy the code
Packaging results:
// ...
import i18n from '@src/i18n';
// xxx component
console.log('I18N one shot :', i18n.t('INVALID_ORDER'));
render() {/ /... <button> {i18n.t('INVALID_ORDER')} </button>
}Copy the code
react-intl
Background:
Use to internationalize React components. Provide React components and apis to format dates, numbers, strings (including plural and translation).
The React-Intl library is one of the most popular libraries in the industry. React-intl decorates your React.Com component as a package component that dynamically injects internationalization messages so that locale data can be loaded dynamically without needing to reload the page
Installation:
npm install react-intl --saveCopy the code
Load locale data.
React Intl relies on this data to support singular, complex and relative time formatting.
// Main.js
import { addLocaleData } from 'react-intl'; /* react-intl imports */
import en from 'react-intl/locale-data/en';
import zh from 'react-intl/locale-data/zh'; addLocaleData([...en, ...zh]); // Introduce data from a multilingual environmentCopy the code
Although I only used the text translation function and thought I wouldn’t need to load this data, it turned out to be a necessary step. Error:
[React Intl] Missing locale data for locale: "zh". Using default locale: "en" as fallback.Copy the code
use
The component package requires the root component to be internationalized, and the component tree will then be in the i18N context of the configuration.
Since react-hot-Loader is used in the project, the root Main component is wrapped in
and imported from a separate file.
//app.js
import { AppContainer } from 'react-hot-loader'
import Main from './components/Main'/ /... . const render = Component => { ReactDOM.render( <AppContainer> <Component /> </AppContainer>, document.getElementById('app')
)
}
render(Main);Copy the code
Use the
component directly in main.js. Just add it to the outermost layer of render() to return the node.
// Main.js
import { addLocaleData, IntlProvider } from 'react-intl'; /* react-intl imports */
render() {return(<IntlProvider> //··· </IntlProvider>)}Copy the code
Add text for multiple languages.
For example, to support Both Chinese and English, in order to facilitate later maintenance, you can create two new files:
// en_us.js const en_US = {hello:"Hello!", / /... . }export default en_US;
// zh_CN.js
const zh_CN = {
hello: "Hello!, / /... . }export default zh_CN;Copy the code
Then introduce these two variables in main.js.
// Main.js
import zh_CN from ".. /locale/zh_CN" // import defined messages in Chinese
import en_US from ".. /locale/en_US" // import defined messages in EnglishCopy the code
Global configures the current language, and the corresponding text.
That is, configure the two properties of the
component, locale and messages.
// Main.js
render() {let messages = {}
messages['en'] = en_US;
messages['zh'] = zh_CN;
return(<IntlProvider locale={this.state.lang} Messages ={messages[this.state.lang]}> //··· </IntlProvider>)}Copy the code
With the basic configuration complete, you can change the page language by changing the value of this.state.lang.
// Main.js
/**
* Change language
* @param {String} lang new language
*/
changeLanguage(lang) {
this.setState({
lang: lang
})
}Copy the code
Next, add the translated text to the page
There is basically only one component to use:
with translated text, which is the value of the corresponding field in messages.
Introduce the FormattedMessage component in the component to which you want to add internationalized text.
import { FormattedMessage } from 'react-intl'; /* react-intl imports */ //... . <FormattedMessage id="hello" />Copy the code
When the current language is EN, the result is generated:
<span>Hello! </span>Copy the code
At this point, the react-Intl basic internationalization is implemented.
Note: You can use useIntl to get locale, messages, formatMessage. You can use useIntl to get locale, messages, formatMessage. You can use useIntl to get locale, messages, formatMessage. The demo address
The end of the
Write specifications
- DefaultMessage must be filled in and used as a Chinese translation
- Id must not be repeated
- When using intl.formatMessage(), you must use defineMessages, predefined messages
Further reading
- react-intl
- react-intl-corner-cases
react-intl-universal
Background:
React international library launched by Alibaba
The best thing about this library is that it is easy to use and less intrusive
The installation
Install using NPM
npm install react-intl-universal --saveCopy the code
Initialize the
On the initial page, initialize the library and configure the language package. The JSON file is determined according to the required languages. In the following picture, only Chinese and English are supported
Configure internationalization in the project entry file
import intl from 'react-intl-universal';
// locale data
const locales = {
"en-US": require('./locales/en-US.json'),
"zh-CN": require('./locales/zh-CN.json'),}; class App extends Component { state = {initDone:false}
componentDidMount() {
this.loadLocales();
}
loadLocales() {// react-inl-universal is a singleton and should only be instantiated once intl.init({currentLocale:'en-US', // TODO: determine locale here
locales,
})
.then(() => {
this.setState({initDone: true});
});
}
render() {
return (
this.state.initDone &&
<div>
{intl.get('SIMPLE')} </div> ); }}Copy the code
The language configuration file can be either JSON or JS. The JSON format is as follows:
English configuration file./locales/ en-us.json
{
"SIMPLE": "Simple Sentence"."LANG_TYPE": "paas-us"."INPUT_MOBILE": "Mobile Number"."HELLO": "Hello, {name}. Welcome to {where}!"
}Copy the code
Chinese configuration file./locales/ zh-cn.json
{
"SIMPLE": "Simple sentences."."LANG_TYPE": "paas-cn"."INPUT_MOBILE": "Cell phone number"."HELLO": "Hello, {name}. Welcome to {where}!"
}Copy the code
call
In the initialization code, the render function is already called. Elsewhere in the project, it can be called directly because it has already been initialized. The following is an example of a call:
import intl from 'react-intl-universal';
class Test extends Component {
render() {
return (
<div>
{intl.get('INPUT_MOBILE')} </div> ); }}Copy the code
switch
Now let’s look at the initialization function
intl.init({
currentLocale: 'en-US', // TODO: determine locale here
locales,
})Copy the code
In addition to specifying the language directly, the initialization can also be specified by the function determineLocale based on the following configuration:
- Query parameter in the Url
- Parameters in cookies
- The browser’s current language (when query and cookie parameters are not configured)
These configurations work as shown in the following code:
let currentLocale = intl.determineLocale({
urlLocaleKey: "lang",
cookieLocaleKey: "lang"
});
intl.init({
currentLocale, // determine locale here
locales,
})Copy the code
Then, we can use the following way to switch: when the appropriate language is selected, trigger the callback function, in the function, change the URL or cookie, and then refresh the page, re-initialize, can switch the language.
Here’s an example of switching by cookie:
handleClick = (lang) => {
Cookies.set('lang', lang, { expires: '1Y' });
window.location.reload(true);
}Copy the code
The advanced
The React-Intil-Universal library has many other features for language processing, such as:
- HTML text with HTML tags
- variable
- Singular and plural form
- currency
- The date of
HTML references text in resource packs
A. Plain text, use intl.get()
<div> {intl.get('SIMPLE')} </div>Copy the code
B. Text with an HTML template, use the intl.gethtml () method
For example, this is defined in resource bundles
{
"SIMPLE": "This is <span style='color:red'>HTML</span>"
}Copy the code
The reference uses the getHTML() method to get the text
<div>{intl.getHTML('SIMPLE')}</div>
Copy the code
Numeric and thousandth separators
In the following example, the variable num can only be a number if you label it plural. When num is 0, “no photos.” is displayed; When the value is 1, “One photo.” is displayed. When the value is another number such as 25000, “25,000 photos.” is displayed, where the ‘#’ indicates adding a thousandth separator to the value of num
{
"PHOTO": "You have {num, plural, =0 {no photos.} =1 {one photo.} other {# photos.}}"
}Copy the code
The results are as follows:
intl.get('PHOTO', {num:0}); // "You have no photos."
intl.get('PHOTO', {num:1}); // "You have one photo."
intl.get('PHOTO', {num:1000000}); // "You have 1000000 photos."Copy the code
Display currency format
The syntax is {variable name, type, format}. In this example, the variable name is “price”, and its type is number. “USD” means that the value is preceded by the dollar sign ($).
{
"SALE_PRICE": "The price is {price, number, USD}"
}Copy the code
Reference and display results are as follows:
intl.get('SALE_PRICE'{price: 123456.78}); // The price isThe $123, 456.78Copy the code
Display the date
The syntax is the same as above: {variable name, type, format}. When the type is “date”, the formatting options are short,medium,long,full, or no formatting
{
"SALE_START": "Sale begins {start, date}"."SALE_END": "Sale ends {end, date, long}"
}Copy the code
Reference and display:
intl.get('SALE_START', {start:new Date()}); // Sale begins 4/19/2017
intl.get('SALE_END', {end:new Date()}); // Sale ends April 19, 2017Copy the code
Configuring the default message
You can configure a default message when, for example, a misspelling fails to match a text in a resource bundle. In this case, the default message will be displayed when the resource bundle does not match
//"defaultMessage()"Can be abbreviated to"d()"
intl.get('not-exist-key').defaultMessage('Can't find that sentence');Copy the code
You can also configure the default message with an HTML template
intl.getHTML('not-exist-key'<h2> </h2>Copy the code
Message with variables
The configuration in the resource bundle is as follows
{
"HELLO": "Hello, {name}. Welcome to {where}!"
}Copy the code
When referencing in HTML
<div> intl.get('HELLO', {name:'banana'.where:'China'}) </div>Copy the code
The command output is Hello, banana.welcome to China!
The end of the
React-intil-universal is a universal universal universal universal universal universal universal universal universal universal universal universal universal universal
Git address: github.com/alibaba/rea…
Antd/ANTD-Mobile internationalization solution
LocaleProvider internationalization
The component LocaleProvider is used to configure international copywriting globally
Ant. The design/components /…
Provide uniform internationalization support for component built-in copywriting
Using the React Context feature with LocaleProvider, it only needs to be wrapped around the application once to take effect globally.
import { LocaleProvider } from 'antd';
import zh_CN from 'antd/lib/locale-provider/zh_CN';
import moment from 'moment';
import 'moment/locale/zh-cn';
moment.locale('zh-cn'); .return <LocaleProvider locale={zh_CN}><App /></LocaleProvider>;Copy the code
English, Chinese, Russian, French, German and other languages are supported, and all language packs can be found here.
Note: If you need to use the UMD version of dist file, you should introduce antd/dist/antd-with-locales.js, along with the moment locale, and then use it as follows:
const { LocaleProvider, locales } = window.antd; .return <LocaleProvider locale={locales.en_US}><App /></LocaleProvider>;Copy the code
To this end today’s international sharing daqo, my personal feeling or React-Intil-Universal is better, if it helps you remember a little attention oh,
The case has been uploaded to Github, there are relevant needs can go to see, the first time to write do not spray, if there is a problem please correct!