Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
react-localize-redux
Advanced tools
A collection of helpers for managing localized content in your React/Redux application.
npm install react-localize-redux --save
localeReducer
to redux store.NOTE: Although the example uses the
locale
prop for the reducer, you can name this prop whatever you like. Just ensure that you use the correct prop name when passing the state to selectors.
...
import { createStore, combineReducers } from 'redux';
import { localeReducer } from 'react-localize-redux';
const store = createStore(combineReducers({
locale: localeReducer
}));
const App = props => {
return (
<Provider store={ store }>
...
</Provider>
);
};
Dispatch setLanguages action creator and pass in the languages for your app. By default the first language in the array will be set as the active language.
import { setLanguages } from 'react-localize-redux';
const languages = ['en', 'fr', 'es'];
store.dispatch(setLanguages(languages));
To set a different default active language pass in the language
.
const languages = ['en', 'fr', 'es'];
store.dispatch(setLanguages(languages, 'fr'));
Typically you will store your translation data in json files, but the data can also be a vanilla JS object. Once your translation data is in the correct format use the addTranslation action creator.
NOTE: The following assumes you are using webpack to bundle json
import { addTranslation } from 'react-localize-redux';
const json = require('global.locale.json');
store.dispatch(addTranslation(json));
The json data should enforce the following format, where each translation string is a represented by a { key: value }
pair.
The value
is an array that should enforce the following...
setLanguages
.{
"greeting": [
"Hello", (en)
"Bonjour", (fr)
"Hola", (es)
],
"farwell": [
"Goodbye", (en)
"Au revoir", (fr)
"Adiós" (es)
]
}
Dispatch setActiveLanguage action creator and pass the language.
import { setActiveLanguage } from 'react-localize-redux';
store.dispatch(setActiveLanguage('fr'));
If you have a component that is already using connect
you can use the getTranslate selector that returns the translate
function. This function will return the localized string based on active language.
import { getTranslate } from 'react-localize-redux';
const Greeting = ({ translate, currentLanguage }) => (
<div>
<h1>{ translate('greeting') }</h1>
<button>{ translate('farwell') }</button>
</div>
);
const mapStateToProps = state => ({
translate: getTranslate(state.locale),
currentLanguage: getActiveLanguage(state.locale).code
});
export default connect(mapStateToProps)(Greeting);
For components not already using connect
instead use localize. This will automatically connect your component with the translate
function and currentLanguage
prop.
import { localize } from 'react-localize-redux';
const Greeting = ({ translate, currentLanguage }) => (
<div>
<h1>{ translate('greeting') }</h1>
<button>{ translate('farwell') }</button>
</div>
);
export default localize(Greeting, 'locale');
Include HTML in your translation strings and it will be rendered in your component.
{
"google-link": [
"<a href='https://www.google.en/'>Google</a>",
"<a href='https://www.google.fr/'>Google</a>"
]
}
You can insert dynamic content into your translation strings by inserting placeholders with the following format ${ placeholder }
.
{
"greeting": [
"Hello ${ name }",
"Bonjour ${ name }"
]
}
Then pass in the data you want to swap in for placeholders to the translate
function.
<h1>{ translate('greeting', { name: 'Testy McTest' }) }</h1>
{
"welcome": {
"greeting": [
"Hello ${ name }!",
"Bonjour ${ name }!"
]
},
"info": {
"greeting": [
"Hello",
"Bonjour"
]
}
}
<h1>{ translate('welcome.greeting', { name: 'Testy McTest' }) }</h1>
<h1>{ translate('info.greeting') }</h1>
A parent component that has added the translate
function by using getTranslate or localize can easily pass multiple translations down to it's child components. Just pass the translate
function an array of translation keys instead of a single key.
{
"heading": ["Heading", "Heading French"],
"article": {
"title": ["Title", "Title French"],
"author": ["By ${ name }", "By French ${ name }"],
"desc": ["Description", "Description French"]
}
}
const Article = props => (
<div>
<h2>{ props['article.title'] }</h2>
<h3>{ props['article.author'] }</h3>
<p>{ props['article.desc'] }</p>
</div>
);
const Page = ({ translate }) => (
<div>
<h1>{ translate('heading') }</h1>
<Article { ...translate(['article.title', 'article.author', 'article.desc'], { name: 'Ted' }) } />
</div>
);
If you have a larger app you may want to break your translation data up into multiple files, or maybe your translation data is being loaded from a service. Either way you can call addTranslation for each new translation file/service, and the new translation data will be merged with any existing data.
Also If you are using a tool like webpack for bundling, then you can use async code-splitting to split translations across bundles, and async load them when you need them.
getTranslate(state)
A selector that takes the localeReducer slice of your state
and returns the translate function. This function will have access to any and all translations that were added with addTranslation.
For single translation:
returns (key: string) => LocalizedElement | string
For multiple translations:
returns (key: []string) => { [key: string]: LocalizedElement | string
Note: If a translation contains HTML a LocalizedElement will be used to render. In all other cases a string will be used.
key: string|array
= A translation key or an array of translation keys.data: object
= Pass data to your dynamic translation string.const Greeting = ({ translate }) => <h1>{ translate('greeting', { name: 'Testy McTest' }) }</h1>
const mapStateToProps = state => ({ translate: getTranslate(state.locale) });
export default connect(mapStateToProps)(Greeting);
See Pass multiple translations to child components.
getActiveLanguage(state)
A selector that takes the localeReducer slice of your state
and returns the currently active language object.
returns { code: 'en', active: true }
;
const Greeting = ({ currentLanguage }) => <h1>My language is: { currentLanguage }</h1>
const mapStateToProps = state => ({ currentLanguage: getActiveLanguage(state.locale).code });
export default connect(mapStateToProps)(Greeting);
getLanguages(state)
A selector that takes the localeReducer slice of your state
and returns the languages you set.
returns [{ code: 'en', active: true }, { code: 'fr', active: false }]
;
const LanguageSelector = ({ languages }) => (
<ul>
{ languages.map(language =>
<a href={ `/${ language.code }` }>{ language.code }</a>
)}
</ul>
)
const mapStateToProps = state => ({ languages: getLanguages(state.locale) });
export default connect(mapStateToProps)(Greeting);
getLanguages(state)
A selector that takes your redux state
and returns the languages you set.
returns [{ code: 'en', active: true }, { code: 'fr', active: false }]
;
const LanguageSelector = ({ languages }) => (
<ul>
{ languages.map(language =>
<li><a href={ `/${ language.code }` }>{ language.code }</a></li>
)}
</ul>
)
const mapStateToProps = state => ({ languages: getLanguages(state) });
export default connect(mapStateToProps)(LanguageSelector);
getTranslations(state)
A selector that takes your redux state
and returns the raw translation data.
localize(Component)
If you have a Component that is not using connect
you can wrap it with localize
to automatically add the translate
function and currentLanguage
prop. When using combineReducers
to add localeReducer
you must pass the slice
param to localize
, where slice
is the name of the prop you used with combineReducers
(e.g. locale).
const Greeting = ({ translate, currentLanguage }) => (
<span>
<h1>languageCode: { currentLanguage }</h1>
<h2>{ translate('greeting', { name: 'Testy McTest' }) }</h2>
</span>
);
export default localize(Greeting, 'locale');
setLanguages(languages, defaultActiveLanguage)
Redux action creator to set which languages you are supporting in your translations. If defaultActiveLanguage
is not passed then the first language in the languages
array will be used.
const languages = ['en', 'fr', 'es'];
store.dispatch(setLanguages(languages));
// if you wanted 'fr' to be default language instead of 'en'
store.dispatch(setLanguages(languages, 'fr'));
addTranslation(data)
Redux action creator to add new translation data to your redux store. Typically this data will be loaded from a json file, but can also be a plain JS object as long as it's structured properly.
IMPORTANT: The order of the translation strings in the array matters! The order MUST follow the order of the languages array passed to setLanguages.
// assuming your app has set languages ['en', 'fr']
const welcomePageTranslations = {
greeting: ['Hi!', 'Bonjour!'],
farwell: ['Bye!', 'Au revoir!']
};
store.dispatch(addTranslation(welcomePageTranslations));
setActiveLanguage(language)
Redux action creator to change the current language being used.
// assuming your app has set languages ['en', 'fr']
store.dispatch(setActiveLanguage('fr'));
FAQs
Localization library for handling translations in React
We found that react-localize-redux demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.