51 | ```
52 |
53 | {% hint style="info" %}
54 | You will get the t function by using the [useTranslation](latest/usetranslation-hook.md) hook or the [withTranslation](latest/withtranslation-hoc.md) hoc.
55 | {% endhint %}
56 |
57 | ### JSX tree
58 |
59 | Sometimes you might want to include html formatting or components like links into your translations. (Always try to get the best result for your translators - the final string to translate should be a complete sentence).
60 |
61 | **Before:** Your react code would have looked something like:
62 |
63 | ```jsx
64 |
65 | Hello {name}, you have {count} unread message(s). Go to messages.
66 |
67 | ```
68 |
69 | **After:** With the trans component just change it to:
70 |
71 | ```jsx
72 |
73 | Hello {{name}}, you have {{count}} unread message. Go to messages.
74 |
75 | ```
76 |
77 | {% hint style="info" %}
78 | Learn more about the Trans Component [here](latest/trans-component.md)
79 | {% endhint %}
80 |
81 | ## Basic sample
82 |
83 | This basic sample tries to add i18n in a one file sample.
84 |
85 | ```javascript
86 | import React from "react";
87 | import { createRoot } from 'react-dom/client';
88 | import i18n from "i18next";
89 | import { useTranslation, initReactI18next } from "react-i18next";
90 |
91 | i18n
92 | .use(initReactI18next) // passes i18n down to react-i18next
93 | .init({
94 | // the translations
95 | // (tip move them in a JSON file and import them,
96 | // or even better, manage them via a UI: https://react.i18next.com/guides/multiple-translation-files#manage-your-translations-with-a-management-gui)
97 | resources: {
98 | en: {
99 | translation: {
100 | "Welcome to React": "Welcome to React and react-i18next"
101 | }
102 | }
103 | },
104 | lng: "en", // if you're using a language detector, do not define the lng option
105 | fallbackLng: "en",
106 |
107 | interpolation: {
108 | escapeValue: false // react already safes from xss => https://www.i18next.com/translation-function/interpolation#unescape
109 | }
110 | });
111 |
112 | function App() {
113 | const { t } = useTranslation();
114 |
115 | return
{t('Welcome to React')}
;
116 | }
117 |
118 | // append app to dom
119 | const root = createRoot(document.getElementById('root'));
120 | root.render(
121 |
122 | );
123 | ```
124 |
125 | #### RESULT:
126 |
127 | .png>)
128 |
129 | {% hint style="info" %}
130 | This sample while very simple does come with some [drawbacks](guides/the-drawbacks-of-other-i18n-solutions.md) to getting the full potential from using react-i18next you should read the extended [step by step guide](latest/using-with-hooks.md).
131 | {% endhint %}
132 |
133 | ### Do you like to read a more complete step by step tutorial?
134 |
135 | {% hint style="success" %}
136 | [Here](https://locize.com/blog/react-i18next/) you'll find a simple tutorial on how to best use react-i18next.\
137 | Some basics of i18next and some cool possibilities on how to optimize your localization workflow.[\
138 | ](https://locize.com/blog/react-i18next/)
139 | {% endhint %}
140 |
--------------------------------------------------------------------------------
/guides/multiple-translation-files.md:
--------------------------------------------------------------------------------
1 | # Multiple Translation Files
2 |
3 | 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 -> as you're accessing keys from a namespace defining that as a prefix:
4 |
5 | So while this takes the translation from the defined default namespace:
6 |
7 | ```javascript
8 | i18next.t('look.deep');
9 | ```
10 |
11 | This will lookup the key in a namespace (file) called common.json:
12 |
13 | ```javascript
14 | i18next.t('common:look.deep'); // not recommended with ns prefix when used in combination with natural language keys
15 | // better use the ns option:
16 | i18next.t('look.deep', { ns: 'common' })
17 | ```
18 |
19 | In order to use multiple namespaces/translation files, you need to specify it when calling [`useTranslation`](https://react.i18next.com/latest/usetranslation-hook) :
20 |
21 | ```javascript
22 | const { t } = useTranslation(['translation', 'common']);
23 | ```
24 |
25 | [`withTranslation`](https://react.i18next.com/latest/withtranslation-hoc):
26 |
27 | ```javascript
28 | withTranslation(['translation', 'common'])(MyComponent);
29 | ```
30 |
31 | or [`Translation`](https://react.i18next.com/latest/translation-render-prop):
32 |
33 | ```javascript
34 |
35 | {
36 | (t) =>
{t('look.deep', { ns: 'common' })}
37 | }
38 |
39 | ```
40 |
41 | ## Separating translation files
42 |
43 | In i18next you have a lot of options to add translations on init, in your code calling API methods or using one of the backend implementation. For a detailed write up check out the ["Add or load translation guide on i18next.com"](https://www.i18next.com/how-to/add-or-load-translations).
44 |
45 | With react-i18next you can use any of the components passing down the `t` function to your components to load namespaces:
46 |
47 | * [useTranslation (hook)](../latest/usetranslation-hook.md)
48 | * [withTranslation (HOC)](../latest/withtranslation-hoc.md)
49 | * [Translation (render prop)](../latest/translation-render-prop.md)
50 |
51 | All take arguments to define which namespaces to load and will Suspense rendering until those got loaded.
52 |
53 | So you do not need to load all translations upfront enabling you to create huge react based applications without slowing down loading of the first page cause all translations need to be loaded upfront (hello other i18n implementations).
54 |
55 | ## Manage your translations with a management GUI
56 |
57 | ### [**locize**](https://locize.com) is the perfect translation management tool for your [**i18next**](https://www.i18next.com) project
58 |
59 | #### ➡️ [i18next](https://www.i18next.com/) + [locize](https://locize.com/) = [true continuous localization](https://locize.com/how-it-works.html#continouslocalization)
60 |
61 | [Here](https://github.com/locize/react-tutorial) you can find a step by step guide, which will unleash the full power of i18next in combination with locize.\
62 | See how your developer experience with this localization workflow [could look like](https://youtu.be/osScyaGMVqo).\
63 | There's also the possibility to have an [even more focused developer experience](https://youtu.be/VfxBpSXarlU), with the help of the [auto-machinetranslation workflow](https://docs.locize.com/whats-inside/auto-machine-translation) and the use of the save missing keys functionality, new keys not only gets added to locize automatically, while developing the app, but are also [automatically translated](https://youtu.be/VfxBpSXarlU) into the target languages using machine translation (like [Google Translate](https://cloud.google.com/translate)).
64 |
65 | {% embed url="https://youtu.be/osScyaGMVqo" %}
66 |
67 | {% embed url="https://youtu.be/VfxBpSXarlU" %}
68 |
69 |
--------------------------------------------------------------------------------
/guides/quick-start.md:
--------------------------------------------------------------------------------
1 | # Quick start
2 |
3 | ## Install needed dependencies
4 |
5 | We expect you having an existing react application - if not give [Vite](https://vite.dev/guide/#scaffolding-your-first-vite-project) (`npm create vite@latest`) or similar a try.
6 |
7 | Install both react-i18next and i18next packages:
8 |
9 | ```bash
10 | npm install react-i18next i18next --save
11 | ```
12 |
13 | Why do you need i18next package? i18next is the core that provides all translation functionality while react-i18next gives some extra power for using with react.
14 |
15 | #### Do you directly want to see an example?
16 |
17 | Check out this basic [react example](https://github.com/i18next/react-i18next/tree/master/example/react) with a [browser language-detector](https://github.com/i18next/i18next-browser-languageDetector) and a [http backend](https://github.com/i18next/i18next-http-backend) to load translations from.
18 |
19 | #### Do you like to read a more complete step by step tutorial?
20 |
21 | {% hint style="success" %}
22 | [Here](https://locize.com/blog/react-i18next/) you'll find a simple tutorial on how to best use react-i18next.\
23 | Some basics of i18next and some cool possibilities on how to optimize your localization workflow.[\
24 | .jpg>)](https://locize.com/blog/react-i18next/)
25 | {% endhint %}
26 |
27 | ## Configure i18next
28 |
29 | Create a new file `i18n.js` beside your `index.js` containing following content:
30 |
31 | ```javascript
32 | import i18n from "i18next";
33 | import { initReactI18next } from "react-i18next";
34 |
35 | // the translations
36 | // (tip move them in a JSON file and import them,
37 | // or even better, manage them separated from your code: https://react.i18next.com/guides/multiple-translation-files)
38 | const resources = {
39 | en: {
40 | translation: {
41 | "Welcome to React": "Welcome to React and react-i18next"
42 | }
43 | },
44 | fr: {
45 | translation: {
46 | "Welcome to React": "Bienvenue à React et react-i18next"
47 | }
48 | }
49 | };
50 |
51 | i18n
52 | .use(initReactI18next) // passes i18n down to react-i18next
53 | .init({
54 | resources,
55 | lng: "en", // language to use, more information here: https://www.i18next.com/overview/configuration-options#languages-namespaces-resources
56 | // you can use the i18n.changeLanguage function to change the language manually: https://www.i18next.com/overview/api#changelanguage
57 | // if you're using a language detector, do not define the lng option
58 |
59 | interpolation: {
60 | escapeValue: false // react already safes from xss
61 | }
62 | });
63 |
64 | export default i18n;
65 | ```
66 |
67 | {% hint style="info" %}
68 | The file does not need to be named `i18n.js`, it can be any other filename. Just make sure you import it accordingly.
69 | {% endhint %}
70 |
71 | The interesting part here is by `i18n.use(initReactI18next)` we pass the i18n instance to react-i18next which will make it available for all the components via the context api.
72 |
73 | Then import that in `index.js`:
74 |
75 | ```javascript
76 | import React, { Component } from "react";
77 | import { createRoot } from 'react-dom/client';
78 | import './i18n';
79 | import App from './App';
80 |
81 | // append app to dom
82 | const root = createRoot(document.getElementById('root'));
83 | root.render(
84 |
85 | );
86 | ```
87 |
88 | {% hint style="info" %}
89 | If you need to access the `t` function or the `i18next` instance from outside of a React component you can simply import your `./i18n.js` and use the exported i18next instance:
90 |
91 |
95 |
96 | \
97 | Also read about this [here](https://www.locize.com/blog/how-to-use-i18next-t-outside-react-components) and [here](https://github.com/i18next/react-i18next/issues/1236#issuecomment-762039023).
98 | {% endhint %}
99 |
100 | ## Translate your content
101 |
102 | ### Using the hook
103 |
104 | Using the hook in functional components is one of the options you have.
105 |
106 | The `t` function is the main function in i18next to translate content. Read the [documentation](https://www.i18next.com/translation-function/essentials) for all the options.
107 |
108 | ```jsx
109 | import React from 'react';
110 |
111 | // the hook
112 | import { useTranslation } from 'react-i18next';
113 |
114 | function MyComponent () {
115 | const { t, i18n } = useTranslation();
116 | return
{t('Welcome to React')}
117 | }
118 | ```
119 |
120 | Learn more about the hook [useTranslation](../latest/usetranslation-hook.md).
121 |
122 | ### Using the HOC
123 |
124 | Using higher order components is one of the most used method to extend existing components by passing additional props to them.
125 |
126 | The `t` function is the main function in i18next to translate content. Read the [documentation](https://www.i18next.com/translation-function/essentials) for all the options.
127 |
128 | ```jsx
129 | import React from 'react';
130 |
131 | // the hoc
132 | import { withTranslation } from 'react-i18next';
133 |
134 | function MyComponent ({ t }) {
135 | return
{t('Welcome to React')}
136 | }
137 |
138 | export default withTranslation()(MyComponent);
139 | ```
140 |
141 | Learn more about the higher order component [withTranslation](../latest/withtranslation-hoc.md).
142 |
143 | ### Using the render prop
144 |
145 | The render prop enables you to use the `t` function inside your component.
146 |
147 | ```jsx
148 | import React from 'react';
149 |
150 | // the render prop
151 | import { Translation } from 'react-i18next';
152 |
153 | export default function MyComponent () {
154 | return (
155 |
156 | {
157 | t =>
{t('Welcome to React')}
158 | }
159 |
160 | )
161 | }
162 | ```
163 |
164 | Learn more about the render prop [Translation](../latest/translation-render-prop.md).
165 |
166 | ### Using the Trans component
167 |
168 | The Trans component is the best way to translate a JSX tree in one translation. This enables you to eg. easily translate text containing a link component or formatting like ``.
169 |
170 | ```jsx
171 | import React from 'react';
172 | import { Trans } from 'react-i18next';
173 |
174 | export default function MyComponent () {
175 | return
Welcome to React
176 | }
177 |
178 | // the translation in this case should be
179 | "<0>Welcome to React0>": "<0>Welcome to React and react-i18next0>"
180 | ```
181 |
182 | Don't worry if you do not yet understand how the Trans component works in detail. Learn more about it [here](../latest/trans-component.md).
183 |
184 | ## Next steps
185 |
186 | Depending on your learning style, you can now read the more in-depth [step by step](../latest/using-with-hooks.md) guide and learn how to load translations using xhr or how to change the language.
187 |
188 | Prefer having code to checkout? Directly dive into our examples:
189 |
190 | * [Example react](https://github.com/i18next/react-i18next/tree/master/example/react)
191 |
192 | > **Would you like to visually check the progress state of your translations?**
193 | >
194 | > _Try_ [_translation-check_](https://github.com/locize/translation-check)_, it shows an overview of your translations in a nice UI. Check which keys are not yet translated._\
195 | > [](https://github.com/locize/translation-check)
196 |
--------------------------------------------------------------------------------
/guides/the-drawbacks-of-other-i18n-solutions.md:
--------------------------------------------------------------------------------
1 | # Drawbacks of other i18n solutions
2 |
3 | Let's make the sample using our own base i18n framework [i18next](https://i18next.com). Like all other solutions, some come with [drawbacks](the-drawbacks-of-other-i18n-solutions.md#the-drawbacks). These will be highlighted after samples.
4 |
5 | ## Using a pure javascript i18n framework
6 |
7 | ```javascript
8 | import React, { Component } from "react";
9 | import { createRoot } from 'react-dom/client';
10 | import i18n from "i18next";
11 |
12 | // translation catalog
13 | const resources = {
14 | en: {
15 | translation: {
16 | "welcome": "Welcome to React and react-i18next"
17 | }
18 | }
19 | };
20 |
21 | // initialize i18next with catalog and language to use
22 | i18n.init({
23 | resources,
24 | lng: "en"
25 | });
26 |
27 | class App extends Component {
28 | render() {
29 | return
{i18n.t('welcome')}
;
30 | }
31 | }
32 |
33 | // append app to dom
34 | const root = createRoot(document.getElementById('root'));
35 | root.render(
36 |
37 | );
38 | ```
39 |
40 | ## More react adapted "react-i18n"
41 |
42 | The above is basically how every i18n framework for react works. The translations and language get set when initiated and a translation function is made available. You could easily extend this hiding the i18n.init inside a provider and pass down the function by context to another component to translate strings.
43 |
44 | So let's make this more visible with some pseudo code:
45 |
46 | ```javascript
47 | import React, { Component } from "react";
48 | import { createRoot } from 'react-dom/client';
49 | import { I18nProvider, FormattedString } from "i18nLib";
50 |
51 | // import translation catalog
52 | import resources from './catalog-en.json';
53 |
54 | class App extends Component {
55 | render() {
56 | return
;
57 | }
58 | }
59 |
60 | // append app to dom
61 | const root = createRoot(document.getElementById('root'));
62 | root.render(
63 |
64 | ,
65 |
66 | );
67 | ```
68 |
69 | ## The drawbacks
70 |
71 | Before we come to the drawbacks let's highlight some advantages of those solutions above - they are very simple to get started.
72 |
73 | ### Changing the language
74 |
75 | Can you easily change the language? Get the translations in other language loaded? Does the language change trigger a rerender?
76 |
77 | That's what the [withTranslation](../latest/withtranslation-hoc.md) higher order component or [useTranslation](../latest/usetranslation-hook.md) hook do!
78 |
79 | ### Scale and split your translations into multiple files
80 |
81 | When your project gets bigger you do not only want code splitting but you also like to load translations on demand to avoid loading all translations upfront which would result in bad load times for your website.
82 |
83 | With loading translations asynchronous there comes another problem - does your framework handle the pending state during loading translation?
84 |
85 | That's what the [withTranslation](../latest/withtranslation-hoc.md) higher order component or [useTranslation](../latest/usetranslation-hook.md) hook do!
86 |
87 | ### Can you translate combined jsx nodes in one sentence
88 |
89 | Let's take following content:
90 |
91 | ```javascript
92 |
93 | Hello {name}, you have
94 | {count} unread message(s).
95 |
96 | ```
97 |
98 | In most frameworks you will end having to split this into multiple translation strings. But for your translators it would make sense to have this as one sentence to translate like eg.:
99 |
100 | ```
101 | Hello <1>{name}1>, you have <3>{count} unread message(s)3>.
102 | ```
103 |
104 | You can do this using the [Trans component](../latest/trans-component.md).
105 |
--------------------------------------------------------------------------------
/latest/i18next-instance.md:
--------------------------------------------------------------------------------
1 | # i18next instance
2 |
3 | The instance is an initialized i18next instance. In the following code snippet, we add a backend to load translations from server and a language detector for detecting user language.
4 |
5 | > You can learn more about [i18next](http://i18next.com) and [plugins](https://www.i18next.com/plugins-and-utils.html#plugins) on the i18next website.
6 |
7 | ```javascript
8 | import i18n from 'i18next';
9 | import Backend from 'i18next-http-backend';
10 | import LanguageDetector from 'i18next-browser-languagedetector';
11 | import { initReactI18next } from 'react-i18next';
12 |
13 |
14 | i18n
15 | .use(Backend)
16 | .use(LanguageDetector)
17 | .use(initReactI18next) // bind react-i18next to the instance
18 | .init({
19 | fallbackLng: 'en',
20 | debug: true,
21 |
22 | interpolation: {
23 | escapeValue: false, // not needed for react!!
24 | },
25 |
26 | // react i18next special options (optional)
27 | // override if needed - omit if ok with defaults
28 | /*
29 | react: {
30 | bindI18n: 'languageChanged',
31 | bindI18nStore: '',
32 | transEmptyNodeValue: '',
33 | transSupportBasicHtmlNodes: true,
34 | transKeepBasicHtmlNodesFor: ['br', 'strong', 'i'],
35 | useSuspense: true,
36 | }
37 | */
38 | });
39 |
40 |
41 | export default i18n;
42 | ```
43 |
44 | All additional options for react in init options:
45 |
46 | | options | default | description |
47 | | -------------------------- | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
48 | | bindI18n | 'languageChanged' |
which events trigger a rerender, can be set to false or string of events separated by ""
|
49 | | bindI18nStore | '' | define which events on [resourceStore](https://www.i18next.com/overview/api#store-events) should trigger a rerender |
50 | | transEmptyNodeValue | '' | how to treat failed lookups in Trans component |
51 | | transSupportBasicHtmlNodes | true |
convert eg. <br/> found in translations to a react component of type br See Trans component
Which nodes not to convert in defaultValue generation in the Trans component. See Trans component
|
53 | | useSuspense | true | If using Suspense or not |
54 | | keyPrefix | undefined | the optional `keyPrefix` will be automatically applied to the returned `t` function in [useTranslation](usetranslation-hook.md#optional-keyprefix-option) for example. |
55 |
56 | For more initialization options have look at the [docs](https://www.i18next.com/overview/configuration-options).
57 |
--------------------------------------------------------------------------------
/latest/i18nextprovider.md:
--------------------------------------------------------------------------------
1 | # I18nextProvider
2 |
3 | ## What it does
4 |
5 | The I18nextProvider does take an i18next instance via prop i18n and passes that down using the context API.
6 |
7 | ```jsx
8 | import { I18nextProvider } from 'react-i18next';
9 | import i18n from './i18n';
10 | import App from './App';
11 |
12 |
13 |
14 |
15 | ```
16 |
17 | ## When to use?
18 |
19 | You will need to use the provider if you need to support multiple i18next instances - eg. if you provide a component library ([like this example](https://github.com/i18next/react-i18next/tree/master/example/react-component-lib)) or in scenarios for [SSR (ServerSideRendering)](ssr.md). Additionally, you have the ability to manage the default namespace(s) by passing defaultNS.
20 |
21 | ## I18nextProvider props
22 |
23 | | _**name**_ | **type (**_**default)**_ | _**description**_ |
24 | | ------------- | ------------------------------ | ----------------------------------------------------------------------------------------- |
25 | | **i18n** | object (undefined) | pass i18next instance the provider will pass it down to translation components by context |
26 | | **defaultNS** | string \| string[] (undefined) | pass defaultNS to manage the default namespace(s) |
27 |
--------------------------------------------------------------------------------
/latest/migrating-v9-to-v10.md:
--------------------------------------------------------------------------------
1 | # Migrating v9 to v10
2 |
3 | v10 is a complete rewrite, taking the chance to clean up some complexity added from v1 to v9.
4 |
5 | This means you will need to test your application more cautiously before release.
6 |
7 | {% hint style="info" %}
8 | This is a specific migration guide regarding the complete react-i18next rewrite in v10.\
9 | If you're looking for general release notes, please have a look in the [CHANGELOG](https://github.com/i18next/react-i18next/blob/master/CHANGELOG.md) file.
10 | {% endhint %}
11 |
12 | ## New in v10
13 |
14 | The most obvious change is the hook function for use inside functional components:
15 |
16 | ```jsx
17 | import React from 'react';
18 | import { useTranslation } from 'react-i18next';
19 |
20 | export function MyComponent() {
21 | const [t, i18n] = useTranslation();
22 |
23 | return
{t('my translated text')}
24 | }
25 | ```
26 |
27 | ## Components without replacement
28 |
29 | The Interpolation component (which was marked as deprecated for a long time and replaced by the Trans Component) was removed finally. You will need to replace it with the Trans Component.
30 |
31 | ## Migration
32 |
33 | Replace your components like described below. If you don't have to use `Suspense` in your existing App you can set `useSuspense: false` in react.init options.react:
34 |
35 | ```javascript
36 | i18n.init({
37 | react: {
38 | useSuspense: false
39 | }
40 | });
41 | ```
42 |
43 | ## I18nextProvider changes
44 |
45 | The `I18nextProvider` no longer provides as many properties as before. Make the necessary changes in your codebase after migrating.
46 |
47 | ```javascript
48 | // New props
49 | {
50 | i18n,
51 | defaultNS,
52 | }
53 |
54 | // Old props
55 | {
56 | i18n,
57 | defaultNS,
58 | reportNS,
59 | lng: i18n && i18n.language,
60 | t: i18n && i18n.t.bind(i18n),
61 | }
62 | ```
63 |
64 | ## Components v9 -> v10
65 |
66 | | Type | <= v7 (v8) | v9 (v8) | v10 |
67 | | ------------------- | ------------------ | ------------------ | ---------------- |
68 | | hook | | - | useTranslation |
69 | | HOC | translate | withNamespaces | withTranslation |
70 | | render prop | I18n | NamespacesConsumer | Translation |
71 | | i18next plugin | reactI18nextModule | reactI18nextModule | initReactI18next |
72 | | Provider | I18nextProvider | I18nextProvider | I18nextProvider |
73 | | Complex Translation | Trans | Trans | Trans |
74 | | Interpolations | Interpolate | Interpolate | Trans |
75 |
--------------------------------------------------------------------------------
/latest/ssr.md:
--------------------------------------------------------------------------------
1 | # SSR (additional components)
2 |
3 | ## Using [Next.js](https://nextjs.org/) App Router?
4 |
5 | Then check out [this article](https://www.locize.com/blog/i18n-next-app-router) describing how to best internationalize it with i18next.
6 |
7 | [](https://www.locize.com/blog/i18n-next-app-router)
8 |
9 | ## Using [Next.js](https://nextjs.org/)?
10 |
11 | You should have a look at [next-i18next](https://github.com/i18next/next-i18next) which extends react-i18next to bring it to next.js the easiest way.
12 |
13 | > With `next-i18next@v8.0.0` and `Next.js v10`, next-i18next has done a major rewrite of the package, leveraging the built-in [internationalized routing](https://nextjs.org/docs/advanced-features/i18n-routing) provided by Next.js.
14 | >
15 | > [Here](https://github.com/locize/next-i18next-locize) you can also find a next-i18next app example in combination with locize, that offers 2 different approaches.
16 | >
17 | > `next-i18next@v5.0.0` supports `Next.js v9.5` in [**Serverless** mode](https://nextjs.org/blog/next-8#serverless-nextjs) (as of [July 2020](https://github.com/isaachinman/next-i18next/issues/274#issuecomment-664616304)). If your goal is to use earlier versions of Next.js with Serverless, then you should have a look at ["Next Right Now"](https://github.com/UnlyEd/next-right-now), which is a Next.js 9 boilerplate with built-in `i18next`, `react-i18next` and Locize.
18 | >
19 | > **Looking for an optimized Next.js translations setup?**\
20 | > [Here](https://locize.com/blog/next-i18next/) you'll find a blog post on how to best use next-i18next with client side translation download and SEO optimization.
21 | >
22 | > [](https://locize.com/blog/next-i18next/)
23 | >
24 | > ***
25 | >
26 | > **Using SSG / `next export`?**\
27 | > [Here](https://locize.com/blog/next-i18n-static/) you'll find a simple tutorial on how to best use next-i18next in a SSG environment.\
28 | > [](https://locize.com/blog/next-i18n-static/)
29 |
30 | ## Using [Remix](https://remix.run)?
31 |
32 | You should have a look at [remix-i18next](https://github.com/sergiodxa/remix-i18next) which extends react-i18next to bring it to Remix the easiest way.
33 |
34 | > [Here](https://github.com/locize/locize-remix-i18next-example) you'll find a simple example and [here a step by step tutorial](https://locize.com/blog/remix-i18n/) on how to best use remix-i18next.
35 | >
36 | > [](https://locize.com/blog/remix-i18n/)
37 |
38 | ## Using [Gatsby](https://www.gatsbyjs.com/)?
39 |
40 | You should have a look at [gatsby-plugin-react-i18next](https://github.com/microapps/gatsby-plugin-react-i18next) which extends react-i18next to bring it to Gatsby the easiest way.
41 |
42 | > [Here](https://github.com/locize/locize-gatsby-example) you'll find a simple example and [here a step by step tutorial](https://locize.com/blog/gatsby-i18n/) on how to best use [gatsby-plugin-react-i18next](https://github.com/microapps/gatsby-plugin-react-i18next).
43 | >
44 | > [](https://locize.com/blog/gatsby-i18n/)
45 |
46 | ## Setting the i18next instance based on req
47 |
48 | Use the [I18nextProvider](i18nextprovider.md) to inject the i18next instance for example bound to the http i18n instance on the request object using [i18next-http-middleware](https://github.com/i18next/i18next-http-middleware).
49 |
50 | ```jsx
51 |
52 |
53 |
54 | ```
55 |
56 | ## Passing initial translations / initial language down to client
57 |
58 | To avoid asynchronous loading of translation on the client side (and the possible Suspense out of that) you will need to pass down initialLanguage (will call changeLanguage on i18next) and initialI18nStore (will prefill translations in i18next store).
59 |
60 | ### using the useSSR hook
61 |
62 | ```jsx
63 | import React from 'react';
64 | import { useSSR } from 'react-i18next';
65 |
66 | export function InitSSR({ initialI18nStore, initialLanguage }) {
67 | useSSR(initialI18nStore, initialLanguage);
68 |
69 | return
70 | }
71 | ```
72 |
73 | ### using the withSSR HOC
74 |
75 | ```jsx
76 | import React from 'react';
77 | import { withSSR } from 'react-i18next';
78 | import App from './App';
79 |
80 | const ExtendedApp = withSSR()(App);
81 |
82 |
83 | ```
84 |
85 | The ExtendedApp in this case will also have the composed `ExtendedApp.getInitialProps()`
86 |
--------------------------------------------------------------------------------
/latest/trans-component.md:
--------------------------------------------------------------------------------
1 | # Trans Component
2 |
3 | ## Important note
4 |
5 | While `` gives you a lot of power by letting you interpolate or translate complex React elements, the truth is: in most cases you don't even need it.
6 |
7 | **As long you have no React/HTML nodes integrated into a cohesive sentence** (text formatting like `strong`, `em`, link components, maybe others), **you won't need it** - most of the times you will be using the good old `t` function.
8 |
9 | You may be looking directly for the [Trans props](https://react.i18next.com/latest/trans-component#trans-props).
10 |
11 | {% hint style="warning" %}
12 | It does ONLY interpolation. It does not rerender on language change or load any translations needed. Check [`useTranslation` hook](usetranslation-hook.md) or [`withTranslation` HOC](withtranslation-hoc.md) for those cases.
13 | {% endhint %}
14 |
15 | ```javascript
16 | import React from 'react';
17 | import { Trans, useTranslation } from 'react-i18next'
18 |
19 | function MyComponent() {
20 | const { t } = useTranslation('myNamespace');
21 |
22 | return Hello World;
23 | }
24 | ```
25 |
26 | {% hint style="info" %}
27 | Have a look at the [i18next documentation](https://www.i18next.com) for details on the the `t` function:
28 |
29 | * [essentials](https://www.i18next.com/translation-function/essentials.html)
30 | * [interpolation](https://www.i18next.com/translation-function/interpolation.html)
31 | * [formatting](https://www.i18next.com/translation-function/formatting.html)
32 | * [plurals](https://www.i18next.com/translation-function/plurals.html)
33 | {% endhint %}
34 |
35 | ## Samples
36 |
37 | ### Using with React components
38 |
39 | So you learned there is no need to use the Trans component everywhere (the plain `t` function will just do fine in most cases).
40 |
41 | This component enables you to nest any React content to be translated as one cohesive string. It supports both plural and interpolation. The `` component will automatically use the most relevant `t()` function (from the [context instance](https://react.i18next.com/latest/i18nextprovider) or the global instance), unless overridden via the `i18n` or `t` props.
42 |
43 | _Let's say you want to create following HTML output:_
44 |
45 | > Hello **Arthur**, you have 42 unread messages. [Go to messages](../legacy-v9/trans-component.md).
46 |
47 | **Before:** Your untranslated React code would have looked something like:
48 |
49 | ```javascript
50 | function MyComponent({ person, messages }) {
51 | const { name } = person;
52 | const count = messages.length;
53 |
54 | return (
55 | <>
56 | Hello {name}, you have {count} unread message(s). Go to messages.
57 | >
58 | );
59 | }
60 | ```
61 |
62 | **After:** With the Trans component just change it to:
63 |
64 | ```javascript
65 | import { Trans } from 'react-i18next';
66 |
67 | function MyComponent({ person, messages }) {
68 | const { name } = person;
69 | const count = messages.length;
70 |
71 | return (
72 |
73 | Hello {{name}}, you have {{count}} unread message. Go to messages.
74 |
75 | );
76 | }
77 | ```
78 |
79 | _Your en.json (translation strings) will look like:_
80 |
81 | ```javascript
82 | "nameTitle": "This is your name",
83 | "userMessagesUnread_one": "Hello <1>{{name}}1>, you have {{count}} unread message. <5>Go to message5>.",
84 | "userMessagesUnread_other": "Hello <1>{{name}}1>, you have {{count}} unread messages. <5>Go to messages5>.",
85 | ```
86 |
87 | {% hint style="info" %}
88 | [**saveMissing**](https://www.i18next.com/overview/configuration-options#missing-keys) will send a valid `defaultValue` based on the component children.\
89 | Also, The `i18nKey` is optional, in case you already use text as translation keys.
90 | {% endhint %}
91 |
92 | ### Alternative usage which lists the components (v11.6.0)
93 |
94 | ```javascript
95 | fallbacks to defaults if not provided
97 | defaults="hello beautiful{{what}}" // optional defaultValue
98 | values={{ what: 'world'}}
99 | components={{ italic: , bold: }}
100 | />
101 | ```
102 |
103 | This format is useful if you want to interpolate the same node multiple times. Another advantage is the simpler named tags, which avoids the trouble with index guessing - however, this can also be achieved with `transSupportBasicHtmlNodes`, see the next section.
104 |
105 | {% hint style="warning" %}
106 | Existing self-closing HTML tag names are reserved keys and won't work. Examples: `link: `, `img: `, `media: `
107 | {% endhint %}
108 |
109 | {% hint style="info" %}
110 | Make sure you also adapt your translation resources to include the _named tags_ (``) instead of the _indexed tags_ (`<0>`)!
111 | {% endhint %}
112 |
113 | ### Overriding React component props (v11.5.0)
114 |
115 | In some cases you may want to override the props of a given component based on the active language.
116 |
117 | This can be achieved by providing prop values inside of your translations. Such values will override whatever has been passed to the component present in the `components` prop of the `Trans` component.
118 |
119 | In the example below we want our custom link component to have a different `href` value based on the active language. This is how our custom link component is being used:
120 |
121 | ```javascript
122 |
126 | }}
127 | />
128 | ```
129 |
130 | with the following being our translation message:
131 |
132 | ```json
133 | "myKey": "This is a link to example.com."
134 | ```
135 |
136 | This setup will render the following JSX:
137 |
138 | ```html
139 | This is a link to example.com.
140 | ```
141 |
142 | This approach also works with listed components:
143 |
144 | ```javascript
145 | ]}
148 | />
149 | ```
150 |
151 | With this then making up our translation message:
152 |
153 | ```json
154 | "myKey": "This is a <0 href=\"https://example.com/\">link to example.com0>."
155 | ```
156 |
157 | ### Usage with simple HTML elements like \ and others (v10.4.0)
158 |
159 | There are two options that allow you to have basic HTML tags inside your translations, instead of numeric indexes. However, this only works for elements without additional attributes (like `className`), having none or a single text children.
160 |
161 | Examples of elements that will be readable in translation strings:
162 |
163 | * ` `
164 | * `bold`
165 | * `
some paragraph
`
166 |
167 | Examples that will be converted to indexed nodes:
168 |
169 | * ``: no attributes allowed
170 | * `{{name}}`: only text nodes allowed
171 | * `bold italic`: no nested elements, even simple ones
172 |
173 | ```jsx
174 |
175 | Hello {{name}}. See my profile
176 |
177 | // JSON -> "welcomeUser": "Hello {{name}}. <1>See my profile1>"
178 |
179 |
180 | Some newlines would be fine
181 |
182 | // JSON -> "multiline": "Some newlines would be fine"
183 | ```
184 |
185 | Here is what can be configured in `i18next.options.react` that affect this behaviour:
186 |
187 | | Option | Default | Description |
188 | | ------------------------------- | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
189 | | `transSupportBasicHtmlNodes` | `true` | Enables keeping the name of simple nodes (e.g. ` `) in translations instead of indexed keys |
190 | | `transKeepBasicHtmlNodesFor` | `['br', 'strong', 'i', 'p']` | Which nodes are allowed to be kept in translations during `defaultValue` generation of ``. |
191 | | `transWrapTextNodes` (v11.10.0) | `''` | Wrap text nodes in a user-specified element. e.g. set it to `span`. By default, text nodes are not wrapped. Can be used to work around a well-known Google Translate issue with React apps. See [facebook/react#11538](https://github.com/facebook/react/issues/11538). |
192 |
193 | ### Interpolation
194 |
195 | You can pass in variables to get interpolated into the translation string by using objects containing those key:values.
196 |
197 | ```jsx
198 | const person = { name: 'Henry', age: 21 };
199 | const { name, age } = person;
200 |
201 |
202 | Hello {{ name }}. // <- = {{ "name": name }}
203 |
204 | // Translation string: "Hello {{name}}"
205 |
206 |
207 |
208 | Hello {{ firstname: person.name }}.
209 |
210 | // Translation string: "Hello {{firstname}}"
211 | ```
212 |
213 | ### Plural
214 |
215 | You will need to pass the `count` prop:
216 |
217 | ```jsx
218 | const messages = ['message one', 'message two'];
219 |
220 |
221 | You have {{ count: messages.length }} messages.
222 |
223 |
224 | // Translation strings:
225 | // "newMessages": "You have one message."
226 | // "newMessages_plural": "You have {{count}} messages."
227 | ```
228 |
229 | ### Using with lists (v10.5.0)
230 |
231 | You can still use `Array.map()` to turn dynamic content into nodes, using an extra option on a wrapping element:
232 |
233 | ```jsx
234 |
235 | My dogs are named:
236 |
237 | {['rupert', 'max'].map(dog => (
{dog}
))}
238 |
239 |
240 | // JSON -> "list_map": "My dogs are named: <1>1>"
241 | ```
242 |
243 | Setting `i18nIsDynamicList` on the parent element will assert the `nodeToString` function creating the string for `saveMissing` will not contain children.
244 |
245 | ### Alternative usage (components array)
246 |
247 | Some use cases, such as the ICU format, might be simpler by just passing content as props:
248 |
249 | ```javascript
250 | fallbacks to defaults if not provided
252 | defaults="hello <0>{{what}}0>" // optional defaultValue
253 | values={{ what: 'world'}}
254 | components={[univers]}
255 | />
256 | ```
257 |
258 | {% hint style="info" %}
259 | `<0>` -> 0 is the index of the component in the components array
260 | {% endhint %}
261 |
262 | E.g. this format is needed when using [ICU as translation format](https://github.com/i18next/i18next-icu) as it is not possible to have the needed syntax as children (invalid jsx).
263 |
264 | ## How to get the correct translation string?
265 |
266 | Guessing replacement tags _(<0>\0>)_ of your component is rather difficult. There are four options to get those translations directly generated by i18next:
267 |
268 | 1. use React Developer Tools to inspect the `` component instance and look at the `props.children` array for array index of the tag in question.
269 | 2. use `debug = true` in `i18next.init()` options and watch your console for the missing key output
270 | 3. use the [saveMissing feature](https://www.i18next.com/configuration-options#missing-keys) of i18next to get those translations pushed to your backend or handled by a custom function.
271 | 4. understand how those numbers get generated from child index:
272 |
273 | **Sample JSX:**
274 |
275 | ```javascript
276 |
277 | Hello {{name}}, you have {{count}} unread message. Go to messages.
278 |
279 | ```
280 |
281 | **Resulting translation string:**
282 |
283 | ```
284 | "Hello <1>{{name}}1>, you have {{count}} unread message. <5>Go to message5>."
285 | ```
286 |
287 | **The complete the node tree**:
288 |
289 | ```javascript
290 | Trans.children = [
291 | 'Hello ', // 0: only a string
292 | { children: [{ name: 'Jan' }] }, // 1: with child object for interpolation
293 | ', you have ', // 2: only a string
294 | { count: 10 }, // 3: plain object for interpolation
295 | ' unread messages. ', // 4: only a string
296 | { children: ['Go to messages'] }, // 5: with a string child
297 | '.' // 6: yep, you guessed: another string
298 | ]
299 | ```
300 |
301 | **Rules:**
302 |
303 | * child is a string: nothing to wrap; just take the string
304 | * child is an object: nothing to do; it's used for interpolation
305 | * child is an element: wrap it's children in `` where `x` is the index of that element's position in the `children` list; handle its children with the same rules (starting `element.children` index at 0 again)
306 |
307 | ## Trans props
308 |
309 | All properties are optional, although you'll need to use `i18nKey` if you're not using natural language keys (text-based).
310 |
311 | | _**name**_ | _**type (default)**_ | _**description**_ |
312 | | ---------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
313 | | `i18nKey` | `string (undefined)` |
If you prefer to use text as keys you can omit this, and the translation will be used as key. Can contain the namespace by prepending it in the form 'ns:key' (depending on i18next.options.nsSeparator)
But this is not recommended when used in combination with natural language keys, better use the dedicated ns parameter: <Trans i18nKey="myKey" ns="myNS"></Trans>
|
314 | | `ns` | `string (undefined)` | Namespace to use. May also be embedded in `i18nKey` but not recommended when used in combination with natural language keys, see above. |
315 | | `t` | `function (undefined)` | `t` function to use instead of the global `i18next.t()` or the `t()` function provided by the nearest [provider](https://react.i18next.com/latest/i18nextprovider). |
316 | | `count` | `integer (undefined)` | Numeric value for pluralizable strings |
317 | | `context` | `string (undefined)` | Value used for the [context feature](https://www.i18next.com/translation-function/context). |
318 | | `tOptions` | `object (undefined)` | Extra options to pass to `t()` (e.g. `context`, `postProcessor`, ...) |
319 | | `parent` | `node (undefined)` | A component to wrap the content into (can be globally set on `i18next.init`). **Required for React < v16** |
320 | | `i18n` | `object (undefined)` | i18next instance to use if not provided by context |
321 | | `defaults` | `string (undefined)` | Use this instead of using the children as default translation value (useful for ICU) |
322 | | `values` | `object (undefined)` | Interpolation values if not provided in children |
323 | | `components` | `array[nodes] (undefined)` | Components to interpolate based on index of tag |
324 | | `shouldUnescape` | `boolean (false)` | HTML encoded tags like: `< & >` should be unescaped, to become: `< & >` |
325 |
326 | ### i18next options
327 |
328 | ```javascript
329 | i18next.init({
330 | // ...
331 | react: {
332 | // ...
333 | hashTransKey: function(defaultValue) {
334 | // return a key based on defaultValue or if you prefer to just remind you should set a key return false and throw an error
335 | },
336 | defaultTransParent: 'div', // a valid react element - required before react 16
337 | transEmptyNodeValue: '', // what to return for empty Trans
338 | transSupportBasicHtmlNodes: true, // allow and simple html elements in translations
339 | transKeepBasicHtmlNodesFor: ['br', 'strong', 'i'], // don't convert to <1>1> if simple react elements
340 | transWrapTextNodes: '', // Wrap text nodes in a user-specified element.
341 | // i.e. set it to 'span'. By default, text nodes are not wrapped.
342 | // Can be used to work around a well-known Google Translate issue with React apps. See: https://github.com/facebook/react/issues/11538
343 | // (v11.10.0)
344 | }
345 | });
346 | ```
347 |
348 | {% hint style="warning" %}
349 | Please be aware if you are using **React 15 or below**, you are required to set the `defaultTransParent` option, or pass a `parent` via props.
350 | {% endhint %}
351 |
352 | {% hint style="danger" %}
353 | **Are you having trouble when your website is ran through Google Translate?**\
354 | Google Translate seems to manipulate the DOM and makes React quite unhappy!\
355 | **There's a work around:** you can wrap text nodes with`` using `transWrapTextNodes: 'span'`.
356 |
357 | _If you want to know more about the Google Translate issue with React, have a look at_ [_this_](https://github.com/facebook/react/issues/11538#issuecomment-390386520)_._
358 | {% endhint %}
359 |
--------------------------------------------------------------------------------
/latest/translation-render-prop.md:
--------------------------------------------------------------------------------
1 | # Translation (render prop)
2 |
3 | ## What it does
4 |
5 | The `Translation` is a render prop and gets the `t` function and `i18n` instance to your component.
6 |
7 | ```jsx
8 | import React from 'react';
9 | import { Translation } from 'react-i18next';
10 |
11 | export function MyComponent() {
12 | return (
13 |
14 | {
15 | (t, { i18n }) =>
{t('my translated text')}
16 | }
17 |
18 | )
19 | }
20 | ```
21 |
22 | While you most time only need the t function to translate your content you also get the i18n instance to eg. change the language.
23 |
24 | ```javascript
25 | i18n.changeLanguage('en-US');
26 | ```
27 |
28 | {% hint style="info" %}
29 | The `Translation` render prop will trigger a [Suspense](https://reactjs.org/docs/code-splitting.html#suspense) if not ready (eg. pending load of translation files). You can set `useSuspense` to false if prefer not using Suspense.
30 | {% endhint %}
31 |
32 | ## When to use?
33 |
34 | Use the `Translation` render prop inside **any component (class or function)** to access the translation function or i18n instance.
35 |
36 | ## Translation params
37 |
38 | ### Loading namespaces
39 |
40 | ```jsx
41 | // load a specific namespace
42 | // the t function will be set to that namespace as default
43 |
44 | {
45 | (t) =>
{t('my translated text')}
// will be looked up from namespace ns1
46 | }
47 |
48 |
49 | // load multiple namespaces
50 | // the t function will be set to first namespace as default
51 |
52 | {
53 | (t) =>
{t('my translated text')}
// will be looked up from namespace ns1
54 | }
55 |
56 | ```
57 |
58 | ### Overriding the i18next instance
59 |
60 | ```jsx
61 | // passing in an i18n instance
62 | // use only if you do not like the default instance
63 | // set by i18next.use(initReactI18next) or the I18nextProvider
64 | import i18n from './i18n';
65 |
66 |
67 | {
68 | (t, { i18n }) =>
{t('my translated text')}
// will be looked up from namespace ns1
69 | }
70 |
71 | ```
72 |
73 |
--------------------------------------------------------------------------------
/latest/typescript.md:
--------------------------------------------------------------------------------
1 | # TypeScript
2 |
3 | {% hint style="warning" %}
4 | Make sure you update to **react-i18next >= 13.0.0** and **i18next >= 23.0.1** and follow the instructions [here](https://www.i18next.com/overview/typescript).
5 | {% endhint %}
6 |
7 |
--------------------------------------------------------------------------------
/latest/usetranslation-hook.md:
--------------------------------------------------------------------------------
1 | # useTranslation (hook)
2 |
3 | ## What it does
4 |
5 | It gets the `t` function and `i18n` instance inside your functional component.
6 |
7 | ```jsx
8 | import React from 'react';
9 | import { useTranslation } from 'react-i18next';
10 |
11 | export function MyComponent() {
12 | const { t, i18n } = useTranslation(); // not passing any namespace will use the defaultNS (by default set to 'translation')
13 | // or const [t, i18n] = useTranslation();
14 |
15 | return
{t('my translated text')}
16 | }
17 | ```
18 |
19 | While most of the time you only need the `t` function to translate your content, you can also get the i18n instance (in order to change the language).
20 |
21 | ```javascript
22 | i18n.changeLanguage('en-US');
23 | ```
24 |
25 | {% hint style="info" %}
26 | The `useTranslation` hook will trigger a [Suspense](https://reactjs.org/docs/concurrent-mode-suspense.html) if not ready (eg. pending load of translation files). You can set `useSuspense` to false if prefer not using Suspense.
27 | {% endhint %}
28 |
29 | ## When to use?
30 |
31 | Use the `useTranslation` hook inside your **functional components** to access the translation function or i18n instance.
32 |
33 | {% hint style="success" %}
34 | In [this tutorial](https://locize.com/blog/react-i18next/) you'll find some ways on how to use this useTranslation hook.
35 |
36 | You'll also see how to use it when you need to work with [multiple namespaces](https://locize.com/blog/react-i18next/#multiple-namespaces).[\
37 | ](https://locize.com/blog/react-i18next/)
38 | {% endhint %}
39 |
40 | ## useTranslation params
41 |
42 | ### Loading namespaces
43 |
44 | ```javascript
45 | // load a specific namespace
46 | // the t function will be set to that namespace as default
47 | const { t, i18n } = useTranslation('ns1');
48 | t('key'); // will be looked up from namespace ns1
49 |
50 | // load multiple namespaces
51 | // the t function will be set to first namespace as default
52 | const { t, i18n } = useTranslation(['ns1', 'ns2', 'ns3']);
53 | t('key'); // will be looked up from namespace ns1
54 | t('key', { ns: 'ns2' }); // will be looked up from namespace ns2
55 | ```
56 |
57 | ### Overriding the i18next instance
58 |
59 | ```javascript
60 | // passing in an i18n instance
61 | // use only if you do not like the default instance
62 | // set by i18next.use(initReactI18next) or the I18nextProvider
63 | import i18n from './i18n';
64 | const { t, i18n } = useTranslation('ns1', { i18n });
65 | ```
66 |
67 | ### Optional keyPrefix option
68 |
69 | > available in react-i18next version >= 11.12.0
70 | >
71 | > depends on i18next version >= 20.6.0
72 |
73 | ```javascript
74 | // having JSON in namespace "translation" like this:
75 | /*{
76 | "very": {
77 | "deeply": {
78 | "nested": {
79 | "key": "here"
80 | }
81 | }
82 | }
83 | }*/
84 | // you can define a keyPrefix to be used for the resulting t function
85 | const { t } = useTranslation('translation', { keyPrefix: 'very.deeply.nested' });
86 | const text = t('key'); // "here"
87 | ```
88 |
89 | {% hint style="warning" %}
90 | Do **not** use the `keyPrefix` option if you want to use keys with prefixed namespace notation:
91 |
92 | i.e.
93 |
94 | ```javascript
95 | const { t } = useTranslation('translation', { keyPrefix: 'very.deeply.nested' });
96 | const text = t('ns:key'); // this will not work
97 | ```
98 | {% endhint %}
99 |
100 | ### Optional lng option
101 |
102 | > available in react-i18next version >= 12.3.1
103 |
104 | ```javascript
105 | // you can pass a language to be used for the resulting t function
106 | const { t } = useTranslation('translation', { lng: 'de' });
107 | const text = t('key'); // "hier"
108 | ```
109 |
110 | ### Not using Suspense
111 |
112 | ```javascript
113 | // additional ready will state if translations are loaded or not
114 | const { t, i18n, ready } = useTranslation('ns1', { useSuspense: false });
115 | ```
116 |
117 | {% hint style="info" %}
118 | Not using Suspense you will need to handle the not ready state yourself by eg. render a loading component as long `!ready` . Not doing so will result in rendering your translations before they loaded which will cause save missing be called although translations exists (just yet not loaded).
119 | {% endhint %}
120 |
--------------------------------------------------------------------------------
/latest/using-with-hooks.md:
--------------------------------------------------------------------------------
1 | # Step by step guide
2 |
3 | ## Install needed dependencies
4 |
5 | We expect you to have an existing react application supporting [hooks](https://reactjs.org/docs/hooks-intro.html) (at least v16.7.0-alpha of react and react-dom).
6 |
7 | Install both react-i18next and i18next packages:
8 |
9 | ```bash
10 | npm install react-i18next i18next --save
11 |
12 | # if you'd like to detect user language and load translation
13 | npm install i18next-http-backend i18next-browser-languagedetector --save
14 | ```
15 |
16 | ### Configure i18next
17 |
18 | I18next is the core of the i18n functionality while react-i18next extends and glues it to react.
19 |
20 | Create a new file `i18n.js` beside your `index.js` containing following content:
21 |
22 | ```javascript
23 | import i18n from 'i18next';
24 | import { initReactI18next } from 'react-i18next';
25 |
26 | import Backend from 'i18next-http-backend';
27 | import LanguageDetector from 'i18next-browser-languagedetector';
28 | // don't want to use this?
29 | // have a look at the Quick start guide
30 | // for passing in lng and translations on init
31 |
32 | i18n
33 | // load translation using http -> see /public/locales (i.e. https://github.com/i18next/react-i18next/tree/master/example/react/public/locales)
34 | // learn more: https://github.com/i18next/i18next-http-backend
35 | // want your translations to be loaded from a professional CDN? => https://github.com/locize/react-tutorial#step-2---use-the-locize-cdn
36 | .use(Backend)
37 | // detect user language
38 | // learn more: https://github.com/i18next/i18next-browser-languageDetector
39 | .use(LanguageDetector)
40 | // pass the i18n instance to react-i18next.
41 | .use(initReactI18next)
42 | // init i18next
43 | // for all options read: https://www.i18next.com/overview/configuration-options
44 | .init({
45 | fallbackLng: 'en',
46 | debug: true,
47 |
48 | interpolation: {
49 | escapeValue: false, // not needed for react as it escapes by default
50 | }
51 | });
52 |
53 |
54 | export default i18n;
55 | ```
56 |
57 | The interesting part here is by `i18n.use(initReactI18next)` we pass the i18n instance to react-i18next which will make it available for all the components.
58 |
59 | Then import that in `index.js`:
60 |
61 | ```javascript
62 | import React, { Component } from "react";
63 | import { createRoot } from 'react-dom/client';
64 | import App from './App';
65 |
66 | // import i18n (needs to be bundled ;))
67 | import './i18n';
68 |
69 | const root = createRoot(document.getElementById('root'));
70 | root.render(
71 |
72 | );
73 | ```
74 |
75 | {% hint style="info" %}
76 | If you need to access the `t` function or the `i18next` instance from outside of a React component you can simply import your `./i18n.js` and use the exported i18next instance:
77 |
78 | ```
79 | import i18next from './i18n'
80 |
81 | i18next.t('my.key')
82 | ```
83 | {% endhint %}
84 |
85 | ### Translate your content
86 |
87 | #### Using the useTranslation hook
88 |
89 | You can use the hook inside your functional components like:
90 |
91 | ```jsx
92 | import React, { Suspense } from 'react';
93 | import { useTranslation } from 'react-i18next';
94 |
95 | function MyComponent() {
96 | const { t, i18n } = useTranslation();
97 |
98 | return
{t('Welcome to React')}
99 | }
100 |
101 | // i18n translations might still be loaded by the http backend
102 | // use react's Suspense
103 | export default function App() {
104 | return (
105 |
106 |
107 |
108 | );
109 | }
110 | ```
111 |
112 | The useTranslation hook function takes one options argument. You can either pass in a namespace or an array of namespaces to load.
113 |
114 | ```javascript
115 | const { t, i18n } = useTranslation('common');
116 |
117 | const { t, i18n } = useTranslation(['page1', 'common']);
118 | ```
119 |
120 | #### Translation Files
121 |
122 | Create a new file `public/locales//translation.json` with the following sample content.
123 |
124 | ```
125 | {
126 | "title": "Welcome to react using react-i18next",
127 | "description": {
128 | "part1": "To get started, edit <1>src/App.js1> and save to reload.",
129 | "part2": "Switch language between english and german using buttons above."
130 | }
131 | }
132 | ```
133 |
134 | Files are plain JSON you can checkout the full sample [here](https://github.com/i18next/react-i18next/tree/master/example/react/public/locales).
135 |
136 | {% hint style="info" %}
137 | Please note the t function will be either bound to the default namespace defined on i18next init or to the first one passed in arguments.
138 | {% endhint %}
139 |
140 | {% content-ref url="../guides/multiple-translation-files.md" %}
141 | [multiple-translation-files.md](../guides/multiple-translation-files.md)
142 | {% endcontent-ref %}
143 |
144 | #### Using the withTranslation HOC
145 |
146 | There might be some legacy cases where you are still forced to use classes. Don't worry, we still provide a hoc to cover these cases:
147 |
148 | ```jsx
149 | import React, { Component, Suspense } from 'react';
150 | import { withTranslation } from 'react-i18next';
151 |
152 | class LegacyComponentClass extends Component {
153 | render() {
154 | const { t } = this.props;
155 |
156 | return (
157 |
{t('Welcome to React')}
158 | )
159 | }
160 | }
161 | const MyComponent = withTranslation()(LegacyComponentClass)
162 |
163 | // i18n translations might still be loaded by the http backend
164 | // use react's Suspense
165 | export default function App() {
166 | return (
167 |
168 |
169 |
170 | );
171 | }
172 | ```
173 |
174 | The withTranslation hook function takes one options argument. You can either pass in a namespace or a array of namespaces to load.
175 |
176 | ```javascript
177 | withTranslation('common')(LegacyComponentClass);
178 |
179 | withTranslation(['page1', 'common'])(LegacyComponentClass);
180 | ```
181 |
182 | #### Using the Trans component
183 |
184 | The Trans component is the best way to translate a JSX tree in one translation. This enables you to eg. easily translate text containing a link component or formatting like ``.
185 |
186 | ```jsx
187 | import React from 'react';
188 | import { Trans } from 'react-i18next';
189 |
190 | export default function MyComponent () {
191 | return Welcome to React
192 | }
193 |
194 | // the translation in this case should be
195 | "Welcome to <1>React1>": "Welcome to <1>React and react-i18next1>"
196 | ```
197 |
198 | Don't worry if you do not yet understand how the Trans component works in detail. Learn more about it [here](trans-component.md).
199 |
200 | ## See the sample
201 |
202 | Prefer having code to checkout? Directly dive into our example:
203 |
204 | * [using hooks with react-i18next](https://github.com/i18next/react-i18next/tree/master/example/react)
205 |
206 | ### Do you like to read a more complete step by step tutorial?
207 |
208 | {% hint style="success" %}
209 | [Here](https://locize.com/blog/react-i18next/) you'll find a simple tutorial on how to best use react-i18next.\
210 | Some basics of i18next and some cool possibilities on how to optimize your localization workflow.[\
211 | .jpg>)](https://locize.com/blog/react-i18next/)
212 | {% endhint %}
213 |
--------------------------------------------------------------------------------
/latest/withtranslation-hoc.md:
--------------------------------------------------------------------------------
1 | # withTranslation (HOC)
2 |
3 | ## What it does
4 |
5 | The `withTranslation` is a classic HOC (higher order component) and gets the `t` function and `i18n` instance inside your component via props.
6 |
7 | ```jsx
8 | import React from 'react';
9 | import { withTranslation } from 'react-i18next';
10 |
11 | function MyComponent({ t, i18n }) {
12 | return
{t('my translated text')}
13 | }
14 |
15 | export default withTranslation()(MyComponent);
16 | ```
17 |
18 | While you most time only need the t function to translate your content you also get the i18n instance to eg. change the language.
19 |
20 | ```javascript
21 | i18n.changeLanguage('en-US');
22 | ```
23 |
24 | {% hint style="info" %}
25 | The `withTranslation` HOC will trigger a [Suspense](https://reactjs.org/docs/code-splitting.html#suspense) if not ready (eg. pending load of translation files). You can set `useSuspense` to false if prefer not using Suspense.
26 | {% endhint %}
27 |
28 | ## When to use?
29 |
30 | Use the `withTranslation` HOC to wrap **any component (class or function)** to access the translation function or i18n instance.
31 |
32 | ## withTranslation params
33 |
34 | ### Loading namespaces
35 |
36 | ```javascript
37 | // load a specific namespace
38 | // the t function will be set to that namespace as default
39 | withTranslation('ns1')(MyComponent);
40 |
41 | // inside your component MyComponent
42 | this.props.t('key'); // will be looked up from namespace ns1
43 |
44 | // load multiple namespaces
45 | // the t function will be set to first namespace as default
46 | withTranslation(['ns1', 'ns2', 'ns3'])(MyComponent);
47 |
48 | // inside your component MyComponent
49 | this.props.t('key'); // will be looked up from namespace ns1
50 | this.props.t('key', { ns: 'ns2' }); // will be looked up from namespace ns2
51 | ```
52 |
53 | ### Overriding the i18next instance
54 |
55 | ```javascript
56 | // passing in an i18n instance
57 | // use only if you do not like the default instance
58 | // set by i18next.use(initReactI18next) or the I18nextProvider
59 | import i18n from './i18n';
60 |
61 | const ExtendedComponent = withTranslation('ns1')(MyComponent);
62 |
63 |
64 | ```
65 |
66 | ### Not using Suspense
67 |
68 | ```javascript
69 | // use tReady prop in MyComponent to check if translations
70 | // are already loaded or not
71 | const ExtendedComponent = withTranslation()(MyComponent);
72 |
73 |
74 | ```
75 |
76 | {% hint style="info" %}
77 | Not using Suspense you will need to handle the not ready state yourself by eg. render a loading component as long `!props.tReady` . Not doing so will result in rendering your translations before they loaded which will cause save missing be called although translations exist (just yet not loaded).
78 | {% endhint %}
79 |
80 | ## How to
81 |
82 | ### use ref (>= v10.6.0)
83 |
84 | You can use forwardRefs like:
85 |
86 | ```jsx
87 | const Wrapped = withTranslation('translation', { withRef: true })(MyComponent);
88 |
89 | // then pass a ref in your render method like
90 | const myRef = React.createRef();
91 | ;
92 |
93 | // use myRef.current to access it
94 | ```
95 |
96 | ### hoist non-react statics
97 |
98 | The HOC does not hoist statics itself so you might append those statics manually or by using a module.
99 |
100 | Use [hoist-non-react-statics](https://github.com/mridgway/hoist-non-react-statics) yourself:
101 |
102 | ```jsx
103 | import React, { Component } from 'react';
104 | import { withTranslation } from 'react-i18next';
105 | import hoistStatics from 'hoist-non-react-statics';
106 |
107 | class MyComponent extends Component {
108 | static ...
109 | }
110 |
111 | export default hoistStatics(withTranslation()(MyComponent), MyComponent);
112 | ```
113 |
114 | Or simply hoist the one/two statics yourself:
115 |
116 | ```jsx
117 | import React, { Component } from 'react';
118 | import { withTranslation } from 'react-i18next';
119 | import hoistStatics from 'hoist-non-react-statics';
120 |
121 | class MyComponent extends Component {
122 | static ...
123 | }
124 |
125 | const Extended = withTranslation()(MyComponent);
126 | Extended.static = MyComponent.static;
127 |
128 | export default Extended;
129 | ```
130 |
131 | ### use TypeScript with class components
132 |
133 | To get proper type annotations while using TypeScript, import the interface `WithTranslation` and extend it with your own props interface.
134 |
135 | ```
136 | import React, { Component } from 'react';
137 | import { withTranslation, WithTranslation } from 'react-i18next';
138 |
139 | class MyComponent extends Component {
140 | render() {
141 | return
{this.props.t('My translated text')}
142 | }
143 | }
144 |
145 | interface IProps extends WithTranslation {
146 | prop: any;
147 | }
148 |
149 | interface IState {
150 | state: any;
151 | }
152 |
153 | export default withTranslation()(MyComponent);
154 | ```
155 |
--------------------------------------------------------------------------------
/legacy-v9/i18next-instance.md:
--------------------------------------------------------------------------------
1 | # i18next instance (v9)
2 |
3 | The instance is an initialized i18next instance. In the following code snippet, we add a backend to load translations from server and a language detector for detecting user language.
4 |
5 | > You can learn more about [i18next](http://i18next.com) and [plugins](https://www.i18next.com/plugins-and-utils.html#plugins) on the i18next website.
6 |
7 | {% hint style="info" %}
8 | The instance could be passed to the [I18nextProvider](i18nextprovider.md) or directly to the [translate hoc](broken-reference).
9 |
10 | The **reactI18nextModule** used below is an alternative to using the [I18nextProvider](i18nextprovider.md) and asserts that components ([render prop](broken-reference), [hoc](broken-reference)) lower in the element tree get access to the i18n instance.
11 | {% endhint %}
12 |
13 | ```javascript
14 | import i18n from 'i18next';
15 | import XHR from 'i18next-xhr-backend';
16 | import LanguageDetector from 'i18next-browser-languagedetector';
17 | import { reactI18nextModule } from 'react-i18next';
18 |
19 |
20 | i18n
21 | .use(XHR)
22 | .use(LanguageDetector)
23 | .use(reactI18nextModule) // if not using I18nextProvider
24 | .init({
25 | fallbackLng: 'en',
26 | debug: true,
27 |
28 | interpolation: {
29 | escapeValue: false, // not needed for react!!
30 | },
31 |
32 | // react i18next special options (optional)
33 | react: {
34 | wait: false,
35 | bindI18n: 'languageChanged loaded',
36 | bindStore: 'added removed',
37 | nsMode: 'default'
38 | }
39 | });
40 |
41 |
42 | export default i18n;
43 | ```
44 |
45 | All additional options for react in init options:
46 |
47 | | _**options**_ | _**default**_ | _**description**_ |
48 | | ------------- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
49 | | wait | false | assert all provided namespaces are loaded before rendering the component (can be set [globally](i18next-instance.md) too); note that rendering will not be blocked again when dynamically updating `ns` on the [render prop component](broken-reference) after initial mount |
50 | | nsMode | 'default' | _default:_ namespaces will be loaded an the first will be set as default or _fallback:_ namespaces will be used as fallbacks used in order provided |
51 | | bindI18n | 'languageChanged loaded' | which events trigger a rerender, can be set to false or string of events |
52 | | bindStore | 'added removed' | which events on store trigger a rerender, can be set to false or string of events |
53 |
54 | For more initialization options have look at the [docs](https://www.i18next.com/configuration-options.html).
55 |
--------------------------------------------------------------------------------
/legacy-v9/i18nextprovider.md:
--------------------------------------------------------------------------------
1 | # I18nextProvider (v9)
2 |
3 | The provider is responsible to pass the i18next instance passed in by props down to all the [withNamespaces](withnamespaces.md) hocs or [NamespacesConsumer](namespacesconsumer.md) render prop using react context api.
4 |
5 | ```javascript
6 | import React from 'react';
7 | import ReactDOM from 'react-dom';
8 | import { I18nextProvider } from 'react-i18next';
9 |
10 | import App from './App'; // your entry page
11 | import i18n from './i18n'; // initialized i18next instance
12 |
13 | ReactDOM.render(
14 |
15 |
16 | ,
17 | document.getElementById('app')
18 | );
19 | ```
20 |
21 | For the i18n instance have a look at the [i18next instance page](i18next-instance.md).
22 |
23 | As an alternative you can use the [reactI18nextModule](i18next-instance.md) in the i18n instance.
24 |
25 | ## The I18nextProvider props:
26 |
27 | | _**name**_ | **type (**_**default)**_ | _**description**_ |
28 | | ---------------- | ------------------------ | --------------------------------------------------------------------------------------------------------------------- |
29 | | **i18n** | object (undefined) | pass i18next instance the provider will pass it down to translation components by context |
30 | | defaultNS | string (undefined) | optionally pass down a default namespace to your translate HOC, I18n render prop (without having to specify it there) |
31 | | initialI18nStore | object (undefined) | pass in initial translations (useful for [serverside rendering](serverside-rendering.md)) |
32 | | initialLanguage | string (undefined) | pass in initial language (useful for [serverside rendering](serverside-rendering.md)) |
33 |
--------------------------------------------------------------------------------
/legacy-v9/interpolate.md:
--------------------------------------------------------------------------------
1 | # Interpolate (v9)
2 |
3 | {% hint style="danger" %}
4 | Deprecated: We highly recommend having a look at the new [trans component](trans-component.md) as it provides a better experience.
5 |
6 | This component will be remove in the next major version v9.0.0!!
7 | {% endhint %}
8 |
9 | The interpolate component enables you to interpolate react components into translation strings (eg. to use links).
10 |
11 | the key:
12 |
13 | ```javascript
14 | {
15 | "interpolateSample": "you can interpolate {{value}} or {{component}} via interpolate component!"
16 | }
17 | ```
18 |
19 | sample:
20 |
21 | ```javascript
22 | import React from 'react';
23 | import { translate, Interpolate } from 'react-i18next';
24 |
25 | function TranslatableView(props) {
26 | const { t } = props;
27 |
28 | let interpolateComponent = a interpolated component;
29 |
30 | return (
31 |
32 |
33 | {/*
34 | =>
35 |
36 | you can interpolate "some string" or a interpolated component via interpolate component!
37 |
38 | */}
39 |
40 | )
41 | }
42 | ```
43 |
44 | You can use [formatting](https://www.i18next.com/formatting.html) as in i18next.
45 |
46 | **props**:
47 |
48 | * i18nKey: the key to lookup
49 | * options: [options](http://i18next.com/docs/options/#t-options) to use for translation (exclude interpolation variables!)
50 | * parent: optional component to wrap translation into (default 'span')
51 | * useDangerouslySetInnerHTML: allows use of raw html tags in translation values
52 | * dangerouslySetInnerHTMLPartElement: optional component to wrap parts of translation values into (default 'span'), used with `useDangerouslySetInnerHTML={true}` only
53 | * i18n: i18next instance to use if not provided via context (using hoc or render props)
54 | * t: t function to use if not provided via context (using hoc or render props)
55 | * ...props: values to interpolate into found translation (eg. `my value with {{replaceMe}} interpolation`)
56 |
57 | ## using useDangerouslySetInnerHtml
58 |
59 | Allows having html tags inside the translation with a restriction as those get wrapped in spans. You can't have a interpolation value inside a html tag.
60 |
61 | the key:
62 |
63 | ```javascript
64 | {
65 | "interpolateSample": "you can interpolate {{value}} or {{component}} via interpolate component!"
66 | }
67 | ```
68 |
69 | sample:
70 |
71 | ```javascript
72 | import React from 'react';
73 | import { translate, Interpolate } from 'react-i18next';
74 |
75 | function TranslatableView(props) {
76 | const { t } = props;
77 |
78 | let interpolateComponent = a interpolated component;
79 |
80 | return (
81 |
82 |
83 | {/*
84 | =>
85 |
86 | you can interpolate "some string" or a interpolated component via interpolate component!
87 |
88 | */}
89 |
90 | )
91 | }
92 | ```
93 |
94 | ## Alternatives
95 |
96 | a) Use standard interpolation of i18next and dangerously insert that:
97 |
98 | ```javascript
99 |
100 | ```
101 |
102 | b) use markdown, eg. [react-remarkable](https://github.com/acdlite/react-remarkable) and pass markdown formatted content from translations to the markdown component.
103 |
--------------------------------------------------------------------------------
/legacy-v9/namespacesconsumer.md:
--------------------------------------------------------------------------------
1 | # NamespacesConsumer (v9)
2 |
3 | {% hint style="info" %}
4 | Was introduced in v8.0.0. Not available in older versions.
5 | {% endhint %}
6 |
7 | The NamespacesConsumer is a so called render prop. The component passes the [**t** function](https://www.i18next.com/overview/api#t) to child function and triggers loading the translation files defined. Further it asserts the component gets rerendered on language change or on changes to the translations themselves.
8 |
9 | {% hint style="info" %}
10 | To learn more about using the **t** function have a look at i18next documentation:
11 |
12 | * [essentials](https://www.i18next.com/translation-function/essentials)
13 | * [interpolation](https://www.i18next.com/translation-function/interpolation)
14 | * [formatting](https://www.i18next.com/translation-function/formatting)
15 | * [plurals](https://www.i18next.com/translation-function/plurals)
16 | * ...
17 | {% endhint %}
18 |
19 | ## Sample usage
20 |
21 | ```javascript
22 | import React from 'react';
23 | import { NamespacesConsumer } from 'react-i18next';
24 |
25 | function TranslatableView() {
26 | return (
27 |
31 | {
32 | (t, { i18n, ready }) => (
33 |
34 |
{t('keyFromDefault')}
35 |
{t('anotherNamespace:key.from.another.namespace', { /* options t options */ })}
assert all provided namespaces are loaded before rendering the component (can be set globally too).
Note that rendering will not be blocked again when dynamically updating the ns prop after initial mount.
In most cases you like to set this to true. If not handling not ready by evaluating ready.
|
49 | | nsMode | string ('default') |
default: namespaces will be loaded and the first will be set as default
fallback: namespaces will be used as fallbacks used in order provided
|
50 | | bindI18n | string ('languageChanged loaded') | which events trigger a rerender, can be set to false or string of events |
51 | | bindStore | string ('added removed') | which events on store trigger a rerender, can be set to false or string of events |
52 | | omitBoundRerenders | boolean (true) | Does not trigger rerenders while state not ready - avoiding unneeded renders on init |
53 | | i18n | object (undefined) | pass i18next via options (useful for [next.js usage](https://github.com/i18next/react-i18next/tree/v9.x.x/example/nextjs)) |
54 | | initialI18nStore | object (undefined) | pass in initial translations (useful for [next.js usage](https://github.com/i18next/react-i18next/tree/v9.x.x/example/nextjs/pages/index.js#L29)) |
55 | | initialLanguage | string (undefined) | pass in initial language (useful for [next.js usage](https://github.com/i18next/react-i18next/tree/v9.x.x/example/nextjs/pages/index.js)) |
56 |
--------------------------------------------------------------------------------
/legacy-v9/overview.md:
--------------------------------------------------------------------------------
1 | # Overview (v9)
2 |
3 | react-i18next depends on i18next to provide the localization features. So there are two main things flowing through your render tree:
4 |
5 | 1. The [i18next instance](i18next-instance.md) (short **i18n**)
6 | 2. The [translation function](https://www.i18next.com/overview/api#t) (short **t**)
7 |
8 | {% hint style="info" %}
9 | While we primary rely on react context to pass down **i18n** and **t** the components are built to also accept those via props, options or in case of i18n via internal context / reactI18nextModule.
10 | {% endhint %}
11 |
12 | ## Components
13 |
14 | | Component | Props | Provides | Consumes |
15 | | ----------------------------------------------------------------------------------------------------------- | ------------------- | ------------------- | --------------- |
16 | | [I18nextProvider](i18nextprovider.md) | **i18n,** defaultNS | **i18n,** defaultNs | |
17 | | [NamespacesConsumer](namespacesconsumer.md) is a render prop | | **t**, i18n | i18n |
18 | | [withNamespaces](withnamespaces.md) hoc | | **t**, i18n | i18n |
19 | | [Trans Component](trans-component.md) is used to translate JSX nodes where just using **t** is insufficient | | | **t**, **i18n** |
20 |
21 | This means your tree will look something like this _(assuming you use the options I18nextProvider):_
22 |
23 | {% hint style="info" %}
24 | **I18nextProvider** --> **NamespacesConsumer** or **withNamespaces HOC** --> **Trans** or using **t** in your component
25 | {% endhint %}
26 |
27 | ```javascript
28 | import { I18nextProvider, NamespacesConsumer, Trans, withNamespaces } from 'react-i18next';
29 | import i18n from `./i18n`; // the initialized i18next instance
30 |
31 | export default function App () {
32 | return (
33 |
34 |
35 | {
36 | t =>
{t('key')}
37 | }
38 |
39 |
40 |
41 | )
42 | }
43 |
44 | function MyComponent({ t }) {
45 | return (
46 |
47 | Hello {{name}}, you have {{count}} unread message. Go to messages.
48 |
49 | )
50 | }
51 |
52 | const MyComponentWithHoc = withNamespaces()(MyComponent);
53 | ```
54 |
55 | ## Getting the t function
56 |
57 | To get the **t** function (providing the translation functionality) down to your component you have two options:
58 |
59 | 1. Using the [withNamespaces](withnamespaces.md) hoc
60 | 2. Using the [NamespacesConsumer](namespacesconsumer.md) render prop
61 |
62 | ## Getting the i18n function into the flow
63 |
64 | You have the following options to pass the [i18next instance](i18next-instance.md) to the hoc, render prop and Trans component:
65 |
66 | ### Use the [provider](i18nextprovider.md)
67 |
68 | ```javascript
69 | import React from 'react';
70 | import ReactDOM from 'react-dom';
71 | import { I18nextProvider } from 'react-i18next';
72 |
73 | import App from './App'; // your entry page
74 | import i18n from './i18n'; // initialized i18next instance
75 |
76 | ReactDOM.render(
77 |
78 |
79 | ,
80 | document.getElementById('app')
81 | );
82 | ```
83 |
84 | ### Use the reactI18nextModule
85 |
86 | ```javascript
87 | import i18n from 'i18next';
88 | import { reactI18nextModule } from 'react-i18next';
89 |
90 |
91 | i18n
92 | .use(reactI18nextModule) // if not using I18nextProvider
93 | .init({ /* options */ });
94 |
95 | export default i18n;
96 | ```
97 |
--------------------------------------------------------------------------------
/legacy-v9/serverside-rendering.md:
--------------------------------------------------------------------------------
1 | # SSR (v9)
2 |
3 | ## Using next.js?
4 |
5 | You should have a look at [next-i18next](https://github.com/isaachinman/next-i18next) which extends react-i18next to bring it to next.js the easiest way.
6 |
7 | ## Samples
8 |
9 | To learn more you should have a look at our samples:
10 |
11 | * [razzle (sample provided by react-i18next)](https://github.com/i18next/react-i18next/tree/v9.x.x/example/razzle-ssr)
12 | * [simpleblack's boilerplate](https://github.com/simpleblack/react-redux-universal-hot-example)
13 |
14 | {% hint style="info" %}
15 | The usage of the `reactI18nextModule` for holding the i18n instance is not a valid option (the instance would be set globally). Always use the I18nextProvider like done in the samples above.
16 | {% endhint %}
17 |
18 | For further information see this [issue](https://github.com/i18next/react-i18next/issues/375).
19 |
20 | ## Pass language and translations down to client
21 |
22 | Both the [i18nextProvider](i18nextprovider.md) and [translate hoc](serverside-rendering.md) allow to pass in `initialI18nStore` and `initialLanguage`. By doing so the translations won't be loaded and initial clientside render will avoid any flickering or rerender by checksum mismatch.
23 |
24 | For details check the docs of those components or **have a look at the examples above**.
25 |
26 | ## loadNamespaces helper
27 |
28 | **loadNamespaces**: Function that will pre-load all namespaces used by your components. Works well with `react-router` `match` function
29 |
30 | **props**:
31 |
32 | * components: Components that need to have namespaces loaded.
33 | * i18n: the i18n instance to load translations into
34 |
35 | ```javascript
36 | import { I18nextProvider, loadNamespaces } from 'react-i18next';
37 | import { match } from 'react-router';
38 |
39 | match({...matchArguments}, (error, redirectLocation, renderProps) => {
40 | loadNamespaces({ ...renderProps, i18n: i18nInstance })
41 | .then(()=>{
42 | // All i18n namespaces required to render this route are loaded
43 | })
44 | });
45 | ```
46 |
47 | ## use the i18next-express-middleware
48 |
49 | When using [i18next-express-middleware](https://github.com/i18next/i18next-express-middleware), you can use `req.i18n` as the `i18next` instance for `I18nextProvider` it will assert no request conflicts happen (each request gets it's cloned instance of i18next):
50 |
51 | ```javascript
52 | import { I18nextProvider } from 'react-i18next';
53 | import i18n from './i18next'; // your own initialized i18next instance
54 | import App from './app';
55 |
56 | app.use((req, res) => {
57 | const component = (
58 |
59 |
60 |
61 | );
62 |
63 | // render as desired now ...
64 | });
65 | ```
66 |
--------------------------------------------------------------------------------
/legacy-v9/step-by-step-guide.md:
--------------------------------------------------------------------------------
1 | # Step by step guide (v9)
2 |
3 | {% hint style="warning" %}
4 | This guide is based on an older react-i18next version! Please have a look at [this detailed guide](https://locize.com/blog/react-i18next/) for a newer version.
5 | {% endhint %}
6 |
7 | Let's start with the sample created in the [quick start guide](../guides/quick-start.md) and extend it to be of more use.
8 |
9 | {% hint style="info" %}
10 | react-i18next will run in any environment without you having to do changes to your babel or webpack setup.
11 | {% endhint %}
12 |
13 | ## Initial situation based on quick start
14 |
15 | We have installed the needed i18n packages react-i18next and i18next:
16 |
17 | ```bash
18 | npm install react-i18next@legacy i18next --save
19 | ```
20 |
21 | Added following files:
22 |
23 | **translation.json** (/public/locales/en/translation.json)
24 |
25 | ```javascript
26 | {
27 | "Welcome to React": "Welcome to React and react-i18next"
28 | }
29 | ```
30 |
31 | **i18n.js** (/src/i18n.js)
32 |
33 | ```javascript
34 | import i18n from "i18next";
35 | import { reactI18nextModule } from "react-i18next";
36 |
37 | import translationEN from '../public/locales/en/translation.json';
38 |
39 | // the translations
40 | const resources = {
41 | en: {
42 | translation: translationEN
43 | }
44 | };
45 |
46 | i18n
47 | .use(reactI18nextModule) // passes i18n down to react-i18next
48 | .init({
49 | resources,
50 | lng: "en",
51 |
52 | keySeparator: false, // we do not use keys in form messages.welcome
53 |
54 | interpolation: {
55 | escapeValue: false // react already safes from xss
56 | }
57 | });
58 |
59 | export default i18n;
60 | ```
61 |
62 | Make sure to import `i18n.js` in **index.js**:
63 |
64 | ```javascript
65 | import React, { Component } from "react";
66 | import ReactDOM from "react-dom";
67 | import './i18n';
68 | import App from './App';
69 |
70 | // append app to dom
71 | ReactDOM.render(
72 | ,
73 | document.getElementById("root")
74 | );
75 | ```
76 |
77 | Have **App.js** using the `t` function for translation:
78 |
79 | ```jsx
80 | import React from 'react';
81 |
82 | // the hoc
83 | import { withNamespaces } from 'react-i18next';
84 |
85 | function App ({ t }) {
86 | return
{t('Welcome to React')}
87 | }
88 |
89 | export default withNamespaces()(App);
90 | ```
91 |
92 | ## 1) Adding more languages
93 |
94 | ### a) Add an additional language file
95 |
96 | **translation.json** (/public/locales/**de**/translation.json)
97 |
98 | ```javascript
99 | {
100 | "Welcome to React": "Willkommen bei react und react-i18next"
101 | }
102 | ```
103 |
104 | ### b) Add the additional translations on init
105 |
106 | in i18n.js:
107 |
108 | ```javascript
109 | // ...
110 | import translationEN from '../public/locales/en/translation.json';
111 | import translationDE from '../public/locales/de/translation.json';
112 |
113 | // the translations
114 | const resources = {
115 | en: {
116 | translation: translationEN
117 | },
118 | de: {
119 | translation: translationDE
120 | }
121 | };
122 |
123 | // ...
124 | ```
125 |
126 | ### c) Auto detect the user language
127 |
128 | As the language is set on `i18n.init` you either could create some custom code setting the needed language or just use one of the provided language detectors coming with i18next.
129 |
130 | For browser usage there is the [i18next-browser-languageDetector](https://github.com/i18next/i18next-browser-languageDetector) which detects language based on:
131 |
132 | * cookie
133 | * localStorage
134 | * navigator
135 | * querystring (append `?lng=LANGUAGE` to URL)
136 | * htmlTag
137 | * path
138 | * subdomain
139 |
140 | ```bash
141 | npm install i18next-browser-languagedetector --save
142 | ```
143 |
144 | Using it before i18n.init is all needed to get this to work:
145 |
146 | ```javascript
147 | import i18n from "i18next";
148 | import detector from "i18next-browser-languagedetector";
149 | import { reactI18nextModule } from "react-i18next";
150 |
151 | import translationEN from '../public/locales/en/translation.json';
152 | import translationDE from '../public/locales/de/translation.json';
153 |
154 | // the translations
155 | const resources = {
156 | en: {
157 | translation: translationEN
158 | },
159 | de: {
160 | translation: translationDE
161 | }
162 | };
163 |
164 | i18n
165 | .use(detector)
166 | .use(reactI18nextModule) // passes i18n down to react-i18next
167 | .init({
168 | resources,
169 | fallbackLng: "en", // use en if detected lng is not available
170 |
171 | keySeparator: false, // we do not use keys in form messages.welcome
172 |
173 | interpolation: {
174 | escapeValue: false // react already safes from xss
175 | }
176 | });
177 |
178 | export default i18n;
179 | ```
180 |
181 | Now we already are able to set language based on the browsers set language or by appending `?lng=LANGUAGE` to the URL.
182 |
183 | ### d) Let the user toggle the language
184 |
185 | Call [i18n.changeLanguage](https://www.i18next.com/overview/api#changelanguage) is all needed to do.
186 |
187 | ```jsx
188 | import React from 'react';
189 | import i18n from './i18n';
190 | import { withNamespaces } from 'react-i18next';
191 |
192 | function App ({ t }) {
193 | const changeLanguage = (lng) => {
194 | i18n.changeLanguage(lng);
195 | }
196 |
197 | return (
198 |
199 |
200 |
201 |
{t('Welcome to React')}
202 |
203 | )
204 | }
205 |
206 | export default withNamespaces()(App);
207 | ```
208 |
209 | {% hint style="info" %}
210 | It's essential to have at least your outer page level / container component wrapped with the [withNamespaces](withnamespaces.md) or [NamespacesConsumer](namespacesconsumer.md) as those are bound to the [languageChanged event](https://www.i18next.com/overview/api#onlanguagechanged) and trigger a needed rerender.
211 | {% endhint %}
212 |
213 | ## 2) Lazy loading translations
214 |
215 | We haven't yet started splitting translations into multiple files (which is highly recommended for larger projects) but we already see that adding more languages would result in bundling unneeded translations into the application.
216 |
217 | > Why not just use dynamic imports to load the language needed?
218 |
219 | This for sure works but comes with one drawback. If you have a change in your translations you will need to rebuild your application and deploy that.
220 |
221 | This might not be a problem when starting but at some point you will learn localization is a complete different beast than just adding i18n to your code. You will keep translations as separated from your code as you can - so developers and translators can work as independent as possible.
222 |
223 | ### a) Adding lazy loading for translations
224 |
225 | This will be simpler than you think. All needed to be done is adding another package called [i18next-http-backend](https://github.com/i18next/i18next-http-backend) and using that.
226 |
227 | ```bash
228 | npm install i18next-http-backend --save
229 | ```
230 |
231 | **i18n.js**
232 |
233 | ```javascript
234 | import i18n from "i18next";
235 | import detector from "i18next-browser-languagedetector";
236 | import backend from "i18next-http-backend";
237 | import { reactI18nextModule } from "react-i18next";
238 |
239 | // translations are already at
240 | // '../public/locales/en/translation.json'
241 | // which is the default for the xhr backend to load from
242 |
243 | i18n
244 | .use(detector)
245 | .use(backend)
246 | .use(reactI18nextModule) // passes i18n down to react-i18next
247 | .init({
248 | fallbackLng: "en", // use en if detected lng is not available
249 |
250 | keySeparator: false, // we do not use keys in form messages.welcome
251 |
252 | interpolation: {
253 | escapeValue: false // react already safes from xss
254 | }
255 | });
256 |
257 | export default i18n;
258 | ```
259 |
260 | {% hint style="info" %}
261 | i18next implementation is smart enough to only load needed languages and comes with intelligent deduplications so even multiple load requests for files in different code locations result in one request while notifying all needed requester.
262 | {% endhint %}
263 |
264 | ### b) Loading multiple translation files
265 |
266 | Lets assume your project started to grow and you like to split translations into multiple files.
267 |
268 | Without configuration i18next will always load one file (namespace) named `translation`. Learn more about namespaces [here](https://www.i18next.com/principles/namespaces).
269 |
270 | You can load them on i18n.init or in code like:
271 |
272 | ```javascript
273 | i18n.init({
274 | ns: ['common', 'moduleA', 'moduleB'],
275 | defaultNS: 'moduleA'
276 | }, (err, t) => {
277 | i18n.t('myKey'); // key in moduleA namespace (defined default)
278 | i18n.t('common:myKey'); // key in common namespace
279 | });
280 |
281 | // load additional namespaces after initialization
282 | i18n.loadNamespaces('anotherNamespace', (err, t) => { /* ... */ });
283 | ```
284 |
285 | But that will load all upfront or in some custom code where you would need to handle manually that the translations were loaded. So there is a better way.
286 |
287 | #### Use the withNamespaces hoc
288 |
289 | As you might guess the withNamespaces hocs role is to lazy load the needed namespaces.
290 |
291 | **page2.json Add more translation files:** (/public/locales/en/page2.json)
292 |
293 | ```javascript
294 | {
295 | "Welcome on page2": "Welcome on page2"
296 | }
297 | ```
298 |
299 | **Page2.js** (/src/Page2.js)
300 |
301 | ```jsx
302 | import React from 'react';
303 |
304 | // the hoc
305 | import { withNamespaces } from 'react-i18next';
306 |
307 | function Page2 ({ t }) {
308 | return
{t('Welcome on page2')}
309 | }
310 |
311 | export default withNamespaces('page2')(Page2);
312 | ```
313 |
314 | ### c) Handle rendering while translations are not yet loaded
315 |
316 | In the above `Page2` you will notice the initial render will trigger the load for `page2.json` but also render the page without the translations ready. There will be a rerender when the translations where loaded resulting in the page flickering.
317 |
318 | #### Using the prop tReady
319 |
320 | tReady will be set to true when translations are loaded so you can eg. suspend rendering and show a Spinner or another placeholder:
321 |
322 | ```jsx
323 | import React from 'react';
324 |
325 | // the hoc
326 | import { withNamespaces } from 'react-i18next';
327 |
328 | function Page2 ({ t, tReady }) {
329 | // just to add some more here we load an additional namespace
330 | // common for "common" used texts and use that namespace
331 | // be prefixing it in front of the key "common:"
332 | if (!tReady) return
{t('common:loading')}
333 |
334 | return
{t('Welcome on page2')}
335 | }
336 |
337 | export default withNamespaces(['page2', 'common'])(Page2);
338 | ```
339 |
340 | #### Set the global wait option
341 |
342 | You can configure the withNamespaces / NamespacesConsumer to not render the content until needed namespaces are loaded.
343 |
344 | **i18n.js:**
345 |
346 | ```javascript
347 | import i18n from "i18next";
348 | import detector from "i18next-browser-languagedetector";
349 | import backend from "i18next-http-backend";
350 | import { reactI18nextModule } from "react-i18next";
351 |
352 | i18n
353 | .use(detector)
354 | .use(backend)
355 | .use(reactI18nextModule) // passes i18n down to react-i18next
356 | .init({
357 | fallbackLng: "en", // use en if detected lng is not available
358 |
359 | keySeparator: false, // we do not use keys in form messages.welcome
360 |
361 | interpolation: {
362 | escapeValue: false // react already safes from xss
363 | },
364 |
365 | // react-i18next options
366 | react: {
367 | wait: true
368 | }
369 | });
370 |
371 | export default i18n;
372 | ```
373 |
374 | Now `Page2` will be blank until the needed translation files were loaded.
375 |
376 | {% hint style="info" %}
377 | You can set the wait option either globally for all instances or individually like:
378 |
379 | `withNamepaces('page2', { wait: true })(Page2);`
380 | {% endhint %}
381 |
382 | ## 3) Sidequest: natural vs. keybased catalog
383 |
384 | ### a) natural keys
385 |
386 | Until now we had organised translation and keys in natural language.
387 |
388 | ```jsx
389 |
{t('Welcome on page2')}
390 | ```
391 |
392 | Having translation files like:
393 |
394 | ```javascript
395 | {
396 | "Welcome on page2": "Welcome on page2"
397 | }
398 | ```
399 |
400 | This was possible by setting `keySeparator: false` on `i18n.init`
401 |
402 | The upside of this the code can be more readable but the content of the key might get soon rather different from the value it reflects. You could even go a step further by disabling any fallback language and [using the key as fallback](https://www.i18next.com/principles/fallback#key-fallback) - but be aware if you have a typo in the key acting as fallback value you will need to change it.
403 |
404 | ### b) keybased catalog
405 |
406 | Some i18n frameworks organise having more technical keys allowing those to be even structured into hierarchies. This is the default in i18next too - so removing `keySeparator: false` on `i18n.init` would enable having catalogs and `t` usage like:
407 |
408 | ```javascript
409 | {
410 | "titles": {
411 | "page2": "Welcome on page2"
412 | }
413 | }
414 | ```
415 |
416 | accessed like:
417 |
418 | ```jsx
419 |
{t('titles.page2')}
420 | ```
421 |
422 | If you prefer natural or keybased is a matter of taste...both can be used with react-i18next. Just avoid mixing those styles.
423 |
424 | ## 4) HOCs are dead - long lives the render props
425 |
426 | We won't open a debate over which is better as in our opinion both have their use case and there is no reason to just use one of the two options.
427 |
428 | So you already saw before that you can use the [withNamespaces](withnamespaces.md) to decorate your component to pass the `t` function down.
429 |
430 | The same works with [a render prop](namespacesconsumer.md):
431 |
432 | ```jsx
433 | import React from 'react';
434 |
435 | // the render prop
436 | import { NamespacesConsumer } from 'react-i18next';
437 |
438 | export default function Page2 () {
439 | (
440 |
441 | {
442 | (t, { i18n, ready }) => (
443 | ready ?
444 |
{t('Welcome on page2')}
:
445 |
{t('common:loading')}
446 | )
447 | }
448 |
449 | )
450 | }
451 | ```
452 |
453 | ## 5) Translate JSX nodes as one string
454 |
455 | Let's translate this:
456 |
457 | > Translating content with **formatting** or a [link](step-by-step-guide.md#5-translate-jxs-nodes-as-one-string) is a pain.
458 |
459 | For this your JSX might look like:
460 |
461 | ```jsx
462 |
463 | Translating content with
464 | formatting
465 | or a
466 | link
467 | is a pain.
468 |
469 | ```
470 |
471 | So naive approach using the `t` function would result in
472 |
473 | ```jsx
474 |
475 | { t('Translating content with ') }
476 | t('formatting')
477 | { t(' or a ') }
478 | t('link')
479 | { t(' is a pain.') }
480 |
481 | ```
482 |
483 | So you end up with 5 keys in your translation file and your translator has no idea about how these 5 keys relate to each other. Further what happens in other languages where the order needs to be changed?!?
484 |
485 | So you won't have luck with this approach.
486 |
487 | ### Using the Trans component
488 |
489 | The [Trans component](trans-component.md) enables you to keep this as one sentence by replacing the JSX nodes with indexed pseudo tags.
490 |
491 | ```jsx
492 | import { Trans } from 'react-i18next';
493 |
494 | // ...
495 |
496 |
497 |
498 | Translating content with
499 | formatting
500 | or a
501 | link
502 | is a pain.
503 |
504 |
505 | ```
506 |
507 | Resulting in JSON:
508 |
509 | ```javascript
510 | {
511 | "Translating content with <1>formatting1> or a <3>link3> is a pain.":
512 | "Translating content with <1>formatting1> or a <3>link3> is a pain."
513 | }
514 | ```
515 |
516 | The `<1>`, `<3>` pseudo tags are based on the index of appearance in `nodes.children`:
517 |
518 | ```jsx
519 |
520 | Translating content with // index 0
521 | formatting // index 1
522 | or a // index 2
523 | link // index 3
524 | is a pain. // index 4
525 |
526 | ```
527 |
528 | The Trans component also supports interpolation and plurals just read the [full documentation](trans-component.md) of that component.
529 |
--------------------------------------------------------------------------------
/legacy-v9/trans-component.md:
--------------------------------------------------------------------------------
1 | # Trans Component (v9)
2 |
3 | ## Important note
4 |
5 | While the Trans components gives you a lot of power by letting you interpolate or translate complexer react elements.
6 |
7 | The truth is - In most cases you won't need it. **As long you have no react nodes you like to be integrated into a translated text** (text formatting, like `strong`, `i`, ...) **or adding some link component - you won't need it.**
8 |
9 | All can be done by using the `t` function you get by the [translate hoc](trans-component.md) or [I18n render prop](trans-component.md).
10 |
11 | {% hint style="info" %}
12 | Using the **t** function have a look at i18next documentation:
13 |
14 | * [essentials](https://www.i18next.com/translation-function/essentials)
15 | * [interpolation](https://www.i18next.com/translation-function/interpolation)
16 | * [formatting](https://www.i18next.com/translation-function/formatting)
17 | * [plurals](https://www.i18next.com/translation-function/plurals)
18 | * ...
19 | {% endhint %}
20 |
21 | ## Sample
22 |
23 | So you learned there is no need to use the Trans component everywhere (the plain t function will just do fine in most cases).
24 |
25 | This component enables you to nest any react content to be translated as one string. Supports both plural and interpolation.
26 |
27 | _Let's say you want to create following html output:_
28 |
29 | > Hello **Arthur**, you have 42 unread messages. [Go to messages](trans-component.md).
30 |
31 | **Before:** Your react code would have looked something like:
32 |
33 | ```javascript
34 |
35 | Hello {name}, you have {count} unread message(s). Go to messages.
36 |
37 | ```
38 |
39 | **After:** With the trans component just change it to:
40 |
41 | ```javascript
42 |
43 | Hello {{name}}, you have {{count}} unread message. Go to messages.
44 |
45 | ```
46 |
47 | _Your en.json (translation strings) will look like:_
48 |
49 | ```javascript
50 | "userMessagesUnread": "Hello <1>{{name}}1>, you have {{count}} unread message. <5>Go to message5>.",
51 | "userMessagesUnread_plural": "Hello <1>{{name}}1>, you have {{count}} unread messages. <5>Go to messages5>.",
52 | ```
53 |
54 | {% hint style="info" %}
55 | [**saveMissing**](https://www.i18next.com/overview/configuration-options#missing-keys) will send a valid defaultValue
56 | {% endhint %}
57 |
58 | ### Alternative usage
59 |
60 | Depending on using [ICU as translation format](https://github.com/i18next/i18next-icu) it is not possible to have the needed syntax as children (invalid jsx). You can alternatively use the component like:
61 |
62 | ```javascript
63 | univers]}
67 | />
68 | ```
69 |
70 | ## How to get the correct translation string?
71 |
72 | Guessing replacement tags _(<0>\0>)_ of your component right is rather difficult. There are two options to get those translations directly generated by i18next.
73 |
74 | 1. use `debug = true` in i18next init call and watch your console for the missing key output
75 | 2. use the [saveMissing feature](https://www.i18next.com/configuration-options#missing-keys) of i18next to get those translations pushed to your backend or handled by a custom missing key handler.
76 | 3. understand how those numbers get generated from child index:
77 |
78 | **jsx:**
79 |
80 | ```javascript
81 |
82 | Hello {{name}}, you have {{count}} unread message. Go to messages.
83 |
84 | ```
85 |
86 | **results in string:**
87 |
88 | ```
89 | "Hello <1>{{name}}1>, you have {{count}} unread message. <5>Go to message5>."
90 | ```
91 |
92 | **based on** the node tree**:**
93 |
94 | ```javascript
95 | Trans.children = [
96 | 'Hello ', // index 0: only a string
97 | { children: [{ name: 'Jan' }] }, // index 1: element strong -> child object for interpolation
98 | ', you have', // index 2: only a string
99 | { count: 10 }, // index 3: just object for interpolation
100 | ' unread messages. ', // index 4
101 | { children: [ 'Go to messages' ] }, // index 5: element link -> child just a string
102 | '.'
103 | ]
104 | ```
105 |
106 | {% hint style="info" %}
107 | **Rules:**
108 |
109 | * child is a string => nothing to wrap just take the string
110 | * child is an object => nothing to do it's used for interpolation
111 | * child is an element: wrap it's children in \\ where i is the index of that element position in children and handle it's children with same rules (starting element.children index at 0 again)
112 | {% endhint %}
113 |
114 | ## Trans props
115 |
116 | | _**name**_ | _**type (default)**_ | _**description**_ |
117 | | ---------- | ------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
118 | | i18nKey | string (undefined) | is optional if you prefer to use text as keys you can omit that and the translation will be used as a key. |
119 | | count | integer (undefined) | optional count if you use a plural |
120 | | parent | node (undefined) | a component to wrap the content into (default none, can be globally set on i18next.init) -> needed for **react < v16** |
121 | | i18n | object (undefined) | i18next instance to use if not provided via context (using hoc or render props) |
122 | | t | function (undefined) | t function to use if not provided via context (using hoc or render props) |
123 | | defaults | string (undefined) | use this instead of default content in children (useful when using ICU) |
124 | | values | object (undefined) | interpolation values if not provided in children |
125 | | components | array\[nodes] (undefined) | components to interpolate based on index of tag <0>\0>, ... |
126 |
127 | ## Additional options on i18next.init
128 |
129 | ```javascript
130 | i18next.init({
131 | // ...
132 | react: {
133 | // ...
134 | hashTransKey: function(defaultValue) {
135 | // return a key based on defaultValue or if you prefer to just remind you should set a key return false and throw an error
136 | },
137 | defaultTransParent: 'div' // a valid react element - required before react 16
138 | }
139 | });
140 | ```
141 |
142 | {% hint style="warning" %}
143 | Please be aware if you are using **React 15 or below**, you need to set the `defaultTransParent` or `parent` in props.
144 | {% endhint %}
145 |
--------------------------------------------------------------------------------
/legacy-v9/withi18n.md:
--------------------------------------------------------------------------------
1 | # withI18n (v9)
2 |
3 | {% hint style="info" %}
4 | Was introduced in v8.0.0. Not available in older versions.
5 | {% endhint %}
6 |
7 | `withI18n` is a basic higher order component which passes mainly the `t` function down to the wrapped component.
8 |
9 | ```jsx
10 | import React, { Component } from "react";
11 | import { withI18n } from "react-i18next";
12 |
13 | class MyComponent extends Component {
14 | render() {
15 | const { t } = this.props;
16 |
17 | return
{t('Welcome to React')}
;
18 | }
19 | }
20 | export default withI18n()(MyComponent);
21 | ```
22 |
23 | {% hint style="danger" %}
24 | This component won't trigger a rerender on language change. The passed down `t` function will be the same as calling `i18n.t` directly and not be bound to a specific namespace or even trigger a load of a namespace.
25 |
26 | If you do **not pass in translations** on `i18n.init` we highly encourage using the [withNamespaces](withnamespaces.md) hoc.
27 | {% endhint %}
28 |
--------------------------------------------------------------------------------
/legacy-v9/withnamespaces.md:
--------------------------------------------------------------------------------
1 | # withNamespaces (v9)
2 |
3 | {% hint style="info" %}
4 | Was introduced in v8.0.0. Not available in older versions.
5 | {% endhint %}
6 |
7 | The withNamespaces [hoc](https://reactjs.org/docs/higher-order-components.html) is responsible for passing the [**t** function](https://www.i18next.com/overview/api#t) to your component. It enables all the translation functionality provided by i18next. Further, it asserts your component gets re-rendered on language change or changes to the translation catalog itself (loaded translations).
8 |
9 | ```javascript
10 | withNamespaces(namespaces, options)(MyComponent);
11 | ```
12 |
13 | {% hint style="info" %}
14 | To learn more about using the **t** function have a look at i18next documentation:
15 |
16 | * [essentials](https://www.i18next.com/essentials.html)
17 | * [interpolation](https://www.i18next.com/interpolation.html)
18 | * [formatting](https://www.i18next.com/formatting.html)
19 | * [plurals](https://www.i18next.com/plurals.html)
20 | * ...
21 | {% endhint %}
22 |
23 | ## Sample
24 |
25 | ```javascript
26 | import React from 'react';
27 | import { withNamespaces } from 'react-i18next';
28 |
29 | function TranslatableView(props) {
30 | const { t, tReady } = props;
31 | // tReady is true if translations were loaded.
32 | // Use wait option to not render before loaded
33 | // or render placeholder yourself if not tReady=false
34 |
35 | return (
36 |
37 |
{t('keyFromDefault')}
38 |
{t('anotherNamespace:key.from.another.namespace', { /* options t options */ })}
39 |
40 | )
41 | }
42 |
43 | export default withNamespaces([
44 | 'defaultNamespace',
45 | 'anotherNamespace'
46 | ], { /* additional options see below */ })(TranslatableView);
47 |
48 | // or: short for only loading one namespace:
49 | export default withNamespaces('defaultNamespace')(TranslatableView);
50 |
51 | // or: short for using defaultNS defined in i18next
52 | export default withNamespaces()(TranslatableView);
53 |
54 | // or: using a function to return namespaces based on props
55 | export default withNamespaces((props) => props.namespaces)(TranslatableView);
56 | ```
57 |
58 | If not using the [reactI18nextModule](i18next-instance.md) this hoc should be nested inside a [I18nextProvider](i18nextprovider.md). Alternatively you can pass the i18next instance via prop `i18n`.
59 |
60 | ## Using with TypeScript
61 |
62 | To help you using TypeScript and the @withNamespaces decorator here is a trival example:
63 |
64 | ```jsx
65 | import * as React from 'react';
66 | import { withNamespaces, WithNamespaces } from 'react-i18next';
67 |
68 | class MyComponent extends React.PureComponent {
69 | public render() {
70 | const { t } = this.props;
71 | return (
72 |
73 | {t('my-component-content')}
74 |
75 | );
76 | }
77 | }
78 | export default withNamespaces()(MyComponent);
79 | ```
80 |
81 |
82 |
83 | ## Set defaults for all used withNamespaces
84 |
85 | Most time you like to change those values for every component.
86 |
87 | Set those on i18next init:
88 |
89 | ```javascript
90 | i18n.init({
91 | // ... other options
92 | react: {
93 | wait: false,
94 | withRef: false,
95 | bindI18n: 'languageChanged loaded',
96 | bindStore: 'added removed',
97 | nsMode: 'default'
98 | }
99 | });
100 | ```
101 |
102 | ## withNamespaces options:
103 |
104 | ```javascript
105 | export default withNamespaces(
106 | 'defaultNamespace',
107 | { wait: true } // <-- options
108 | )(TranslatableView);
109 | ```
110 |
111 | | _**option**_ | _**type (default)**_ | _**description**_ |
112 | | ------------------ | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
113 | | **wait** | boolean (false) |
assert all provided namespaces are loaded before rendering the component (can be set globally too)
In most cases you like to set this to true. If not handling not ready by evaluating tReady.
|
114 | | nsMode | string ('default') |
default: namespaces will be loaded an the first will be set as default or
fallback: namespaces will be used as fallbacks used in order provided
|
115 | | innerRef | function or object (undefined) |
either pass in a object React.createRef or a ref function like (c) => this.myRef = c;
69 | ```
70 |
71 | ### using the Trans Component
72 |
73 | As is including plain ICU syntax inside a JSX node will result in invalid JSX as the ICU format uses curly brackets that are reserved by JSX.
74 |
75 | So the default option is to use the [Trans Component](../legacy-v9/trans-component.md) just with props like:
76 |
77 | ```javascript
78 | import { Trans } from 'react-i18next';
79 |
80 | const user = 'John Doe';
81 |
82 | dummyChild]}
86 | values={{ user }}
87 | />
88 |
89 | // json
90 | "icu_and_trans": "We invited <0>{user}0>."
91 |
92 | // result
93 | We invited John Doe.
94 | ```
95 |
96 | While this works the resulting JSX is very verbose - guess we could do better.
97 |
98 | ### using babel macros (Trans, Plural, Select)
99 |
100 | {% hint style="info" %}
101 | Thanks to using [kentcdodds/babel-plugin-macros](https://github.com/kentcdodds/babel-plugin-macros) we could use some babel magic to transpile nicer looking jsx to above Trans markup.
102 |
103 | Check [https://github.com/kentcdodds/babel-plugin-macros/blob/master/other/docs/user.md](https://github.com/kentcdodds/babel-plugin-macros/blob/master/other/docs/user.md) for setting babel-plugin-macros up.
104 |
105 | Using create-react-app? Make sure you are using react-scripts v2 as it includes the macro plugin.
106 |
107 | ```
108 | $ # Create a new application
109 | $ npx create-react-app
110 | $ # Upgrade an existing application
111 | $ yarn upgrade react-scripts@2
112 | ```
113 | {% endhint %}
114 |
115 | ```javascript
116 | import { Trans } from 'react-i18next/icu.macro';
117 |
118 | const user = 'John Doe';
119 |
120 |
121 | We invited {user}.
122 |
123 | ```
124 |
125 | The macro will add the needed import for Trans Component and generate the correct Trans component for you.
126 |
127 | The correct string for translations will be shown in the browser console output as a missing string (if set debug: true on i18next init) or submitted via saveMissing (have saveMissing set true and a i18next backend supporting saving missing keys).
128 |
129 | If linting or other code analysis tools are complaining or failing because of the invalid JSX syntax, you can use the `defaults` prop instead of putting your message as a child, and it will be parsed and updated to the correct format.
130 |
131 | ```javascript
132 | import { Trans } from 'react-i18next/icu.macro';
133 |
134 | const user = 'John Doe';
135 |
136 |
140 | ```
141 |
142 | This will be converted by the macro into:
143 |
144 | ```javascript
145 | import { Trans } from 'react-i18next';
146 |
147 | const user = 'John Doe';
148 |
149 | {user}]}
154 | />
155 | ```
156 |
157 | The defaults parsing supports the `@babel/react` preset, so any expressions that require more complex parsing may not work.
158 |
159 | **More samples:**
160 |
161 | ```markup
162 | // basic interpolation
163 | Welcome, { name }!
164 |
165 | // interpolation and components
166 | Welcome, { name }!
167 |
168 |
169 | // number formatting
170 | Trainers: { trainersCount, number }
171 | Trainers: { trainersCount, number }!
172 |
173 |
174 | // date formatting
175 | Caught on { catchDate, date, short }
176 | Caught on { catchDate, date, short }!
177 |
178 |
179 | You have { unread, number } messages
180 |
181 | ```
182 |
183 | #### Tagged Template for ICU
184 |
185 | To support complex interpolations, `react-i18next` provides additional imports from the `icu.macro`. These provide a way to represent translations closer to the ICU messageformat syntax, but in a manner that is compatible with React and strictly typed in typescript.
186 |
187 | For example, to format a number:
188 |
189 | ```javascript
190 | import { Trans } from "react-i18next/icu.macro";
191 |
192 | const num = 1;
193 |
194 |
195 | Incremented {num, number} times
196 |
197 | ```
198 |
199 | the above syntax, although valid javascript, will error when using a linting tool like eslint. Instead, we can do this:
200 |
201 | ```javascript
202 | import { Trans, number } from "react-i18next/icu.macro";
203 |
204 | const num = 1;
205 |
206 |
207 | Incremented {number`${num}`} times
208 |
209 | ```
210 |
211 | This results in the translation string `Incremented {num, number} times`
212 |
213 | Supported interpolators are `number`, `date`, `time`, `select`, `plural`, and `selectOrdinal`.
214 |
215 | More complex skeletons can also be represented:
216 |
217 | ```javascript
218 | import { Trans, number } from "react-i18next/icu.macro";
219 |
220 | const awesomePercentage = 100;
221 |
222 |
223 | It's awesome {number`${awesomePercentage}, ::percent`} of the time
224 |
225 | ```
226 |
227 | This results in the translation string `It's awesome {awesomePercentage, number, ::percent} of the time`.
228 |
229 | **Complex interpolations with plural/select/selectOrdinal**
230 |
231 | The `plural` and `select` and `selectOrdinal` interpolations support more advanced syntax. For instance, it is possible to interpolate both React elements and other interpolations:
232 |
233 | ```javascript
234 | import { Trans, plural, number } from "react-i18next/icu.macro";
235 |
236 | const awesomePercentage = 100;
237 |
238 |
239 | {plural`${awesomePercentage},
240 | =0 { It's ${never} awesome }
241 | =100 { It is ${ALWAYS} awesome! }
242 | other { It's awesome {number`${awesomePercentage}, ::percent`} of the time }`}
243 |
244 | ```
245 |
246 | This will result in the translation string `{awesomePercentage, plural, =0 { It's <0>never</0> awesome } =100 { It is <1>ALWAYS</1> awesome! } =100 { It's awesome {awesomePercentage, number, ::percent} of the time }}`
247 |
248 | It possible to nest any interpolated type, including nested `plural`, `select`, or `selectOrdinal`.
249 |
250 | **Typescript support for interpolated template strings**
251 |
252 | The `number`, `plural`, and `selectOrdinal` functions will error if a non-number typed variable is interpolated.
253 |
254 | ```javascript
255 | import { Trans, number } from "react-i18next/icu.macro";
256 |
257 | // type error below - awesomePercentage must be a number
258 | const awesomePercentage = "100";
259 |
260 |
261 | It's awesome {number`${awesomePercentage}, ::percent`} of the time
262 |
263 | ```
264 |
265 | The `date` and `time` functions will error if a non-Date object is interpolated.
266 |
267 | ```javascript
268 | import { Trans, date } from "react-i18next/icu.macro";
269 |
270 | // type error below - awesomePercentage must be a number
271 | const notADate = "100";
272 |
273 |
274 | What time is it? it's {date`${notADate}`} o'clock
275 |
276 | ```
277 |
278 | Finally, the `select` function will error if a non-string is interpolated.
279 |
280 | ```javascript
281 | import { Trans, select } from "react-i18next/icu.macro";
282 |
283 | // type error below - awesomePercentage must be a number
284 | const notAString = 100;
285 |
286 |
287 | {select`${notAString} oops { you have to pass in a string } other { oh well }`}
288 |
289 | ```
290 |
291 | ### Alternative syntax for select and plural
292 |
293 | It is also possible to display `select` and `plural` and `selectOrdinal` using Elements `Select`, `Plural` and `SelectOrdinal`. All of them have full type safety in typescript.
294 |
295 | #### Select
296 |
297 | There is no way to directly add the needed ICU format inside a JSX child - so we had to add another component that gets transpiled to needed Trans component:
298 |
299 | ```javascript
300 | import { Select } from 'react-i18next/icu.macro';
301 |
302 | // simple select
303 |
310 | ```
311 |
312 | ```javascript
313 | import { Select } from 'react-i18next/icu.macro';
314 |
315 | // select with inner components
316 |