The principle of
- Language packs are kept separately as static resources
- There is one file for each language
- When switching language Settings, the language file is switched
tool
React-i18next: Provides more react-oriented apis
Configuration i18n
First create the i18n folder and create configs.ts
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
Copy the code
Before proceeding to the next step, we need to introduce the language file package. Here I use both Chinese and English languages, and the file is in JSON format, so we have introduced the Chinese version zh.json and the English version en.json. In fact, it is a normal JSON object, the structure of the two files is the same, only the final value is different, one is Chinese and the other is English.
Next, we import these two files into the configuration file and define a local variable that represents the language resource:
import translation_en from './en.json'
import translation_zh from './zh.json'
const resources = {
en: {
translation: translation_en
},
zh: {
translation: translation_zh
}
}
Copy the code
Then initialize as per the official document:
I18n. use(initReactI18next) // Initialize with react-i18Next. Init ({resources, // pass in the local resource variable LNG: "Zh ", // Default language: zh // keySeparator is true, which means that we can access the string via a chained structure, such as "header.slogan" // keySeparator: False, // We do not use keys in form messages. Welcome interpolation: {// Will not force HTML string to normal string escapeValue: false // react already safes from xss } });Copy the code
Finally, export the configuration:
export default i18n
Copy the code
The use of i18n
The basic principle of i18Next is Context, which is to inject a provider globally and then use the appropriate API in the child component to fetch data. But actually, we just need to import the configuration file in the index.js file and we’re done, because the React-i18Next framework does the context API injection for us when we initialize the object. So we are now ready to use the Context API in our components.
Class components
In the class component, we use higher-order functions to complete the language injection, import withTranslation, the higher-order function of React-i18Next, and modify the structure of the component:
import { withTranslation } from "react-i18next"
class HomeComponent extends React.Component {
...
}
export default withTranslation()(HomeComponent)
Copy the code
This higher-order function requires two parentheses, the first for the namespace and the second for our component. This allows us to access function T in props, which allows us to access the JSON object of the language file as a string.
To use t in props, we need to pass in the typescript definition of i18n. Import WithTranslation, which is typescript’s type definition:
import { withTranslation, WithTranslation } from "react-i18next";
type PropsType = WithTranslation
class HomeComponent extends React.Component<PropsType> {
...
}
Copy the code
We then replace the hard-coded string with the t function. For example, replace the “hot recommendations” on your home page with {t(“home_page.hot_recommend”)}.
Functional component
To retrieve global data from functional components, hook functions are used. First, we need to introduce useTranslation hook
import { useTranslation } from 'react-i18next';
You can then use the t function directly, and then use it exactly the same as the class component.
const { t } = useTranslation();
Language switching
Now we can display the language normally, but we need one last step, which is to switch between Chinese and English. Since the language is saved in store, we changed the state in the store with Reducer when we clicked the language switch, and at the same time processed the global language data, we called the API of I18Next to switch the language.
// languageReducer.ts import i18n from 'i18next'; Switch (action.type) {case CHANGE_LANGUAGE: // I18n.Changelanguage (action.payload); return { ... state, language: action.payload }; . }Copy the code
Now we have the functionality implemented, but this implementation is problematic. According to the definition of Redux, all reducer functions are pure functions, that is, functions without side effects. However, when we call the function i18N.Changelanguage (), this reducer is no longer a pure function, so we need to use middleware to improve it.
Create changelanguage. ts in middlewares folder and write middleware:
import { Middleware } from 'redux'; import { CHANGE_LANGUAGE } from ".. /language/languageActions"; import i18n from "i18next"; export const changeLanguage : Middleware = (store) => (next) => (action) => { if(action.type === CHANGE_LANGUAGE){ i18n.changeLanguage(action.payload); } next(action); }Copy the code
Then add it to the store file:
const store = configureStore({
reducer: persistedReducer,
middleware: (getDefaultMiddleware) => [...getDefaultMiddleware(), changeLanguage, actionLog],
devTools: true,
})
Copy the code
Now we have fully implemented language switching.