A simple and powerful package for translate your react applications.
npm install redux-i18nredux-i18n is a simple yet powerful package to translate your _react_ applications using _react-redux_.

!downloads
```
npm i redux-i18n --save
or
``
yarn add redux-i18n
- Translate literals.
- Pluralize literals.
- Designed for react-redux.
- Compatible with Immutable.js.
- Export translations to POT files (make your translations with Poedit).
- Import translations from .PO files to _translations.js_ object (for use in your project).
- Add comments for translators.
- node >= 4.0.0
redux-i18n offers your app the t() function to translate literals.
The t() function is available in the components of your app via React context. To achieve this you need to wrap your app into the component from redux-i18n that provides for the context. Furthermore, for all components that want to use the t() function you need to define contextTypes, e.g.:
`javascript
// import ...
import PropTypes from 'prop-types'
class MyComponent extends React.Component {
render() {
return
MyComponent.contextTypes = {
t: PropTypes.func
}
`
If contextTypes is not defined, then context will be an empty object.
The t() function takes up to three arguments t(textKey [, params, comments]), where textKey is either the string to be translated or --- for pluralization --- an object as defined below.
For setting the language in the redux store redux-i18n offers an action creator setLanguage.
To manage the translations in your React app, redux-i18n supports two choices:
1. load all your translations into a one big JS object
1. load your translations into a slice of your redux store
For the latter redux-i18n provides an action function creator setTranslations. As setTranslations is an action function creator you need to add _redux-thunk_ to your middleware for it to work.
redux-i18n supports your store in plain JavaScript structures, but also if it is managed by help of _immutable.js_.
Finally, redux-i18n offers scripts to generate a translations object from po files that can be managed in Poedit.
The package provides a parent component to encapsulate your application as well as helpers functions to translate your project.
`javascript
// import ...
import I18n from 'redux-i18n'
// with Immutable.js:
import I18n from 'redux-i18n/immutable'
import { translations } from './translations'
class Root extends React.Component {
render() {
return (
)
}
}
`
Where translations is a dictionary similar to this:
`javascript`
export const translations = {
es: {
'Translate this text': 'Traduce este texto',
'Hello {n}!': 'Hola {n}!'
}
}
You can also set the initial language with the _initialLang_ prop:
`javascript`
My Project
{this.props.children}
If you have partial translations, this means that you don't have your translations at 100% and you want to show untranslated literals in an other language, you can use the fallbackLang prop.
`javascript`
My Project
{this.props.children}
In this case, if you want to show this translations:
`html`{this.context.t('_hello_')}
And this isn't in "de" language, it will show in "en".
The language state is managed in a slice of the store named i18nState. Therefore, you have to add the i18nState reducer in your combineReducers.
`javascript
import { otherreducers } from './Yourproject'
import { i18nState } from 'redux-i18n'
// with Immutable.js:
import { i18nState } from 'redux-i18n/immutable'
const appReducer = combineReducers({
otherreducers,
i18nState
})
`
The current language is contained in the lang key of i18nState.
The i18nState is initially defined as
`javascript
const defaultI18nState = {
lang: 'en',
translations: {},
forceRefresh: false
}
// immutablejs
const defaultI18nState = new Map({
lang: 'en',
translations: {},
forceRefresh: false
})
`
When you map your state to props with connect you can also access the lang attribute in your components:
`javascript
export default connect(state => ({
lang: state.i18nState.lang,
}))(Home)
// with Immutable.js:
export default connect(state => ({
lang: state.getIn(['i18nState', 'lang']),
}))(Home)
`
You can access the functions of using your component's context. For example:
`javascript`
Home.contextTypes = {
t: PropTypes.func.isRequired
}
...you will then be able to use the t() method in your component.
`javascript`
render() {
return (
Your current language, is: {this.props.lang}
{this.context.t("Translate this text")}
{this.context.t("Hello {n}!", {n: "World"})}
)
}
You can also use the t() function to change date formats
`javascript`
export const translations = {
de: {
'YYYY-MM-DD': 'DD.MM.YYYY'
}
}
`javascript`
render() {
let today = moment()
return (
{today.format(this.context.t("YYYY-MM-DD"))}
)
}
Add comments for translators.
`javascript`
render() {
return (
{this.context.t("Translate this text", {},
"This is a comment for translators.")}
{this.context.t("Hello {n}!", {n: "Cesc"},
"This is another comment.")}
)
}
Here's how _Poedit_ will show the comments:
`javascript`
const user = { name: 'World' }
const name = {user.name}
return
Result:
`html`
Hello Cesc
Notice that for security reasons we can't print html code directly, which is why we need to use the "dangerouslySetInnerHTML" method for that.
Example:
`javascript`
const Foo = ({}, context) => {context.t('Hello World')}
To use plurals in your translations.
`javascript`{this.context.t(['una noche', '{n} noches', 'n'], { n: 1 })}
Pass an array instead of a string as first parameter. The first element is a singular term, the second is the plural form and the last one is an object used to set the quantity.
After extracting the translations to a POT file and opening it with Poedit you will see the following:
Also the translations object allows to set an options node. There you can set a plurals form rule and a plurals number. Also, you can suppress warnings logged in console. For example:
`javascript`
export const translations = {
es: {
'Translate this text': 'Traduce este texto',
'Hello {n}!': 'Hola {n}!'
},
options: {
plural_rule: 'n > 1',
plural_number: '2',
suppress_warnings: true // defaults to false
}
}
When the translations are generated from po import file, this node is created automatically.
_Note_: Versions >=1.5.10 allow to use all existing pluralization rules:
http://docs.translatehouse.org/projects/localization-guide/en/latest/l10n/pluralforms.html
Use the _setLanguage_ action.
`javascript
import {setLanguage} from "redux-i18n"
componentWillMount() {
this.props.dispatch(setLanguage("es"))
}
`
If you work with combined languages like "es-ES", "en-GB", but your translations object doesn't include those properties...
`javascript`
export const translations = {
"es": {
...
},
"en": {
...
}
}
..._redux-i18n_ will fallback on the closest property. In this case, "es" or "en".
redux-i18n includes a script to extract your translation strings to a _.pot_ template which you can use in _Poedit_, and another to import strings from _po_ files to a translation.js.
Add the scripts in your _package.json_ for this purpose:
`json`
"scripts": {
"extract": "i18n_extract",
"import": "i18n_import"
}
You can then run the following commands in your terminal:
``
npm run extract
npm run import
``
npm run extract
By default, this script will search for all literals inside your src folder with a regular expression and build a locales/template.pot file. This file can then be used in Poedit to build _en.po_, _es.po_, etc. files.
If you want to set other source folder, you can use the --source switch.
`json`
"scripts": {
"extract": "i18n_extract --source=mysourcefolder",
"import": "i18n_import"
}
Or if you want to export your locales to a different folder...
`json`
"scripts": {
"extract": "i18n_extract --source=mysourcefolder --locales=mylocalesfolder",
"import": "i18n_import"
}
By default this command find in all _.js_ and _.jsx_ file extensions, but you can customize it with _fexts_ parameter. Check out this example:
`json`
"scripts": {
"extract": "i18n_extract --fexts=js,jsx,coffee",
"import": "i18n_import"
}
The default regular expression will search all occurrences of this.context.t string, but you can also supply your own custom pattern, as in the following example:
`javascript`
export default function App({ aProp, bProp }, { t: translate }) {
return {translate('Hello world!')}
}
You will then need to set the --pattern flag in _package.json_:
`json`
"scripts": {
"extract": "i18n_extract --pattern=translate",
"import": "i18n_import"
}
When your translators are done translating your terms, you can import your _po_ files running the import script:
``
npm run import
This script read all _po_ files inside your _locales_ folder, extract all translations and build a src/translations.js that you can then use in your project.
Your _.po_ files must define header language, check mininal format for more information.
You can also set another _locales_ folder:
`json`
"scripts": {
"extract": "i18n_extract --source=mysource --locales=mylocales",
"import": "i18n_import --locales=mylocales"
}
Or, save _translation.js_ to a different location:
`json`
"scripts": {
"extract": "i18n_extract --source=mysource --locales=mylocales",
"import": "i18n_import --locales=mylocales --translations=myfolder"
}
You can also change the encoding for your extraction from PO (default is iso-8859-1)
`json`
"scripts": {
"extract": "i18n_extract --source=mysource --locales=mylocales",
"import": "i18n_import --encoding=utf-8"
}
When applications grow, translations tend to bigger as well, adding a lot to the overall size of the js bundle.
You can set an empty translations object to the component and set the useReducer prop to true to use the store as the source of strings. For example:
`javascript`
Then you can use the setTranslations action.
`javascript`
import { setTranslations } from 'redux-i18n'
api.get('...').then((r) => this.props.dispatch(setTranslations(r.translations)))
You can pass a second parameter to the action to set the language.
Depending on your response's structure, it could look like this:
`javascript`
api.get('...').then((r) => this.props.dispatch(setTranslations(r.translations, 'en')))
Since version 1.5.1 is possible pass a dictionary as a second param with some options. This allows us set more functionalities to method.
- preserveExisting (bool): If is true, the translations received does merge with existing translations.
- language (string): Language code
Some examples:
`javascript`
setTranslations(newTranslations, { preserveExisting: true })
setTranslations({ Hello: 'Hallo' }, { language: 'de' })
Sometimes language is set initially by the redux store creation, or in an isomorphic way. In this case, you can set the initialized prop to stop the I18n provider from dispatching an action.
If you want to isolate the use of context from your components, you can import the Localize Hoc to provide the translate function as a prop to your component. For example:
`javascript
import { localize } from 'redux-i18n'
class SomeComponent extends Component {
render() {
return this.props.t('hello world')
}
}
export default localize()(SomeComponent)
`
You can also change the name of the provided prop:
`javascript
import { localize } from 'redux-i18n'
class SomeComponent extends Component {
render() {
return this.props.translate('hello world')
}
}
export default localize('translate')(SomeComponent)
``
---
Please, if you like my package, don't forget to rate it. Click on the "star"!