React - i18next
12 Jul 2019- full locale
- aka locale - <LANGUAGE>-<REGION>
configuration
- https://i18next.github.io/i18next/pages/doc_init.html
- http://www.uxshaper.com/how-we-do-internationalization-in-reactjs/
import i18next instance
it’s necessary to import initialized i18next instance in top-level component because the former needs to be bundled (even though it’s not used directly):
// app/App.js
import './i18n';
add translations
add on init
- https://www.i18next.com/how-to/add-or-load-translations#add-on-init
- https://www.codeandweb.com/babeledit/tutorials/how-to-translate-your-react-app-with-react-i18next
the simplest way to add translations is via resources
configuration option on
init - all top-level keys (after language keys) become namespaces then.
// app/i18n/index.js
import en from './locales/en';
import ru from './locales/ru';
i18n.use(initReactI18next).init({
resources: {en, ru},
// ...
});
export default i18n;
// app/i18n/locales/en.js
// prettier-ignore
export default {
welcome_page: { // namespace
foo: 'bar', // key
},
};
[NOT TESTED] load using a backend plugin
- https://www.i18next.com/how-to/add-or-load-translations#load-using-a-backend-plugin
- https://react.i18next.com/legacy-v9/step-by-step-guide#b-loading-multiple-translation-files
https://react.i18next.com/guides/multiple-translation-files
One of the advantages of react-i18next is based on i18next it supports the separation of translations into multiple files - which are called namespaces in i18next context
when using custom backend, i18next inspects ns
configuration option to decide
which files to load (file name == namespace).
ns
configuration option has default value translation
so translation.json
file is looked up by default.
AFAIU if translations are added on init (via resources
configuration option),
specifying ns
configuration option has no effect.
notes
using locale in lng
option and language in resources
option
https://www.i18next.com/principles/fallback#locals-resolving
Per default locals containing region or script will take a translation from the pure language file if not found.
it’s possible to specify a full locale in lng
configuration option and use
resources with language-only top-level keys (resources
configuration option) -
i18next will detect the language from locale automatically:
// app/i18n/index.js
i18n.use(initReactI18next).init({
resources: {
en: {foo: 'foo'},
ru: {foo: 'фу'},
},
lng: 'en-US',
// ...
});
tips
Trans component namespace
even if your component is wrapped into withTranslation
HOC, Trans
still
doesn’t use its namespace by default => specify it explicitly:
-
[RECOMMENDED] by passing
t
function from propshttps://react.i18next.com/latest/trans-component#trans-props
t - t function to use instead of i18next.t
<Trans t={this.props.t} i18nKey='foo' />
-
in
ns
attribute<Trans ns={'ns1'} i18nKey='foo' />
-
in key itself
<Trans i18nKey='ns1:foo' />
for this to work set
nsSeparator: ':'
configuration option:// app/i18n/index.js i18n.init({ nsSeparator: ':', });
insert NBSP
i18next allows to escape/unescape interpolation values but not HTML entities inlined inside translations, say:
// app/i18n/locales/en.js
export default {
login_welcome_page: {
welcome: `Welcome to «MyApp»`,
},
};
=> use Unicode character instead of HTML entity - directly or via constant:
// app/i18n/locales/en.js
export default {
login_welcome_page: {
welcome: 'Welcome to\u00A0«MyApp»',
},
};
// OR
const NBSP = '\u00A0';
export default {
login_welcome_page: {
welcome: `Welcome to${NBSP}«MyApp»`,
},
};
style guide
semantic keys vs. text
prefer semantic keys to text (welcomeMessage
vs. Welcome to MyApp
).
troubleshooting
Function components cannot be given refs
emulator window:
Warning: Function components cannot be given refs. Attempts to access this ref
will fail. Did you mean to use React.forwardRef()?
Check the render method of `ProfilePage`.
in withI18nextTranslation(Connect(Form)) (at ProfilePage.js:47)
...
solution
// app/components/_new/profile/Form.js
- export default withTranslation('profileForm')(Form);
+ export default withTranslation('profileForm', {withRef: true})(Form);
[flow] all branches are incompatible
ESlint error in MacVim:
[flow] all branches are incompatible: Either property `t` is missing in
`OwnProps` [1]. Or property `t` is missing in `StateProps` [2]. Or property `t`
is missing in `DispatchProps` [3].
solution
// app/components/_new/profile/Form.js
type OwnProps = {
+ t: (text: string, value?: {}) => string,
// ...
};