├── .gitbook
└── assets
│ ├── 2captcha.jpg
│ ├── avocode.jpg
│ ├── beelance.jpg
│ ├── dashboard.png
│ ├── deno_i18next.jpg
│ ├── dutzi.jpg
│ ├── ecosys.jpg
│ ├── fideli.jpg
│ ├── first i18next post.jpg
│ ├── first-i18next-post.jpg
│ ├── general-locize-screen.png
│ ├── i18next downloads.jpg
│ ├── i18next first website.jpg
│ ├── i18next-downloads.jpg
│ ├── i18next-ecosystem (1) (1).jpg
│ ├── i18next-ecosystem (1).jpg
│ ├── i18next-ecosystem.jpg
│ ├── i18next-first-website.jpg
│ ├── i18next-locize-ai-human.jpg
│ ├── i18next-logo.png
│ ├── i18next-vue.jpg
│ ├── i18next_eco.jpg
│ ├── image.png
│ ├── jquery-localization.jpg
│ ├── locize-teaser_small.gif
│ ├── locize.png
│ ├── locize_plurals.png
│ ├── locize_recap_big_low.gif
│ ├── logiscool.jpg
│ ├── logo_big.png
│ ├── photogram.jpg
│ ├── realadvisor.jpg
│ ├── server_side_backend.jpg
│ ├── speaker.jpg
│ ├── title (1).jpg
│ ├── title width.jpg
│ ├── title-width.jpg
│ ├── title.jpg
│ ├── title1.png
│ ├── transform your localization process small.png
│ ├── transform-your-localization-process-small.png
│ ├── translate.i18next.jpg
│ ├── video_sample.png
│ └── worldshopping.jpg
├── .gitignore
├── README.md
├── SUMMARY.md
├── _layouts
├── README.md
└── website
│ ├── README.md
│ └── summary.html
├── assets
├── favicon.ico
├── img
│ ├── dashboard.png
│ ├── frameworks.png
│ ├── i18next-frameworks.png
│ ├── locize_recap_big_low.gif
│ ├── locizify-frameworks.png
│ ├── logo.svg
│ └── logo_web.png
└── js
│ ├── README.md
│ └── custom.js
├── book.json
├── how-to
├── add-or-load-translations.md
├── backend-fallback.md
├── caching.md
├── extracting-translations.md
└── faq.md
├── load-translations.md
├── loading-translations.md
├── locales
├── README.md
├── de
│ ├── README.md
│ ├── common.json
│ └── special.json
└── en
│ ├── README.md
│ ├── common.json
│ └── special.json
├── methods.md
├── misc
├── creating-own-plugins.md
├── json-format.md
├── migration-guide.md
├── testimonials.md
└── the-history-of-i18next.md
├── overview
├── api.md
├── comparison-to-others.md
├── configuration-options.md
├── first-setup-help.md
├── for-enterprises.md
├── getting-started.md
├── plugins-and-utils.md
├── supported-frameworks.md
└── typescript.md
├── principles
├── best-practices.md
├── fallback.md
├── namespaces.md
├── plugins.md
└── translation-resolution.md
├── styles
├── README.md
└── website.css
└── translation-function
├── context.md
├── essentials.md
├── formatting.md
├── interpolation.md
├── nesting.md
├── objects-and-arrays.md
└── plurals.md
/.gitbook/assets/2captcha.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/2captcha.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/avocode.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/avocode.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/beelance.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/beelance.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/dashboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/dashboard.png
--------------------------------------------------------------------------------
/.gitbook/assets/deno_i18next.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/deno_i18next.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/dutzi.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/dutzi.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/ecosys.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/ecosys.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/fideli.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/fideli.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/first i18next post.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/first i18next post.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/first-i18next-post.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/first-i18next-post.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/general-locize-screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/general-locize-screen.png
--------------------------------------------------------------------------------
/.gitbook/assets/i18next downloads.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/i18next downloads.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/i18next first website.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/i18next first website.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/i18next-downloads.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/i18next-downloads.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/i18next-ecosystem (1) (1).jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/i18next-ecosystem (1) (1).jpg
--------------------------------------------------------------------------------
/.gitbook/assets/i18next-ecosystem (1).jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/i18next-ecosystem (1).jpg
--------------------------------------------------------------------------------
/.gitbook/assets/i18next-ecosystem.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/i18next-ecosystem.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/i18next-first-website.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/i18next-first-website.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/i18next-locize-ai-human.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/i18next-locize-ai-human.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/i18next-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/i18next-logo.png
--------------------------------------------------------------------------------
/.gitbook/assets/i18next-vue.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/i18next-vue.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/i18next_eco.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/i18next_eco.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/image.png
--------------------------------------------------------------------------------
/.gitbook/assets/jquery-localization.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/jquery-localization.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/locize-teaser_small.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/locize-teaser_small.gif
--------------------------------------------------------------------------------
/.gitbook/assets/locize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/locize.png
--------------------------------------------------------------------------------
/.gitbook/assets/locize_plurals.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/locize_plurals.png
--------------------------------------------------------------------------------
/.gitbook/assets/locize_recap_big_low.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/locize_recap_big_low.gif
--------------------------------------------------------------------------------
/.gitbook/assets/logiscool.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/logiscool.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/logo_big.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/logo_big.png
--------------------------------------------------------------------------------
/.gitbook/assets/photogram.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/photogram.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/realadvisor.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/realadvisor.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/server_side_backend.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/server_side_backend.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/speaker.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/speaker.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/title (1).jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/title (1).jpg
--------------------------------------------------------------------------------
/.gitbook/assets/title width.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/title width.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/title-width.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/title-width.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/title.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/title.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/title1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/title1.png
--------------------------------------------------------------------------------
/.gitbook/assets/transform your localization process small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/transform your localization process small.png
--------------------------------------------------------------------------------
/.gitbook/assets/transform-your-localization-process-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/transform-your-localization-process-small.png
--------------------------------------------------------------------------------
/.gitbook/assets/translate.i18next.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/translate.i18next.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/video_sample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/video_sample.png
--------------------------------------------------------------------------------
/.gitbook/assets/worldshopping.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/.gitbook/assets/worldshopping.jpg
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Node rules:
2 | ## Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
3 | .grunt
4 |
5 | ## Dependency directory
6 | ## Commenting this out is preferred by some people, see
7 | ## https://docs.npmjs.com/misc/faq#should-i-check-my-node_modules-folder-into-git
8 | node_modules
9 |
10 | # Book build output
11 | _book
12 |
13 | # eBook build output
14 | *.epub
15 | *.mobi
16 | *.pdf
17 | .DS_Store
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 |
3 | i18next is an **internationalization-framework** written in and for JavaScript. But it's much more than that!
4 |
5 | > Want to know how to easily add internationalization to your software project?\
6 | > NAN;_⇒ Check out_ [_this article_](https://www.locize.com/blog/how-to-easily-add-i18n-to-your-software)_._
7 |
8 | i18next goes beyond just providing the standard i18n features such as ([plurals](translation-function/plurals.md), [context](translation-function/context.md), [interpolation](translation-function/interpolation.md), [format](translation-function/formatting.md)). It provides you with a complete solution to localize your product from web to mobile and desktop.
9 |
10 | {% embed url="https://youtu.be/SA_9i4TtxLQ" %}
11 |
12 | ## learn once - translate everywhere
13 |
14 | 
15 |
16 | The i18next-community created integrations for frontend-frameworks such as [React](https://locize.com/blog/react-i18next/), [Angular](https://locize.com/blog/unleash-the-full-power-of-angular-i18next/), [Vue.js](https://locize.com/blog/i18next-vue/) and many more.
17 |
18 | But this is not where it ends. You can also use i18next with [Node.js](https://locize.com/blog/how-does-server-side-internationalization-look-like/), [Deno](https://locize.com/blog/i18n-for-deno-with-i18next/), PHP, iOS, Android and [other platforms](overview/supported-frameworks.md).
19 |
20 | {% hint style="info" %}
21 | **Your software is using i18next? -** _Spread the word and let the world know!_
22 |
23 | make a tweet... write it on your website... create a blog post... etc...
24 |
25 | \
26 | \
27 | NAN;_Are you working on an open source project and are looking for a way to manage your translations? -_ [_locize_](https://locize.com) _loves the open-source philosophy and may be able to support you._
28 | {% endhint %}
29 |
30 | [Learn more about supported frameworks](overview/supported-frameworks.md)
31 |
32 | {% hint style="success" %}
33 | Check out [this video](https://youtu.be/37rcHVcQ6t0) and the corresponding [blog post](https://www.locize.com/blog/how-to-easily-add-i18n-to-your-software) about "Vite + React + TypeScript" with i18next.
34 |
35 | [](https://youtu.be/37rcHVcQ6t0)
36 | {% endhint %}
37 |
38 | {% hint style="success" %}
39 | [Here](https://locize.com/blog/react-i18next/) you'll find a simple tutorial on how to best use [react-i18next](https://react.i18next.com/).\
40 | Some basics of i18next and some cool possibilities on how to optimize your localization workflow.[\
41 | ](https://locize.com/blog/react-i18next/)
42 | {% endhint %}
43 |
44 | {% hint style="success" %}
45 | Do you want to use i18next in [Vue.js](https://github.com/locize/locize-i18next-vue-example)? Check out [this tutorial blog post](https://locize.com/blog/i18next-vue/).
46 |
47 | [](https://locize.com/blog/i18next-vue/)
48 | {% endhint %}
49 |
50 | {% hint style="success" %}
51 | Did you know internationalization is also important on your app's backend? In [this tutorial blog post](https://locize.com/blog/how-does-server-side-internationalization-look-like/) you can check out how this works.[\
52 | ](https://locize.com/blog/how-does-server-side-internationalization-look-like/)[](https://locize.com/blog/how-does-server-side-internationalization-look-like/)
53 | {% endhint %}
54 |
55 | {% hint style="success" %}
56 | Are you still using i18next in [jQuery](https://github.com/i18next/jquery-i18next)? Check out [this tutorial blog post](https://www.locize.com/blog/jquery-i18next).
57 |
58 | [](https://www.locize.com/blog/jquery-i18next)
59 | {% endhint %}
60 |
61 | ## Complete solution
62 |
63 | Most frameworks leave it to you how translations are being loaded. You are responsible to detect the user language, to load the translations and push them into the framework.
64 |
65 | i18next takes care of these issues for you. We provide you with plugins to:
66 |
67 | * detect the user language
68 | * load the translations
69 | * optionally cache the translations
70 | * extension, by using post-processing - e.g. to enable sprintf support
71 |
72 | [Learn more about plugins and utilities](overview/plugins-and-utils.md)
73 |
74 | ## Flexibility
75 |
76 | i18next comes with strong defaults but it is flexible enough to fulfill custom needs.
77 |
78 | * Use moment.js over intl for date formatting?
79 | * Prefer different pre- and suffixes for interpolation?
80 | * Like gettext style keys better?
81 |
82 | i18next has you covered!
83 |
84 | [Learn more about options](overview/configuration-options.md)
85 |
86 | ## Scalability
87 |
88 | The framework was built with scalability in mind. For smaller projects, having a single file with all the translation might work, but for larger projects this approach quickly breaks down. i18next gives you the option to separate translations into multiple files and to load them on demand.
89 |
90 | [Learn more about namespaces](principles/namespaces.md)
91 |
92 | ## Ecosystem
93 |
94 | There are tons of modules built for and around i18next: from extracting translations from your code over bundling translations using webpack, to converting gettext, CSV and RESX to JSON.
95 |
96 | * [Learn more about plugins and utils](overview/plugins-and-utils.md)
97 | * [Learn more about frameworks supported](overview/supported-frameworks.md)
98 |
99 | ## [Localization as a service](https://locize.com)
100 |
101 | Through [locize.com](http://locize.com/?utm_source=i18next_com\&utm_medium=gitbook), i18next even provides its own translation management tool: localization as a service.
102 |
103 | {% embed url="https://www.youtube.com/watch?v=TFV_vhJs5DY" %}
104 |
105 | [Learn more about the enterprise offering](overview/for-enterprises.md)
106 |
107 | Imagine you run a successful online business, and you want to expand it to reach customers in different countries. You know that to succeed in those markets, your website or app needs to speak the language and understand the culture of each place.
108 |
109 | 1. **i18next**: Think of 'i18next' as a sophisticated language expert for your website or app. It's like hiring a team of translators and cultural experts who ensure that your online business is fluent in multiple languages. It helps adapt your content, menus, and messages to fit perfectly in each target market, making your business more appealing and user-friendly.
110 | 2. **locize**: Now, 'locize' is your efficient manager in charge of organizing and streamlining the translation process. It keeps all your language versions organized and ensures they're always accurate and up-to-date. So, if you want to introduce a new product or promotion, locize helps you do it seamlessly in all the languages you operate in, saving you time and resources.
111 |
112 | Together, 'i18next' and '[locize](https://locize.com)' empower your business to effortlessly reach international audiences. They help you speak the language of your customers, making your business more accessible, relatable, and successful in global markets.
113 |
--------------------------------------------------------------------------------
/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # Table of contents
2 |
3 | * [Introduction](README.md)
4 |
5 | ## Overview
6 |
7 | * [Getting started](overview/getting-started.md)
8 | * [Comparison to others](overview/comparison-to-others.md)
9 | * [API](overview/api.md)
10 | * [Configuration Options](overview/configuration-options.md)
11 | * [Supported Frameworks](overview/supported-frameworks.md)
12 | * [Plugins and Utils](overview/plugins-and-utils.md)
13 | * [For Enterprises](overview/for-enterprises.md)
14 | * [First setup help](overview/first-setup-help.md)
15 | * [TypeScript](overview/typescript.md)
16 |
17 | ## Translation Function
18 |
19 | * [Essentials](translation-function/essentials.md)
20 | * [Interpolation](translation-function/interpolation.md)
21 | * [Formatting](translation-function/formatting.md)
22 | * [Plurals](translation-function/plurals.md)
23 | * [Nesting](translation-function/nesting.md)
24 | * [Context](translation-function/context.md)
25 | * [Objects and Arrays](translation-function/objects-and-arrays.md)
26 |
27 | ## Principles
28 |
29 | * [Best Practices](principles/best-practices.md)
30 | * [Translation Resolution](principles/translation-resolution.md)
31 | * [Namespaces](principles/namespaces.md)
32 | * [Fallback](principles/fallback.md)
33 | * [Plugins](principles/plugins.md)
34 |
35 | ## How to
36 |
37 | * [Add or Load Translations](how-to/add-or-load-translations.md)
38 | * [Extracting translations](how-to/extracting-translations.md)
39 | * [Caching](how-to/caching.md)
40 | * [Backend Fallback](how-to/backend-fallback.md)
41 | * [FAQ](how-to/faq.md)
42 |
43 | ## Misc
44 |
45 | * [JSON Format](misc/json-format.md)
46 | * [Creating own Plugins](misc/creating-own-plugins.md)
47 | * [Migration Guide](misc/migration-guide.md)
48 | * [The history of i18next](misc/the-history-of-i18next.md)
49 | * [Testimonials](misc/testimonials.md)
50 |
51 | ***
52 |
53 | * [🌐 localization as a service](https://locize.com)
54 | * [🎓 i18next crash course](https://youtu.be/SA\_9i4TtxLQ)
55 | * [💾 GitHub Repository](https://github.com/i18next/i18next)
56 |
--------------------------------------------------------------------------------
/_layouts/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/_layouts/README.md
--------------------------------------------------------------------------------
/_layouts/website/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/_layouts/website/README.md
--------------------------------------------------------------------------------
/_layouts/website/summary.html:
--------------------------------------------------------------------------------
1 | {% macro articles(_articles) %}
2 | {% for article in _articles %}
3 |
--------------------------------------------------------------------------------
/assets/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/assets/favicon.ico
--------------------------------------------------------------------------------
/assets/img/dashboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/assets/img/dashboard.png
--------------------------------------------------------------------------------
/assets/img/frameworks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/assets/img/frameworks.png
--------------------------------------------------------------------------------
/assets/img/i18next-frameworks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/assets/img/i18next-frameworks.png
--------------------------------------------------------------------------------
/assets/img/locize_recap_big_low.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/assets/img/locize_recap_big_low.gif
--------------------------------------------------------------------------------
/assets/img/locizify-frameworks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/assets/img/locizify-frameworks.png
--------------------------------------------------------------------------------
/assets/img/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
79 |
--------------------------------------------------------------------------------
/assets/img/logo_web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/assets/img/logo_web.png
--------------------------------------------------------------------------------
/assets/js/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/assets/js/README.md
--------------------------------------------------------------------------------
/assets/js/custom.js:
--------------------------------------------------------------------------------
1 | var target = window.location.hash;
2 |
3 | window.location.hash = "";
4 |
5 | $(document).ready(function() {
6 | setTimeout(function() {
7 | document.location.hash = target;
8 | }, 50);
9 | });
--------------------------------------------------------------------------------
/book.json:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [ "addcssjs", "edit-link", "theme-api", "jsfiddle", "custom-favicon", "simple-page-toc", "anchors" ],
3 | "pluginsConfig": {
4 | "edit-link": {
5 | "base": "https://github.com/i18next/i18next-gitbook/edit/master/",
6 | "label": "Edit"
7 | },
8 | "theme-api": {
9 | "languages": [
10 | {
11 | "lang": "js",
12 | "name": "js",
13 | "default": true
14 | }
15 | ],
16 | "split": true
17 | },
18 | "jsfiddle":{
19 | "type": "script",
20 | "tabs": ["result","js"],
21 | "height": "500",
22 | "width": "500"
23 | },
24 | "favicon": "assets/favicon.ico",
25 | "simple-page-toc": {
26 | "maxDepth": 3,
27 | "skipFirstH1": true
28 | },
29 | "addcssjs": {
30 | "js": ["assets/js/custom.js"]
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/how-to/add-or-load-translations.md:
--------------------------------------------------------------------------------
1 | # Add or Load Translations
2 |
3 | There are a few options to load translations to your application instrumented by i18next. The most common approach to this adding a so called [**backend plugin**](https://www.i18next.com/overview/plugins-and-utils#backends) to i18next. The range of backends is large from loading translations in the browser using [xhr/fetch](https://github.com/i18next/i18next-http-backend) request to loading translations from databases or [filesystem](https://github.com/i18next/i18next-fs-backend) in [Node.js](https://nodejs.org/).
4 |
5 | ## Add on init
6 |
7 | You can add the translations on init
8 |
9 | ```javascript
10 | import i18next from 'i18next';
11 |
12 | i18next
13 | .init({
14 | resources: {
15 | en: {
16 | namespace1: {
17 | key: 'hello from namespace 1'
18 | },
19 | namespace2: {
20 | key: 'hello from namespace 2'
21 | }
22 | },
23 | de: {
24 | namespace1: {
25 | key: 'hallo von namespace 1'
26 | },
27 | namespace2: {
28 | key: 'hallo von namespace 2'
29 | }
30 | }
31 | }
32 | });
33 | ```
34 |
35 | ## Add after init
36 |
37 | You can add the translations after init
38 |
39 | ```javascript
40 | import i18next from 'i18next';
41 |
42 | i18next.init({ resources: {} });
43 | i18next.addResourceBundle('en', 'namespace1', {
44 | key: 'hello from namespace 1'
45 | });
46 | ```
47 |
48 | There are more options to adding, removing translations...learn more about [resource handling](../overview/api.md).
49 |
50 | {% hint style="info" %}
51 | Please make sure to at least pass in an empty resources object on init. Else i18next will try to load translations and give you a warning that you are not using a backend.
52 | {% endhint %}
53 |
54 | ### Combined with a backend plugin
55 |
56 | If you want to lazy load some translations via a backend plugin, you may need to use the `partialBundledLanguages: true` option. This allows some resources (or no resources) to be set on initialization while others can be loaded using a backend connector.
57 |
58 | You may also want to set the `ns` option. To an empty array if you do not want to load any namespaces (also not the [default namespace](../overview/configuration-options.md#languages-namespaces-resources): `'translation'`) or to an array containing the namespaces to load.
59 |
60 | ```javascript
61 | import i18next from 'i18next';
62 |
63 | i18next.init({
64 | partialBundledLanguages: true,
65 | ns: [],
66 | resources: {}
67 | });
68 | i18next.addResourceBundle('en', 'namespace1', {
69 | key: 'hello from namespace 1'
70 | });
71 | // or via backend
72 | // i18next.loadNamespaces(['myNamespace1', 'myNamespace2'])
73 | // i18next.loadLanguages(['de', 'fr'])
74 | // etc.
75 | ```
76 |
77 | ## Lazy load in memory translations
78 |
79 | [i18next-resources-to-backend](https://github.com/i18next/i18next-resources-to-backend) helps to transform resources to an i18next backend. This means, you can also lazy load translations, for example when using webpack:
80 |
81 | ```javascript
82 | import i18next from 'i18next';
83 | import resourcesToBackend from 'i18next-resources-to-backend';
84 |
85 | i18next
86 | .use(resourcesToBackend((language, namespace) => import(`./locales/${language}/${namespace}.json`)))
87 | .init({ /* other options */ })
88 | ```
89 |
90 | ## Load using a backend plugin
91 |
92 | Each [plugin](../principles/plugins.md) comes with a set of configuration settings like path to load resources from. Those settings are documented on the individual readme file of each repository.
93 |
94 | Here is a sample using the [i18next-http-backend](https://github.com/i18next/i18next-http-backend) to load resources from the server.
95 |
96 | ```javascript
97 | import i18next from 'i18next';
98 | import Backend from 'i18next-http-backend';
99 |
100 | i18next
101 | .use(Backend)
102 | .init({
103 | backend: {
104 | // for all available options read the backend's repository readme file
105 | loadPath: '/locales/{{lng}}/{{ns}}.json'
106 | }
107 | });
108 | ```
109 |
110 | {% hint style="danger" %}
111 | Having a combination of [defining resources](add-or-load-translations.md#add-on-init) + [having a backend](add-or-load-translations.md#load-using-a-backend-plugin) will not implicitly take one or the other source as fallback resources.\
112 | If you need some fallback behaviour you may use the [i18next-chained-backend](https://github.com/i18next/i18next-chained-backend). A short example can be found [here](https://github.com/i18next/i18next-http-backend/blob/master/example/fallback/app.js).\
113 | With [i18next-chained-backend](https://github.com/i18next/i18next-chained-backend) you can also create some [caching behaviour](caching.md).
114 | {% endhint %}
115 |
116 | {% hint style="info" %}
117 | [What's a plugin?](../principles/plugins.md)
118 | {% endhint %}
119 |
120 | {% hint style="info" %}
121 | 🎓 Check out this topic in the [i18next crash course video](https://youtu.be/SA_9i4TtxLQ?t=953).
122 | {% endhint %}
123 |
124 | ## Load using a [smart backend plugin](https://github.com/locize/i18next-locize-backend) serving directly from a [CDN](https://docs.locize.com/whats-inside/cdn-content-delivery-network)
125 |
126 | Just use the [i18next-locize-backend](https://github.com/locize/i18next-locize-backend) to load resources from the [CDN](https://docs.locize.com/whats-inside/cdn-content-delivery-network).
127 |
128 | ```javascript
129 | import i18next from 'i18next';
130 | import Backend from 'i18next-locize-backend';
131 |
132 | i18next
133 | .use(Backend)
134 | .init({
135 | backend: {
136 | projectId: '[PROJECT_ID]',
137 | apiKey: '[API_KEY]',
138 | referenceLng: '[LNG]'
139 | }
140 | });
141 | ```
142 |
143 | [Here](https://github.com/locize/react-tutorial) you can find a step by step guide with a React.js app, which will unleash the full power of i18next in combination with locize.\
144 | See how your developer experience with this localization workflow [could look like](https://youtu.be/osScyaGMVqo).\
145 | There's also the possibility to have an [even more focused developer experience](https://youtu.be/VfxBpSXarlU), with the help of the [autoutomatic translation workflow](https://www.locize.com/docs/automatic-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)).
146 |
147 | {% embed url="https://youtu.be/osScyaGMVqo" %}
148 |
149 | {% embed url="https://youtu.be/VfxBpSXarlU" %}
150 |
151 | {% hint style="success" %}
152 | Check out [this blog post](https://www.locize.com/blog/i18next-locize-ai-human) to learn more about how you can use generative AI together with i18next.
153 |
154 | [](https://www.locize.com/blog/i18next-locize-ai-human)
155 | {% endhint %}
156 |
157 | #### [**locize**](https://locize.com) is the perfect translation management tool for your [**i18next**](https://www.i18next.com) project
158 |
159 | #### ➡️ [i18next](https://www.i18next.com/) + [locize](https://locize.com/) = [true continuous localization](https://locize.com/how-it-works.html#continouslocalization)
160 |
--------------------------------------------------------------------------------
/how-to/backend-fallback.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: Do you want to define a fallback which uses local translations?
3 | ---
4 |
5 | # Backend Fallback
6 |
7 | ## Browser fallback with local / bundled translations
8 |
9 | With i18next you can configure a fallback backend to be used in the browser. It will try to load from your primary backend (in this case from your [http backend](https://github.com/i18next/i18next-http-backend)) and if the primary backend is not reachable or does not serve translations, your second backend (in this case [local or bundled](https://github.com/i18next/i18next-resources-to-backend) translations) will be used. This is all possible thanks to the [chained backend](https://github.com/i18next/i18next-chained-backend).
10 |
11 | ```javascript
12 | import i18next from "i18next";
13 | import ChainedBackend from "i18next-chained-backend";
14 | import HttpBackend from "i18next-http-backend";
15 | import resourcesToBackend from "i18next-resources-to-backend";
16 |
17 | const bundledResources = {
18 | en: {
19 | translation: {
20 | key: 'value'
21 | }
22 | }
23 | };
24 |
25 | i18next
26 | .use(ChainedBackend)
27 | .init({
28 | fallbackLng: "en",
29 | // ... your i18next config
30 | backend: {
31 | backends: [
32 | HttpBackend,
33 | resourcesToBackend(bundledResources)
34 | ],
35 | backendOptions: [{
36 | loadPath: '/locales/{{lng}}/{{ns}}.json'
37 | }]
38 | }
39 | });
40 | ```
41 |
42 | ### You can also lazy load the in memory translations, i.e. when using webpack
43 |
44 | ```javascript
45 | import i18next from "i18next";
46 | import ChainedBackend from "i18next-chained-backend";
47 | import HttpBackend from "i18next-http-backend";
48 | import resourcesToBackend from "i18next-resources-to-backend";
49 |
50 | i18next
51 | .use(ChainedBackend)
52 | .init({
53 | fallbackLng: "en",
54 | // ... your i18next config
55 | backend: {
56 | backends: [
57 | HttpBackend,
58 | resourcesToBackend((lng, ns) => import(`./locales/${lng}/${ns}.json`))
59 | ],
60 | backendOptions: [{
61 | loadPath: '/locales/{{lng}}/{{ns}}.json'
62 | }]
63 | }
64 | });
65 | ```
66 |
67 | {% hint style="info" %}
68 | More information can be found here:\
69 | [i18next-chained-backend](https://github.com/i18next/i18next-chained-backend)\
70 | [i18next-resources-to-backend](https://github.com/i18next/i18next-resources-to-backend)\
71 | [i18next-http-backend](https://github.com/i18next/i18next-http-backend)
72 | {% endhint %}
73 |
74 | ## Server side fallback with filesystem
75 |
76 | On server side you can also use the i18next-fs-backend for example instead of the in memory fallback.
77 |
78 | ```javascript
79 | import i18next from "i18next";
80 | import ChainedBackend from "i18next-chained-backend";
81 | import HttpBackend from "i18next-http-backend";
82 | import FsBackend from "i18next-fs-backend";
83 |
84 | i18next
85 | .use(ChainedBackend)
86 | .init({
87 | fallbackLng: "en",
88 | // ... your i18next config
89 | backend: {
90 | backends: [
91 | HttpBackend,
92 | FsBackend
93 | ],
94 | backendOptions: [{
95 | loadPath: '/locales/{{lng}}/{{ns}}.json'
96 | }, {
97 | loadPath: './locales_cache/{{lng}}/{{ns}}.json'
98 | }]
99 | }
100 | });
101 | ```
102 |
103 | {% hint style="info" %}
104 | More information can be found here:\
105 | [i18next-chained-backend](https://github.com/i18next/i18next-chained-backend)\
106 | [i18next-fs-backend](https://github.com/i18next/i18next-fs-backend)\
107 | [i18next-http-backend](https://github.com/i18next/i18next-http-backend)
108 | {% endhint %}
109 |
110 | {% hint style="danger" %}
111 | We suggest not to use multiple backends with the [i18next-chained-backend](https://github.com/i18next/i18next-chained-backend) in combination with saveMissing or updateMissing, because it may happen, that the trigger for this is based on stale data.
112 | {% endhint %}
113 |
--------------------------------------------------------------------------------
/how-to/caching.md:
--------------------------------------------------------------------------------
1 | # Caching
2 |
3 | ## Browser caching with local storage
4 |
5 | With i18next you can configure a cache layer to be used in the browser. It will load and cache resources from [localStorage](https://github.com/i18next/i18next-localstorage-backend) and can be used in combination with the [chained backend](https://github.com/i18next/i18next-chained-backend).
6 |
7 | ```javascript
8 | import i18next from "i18next";
9 | import ChainedBackend from "i18next-chained-backend";
10 | import HttpBackend from "i18next-http-backend";
11 | import LocalStorageBackend from "i18next-localstorage-backend";
12 |
13 | i18next
14 | .use(ChainedBackend)
15 | .init({
16 | fallbackLng: "en",
17 | // ... your i18next config
18 | backend: {
19 | backends: [
20 | LocalStorageBackend,
21 | HttpBackend
22 | ],
23 | backendOptions: [{
24 | expirationTime: 7 * 24 * 60 * 60 * 1000 // 7 days
25 | }, {
26 | loadPath: '/locales/{{lng}}/{{ns}}.json'
27 | }]
28 | }
29 | });
30 | ```
31 |
32 | {% hint style="info" %}
33 | More information can be found here:
34 | [i18next-chained-backend](https://github.com/i18next/i18next-chained-backend)
35 | [i18next-localstorage-backend](https://github.com/i18next/i18next-localstorage-backend)
36 | [i18next-http-backend](https://github.com/i18next/i18next-http-backend)
37 | {% endhint %}
38 |
39 | ## Server side caching with filesystem
40 |
41 | With i18next you can configure a cache layer to be used on server side. It will load and cache resources from the [filesystem](https://github.com/i18next/i18next-fs-backend) and can be used in combination with the [chained backend](https://github.com/i18next/i18next-chained-backend).
42 |
43 | ```javascript
44 | import i18next from "i18next";
45 | import ChainedBackend from "i18next-chained-backend";
46 | import HttpBackend from "i18next-http-backend";
47 | import FsBackend from "i18next-fs-backend";
48 |
49 | i18next
50 | .use(ChainedBackend)
51 | .init({
52 | fallbackLng: "en",
53 | // ... your i18next config
54 | backend: {
55 | backends: [
56 | FsBackend,
57 | HttpBackend
58 | ],
59 | backendOptions: [{
60 | expirationTime: 7 * 24 * 60 * 60 * 1000, // 7 days
61 | loadPath: './locales_cache/{{lng}}/{{ns}}.json',
62 | addPath: './locales_cache/{{lng}}/{{ns}}.json' // make sure the folders "locales_cache/{{lng}}" exists
63 | }, {
64 | loadPath: '/locales/{{lng}}/{{ns}}.json'
65 | }]
66 | }
67 | });
68 | ```
69 |
70 | {% hint style="info" %}
71 | More information can be found here:
72 | [i18next-chained-backend](https://github.com/i18next/i18next-chained-backend)
73 | [i18next-fs-backend](https://github.com/i18next/i18next-fs-backend)
74 | [i18next-http-backend](https://github.com/i18next/i18next-http-backend)
75 | {% endhint %}
76 |
77 | ## React-native caching with AsyncStorage
78 |
79 | With i18next you can configure a cache layer to be used on react-native. It will load and cache resources from the [AsyncStorage](https://github.com/timbrandin/i18next-async-storage-backend) and can be used in combination with the [chained backend](https://github.com/i18next/i18next-chained-backend).
80 |
81 | ```javascript
82 | import i18next from "i18next";
83 | import ChainedBackend from "i18next-chained-backend";
84 | import HttpBackend from "i18next-http-backend";
85 | import AsyncStorageBackend from "i18next-async-storage-backend";
86 |
87 | i18next
88 | .use(ChainedBackend)
89 | .init({
90 | fallbackLng: "en",
91 | // ... your i18next config
92 | backend: {
93 | backends: [
94 | AsyncStorageBackend,
95 | HttpBackend
96 | ],
97 | backendOptions: [{
98 | expirationTime: 7 * 24 * 60 * 60 * 1000 // 7 days
99 | }, {
100 | loadPath: '/locales/{{lng}}/{{ns}}.json'
101 | }]
102 | }
103 | });
104 | ```
105 |
106 | {% hint style="info" %}
107 | More information can be found here:
108 | [i18next-chained-backend](https://github.com/i18next/i18next-chained-backend)
109 | [i18next-async-storage-backend](https://github.com/timbrandin/i18next-async-storage-backend)
110 | [i18next-http-backend](https://github.com/i18next/i18next-http-backend)
111 | {% endhint %}
112 |
113 | ## Server side Next.js caching with filesystem
114 |
115 | Similar to the normal [server side caching with filesystem](caching.md#server-side-caching-with-filesystem), you can use the same approach in a Next.js app in combination with [next-i18next](https://github.com/isaachinman/next-i18next). It will load and cache resources from the [filesystem](https://github.com/i18next/i18next-fs-backend) and can be used in combination with the [chained backend](https://github.com/i18next/i18next-chained-backend).
116 |
117 | The config file, will probably look similar to this, but for a more complete example have a look [at this example by locize](https://github.com/locize/next-i18next-locize/tree/local-caching#optional-server-side-caching-to-filesystem).
118 |
119 | ```javascript
120 | // next-i18next.config.js
121 | const ChainedBackend = require('i18next-chained-backend')
122 | const FSBackend = require('i18next-fs-backend/cjs')
123 | const HttpBackend = require('i18next-http-backend/cjs')
124 |
125 | module.exports = {
126 | i18n: {
127 | defaultLocale: 'en',
128 | locales: ['en', 'de'],
129 | },
130 | backend: {
131 | backends: [
132 | FSBackend,
133 | HttpBackend
134 | ],
135 | backendOptions: [{ // make sure public/locales_cache/en and public/locales_cache/de exists
136 | loadPath: './public/locales_cache/{{lng}}/{{ns}}.json',
137 | addPath: './public/locales_cache/{{lng}}/{{ns}}.json',
138 | expirationTime: 7 * 24 * 60 * 60 * 1000 // 7 days
139 | }, {
140 | loadPath: '/locales/{{lng}}/{{ns}}.json'
141 | }]
142 | },
143 | use: [ChainedBackend],
144 | ns: ['common', 'footer', 'second-page'], // the namespaces needs to be listed here, to make sure they got preloaded
145 | serializeConfig: false, // because of the custom use i18next plugin
146 | // debug: true,
147 | }
148 | ```
149 |
150 | {% hint style="info" %}
151 | More information can be found here:
152 | [next-i18next-locize example](https://github.com/locize/next-i18next-locize/tree/local-caching#optional-server-side-caching-to-filesystem)
153 | [i18next-chained-backend](https://github.com/i18next/i18next-chained-backend)
154 | [i18next-fs-backend](https://github.com/i18next/i18next-fs-backend)
155 | [i18next-http-backend](https://github.com/i18next/i18next-http-backend)
156 | {% endhint %}
157 |
158 | {% hint style="danger" %}
159 | We suggest not to use multiple backends with the [i18next-chained-backend](https://github.com/i18next/i18next-chained-backend) in combination with saveMissing or updateMissing, because it may happen, that the trigger for this is based on stale data.
160 | {% endhint %}
161 |
162 |
--------------------------------------------------------------------------------
/how-to/extracting-translations.md:
--------------------------------------------------------------------------------
1 | # Extracting translations
2 |
3 | At some point you will come to the question how to get new translation key/values into your namespace \(translation\) file.
4 |
5 | ## 1\) Adding new strings manually
6 |
7 | While for sure this is the least efficient method for adding new translations, we know a lot of projects are doing this. There is actually nothing wrong with it beside being some extra work developers could avoid.
8 |
9 | ## 2\) Using an extraction tool
10 |
11 | Static extraction tools can read through your code files to automatically find and export translation keys. [i18next-scanner](http://i18next.github.io/i18next-scanner), [i18next-parser](https://github.com/i18next/i18next-parser) and [babel-plugin-i18next-extract](https://github.com/gilbsgilbs/babel-plugin-i18next-extract) are sensible choices to achieve this goal.
12 |
13 | _Or 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._
14 |
15 | For more information about extraction tools, see [plugin and utils](https://www.i18next.com/overview/plugins-and-utils#extraction-tools) documentation page.
16 |
17 | ## 3\) Runtime extraction
18 |
19 | I18next has a setting to send all keys that it was unable to resolve during runtime using the attached backend.
20 |
21 | In case of the http-backend just set `saveMissing: true` on init:
22 |
23 | ```javascript
24 | import i18n from "i18next";
25 | import detector from "i18next-browser-languagedetector";
26 | import backend from "i18next-http-backend";
27 | import { initReactI18next } from "react-i18next";
28 |
29 | i18n
30 | .use(detector)
31 | .use(backend)
32 | .use(initReactI18next) // passes i18n down to react-i18next
33 | .init({
34 | fallbackLng: "en", // use en if detected lng is not available
35 | saveMissing: true // send not translated keys to endpoint
36 | });
37 |
38 | export default i18n;
39 | ```
40 |
41 | Check the [options](https://github.com/i18next/i18next-http-backend#backend-options) for where missing translation gets sent.
42 |
43 | Using node.js and express? You can get that endpoint for free: [https://github.com/i18next/i18next-http-middleware\#add-routes](https://github.com/i18next/i18next-http-middleware#add-routes)
44 |
45 | This is the most convenient way of working with react-i18next: just develop and run your applications without worrying too much about adding translations to your catalog as those get added automatically.
46 |
47 | {% hint style="info" %}
48 | Wanna have this process on steroids? Just hook up a [locize.com](https://locize.com/) localization project using the provided backend and get both the saveMissing and loading of translations automated in a true continuous localization process. [Check out this tutorial!](https://github.com/locize/react-tutorial)
49 | {% endhint %}
50 |
51 | {% embed url="https://youtu.be/osScyaGMVqo" %}
52 |
53 |
--------------------------------------------------------------------------------
/how-to/faq.md:
--------------------------------------------------------------------------------
1 | # FAQ
2 |
3 | ## Misc
4 |
5 | ### **i18next is awesome. How can I support the project?**
6 |
7 | _There are a lot of ways to support us. Make a PR for a feature requested. Improve the documentation. Help others to get started. Spread the word._
8 |
9 | _Further you could try_ [_locize.com_](http://locize.com) _- our localization as a service offering. It's like donating to i18next but with additional benefits for you - like saving hours of time translating your project._
10 |
11 | ## Loading issues
12 |
13 | ### **I don't see my translations!!!**
14 |
15 | _Try setting_ `debug: true` _on init and check the console log. There is rather sure a warning for unable to resolve the loadPath or invalid json. Check if the translation files are accessible via browser._
16 |
17 | ## Translation
18 |
19 | ### **How to translate the resource files?**
20 |
21 |
22 |
23 | For a quick and dirty machine translation you may have a look at [this free translator](https://translate.i18next.com).\
24 | But in general we suggest to use a smart Translation Management Service like [locize](https://locize.com) to translate your i18next resources.
25 |
26 | For professional translations we advice you to work with [human translators](https://docs.locize.com/guides-tips-and-tricks/working-with-translators). Or at least proofread the results coming from machine translations.
27 |
28 | ### **How do i know which plural suffix i have to use?**
29 |
30 | _On the_ [_plural page_](../translation-function/plurals.md) _there is a tool to get them._
31 |
32 | _Or try_ [_translation-check_](https://github.com/locize/translation-check)_, it shows an overview of your translations in a nice UI. It shows also the appropriate plural forms._
33 |
34 | _Or you use a smart translation management system, like_ [_locize_](https://locize.com)_._
35 |
36 | 
37 |
38 | ### **Why are my plural keys not working?**
39 |
40 | _Are you seeing this warning in the development console?_
41 |
42 | > i18next::pluralResolver: Your environment seems not to be Intl API compatible, use an Intl.PluralRules polyfill. Will fallback to the compatibilityJSON v3 format handling.
43 |
44 | _With v21 we_ streamlined the suffix with the one used in the [Intl API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/PluralRules/PluralRules).
45 |
46 | _In environments where the_ [_Intl.PluralRules_](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/PluralRules) _API is not available (like older Android devices), you may need to_ [_polyfill_](https://github.com/eemeli/intl-pluralrules) _the_ [_Intl.PluralRules_](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/PluralRules) _API._\
47 | _In case it is not available it will fallback to the_ [_i18next JSON format v3_](../misc/json-format.md#i-18-next-json-v3) _plural handling. And if your json is already using the new suffixes, your plural keys will probably not be shown._
48 |
49 | _tldr;_
50 |
51 | ```shell
52 | npm install intl-pluralrules
53 | ```
54 |
55 | ```javascript
56 | import 'intl-pluralrules'
57 | ```
58 |
59 | ### How should the language codes be formatted?
60 |
61 | _Theoretically, you're not bound to any specific language code format, but if you want to make use of all the in built language features, like proper_ [_pluralization_](../translation-function/plurals.md) _and correct_ [_fallback resolution_](../principles/fallback.md#language-fallback)_, we strongly suggest to use the following iso norm (BCP 47 language tag):_
62 |
63 | `lng-(script)-REGION-(extensions)`\
64 | \
65 | NAN;_i.e._
66 |
67 | * _en, en-US or en-GB_
68 | * _zh, zh-HK or zh-Hant-HK_
69 |
70 | _Other examples are listed here:_ [_https://www.iana.org/assignments/language-tags/language-tags.xhtml_](https://www.iana.org/assignments/language-tags/language-tags.xhtml)
71 |
72 | _And more information about the format can be found here:_ [_https://www.w3.org/International/articles/language-tags/_](https://www.w3.org/International/articles/language-tags/)
73 |
74 | {% hint style="info" %}
75 | As soon as you use the dash character `-` the language codes are tried to be formatted with `Intl.getCanonicalLocales`.
76 | {% endhint %}
77 |
78 | ## Process
79 |
80 | ### **How do I keep overview over my translation progress?**
81 |
82 | _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._
83 |
84 | _If you need more, it might be time to use a_ [_translation management tool_](https://locize.com)_._
85 |
86 | ### **How to handle with changes in e2e tests?**
87 |
88 | _For e2e tests a good tactic is to set language to_ `cimode` _on init. This will set i18next to always return the key on calling_ `i18next.t`_. Want to add the namespace to returned value change_ `appendNamespaceToCIMode: true` _on init._
89 |
90 | ### **How to use i18next in serverless environments?**
91 |
92 | Due to how serverless functions work, you cannot guarantee that a cached version of your data is available. Serverless functions are short-lived, and can shut down at any time, purging any in-memory or filesystem cache. This may be an acceptable trade-off, but sometimes it isn't acceptable.
93 |
94 | Because of this we suggest to not use a remote backend and to download the translations and package them with your serverless function.
95 |
96 | {% hint style="success" %}
97 | Read more about this topic, [here](https://locize.com/blog/i18n-serverless/).[\
98 | ](https://locize.com/blog/how-does-server-side-internationalization-look-like/)[.jpg>)](https://locize.com/blog/i18n-serverless/)
99 | {% endhint %}
100 |
--------------------------------------------------------------------------------
/load-translations.md:
--------------------------------------------------------------------------------
1 |
2 | # Load Translations
3 |
4 | There are a few options to load translations to your application instrumented by i18next. The most common approach to this adding a so called **backend plugin** to i18next. The range of backends is large from loading translations in the browser using xhr request to loading translations from databases or filesystem in nodejs.
5 |
6 | {% method %}
7 | ## Adding backend plugins
8 |
9 |
10 | Each plugin comes with a set of on configuration settings like path to load resources from. Those settings are documented on the individual readme file of each repository.
11 |
12 | {% sample lang="js" %}
13 | Here is a sample using the [i18next-xhr-backend](https://github.com/i18next/i18next-xhr-backend) to load resources from the server.
14 |
15 | ```js
16 | import i18next from 'i18next';
17 | import Backend from 'i18next-xhr-backend';
18 |
19 | i18next
20 | .use(Backend)
21 | .init({
22 | // for all available options read the backend's repository readme file
23 | loadPath: '/locales/{{lng}}/{{ns}}.json',
24 | });
25 | ```
26 |
27 | {% endmethod %}
28 |
29 |
30 |
--------------------------------------------------------------------------------
/loading-translations.md:
--------------------------------------------------------------------------------
1 | # Loading Translations
2 |
3 | There are a few options to load translations to your application instrumented by i18next. The most common approach to this adding a so called **backend plugin** to i18next. The range of backends is large from loading translations in the browser using xhr request to loading translations from databases or filesystem in nodejs.
4 |
5 | {% method %}
6 | ## Adding backend plugins
7 |
8 |
9 | Each plugin comes with a set of on configuration settings like path to load resources from. Those settings are documented on the individual readme file of each repository.
10 |
11 | {% sample lang="js" %}
12 | Here is a sample using the [i18next-xhr-backend](https://github.com/i18next/i18next-xhr-backend) to load resources from the server.
13 |
14 | ```js
15 | import i18next from 'i18next';
16 | import Backend from 'i18next-xhr-backend';
17 |
18 | i18next
19 | .use(Backend)
20 | .init({
21 | // for all available options read the backend's repository readme file
22 | loadPath: '/locales/{{lng}}/{{ns}}.json',
23 | });
24 | ```
25 |
26 | {% endmethod %}
27 |
28 | [source code](https://jsfiddle.net/jamuhl/wb1qvxu9/#tabs=result,html,js)
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/locales/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/locales/README.md
--------------------------------------------------------------------------------
/locales/de/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/locales/de/README.md
--------------------------------------------------------------------------------
/locales/de/common.json:
--------------------------------------------------------------------------------
1 | {
2 | "button": {
3 | "save": "Speichere {{count}} Änderung",
4 | "save_plural": "Speichere {{count}} Änderungen"
5 | }
6 | }
--------------------------------------------------------------------------------
/locales/de/special.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "{{what}} auf Deutsch"
3 | }
4 |
--------------------------------------------------------------------------------
/locales/en/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/locales/en/README.md
--------------------------------------------------------------------------------
/locales/en/common.json:
--------------------------------------------------------------------------------
1 | {
2 | "button": {
3 | "save": "save {{count}} change",
4 | "save_plural": "save {{count}} changes"
5 | }
6 | }
--------------------------------------------------------------------------------
/locales/en/special.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "{{what}} in english"
3 | }
--------------------------------------------------------------------------------
/methods.md:
--------------------------------------------------------------------------------
1 |
2 | # Interpolation
3 |
4 | Interpolation is one of the most used functionality used. It enables you to integrate dynamic values into your translations.
5 |
6 | Per default those interpolations get escaped to safe you from possible xss attacks.
7 |
8 | {% method %}
9 | ## Basic
10 |
11 | Interpolation is one of the most used functionality.
12 |
13 | keys
14 |
15 | ```json
16 | {
17 | "key": "{{what}} is {{how}}"
18 | }
19 | ```
20 |
21 | {% sample lang="js" %}
22 | sample
23 |
24 | ```js
25 | i18next.t('key', { what: 'i18next', how: 'great' });
26 | // -> "i18next is great"
27 | ```
28 |
29 | {% endmethod %}
30 |
31 | {% method %}
32 | ## Working with data models
33 |
34 | You can pass entire data models in options.
35 |
36 | keys
37 |
38 | ```json
39 | {
40 | "key": "i am {{author.name}}"
41 | }
42 | ```
43 |
44 | {% sample lang="js" %}
45 | sample
46 |
47 | ```js
48 | const author = {
49 | name: 'Jan',
50 | github: 'jamuhl'
51 | };
52 | i18next.t('key', { author });
53 | // -> "i am Jan"
54 | ```
55 |
56 | {% endmethod %}
57 |
58 |
59 |
60 |
61 | {% method %}
62 | ## Unescape
63 |
64 | Per default the values get escaped to safe from possible xss attacks. You can toggle escaping off.
65 |
66 | keys
67 |
68 | ```json
69 | {
70 | "keyEscaped": "no danger {{myVar}}",
71 | "keyUnescaped": "dangerous {{- myVar}}"
72 | }
73 | ```
74 |
75 | {% sample lang="js" %}
76 | sample
77 |
78 | ```js
79 | i18next.t('keyEscaped', { myVar: '' });
80 | // -> "no danger <img />"
81 |
82 | i18next.t('keyUnescaped', { myVar: '' });
83 | // -> "dangerous "
84 |
85 | i18next.t('keyEscaped', { myVar: '', interpolation: { escape: false } });
86 | // -> "no danger " (obviously could be dangerous)
87 |
88 | ```
89 |
90 | *Dangerzone:* Toggling escaping off you should escape any user input yourself!
91 |
92 |
93 | {% endmethod %}
94 |
95 |
96 |
97 | {% method %}
98 | ## Additional options
99 |
100 | Prefix/Suffix for interpolation and other options can be overridden in init option or by passing additional options to t function:
101 |
102 | {% sample lang="js" %}
103 | sample
104 |
105 | ```js
106 | i18next.init({
107 | interpolation: { ... }
108 | });
109 |
110 | i18next.t('key', {
111 | interpolation: { ... }
112 | });
113 | ```
114 | {% endmethod %}
115 |
116 |
117 |
118 |
119 | option | default | description
120 | ----------------- | --------------------| -----------------
121 | format | noop function | format function `function format(value, format, lng) {}`
122 | escape | function | escape function `function escape(str) { return str; }`
123 | escapeValue | true | escapes passed in values to avoid xss injection
124 | prefix | '{{' | prefix for interpolation
125 | suffix | '}}' | suffix for interpolation
126 | formatSeparator | ',' | used to separate format from interpolation value
127 | prefixEscaped | undefined | escaped prefix for interpolation (regexSafe)
128 | suffixEscaped | undefined | escaped suffix for interpolation (regexSafe)
129 | unescapeSuffix | undefined | suffix to unescaped mode
130 | unescapePrefix | '-' | prefix to unescaped mode
131 | nestingPrefix | '$t(' | prefix for nesting
132 | nestingSuffix | ')' | suffix for nesting
133 | nestingPrefixEscaped | undefined | escaped prefix for nesting (regexSafe)
134 | nestingSuffixEscaped | undefined | escaped suffix for nesting (regexSafe)
135 | defaultVariables | undefined | default variables to use in interpolation replacements
136 |
137 | While there are a lot of options going with the defaults should get you covered.
138 |
139 |
140 |
--------------------------------------------------------------------------------
/misc/creating-own-plugins.md:
--------------------------------------------------------------------------------
1 | # Creating own Plugins
2 |
3 | i18next comes with a lot of modules to enhance the features available. There are modules to:
4 |
5 | * load resources, eg. via xhr or from filesystem (node.js)
6 | * cache resources on client, eg. localStorage
7 | * detect user language by querystring, navigator, cookie, ...
8 | * post processors to further manipulate values, eg. to add sprintf support
9 |
10 | The plugins need to support following APIs:
11 |
12 | **HINT:** You can provide a singleton or a prototype constructor (prefered for supporting multiple instances of i18next).
13 |
14 | ## backend
15 |
16 | Backend plugins are used to load data for i18next.
17 |
18 | ```javascript
19 | {
20 | type: 'backend',
21 | init: function(services, backendOptions, i18nextOptions) {
22 | /* use services and options */
23 | },
24 | read: function(language, namespace, callback) {
25 | /* return resources */
26 | callback(null, {
27 | key: 'value'
28 | });
29 |
30 | /* if method fails/returns an error, call this: */
31 | /* callback(truthyValue, null); */
32 | },
33 | // or new since i18next v22.1.0
34 | // read: function(language, namespace) {
35 | // return new Promise((resolve) => {
36 | // resolve({
37 | // key: 'value'
38 | // })
39 | // })
40 | // },
41 |
42 | // optional
43 | readMulti: function(languages, namespaces, callback) {
44 | /* return multiple resources - useful eg. for bundling loading in one xhr request */
45 | callback(null, {
46 | en: {
47 | translations: {
48 | key: 'value'
49 | }
50 | },
51 | de: {
52 | translations: {
53 | key: 'value'
54 | }
55 | }
56 | });
57 |
58 | /* if method fails/returns an error, call this: */
59 | /* callback(truthyValue, null); */
60 | },
61 | // or new since i18next-multiload-backend-adapter v2.1.0
62 | // readMulti: function(languages, namespaces) {
63 | // return new Promise((resolve) => {
64 | // resolve({
65 | // en: {
66 | // translations: {
67 | // key: 'value'
68 | // }
69 | // },
70 | // de: {
71 | // translations: {
72 | // key: 'value'
73 | // }
74 | // }
75 | // })
76 | // })
77 | // },
78 |
79 | // only used in backends acting as cache layer
80 | save: function(language, namespace, data) {
81 | // store the translations
82 | },
83 |
84 | create: function(languages, namespace, key, fallbackValue) {
85 | /* save the missing translation */
86 | }
87 | }
88 | ```
89 |
90 | {% hint style="info" %}
91 | Using `readMulti` is only supported when using the [https://github.com/i18next/i18next-multiload-backend-adapter](https://github.com/i18next/i18next-multiload-backend-adapter)
92 | {% endhint %}
93 |
94 | ## languageDetector
95 |
96 | Language Detector plugins are used to detect language in user land.
97 |
98 | ```javascript
99 | {
100 | type: 'languageDetector',
101 | async: true, // If this is set to true, your detect function receives a callback function that you should call with your language, useful to retrieve your language stored in AsyncStorage for example
102 | init: function(services, detectorOptions, i18nextOptions) { // optional since v22.3.0
103 | /* use services and options */
104 | },
105 | detect: function(callback) { // You'll receive a callback if you passed async true
106 | /* return detected language */
107 | // callback('de'); if you used the async flag
108 | return 'de';
109 | },
110 | // or new since v22.3.0
111 | // detect: async function () { // you can also return a normal Promise
112 | // /* return detected language */
113 | // return 'de';
114 | // // or
115 | // // return Promise.resolve('de')
116 | // },
117 | cacheUserLanguage: function(lng) { // optional since v22.3.0
118 | /* cache language */
119 | }
120 | // or new since v22.3.0, but i18next will not await for it... so it's basically a fire and forget
121 | // cacheUserLanguage: async function(lng) {
122 | // /* await cache language */
123 | // }
124 | }
125 | ```
126 |
127 | ## post processor
128 |
129 | Post Processors are used to extend or manipulate the translated values before returning them in `t` function.
130 |
131 | (Post Processors do not need to be prototype functions)
132 |
133 | ```javascript
134 | {
135 | type: 'postProcessor',
136 | name: 'nameOfProcessor',
137 | process: function(value, key, options, translator) {
138 | /* return manipulated value */
139 | return value;
140 | }
141 | }
142 | ```
143 |
144 | ## logger
145 |
146 | Override the built in console logger.
147 |
148 | (loggers do not need to be prototype functions)
149 |
150 | ```javascript
151 | {
152 | type: 'logger',
153 |
154 | log: function(args) {},
155 | warn: function(args) {},
156 | error: function(args) {}
157 | }
158 | ```
159 |
160 | ## Helpful tips
161 |
162 | ### Make sure to set the plugin type
163 |
164 | If you do not set the plugin type, you may get an error like this.
165 |
166 | `... No [plugin type] was added via i18next.use. Will not load resources.`
167 |
168 | If you are creating a class for your plugin, you may set the type like in the following example (the following is an example if you are making a backend plugin):
169 |
170 | ```javascript
171 | class Backend {
172 | constructor(services, backendOptions, i18nextOptions){
173 |
174 | }
175 |
176 | // other required methods;
177 | // ie. read, create, etc.
178 | }
179 | Backend.type = "backend";
180 |
181 | export default Backend;
182 | ```
183 |
184 | ### Create a private method to initialize your plugin
185 |
186 | The constructor of your plugin (if the plugin is of type `backend` or `languageDetector`) will be [called without arguments](https://github.com/i18next/i18next/issues/1379#issuecomment-571913660) if you use the plugin as a class. Using the plugin as a class looks like this:
187 |
188 | ```javascript
189 | import i18n from "i18next";
190 | import {
191 | initReactI18next
192 | } from "react-i18next";
193 | import i18nBackend from "my-custom-backend";
194 |
195 | i18n
196 | .use(i18nBackend)
197 | .use(initReactI18next)
198 | .init({
199 | backend: {
200 | // custom options
201 | },
202 | // other options
203 | });
204 | ```
205 |
206 | While using your plugin in this way, you may want to validate the `options` passed into the **backend** property of the `.init` method. A good way to validate them is to have a private method where you initialize your plugin.
207 |
208 | ```javascript
209 | class Backend {
210 | constructor(services, backendOptions = {}, i18nextOptions = {}){
211 | this.init(services, backendOptions, i18nextOptions);
212 | }
213 |
214 | init(services, backendOptions, i18nextOptions){
215 | // Validate backendOptions
216 | }
217 |
218 | // other required methods;
219 | // ie. read, create, etc.
220 | }
221 | Backend.type = "backend";
222 |
223 | export default Backend;
224 | ```
225 |
--------------------------------------------------------------------------------
/misc/json-format.md:
--------------------------------------------------------------------------------
1 | # JSON Format
2 |
3 | ## i18next JSON v4
4 |
5 | ```javascript
6 | {
7 | "key": "value",
8 | "keyDeep": {
9 | "inner": "value"
10 | },
11 | "keyNesting": "reuse $t(keyDeep.inner)",
12 | "keyInterpolate": "replace this {{value}}",
13 | "keyInterpolateUnescaped": "replace this {{- value}}",
14 | "keyInterpolateWithFormatting": "replace this {{value, format}}",
15 | "keyContext_male": "the male variant",
16 | "keyContext_female": "the female variant",
17 | "keyPluralSimple_one": "the singular",
18 | "keyPluralSimple_other": "the plural",
19 | "keyPluralMultipleEgArabic_zero": "the plural form 0",
20 | "keyPluralMultipleEgArabic_one": "the plural form 1",
21 | "keyPluralMultipleEgArabic_two": "the plural form 2",
22 | "keyPluralMultipleEgArabic_few": "the plural form 3",
23 | "keyPluralMultipleEgArabic_many": "the plural form 4",
24 | "keyPluralMultipleEgArabic_other": "the plural form 5",
25 | "keyWithArrayValue": ["multiple", "things"],
26 | "keyWithObjectValue": { "valueA": "return this with valueB", "valueB": "more text" }
27 | }
28 | ```
29 |
30 | These are the defaults. Nesting and Interpolation formats are configurable.
31 |
32 | To learn more about the features check the documentation:
33 |
34 | * [Interpolation](../translation-function/interpolation.md)
35 | * [Formatting](../translation-function/formatting.md)
36 | * [Plurals](../translation-function/plurals.md)
37 | * [Nesting](../translation-function/nesting.md)
38 | * [Objects and Arrays](../translation-function/objects-and-arrays.md)
39 |
40 | The only difference to _v3_ is the plural suffixes.
41 |
42 | You may need to [polyfill](https://github.com/eemeli/intl-pluralrules) the [Intl.PluralRules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global\_Objects/PluralRules) API, in case it is not available it will fallback to the [i18next JSON format v3](json-format.md#i-18-next-json-v3) plural handling.
43 |
44 | To convert your existing translations to the new v4 format, have a look at [i18next-v4-format-converter](https://github.com/i18next/i18next-v4-format-converter) or [this web tool](https://i18next.github.io/i18next-v4-format-converter-web/). _(It will only handle keys with the default pluralSeparator `_`)_
45 |
46 | ## i18next JSON v3
47 |
48 | enabled by:
49 |
50 | ```javascript
51 | i18next.init({
52 | compatibilityJSON: 'v3'
53 | });
54 | ```
55 |
56 | formats:
57 |
58 | ```javascript
59 | {
60 | "key": "value",
61 | "keyDeep": {
62 | "inner": "value"
63 | },
64 | "keyNesting": "reuse $t(keyDeep.inner)",
65 | "keyInterpolate": "replace this {{value}}",
66 | "keyInterpolateUnescaped": "replace this {{- value}}",
67 | "keyInterpolateWithFormatting": "replace this {{value, format}}",
68 | "keyContext_male": "the male variant",
69 | "keyContext_female": "the female variant",
70 | "keyPluralSimple": "the singular",
71 | "keyPluralSimple_plural": "the plural",
72 | "keyPluralMultipleEgArabic_0": "the plural form 0",
73 | "keyPluralMultipleEgArabic_1": "the plural form 1",
74 | "keyPluralMultipleEgArabic_2": "the plural form 2",
75 | "keyPluralMultipleEgArabic_3": "the plural form 3",
76 | "keyPluralMultipleEgArabic_4": "the plural form 4",
77 | "keyPluralMultipleEgArabic_5": "the plural form 5",
78 | "keyWithArrayValue": ["multiple", "things"],
79 | "keyWithObjectValue": { "valueA": "return this with valueB", "valueB": "more text" }
80 | }
81 | ```
82 |
83 | The only difference to _v2_ is the plural suffixes for languages with multiple plural forms.
84 |
85 | ## i18next JSON v2
86 |
87 | enabled by:
88 |
89 | ```javascript
90 | i18next.init({
91 | compatibilityJSON: 'v2'
92 | });
93 | ```
94 |
95 | formats:
96 |
97 | ```javascript
98 | {
99 | "key": "value",
100 | "keyDeep": {
101 | "inner": "value"
102 | },
103 | "keyNesting": "reuse $t(keyDeep.inner)",
104 | "keyInterpolate": "replace this {{value}}",
105 | "keyInterpolateUnescaped": "replace this {{- value}}",
106 | "keyContext_male": "the male variant",
107 | "keyContext_female": "the female variant",
108 | "keyPluralSimple": "the singular",
109 | "keyPluralSimple_plural": "the plural",
110 | "keyPluralMultipleEgArabic_0": "the plural form 0",
111 | "keyPluralMultipleEgArabic_1": "the plural form 1",
112 | "keyPluralMultipleEgArabic_2": "the plural form 2",
113 | "keyPluralMultipleEgArabic_3": "the plural form 3",
114 | "keyPluralMultipleEgArabic_11": "the plural form 4",
115 | "keyPluralMultipleEgArabic_100": "the plural form 5"
116 | }
117 | ```
118 |
119 | These are the defaults. Nesting and Interpolation formats are configurable.
120 |
121 | ## i18next JSON v1
122 |
123 | enabled by:
124 |
125 | ```javascript
126 | i18next.init({
127 | compatibilityJSON: 'v1'
128 | });
129 | ```
130 |
131 | formats:
132 |
133 | ```javascript
134 | {
135 | "key": "value",
136 | "keyDeep": {
137 | "inner": "value"
138 | },
139 | "keyNesting": "reuse $t(keyDeep.inner)",
140 | "keyInterpolate": "replace this __value__",
141 | "keyInterpolateUnescaped": "replace this __valueHTML__",
142 | "keyContext_male": "the male variant",
143 | "keyContext_female": "the female variant",
144 | "keyPluralSimple": "the singular",
145 | "keyPluralSimple_plural": "the plural",
146 | "keyPluralMultipleEgArabic": "the plural form 0",
147 | "keyPluralMultipleEgArabic_plural_1": "the plural form 1",
148 | "keyPluralMultipleEgArabic_plural_2": "the plural form 2",
149 | "keyPluralMultipleEgArabic_plural_3": "the plural form 3",
150 | "keyPluralMultipleEgArabic_plural_11": "the plural form 4",
151 | "keyPluralMultipleEgArabic_plural_100": "the plural form 5"
152 | }
153 | ```
154 |
155 | These are the defaults. Nesting and Interpolation formats are configurable.
156 |
--------------------------------------------------------------------------------
/misc/testimonials.md:
--------------------------------------------------------------------------------
1 | # Testimonials
2 |
3 |
<<How we translated the Avocode website written in Next.js with the i18next package
Using i18next as our international framework enables us to use the same technology around our whole software stack, regardless the actual backend or framework we use. locize is the icing on the cake – it made translation management unspeakably easier.
We use i18next as an internationalization framework. locize being perfectly integrated with the framework become a really good translation management tool for us.
Using i18next in conjunction with react-i18next (there’s an Angular, Vue and even jQuery support, among others) will help you maintain expressive code that’s i18n ready.
4 |
--------------------------------------------------------------------------------
/misc/the-history-of-i18next.md:
--------------------------------------------------------------------------------
1 | # The history of i18next
2 |
3 | ## How all began - back in 2011
4 |
5 | All started back in 2011 when we were in search for an internationalization library that meets our demand - allowing to run both on server side [Node.js](https://nodejs.org) and on our client side single page applications.
6 |
7 | 
8 |
9 | I18next was born and fastly grown to one of the most used frameworks for translating web applications and in [Node.js](https://nodejs.org). The response of the community was amazing and a fast growing [ecosystem](../overview/supported-frameworks.md) established itself around i18next.
10 |
11 | 
12 |
13 | ## V2
14 |
15 | With v2 of i18next, released in 2015, we completely rebuild i18next to be as extensible as possible.
16 |
17 | {% hint style="success" %}
18 | Since v1 all newer releases can be dropped in as a replacement for v1 by just adding a minimal compatibility layer. The v1 API is still actively tested, [here](https://github.com/i18next/i18next/blob/master/test/backward/v1.11.1.compat.js).
19 | {% endhint %}
20 |
21 | Shortly after the i18next v2 release in 2015, another big community driven i18next extension was released: [react-i18next](https://react.i18next.com/).
22 |
23 | 
24 |
25 | ## Internationalization (i18n) is not enough
26 |
27 | Our community provided us with great feedback. Out of that response and our own experiences we learnt providing instrumentation for doing proper internationalization just is not enough.
28 |
29 | Helping developers to get their applications translated is great - but there is more to it.
30 |
31 | * How do you integrate any translation services / agencies?
32 | * How do you keep track of new or removed content?
33 | * How do you handle proper versioning?
34 | * How do you deploy translation changes without deploying your complete application?
35 | * and a lot more...
36 |
37 | ### [locize](https://locize.com) to the rescue
38 |
39 | Having created the foundation with i18next it was a long journey to [**localization as a service**](https://locize.com).
40 |
41 | * [Easy to integrate](https://docs.locize.com/integration/instrumenting-your-code#i-18-next)
42 | * Continuous deployment? [Continuous localization](https://locize.com/how-it-works.html#continouslocalization) with a [CDN](https://docs.locize.com/whats-inside/cdn-content-delivery-network)!
43 | * Manage the translation files with ease
44 | * [Order professional translations](https://docs.locize.com/guides-tips-and-tricks/working-with-translators/localistars)
45 | * Analytics & Statistics
46 | * [Profit from a content delivery network](https://docs.locize.com/whats-inside/cdn-content-delivery-network)
47 | * [Versioning of your translations](https://docs.locize.com/more/versioning)
48 | * [Automatic and On-Demand Machine Translation](https://docs.locize.com/whats-inside/auto-machine-translation)
49 | * [Risk free: Take your data with you](https://docs.locize.com/more/general-questions/how-is-locize-different-from-the-alternatives#service-lock-in)
50 | * [Transparent and fair pricing](https://locize.com/pricing.html)
51 | * and a lot more...
52 |
53 | 
54 |
55 | {% hint style="success" %}
56 | 🙏 **The best way to directly support the future of i18next is to use** [**locize**](https://locize.com)**.** 💙
57 | {% endhint %}
58 |
59 | > _<\>_ [read the full interview](https://www.websiteplanet.com/blog/interview-locize/).
60 |
--------------------------------------------------------------------------------
/overview/api.md:
--------------------------------------------------------------------------------
1 | # API
2 |
3 | ### init
4 |
5 | `i18next.init(options, callback) // -> returns a Promise`
6 |
7 | The default export of the i18next module is an i18next instance ready to be initialized by calling `init`. You can create additional instances using the [createInstance](api.md#createinstance) function.
8 |
9 | Please read the [options page](configuration-options.md) for details on configuration options.
10 |
11 | The callback will be called after all translations were loaded or with an error when failed (in case of using a backend).
12 |
13 | **So you should wait for init to complete (wait for the callback or promise resolution) before using the `t` function!**
14 |
15 | {% hint style="info" %}
16 | In case of [react-i18next](https://react.i18next.com/) make sure useSuspense is enabled or handle the ready state in [HOCs](https://react.i18next.com/latest/withtranslation-hoc#not-using-suspense) or [hooks](https://react.i18next.com/latest/usetranslation-hook#not-using-suspense) yourself.
17 | {% endhint %}
18 |
19 | {% hint style="danger" %}
20 | Do not call init multiple times.\
21 | To change language use [changeLanguage](api.md#changelanguage). If you need complete different configs use [createInstance](api.md#createinstance) or [cloneInstance](api.md#cloneinstance).
22 | {% endhint %}
23 |
24 | {% hint style="warning" %}
25 | An error can occur if for example there was a loading issue when using a [backend](plugins-and-utils.md#backends) plugin.
26 | {% endhint %}
27 |
28 | ```javascript
29 | i18next.init({
30 | fallbackLng: 'en',
31 | ns: ['file1', 'file2'],
32 | defaultNS: 'file1',
33 | debug: true
34 | }, (err, t) => {
35 | if (err) return console.log('something went wrong loading', err);
36 | t('key'); // -> same as i18next.t
37 | });
38 |
39 | // with only callback
40 | i18next.init((err, t) => {
41 | if (err) return console.log('something went wrong loading', err);
42 | t('key'); // -> same as i18next.t
43 | });
44 |
45 | // using Promises
46 | i18next
47 | .init({ /* options */ })
48 | .then(function(t) { t('key'); });
49 | ```
50 |
51 | ### use
52 |
53 | `i18next.use(module)`
54 |
55 | The use function is there to load additional plugins to i18next.
56 |
57 | For available module see the [plugins page](plugins-and-utils.md) and don't forget to read the documentation of the plugin.
58 |
59 | ```javascript
60 | import i18next from 'i18next';
61 | import Backend from 'i18next-http-backend';
62 | import Cache from 'i18next-localstorage-cache';
63 | import postProcessor from 'i18next-sprintf-postprocessor';
64 | import LanguageDetector from 'i18next-browser-languagedetector';
65 |
66 | i18next
67 | .use(Backend)
68 | .use(Cache)
69 | .use(LanguageDetector)
70 | .use(postProcessor)
71 | .init(options, callback);
72 | ```
73 |
74 | ### t
75 |
76 | `i18next.t(keys, options)`
77 |
78 | Please have a look at the translation functions like [interpolation](../translation-function/interpolation.md), [formatting](../translation-function/formatting.md) and [plurals](../translation-function/plurals.md) for more details on using it.
79 |
80 | You can specify either one key as a `String` or multiple keys as an `Array` of `String`. The first one that resolves will be returned.
81 |
82 | ```javascript
83 | i18next.t('my.key'); // -> will return value in set language
84 |
85 | i18next.t(['unknown.key', 'my.key']); // -> will return value for 'my.key' in set language
86 | ```
87 |
88 | ### exists
89 |
90 | `i18next.exists(key, options)`
91 |
92 | Uses the same resolve functionality as the `t` function and returns true if a key exists.
93 |
94 | ```javascript
95 | i18next.exists('my.key'); // -> true if exists, false if not
96 | ```
97 |
98 | ### getFixedT
99 |
100 | `i18next.getFixedT(lng, ns, keyPrefix)`
101 |
102 | Returns a `t` function that defaults to given language or namespace.
103 |
104 | All arguments can be optional/null.
105 |
106 | `lng` and `ns` params could be arrays of languages or namespaces and will be treated as fallbacks in that case.
107 |
108 | The optional `keyPrefix` will be automatically applied to the returned t function. i.e.
109 |
110 | ```javascript
111 | const t = i18next.getFixedT(null, null, 'user.accountSettings.changePassword')
112 | const title = t('title'); // same as i18next.t('user.accountSettings.changePassword.title');
113 | ```
114 |
115 | {% hint style="warning" %}
116 | Do **not** use the `keyPrefix` option if you want to use keys with prefixed namespace notation:
117 |
118 | i.e.
119 |
120 | ```javascript
121 | const t = i18next.getFixedT(null, null, 'user.accountSettings.changePassword')
122 | const title = t('ns:title'); // this will not work
123 | ```
124 | {% endhint %}
125 |
126 | On the returned function you can like in the `t` function override the languages or namespaces by passing them in options or by prepending namespace.
127 |
128 | ```javascript
129 | // fix language to german
130 | const de = i18next.getFixedT('de');
131 | de('myKey');
132 |
133 | // or fix the namespace to anotherNamespace
134 | const anotherNamespace = i18next.getFixedT(null, 'anotherNamespace');
135 | anotherNamespace('anotherNamespaceKey'); // no need to prefix ns i18n.t('anotherNamespace:anotherNamespaceKey');
136 | ```
137 |
138 | ### changeLanguage
139 |
140 | `i18next.changeLanguage(lng, callback) // -> returns a Promise`
141 |
142 | Changes the language. The callback will be called as soon translations were loaded or an error occurs while loading.
143 |
144 | Calling `changeLanguage` without `lng` uses the [language detector](../misc/creating-own-plugins.md#languagedetector) to choose the language to set.
145 |
146 | **HINT:** For easy testing—setting `lng` to 'cimode' will cause the `t` function to always return the key.
147 |
148 | ```javascript
149 | i18next.changeLanguage('en', (err, t) => {
150 | if (err) return console.log('something went wrong loading', err);
151 | t('key'); // -> same as i18next.t
152 | });
153 |
154 | // using Promises
155 | i18next
156 | .changeLanguage('en')
157 | .then((t) => {
158 | t('key'); // -> same as i18next.t
159 | });
160 |
161 | // manually re-detecting language
162 | i18next.changeLanguage().then(...)
163 | ```
164 |
165 | ### language
166 |
167 | `i18next.language`
168 |
169 | Is set to the current detected or set language.
170 |
171 | If you need the primary used language depending on your configuration (supportedLngs, load) you will prefer using [`i18next.resolvedLanguage`](api.md#resolvedlanguage) or [`i18next.languages[0]`](api.md#languages).
172 |
173 | ### languages
174 |
175 | `i18next.languages`
176 |
177 | Is set to an array of language codes that will be used to look up the translation value.
178 |
179 | When the language is set, this array is populated with the new language codes. Unless overridden, this array is populated with less-specific versions of that code for fallback purposes, followed by the list of fallback languages.
180 |
181 | {% hint style="info" %}
182 | Values are unique, so if they appear earlier in the array, they will not be added again.
183 | {% endhint %}
184 |
185 | ```javascript
186 | // initialize with fallback languages
187 | i18next.init({
188 | fallbackLng: ["es", "fr", "en-US", "dev"]
189 | });
190 |
191 | // change the language
192 | i18next.changeLanguage("en-US-xx");
193 |
194 | // new language and its more generic forms, followed by fallbacks
195 | i18next.languages; // ["en-US-xx", "en-US", "en", "es", "fr", "dev"]
196 |
197 | // change the language again
198 | i18next.changeLanguage("de-DE");
199 |
200 | // previous language is not retained
201 | i18next.languages; // ["de-DE", "de", "es", "fr", "en-US", "dev"]
202 | ```
203 |
204 | ### resolvedLanguage
205 |
206 | `i18next.resolvedLanguage`
207 |
208 | Is set to the current resolved language.\
209 | It can be used as primary used language, for example in a language switcher.
210 |
211 | _(introduced in v21.0.0)_
212 |
213 | ### hasLoadedNamespace
214 |
215 | `i18next.hasLoadedNamespace(ns, options) // -> returns true or false`
216 |
217 | Checks if namespace has loaded yet. i.e. used by [react-i18next](https://react.i18next.com/)
218 |
219 | ### loadNamespaces
220 |
221 | `i18next.loadNamespaces(ns, callback) // -> returns a Promise`
222 |
223 | Loads additional namespaces not defined in init options.
224 |
225 | ```javascript
226 | i18next.loadNamespaces('myNamespace', (err) => { /* resources have been loaded */ });
227 | i18next.loadNamespaces(['myNamespace1', 'myNamespace2'], (err) => { /* resources have been loaded */ });
228 |
229 | // using Promises
230 | i18next
231 | .loadNamespaces(['myNamespace1', 'myNamespace2'])
232 | .then(() => {});
233 | ```
234 |
235 | ### loadLanguages
236 |
237 | `i18next.loadLanguages(lngs, callback) // -> returns a Promise`
238 |
239 | Loads additional languages not defined in init options (preload).
240 |
241 | ```javascript
242 | i18next.loadLanguages('de', (err) => { /* resources have been loaded */ });
243 | i18next.loadLanguages(['de', 'fr'], (err) => { /* resources have been loaded */ });
244 |
245 | // using Promises
246 | i18next
247 | .loadLanguages(['de', 'fr'])
248 | .then(() => {});
249 | ```
250 |
251 | ### reloadResources
252 |
253 | `i18next.reloadResources() // -> returns a Promise`
254 |
255 | Reloads resources on given state. Optionally you can pass an array of languages and namespaces as params if you don't want to reload all.
256 |
257 | ```javascript
258 | // reload all
259 | i18next.reloadResources();
260 |
261 | // reload languages
262 | i18next.reloadResources(['de', 'fr']);
263 |
264 | // reload namespaces for all languages
265 | i18next.reloadResources(null, ['ns1', 'ns2']);
266 |
267 | // reload namespaces in languages
268 | i18next.reloadResources(['de', 'fr'], ['ns1', 'ns2']);
269 |
270 | // reload a namespace in a language
271 | i18next.reloadResources('de', 'ns1');
272 |
273 | // optional third param callback i18next@>=11.9.0
274 | i18next.reloadResources('de', 'ns1', () => { /* reloaded */ });
275 |
276 | // using Promises
277 | i18next
278 | .reloadResources()
279 | .then(() => {});
280 | ```
281 |
282 | ### setDefaultNamespace
283 |
284 | `i18next.setDefaultNamespace(ns)`
285 |
286 | Changes the default namespace.
287 |
288 | ### dir
289 |
290 | `i18next.dir(lng)`
291 |
292 | Returns `rtl` or `ltr` depending on languages read direction.
293 |
294 | ```javascript
295 | // for current language
296 | i18next.dir();
297 |
298 | // for another language
299 | i18next.dir('en-US'); // -> "ltr";
300 | i18next.dir('ar'); // -> "rtl";
301 | ```
302 |
303 | ### format
304 |
305 | `i18next.format(data, format, lng)`
306 |
307 | _introduced in v8.4.0 and legacy since v21.3.0_
308 |
309 | Exposes `interpolation.format`t function added on init.
310 |
311 | For formatting used in translation files checkout the [formatting doc](../translation-function/formatting.md#legacy-format-function-i18next-less-than-21.3.0).
312 |
313 | ```javascript
314 | // key = 'hello {{what}}'
315 | i18next.t('key', { what: i18next.format('world', 'uppercase') }); // -> hello WORLD
316 | ```
317 |
318 | ## instance creation
319 |
320 | ### createInstance
321 |
322 | `i18next.createInstance(options, callback)`
323 |
324 | Will return a new i18next instance.
325 |
326 | Please read the [options page](configuration-options.md) for details on configuration options.
327 |
328 | Providing a callback will automatically call init.
329 |
330 | The callback will be called after all translations were loaded or with an error when failed (in case of using a backend).
331 |
332 | ```javascript
333 | const newInstance = i18next.createInstance({
334 | fallbackLng: 'en',
335 | ns: ['file1', 'file2'],
336 | defaultNS: 'file1',
337 | debug: true
338 | }, (err, t) => {
339 | if (err) return console.log('something went wrong loading', err);
340 | t('key'); // -> same as i18next.t
341 | });
342 |
343 | // is the same as
344 | const newInstance = i18next.createInstance();
345 | newInstance.init({
346 | fallbackLng: 'en',
347 | ns: ['file1', 'file2'],
348 | defaultNS: 'file1',
349 | debug: true
350 | }, (err, t) => {
351 | if (err) return console.log('something went wrong loading', err);
352 | t('key'); // -> same as i18next.t
353 | });
354 | ```
355 |
356 | ### cloneInstance
357 |
358 | `i18next.cloneInstance(options)`
359 |
360 | Creates a clone of the current instance. Shares store, plugins and initial configuration. Can be used to create an instance sharing storage but being independent on set language or default namespaces.
361 |
362 | ```javascript
363 | const newInstance = i18next.cloneInstance({
364 | fallbackLng: 'en',
365 | defaultNS: 'file1'
366 | });
367 | ```
368 |
369 | #### forkResourceStore
370 |
371 | By setting the forkResourceStore option to true, it will not shares the store.
372 |
373 | ```javascript
374 | const newInstance = i18next.cloneInstance({
375 | forkResourceStore: true,
376 | keySeparator: '[[my-new-separator]]'
377 | });
378 | ```
379 |
380 | ## events
381 |
382 | {% hint style="info" %}
383 | Every event can be unsubscribed using
384 |
385 | `i18next.off('name', myFunction);`
386 |
387 | All attached listeners can be unsubscribed using
388 |
389 | `i18next.off('name');`
390 | {% endhint %}
391 |
392 | ### onInitialized
393 |
394 | `i18next.on('initialized', function(options) {})`
395 |
396 | Gets fired after initialization.
397 |
398 | ### onLanguageChanged
399 |
400 | `i18next.on('languageChanged', function(lng) {})`
401 |
402 | Gets fired when changeLanguage got called.
403 |
404 | ### onLoaded
405 |
406 | `i18next.on('loaded', function(loaded) {})`
407 |
408 | Gets fired on loaded resources.
409 |
410 | ### onFailedLoading
411 |
412 | `i18next.on('failedLoading', function(lng, ns, msg) {})`
413 |
414 | Gets fired if loading resources failed (after the in-built retry algorithm).
415 |
416 | ### onMissingKey
417 |
418 | `i18next.on('missingKey', function(lngs, namespace, key, res) {})`
419 |
420 | Gets fired on accessing a key not existing. Needs [saveMissing](configuration-options.md#missing-keys) set to true.
421 |
422 | ## store events
423 |
424 | Please be aware the `i18next.store` is only available on i18next after the init call.
425 |
426 | ### onAdded
427 |
428 | `i18next.store.on('added', function(lng, ns) {})`
429 |
430 | Gets fired when resources got added.
431 |
432 | ### onRemoved
433 |
434 | `i18next.store.on('removed', function(lng, ns) {})`
435 |
436 | Gets fired when resources got removed.
437 |
438 | ## resource handling
439 |
440 | Can be accessed on `i18next` or `i18next.services.resourceStore`.
441 |
442 | ### getResource
443 |
444 | `i18next.getResource(lng, ns, key, options)`
445 |
446 | Gets one value by given key.
447 |
448 | options:
449 |
450 | | option | default | description |
451 | | ------------------- | ------- | ---------------------------------------------------------------------- |
452 | | keySeparator | "." | char to separate keys, or false if no separator is preferred |
453 | | ignoreJSONStructure | true | if a key is not found as nested key, it will try to lookup as flat key |
454 |
455 | ### addResource
456 |
457 | `i18next.addResource(lng, ns, key, value, options)`
458 |
459 | Adds one key/value.
460 |
461 | options:
462 |
463 | | option | default | description |
464 | | ------------ | ------- | ------------------------------------------------------------ |
465 | | keySeparator | "." | char to separate keys, or false if no separator is preferred |
466 | | silent | false | if set to true adding will not emit an added event |
467 |
468 | ### addResources
469 |
470 | `i18next.addResources(lng, ns, resources)`
471 |
472 | Adds multiple key/values.
473 |
474 | ### addResourceBundle
475 |
476 | `i18next.addResourceBundle(lng, ns, resources, deep, overwrite)`
477 |
478 | Adds a complete bundle.
479 |
480 | Setting deep (default false) param to true will extend existing translations in that file. Setting deep and overwrite (default false) to true it will overwrite existing translations in that file.
481 |
482 | So omitting deep and overwrite will overwrite all existing translations with the one provided in resources. Using deep you can choose to keep existing nested translation and to overwrite those with the new ones.
483 |
484 | ```javascript
485 | i18next.addResourceBundle('en', 'translations', {
486 | key: 'value',
487 | }, true, true);
488 | ```
489 |
490 | ### hasResourceBundle
491 |
492 | `i18next.hasResourceBundle(lng, ns)`
493 |
494 | Checks if a resource bundle exists.
495 |
496 | ### getDataByLanguage
497 |
498 | `i18next.getDataByLanguage(lng)`
499 |
500 | Returns a resource data by language.
501 |
502 | ### getResourceBundle
503 |
504 | `i18next.getResourceBundle(lng, ns)`
505 |
506 | Returns a resource bundle.
507 |
508 | ### removeResourceBundle
509 |
510 | `i18next.removeResourceBundle(lng, ns)`
511 |
512 | Removes an existing bundle.
513 |
--------------------------------------------------------------------------------
/overview/comparison-to-others.md:
--------------------------------------------------------------------------------
1 | # Comparison to others
2 |
3 | You now might expect we compare eg. react-i18next to react-intl but that won't happen ;). But we will list why you should trust i18next to be the best choice for internationalization.
4 |
5 | ## Sustainability
6 |
7 | i18next was created in late 2011. What does that mean? It's older than most of the libraries you will use nowadays, including your main frontend tech (react, vue, ...).
8 |
9 | Believe it or not but by the time of writing, the v11.x.x can be dropped in as a replacement for v1 by just adding a minimal compatibility layer. It's important to us not breaking things just for the sake of using new fancy stuff (which does not mean we do not keep up with latest possibilities of development).
10 |
11 | ## Maturity
12 |
13 | Based on how long i18next already is available open source, there is no real i18n case that could not be solved with i18next.
14 |
15 | i18next and its localization service [https://locize.com](https://locize.com/) are used by companies small to very large.
16 |
17 | ## Extensibility
18 |
19 | With v2 of i18next we completely rebuild i18next to be as extensible as possible. Doing this i18next can be used in any javascript (and a few non-javascript - .net, elm, iOS, android, ...) environment, with any UI framework, with any i18n format, ... the possibilities are endless.
20 |
21 | Just have a look at what the community built around the i18next core:
22 |
23 | * [Supported Frameworks](supported-frameworks.md)
24 | * [Plugins and Utils](plugins-and-utils.md)
25 |
26 | ## Richness
27 |
28 | The regular i18n frameworks work like this:
29 |
30 | 1. You pass in all translations and the used language
31 | 2. You call a function that returns the correct translation based on the translations you passed in and provided values for plural and interpolation.
32 |
33 | What you don't get by others - but get with i18next
34 |
35 | * Splitting translations into multiple files. Only load translations needed.
36 | * There are plugins to **detect languages** for most environments (browser, native, server). This enables to set priority of where to detect and even enables to cache set languages over requests / visits.
37 | * There are endless plugins to **load translation** from server, filesystem, ... these backends also assert that loading gets retried on failure, or that a file does not get loaded twice and callbacks of success are only called once. Those backends can even provide an additional layer for **local caching** eg. in localStorage.
38 | * Options what to load and how to fallback depending on language.
39 | * Support for [objects and arrays](https://www.i18next.com/translation-function/objects-and-arrays)
40 | * Full control over management of the translations stored.
41 | * Rich system of events to react on changes important to your application.
42 | * Freedom of [i18n formats](https://www.i18next.com/overview/plugins-and-utils#i-18-n-formats) - prefer ICU? Just use i18next-icu plugin.
43 |
44 | ## But I heard
45 |
46 | ### i18next is complicated
47 |
48 | True, i18next's documentation is bigger than that of other i18n frameworks - but that's also a tribute to offering a lot more features that you would have to build yourself otherwise (language detection, translation loading, ...).
49 |
50 | If you do not need that i18next is as simple as any other i18n framework:
51 |
52 | ```javascript
53 | import i18next from 'i18next';
54 |
55 | i18next.init({
56 | lng: 'de',
57 | resources: {
58 | de: {
59 | translation: {
60 | "hello world": "hallo Welt"
61 | }
62 | }
63 | }
64 | });
65 | i18next.t('hello world'); // hallo Welt
66 | ```
67 |
68 | ### i18next is bloated
69 |
70 | Hm... ask this in one year again. When your i18n framework needs to catch up with the needs of production systems.
71 |
72 | We work hard on keeping the code base clean and readable. We add new features which might help a lot of users and not based on we think it's easy to solve.
73 |
74 | ### i18next is too big
75 |
76 | Yes, a size of 33kb minified and 9kb gzipped is huge. But like you saw before there is a lot more inside than just the basic i18n functionality.
77 |
78 | But you could make this smaller by precompiling the translations. We could bring down i18next to 4kb gzipped (good to advertise) but on the other hand your translation files would grow significantly.
79 |
80 | ## We tell you
81 |
82 | ### I18next can do more
83 |
84 | Just two samples of extended functionality you can get:
85 |
86 | #### a) Ever liked to **dynamically fallback** your error messages to a general info if no specific message is available?
87 |
88 | translation.json
89 |
90 | ```javascript
91 | {
92 | "error": {
93 | "unspecific": "Something went wrong.",
94 | "404": "The page was not found."
95 | }
96 | }
97 | ```
98 |
99 | Sample
100 |
101 | ```javascript
102 | const error = '404';
103 | i18next.t([`error.${error}`, 'error.unspecific']) // -> "The page was not found"
104 |
105 | const error = '502';
106 | i18next.t([`error.${error}`, 'error.unspecific']) // -> "Something went wrong"
107 | ```
108 |
109 | #### b) Or like to say something like **interval plurals**:
110 |
111 | * many goodies still available
112 | * just a few goodies remaining...
113 | * no goodies remaining...sorry you're too late
114 |
115 | Just drop in the [interval-postprocessor](https://github.com/i18next/i18next-intervalPlural-postProcessor)
116 |
117 | ```javascript
118 | {
119 | key_interval: '(0){no goodies remaining...sorry you`re too late};(1-100){just a few goodies remaining...};(100-inf){many goodies still available};'
120 | }
121 | ```
122 |
123 | ### Works on serverside
124 |
125 | While some other i18n frameworks run on serverside too there are not many optimized for it. Loading translations only once (think of a render to string in react.js where you create a new instance and inject translations over and over). Also does it keep the set language during async requests or do simultaneous requests create race conditions in setting the right language?
126 |
127 | ### Learn once - translate everywhere
128 |
129 | 
130 |
131 | Should speak for itself.
132 |
133 | ### We bridge the gap to localization
134 |
135 | Being honest, internationalization is the smaller pain in getting a site translated. Localization and the translation process are where the real hard work starts.
136 |
137 | With [https://locize.com](https://locize.com/) we fill this gap and enable a localization workflow as never seen before:
138 |
139 | {% embed url="https://youtu.be/osScyaGMVqo" %}
140 |
--------------------------------------------------------------------------------
/overview/first-setup-help.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: Let's try to figure out what you need.
3 | ---
4 |
5 | # First setup help
6 |
7 | * [For which environment are you looking for an i18n solution?](first-setup-help.md#for-which-environment-are-you-looking-for-an-i-18-n-solution)
8 | * [Special handling for serverless environments (AWS lambda, Google Cloud Functions, Azure Functions, etc...)](first-setup-help.md#special-handling-for-serverless-environments-aws-lambda-google-cloud-functions-azure-functions-etc)
9 | * [Do you need a language detector for your environment?](first-setup-help.md#do-you-need-a-language-detector-for-your-environment)
10 | * [Do you want to bundle the translations with your app?](first-setup-help.md#do-you-want-to-bundle-the-translations-with-your-app)
11 | * [Do you want to load the translations separate from your app via http?](first-setup-help.md#do-you-want-to-load-the-translations-separate-from-your-app-via-http)
12 | * [Do you want to manage your translations with an awesome translation management system?](first-setup-help.md#do-you-want-to-manage-your-translations-with-an-awesome-translation-management-system)
13 |
14 | ## For which environment are you looking for an i18n solution?
15 |
16 | [Client](https://react.i18next.com/), [server](https://github.com/i18next/i18next-http-middleware), [browser](https://github.com/i18next/jquery-i18next), [React](https://react.i18next.com), [mobile](https://github.com/i18next/react-i18next/tree/master/example/ReactNativeProject), [desktop](https://github.com/i18next/react-i18next/tree/master/example/react_native_windows), [Node.js](https://github.com/i18next/i18next-fs-backend/blob/master/example/node/index.js), [Deno](https://github.com/i18next/i18next-fs-backend/blob/master/example/deno/index.js)...
17 |
18 | There are a lot of appropriate libraries. [Have a look at this list.](supported-frameworks.md)
19 |
20 | ### Special handling for serverless environments (AWS lambda, Google Cloud Functions, Azure Functions, etc...)
21 |
22 | Make use of [i18next-fs-backend](https://github.com/i18next/i18next-fs-backend)
23 |
24 | ```javascript
25 | import i18next from 'i18next';
26 | import Backend from 'i18next-fs-backend';
27 |
28 | const backend = new Backend({
29 | // path where resources get loaded from
30 | loadPath: '/locales/{{lng}}/{{ns}}.json'
31 | });
32 |
33 | i18next
34 | .use(backend)
35 | .init({
36 | // initImmediate: false, // setting initImediate to false, will load the resources synchronously
37 | ...opts,
38 | ...yourOptions
39 | }); // yourOptions should not include backendOptions!
40 | ```
41 |
42 | or just [import/require](https://www.i18next.com/how-to/add-or-load-translations#add-on-init) your files directly
43 |
44 | ```javascript
45 | import i18next from 'i18next';
46 | import en from './locales/en.json'
47 | import de from './locales/de.json'
48 |
49 | i18next
50 | .init({
51 | ...opts,
52 | ...yourOptions,
53 | resources: {
54 | en,
55 | de
56 | }
57 | });
58 | ```
59 |
60 | ## Do you need a language detector for your environment?
61 |
62 | * for example for the browser: [i18next-browser-languageDetector](https://github.com/i18next/i18next-browser-languageDetector)
63 | * for example for http server (express, Fastify, etc...): [i18next-http-middleware](https://github.com/i18next/i18next-http-middleware#language-detection)
64 | * [there are other plugins here](https://www.i18next.com/overview/plugins-and-utils#language-detector)
65 |
66 | ## Do you want to bundle the translations with your app?
67 |
68 | * [you can add translations on init](../how-to/add-or-load-translations.md#add-on-init)
69 | * [you can add translations after init](../how-to/add-or-load-translations.md#add-after-init)
70 | * [you can lazy load translations via dynamic import](../how-to/add-or-load-translations.md#lazy-load-in-memory-translations)
71 | * on server side: [you can load translations from filesystem](https://github.com/i18next/i18next-fs-backend)
72 |
73 | ## Do you want to load the translations separate from your app via http?
74 |
75 | * served from your own endpoint: [i18next-http-backend](https://github.com/i18next/i18next-http-backend)
76 | * served from a professional CDN of a translation management system: [i18next-locize-backend](https://github.com/locize/i18next-locize-backend)
77 | * [there are a lot of other backend possibilities here](plugins-and-utils.md#backends)
78 |
79 | ## Do you want to manage your translations with an awesome translation management system?
80 |
81 | ### [Ready to take i18next to the next level?](for-enterprises.md)
82 |
--------------------------------------------------------------------------------
/overview/for-enterprises.md:
--------------------------------------------------------------------------------
1 | # For Enterprises
2 |
3 | ## Is i18n enough?
4 |
5 | We believe not. The closer the release date of your product gets the more obvious it gets, that instrumenting your code for localization is not enough.
6 |
7 | There are more points to address:
8 |
9 | * How does the translation process work?
10 | * How do the source files get to the translators and back?
11 | * How do you keep track which parts are already translated and which parts are not - and additional are all target languages fully translated?
12 | * How do you deploy new languages after release?
13 | * How do you handle versioning?
14 | * How do you update / fix typos in translations after deployment?
15 |
16 | Translation Management Systems are a great help. But most tools out there are built for one-time translation of your documents. Not for continuously translating your application. So there is still a gap between the development and the translation process.
17 |
18 | > So is there a smart localization management platform? An [i18n(ext) platform](https://www.locize.com/i18next)?
19 |
20 | ## Locize
21 |
22 | 
23 |
24 | [Locize](http://locize.com/?utm_source=i18next_com\&utm_medium=gitbook) is a localization as a service platform made by i18next. The close integration of i18next brings a lot of additional value and asserts you an additional level of support and saves you endless time spent on localization.
25 |
26 | {% embed url="https://www.youtube.com/watch?v=TFV_vhJs5DY" %}
27 |
28 | Locize brings you:
29 |
30 | * A beautiful editor to edit your translations
31 | * Enables a continuous localization process
32 | * An in-context editor to edit on your own website
33 | * Progress reporting
34 | * Usage reporting
35 | * Plural conversion between languages
36 | * Support for versions
37 | * Gets your missing keys passed directly to the project
38 | * Hosts translation on its CDN and allows for automatic or manual publishing (You still have the option to host translations yourself)
39 |
40 | Check out how it works => [https://www.youtube.com/watch?v=TFV\_vhJs5DY](https://www.youtube.com/watch?v=TFV_vhJs5DY)
41 |
42 | _Together, 'i18next' and '_[_locize_](https://locize.com)_' empower your business to effortlessly reach international audiences. They help you speak the language of your customers, making your business more accessible, relatable, and successful in global markets._
43 |
--------------------------------------------------------------------------------
/overview/getting-started.md:
--------------------------------------------------------------------------------
1 | # Getting started
2 |
3 | ## Installation
4 |
5 | i18next can be added to your project using **npm** or **yarn**:
6 |
7 | ```bash
8 | # npm
9 | $ npm install i18next --save
10 |
11 | # yarn
12 | $ yarn add i18next
13 | ```
14 |
15 | The default export is UMD compatible (commonjs, requirejs, global).
16 |
17 | In the `/dist` folder you may find additional builds for commonjs, es6 modules. Optimized to load i18next in webpack, rollup, ... or node.js. The correct entry points are already configured in the package.json so there should be no extra setup to get the best build option.
18 |
19 | ## Load in [Deno](https://deno.land/)
20 |
21 | i18next can be imported like this:
22 |
23 | ```javascript
24 | import i18next from 'https://deno.land/x/i18next/index.js'
25 | // or import i18next from 'https://raw.githubusercontent.com/i18next/i18next/master/src/index.js'
26 | // or import i18next from 'https://cdn.jsdelivr.net/gh/i18next/i18next/src/index.js'
27 | ```
28 |
29 | {% hint style="success" %}
30 | In [this tutorial blog post](https://locize.com/blog/i18n-for-deno-with-i18next/) you can check out how this works.[\
31 | ](https://locize.com/blog/i18n-for-deno-with-i18next/)[](https://locize.com/blog/i18n-for-deno-with-i18next/)
32 | {% endhint %}
33 |
34 | ## Load from CDN
35 |
36 | You can also directly add a script tag loading i18next from one of the CDNs providing it:
37 |
38 | **unpkg.com**
39 |
40 | * [https://unpkg.com/i18next/dist/umd/i18next.js](https://unpkg.com/i18next/dist/umd/i18next.js)
41 | * [https://unpkg.com/i18next/dist/umd/i18next.min.js](https://unpkg.com/i18next/dist/umd/i18next.min.js)
42 |
43 | esm or cjs:
44 |
45 | * [https://unpkg.com/i18next/dist/esm/i18next.js](https://unpkg.com/i18next/dist/esm/i18next.js)
46 | * [https://unpkg.com/i18next/dist/cjs/i18next.js](https://unpkg.com/i18next/dist/cjs/i18next.js)
47 |
48 | Make sure to use a fixed version in production like [https://unpkg.com/i18next@17.0.0/dist/umd/i18next.js](https://unpkg.com/i18next/dist/umd/i18next.js) as passing no version will redirect to latest version which might contain breaking changes in future.
49 |
50 | **cdnjs.com**
51 |
52 | * [https://cdnjs.com/libraries/i18next](https://cdnjs.com/libraries/i18next)
53 |
54 | **jsdelivr.com**
55 |
56 | * [https://www.jsdelivr.com/package/npm/i18next](https://www.jsdelivr.com/package/npm/i18next)
57 |
58 | ## Important Caveat
59 |
60 | Before we dive into the first sample, please note the following: By default, i18next uses a key-based notation to look up translations, which comes with the benefit of [additional structure](../translation-function/essentials.md) for your translation files.
61 |
62 | The downside of this is that your keys must not be in natural language — the names of the keys are not used as fallback content and the key names must not include reserved characters `:` and `.` since those are used by i18next.
63 |
64 | If you prefer using natural language in keys, please read the [fallback guide](../principles/fallback.md#key-fallback).
65 |
66 | ## Basic sample
67 |
68 | Please be aware these samples are just showing basic usage of the core functionality. For production usage please consider using one of our [framework integrations](supported-frameworks.md) to get better and simpler integrations (Setting innerHTML is just done to show how it works).
69 |
70 | ```javascript
71 | import i18next from 'i18next';
72 |
73 | i18next.init({
74 | lng: 'en', // if you're using a language detector, do not define the lng option
75 | debug: true,
76 | resources: {
77 | en: {
78 | translation: {
79 | "key": "hello world"
80 | }
81 | }
82 | }
83 | });
84 | // initialized and ready to go!
85 | // i18next is already initialized, because the translation resources where passed via init function
86 | document.getElementById('output').innerHTML = i18next.t('key');
87 | ```
88 |
89 | Or using callback init signature:
90 |
91 | ```javascript
92 | import i18next from 'i18next';
93 |
94 | i18next.init({
95 | lng: 'en', // if you're using a language detector, do not define the lng option
96 | debug: true,
97 | resources: {
98 | en: {
99 | translation: {
100 | "key": "hello world"
101 | }
102 | }
103 | }
104 | }, function(err, t) {
105 | // initialized and ready to go!
106 | document.getElementById('output').innerHTML = i18next.t('key');
107 | });
108 | ```
109 |
110 | Or using Promises:
111 |
112 | ```javascript
113 | i18next.init({
114 | lng: 'en', // if you're using a language detector, do not define the lng option
115 | debug: true,
116 | resources: {
117 | en: {
118 | translation: {
119 | "key": "hello world"
120 | }
121 | }
122 | }
123 | }).then(function(t) {
124 | // initialized and ready to go!
125 | document.getElementById('output').innerHTML = i18next.t('key');
126 | });
127 | ```
128 |
129 | Or using async/await:
130 |
131 | ```javascript
132 | await i18next.init({
133 | lng: 'en', // if you're using a language detector, do not define the lng option
134 | debug: true,
135 | resources: {
136 | en: {
137 | translation: {
138 | "key": "hello world"
139 | }
140 | }
141 | }
142 | });
143 | // initialized and ready to go!
144 | document.getElementById('output').innerHTML = i18next.t('key');
145 | ```
146 |
147 | {% hint style="info" %}
148 | if you are [lazy loading the translation resources](../how-to/add-or-load-translations.md), you may need to wait for i18next to have finished to initialize.
149 | {% endhint %}
150 |
151 | As you might see, this basic sample provides only one language directly added on init… let's extend this to have buttons to change language from English to German:
152 |
153 | [source code](https://jsfiddle.net/jamuhl/dvk0e8a9/#tabs=js,result,html)
154 |
155 | {% hint style="info" %}
156 | Do you quickly want to translate your resources to other languages?\
157 | Try: [https://translate.i18next.com](https://translate.i18next.com/)
158 | {% endhint %}
159 |
160 | This is a working sample showing translated text. To learn more, have a look at the following extended sample:
161 |
162 | ## Extended sample
163 |
164 | The extended sample adds the language detector for our browser and the http-backend to load translation files from this documentation's [i18next-gitbook repo](https://github.com/i18next/i18next-gitbook/tree/master/locales).
165 |
166 | [source code](https://jsfiddle.net/jamuhl/ferfywyf/525/)
167 |
168 | You should now have an idea about how to achieve the basic setup. It's time to learn more about:
169 |
170 | * The translation functions like [interpolation](../translation-function/interpolation.md), [formatting](../translation-function/formatting.md) and [plurals](../translation-function/plurals.md).
171 | * Find an [extension for your project](supported-frameworks.md), eg. **react-i18next**, **jquery-i18next** and **others**. Using those wrappers around i18next makes using i18next a lot simpler in your project. Most of such modules come with extended examples.
172 | * Find out more about the [configuration options](configuration-options.md).
173 | * Add a [language detector](plugins-and-utils.md) to detect the preferred language of your user
174 | * Add a [backend plugin](plugins-and-utils.md) to load the translations from the server or filesystem
175 | * Connect i18next with a smart [Translation Management System](https://locize.com), like in [this React.js example](https://github.com/locize/react-tutorial)
176 |
--------------------------------------------------------------------------------
/overview/typescript.md:
--------------------------------------------------------------------------------
1 | # TypeScript
2 |
3 | i18next has embedded type definitions. If you want to enhance IDE Experience and prevent errors (such as type coercion), you should follow the instructions below in order to get the t function fully-type safe (keys and return type).
4 |
5 | {% hint style="info" %}
6 | This is an optional feature and may affect the **compilation time** depending on your project's size. If you opt not to leverage the type enhancements suggested here, you can ignore this section.
7 | {% endhint %}
8 |
9 | {% hint style="info" %}
10 | Make sure your tsconfig compilerOptions has the [`strict`](https://www.typescriptlang.org/tsconfig#strict) flag or the [`strictNullChecks`](https://www.typescriptlang.org/tsconfig#strictNullChecks) set to `true`.\
11 | The newest i18next versions only support **TypeScript v5**. Older TypeScript versions are not supported any longer with `i18next > v23`.\
12 | NAN;_To use it with TypeScript v4, use `i18next@22.5.1`._
13 | {% endhint %}
14 |
15 | {% hint style="warning" %}
16 | If your project spans multiple i18next instances with different translation resources, you probably can't use type-safe translations.
17 | {% endhint %}
18 |
19 | {% hint style="success" %}
20 | [Here](https://locize.com/blog/i18next-typescript/) you'll find a simple guide on how to best use TypeScript for i18next.\
21 | Discover how to unleash the full potential of i18next in your TypeScript applications by mastering type-safe translations, ensuring accurate localization and eliminating runtime errors.\
22 | [](https://locize.com/blog/i18next-typescript/)
23 | {% endhint %}
24 |
25 | {% embed url="https://youtu.be/GLIas4DH3Ww" %}
26 |
27 | ## Create a declaration file
28 |
29 | TypeScript definitions for i18next can be extended by using [Type Augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation) and [Merging Interfaces](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#merging-interfaces). So the first step is creating a declaration file (`i18next.d.ts`), for example:
30 |
31 | ```typescript
32 | // import the original type declarations
33 | import "i18next";
34 | // import all namespaces (for the default language, only)
35 | import ns1 from "locales/en/ns1.json";
36 | import ns2 from "locales/en/ns2.json";
37 |
38 | declare module "i18next" {
39 | // Extend CustomTypeOptions
40 | interface CustomTypeOptions {
41 | // custom namespace type, if you changed it
42 | defaultNS: "ns1";
43 | // custom resources type
44 | resources: {
45 | ns1: typeof ns1;
46 | ns2: typeof ns2;
47 | };
48 | // other
49 | }
50 | }
51 | ```
52 |
53 | Or, if you want to include all namespaces at once, you can use our preferred approach:
54 |
55 | **`i18n.ts`**
56 |
57 | ```typescript
58 | export const defaultNS = "ns1";
59 | export const resources = {
60 | en: {
61 | ns1,
62 | ns2,
63 | },
64 | } as const;
65 |
66 | i18n.use(initReactI18next).init({
67 | lng: "en",
68 | ns: ["ns1", "ns2"],
69 | defaultNS,
70 | resources,
71 | });
72 | ```
73 |
74 | **`i18next.d.ts`**
75 |
76 | ```typescript
77 | import { resources, defaultNS } from "./i18n";
78 |
79 | declare module "i18next" {
80 | interface CustomTypeOptions {
81 | defaultNS: typeof defaultNS;
82 | resources: typeof resources["en"];
83 | }
84 | }
85 | ```
86 |
87 | **We recommend creating a `@types` directory under `src` or above it and placing all your type declarations there. E.g.: `@types/i18next.d.ts`**
88 |
89 | ### Some examples
90 |
91 | * [various examples](https://github.com/locize/i18next-typescript-examples) _(from simple i18next only to react-i18next prod ready)_
92 | * [react-i18next](https://github.com/i18next/react-i18next/tree/master/example/react-typescript)
93 | * [next-i18next](https://github.com/i18next/next-i18next/tree/master/examples/simple)
94 | * [next-13-app-dir-i18next-example-ts](https://github.com/i18next/next-13-app-dir-i18next-example-ts)
95 | * [react-i18next-example-app-ts](https://github.com/locize/react-i18next-example-app-ts)
96 |
97 | ### Custom Type Options
98 |
99 | We provide a few options that can improve TypeScript for `i18next`. All options come with default values, and if you want to change them, you just need to add them under `CustomTypeOptions` interface in your i18next type declaration file (`i18next.d.ts`).
100 |
101 | | option | default | description |
102 | | ------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
103 | | defaultNS | 'translation' | Default namespace. This is more practical in React applications, so when you call `useTranslation()` hooks without passing the namespace, it will infer the types for the `translation` namespace. |
104 | | resources | object | Resources to initialize with. This is the most important option that is used to infer the appropriate keys and return types. |
105 | | fallbackNS | false | Fallback namespace. string or array of namespaces to lookup key if not found in given namespace. [See NS fallback docs](../principles/fallback.md#namespace-fallback). |
106 | | keySeparator | '.' | Char to separate keys. |
107 | | nsSeparator | ':' | Char to split namespace from key |
108 | | pluralSeparator | '\_' | Char to split namespace from key |
109 | | contextSeparator | '\_' | Char to split context from key |
110 | | returnNull | true | Allows null values as valid translation. |
111 | | returnObjects | false | Allows objects as valid translation result |
112 | | compatibilityJSON | 'v4' | Only 'v4' is supported. Enable plurals keys support. See [Plurals docs](../translation-function/plurals.md). |
113 | | allowObjectInHTMLChildren | false | Flag that allows HTML elements to receive objects. This is only useful for React applications where you pass objects to HTML elements so they can be replaced to their respective interpolation values (mostly with Trans component) |
114 | | interpolationPrefix | '\{{' | Prefix for interpolation |
115 | | interpolationSuffix | '\}}' | Suffix for interpolation |
116 | | strictKeyChecks | false | Flag that enables strict key checking even if a `defaultValue` has been provided. This ensures all calls of `t` function don't accidentally use implicitly missing keys. |
117 |
118 | ## Troubleshooting
119 |
120 | ### Intellisense not working
121 |
122 | Try to update the used TypeScript version _(>= v5 is recommended)_.
123 |
124 | ### Out of memory (OOM) errors
125 |
126 | Running typechecking with key validation might result in OOM errors. This can be facilitated by additional factors like:
127 |
128 | * large codebase with a lot of namespace with hundreds of keys
129 | * running typechecking alongside other tools like `ESLint` combined with `typescript-eslint`
130 |
131 | {% hint style="info" %}
132 | When having this kind of error consider to:
133 |
134 | * If you are on a large codebase consider split the typecheck / lint process in separate tasks
135 | * Split the code in multiple packages (monorepo)
136 | * Use Node `--max-old-space-size` option to increase Node memory
137 |
138 | E.g.:
139 |
140 | ```shell
141 | export NODE_OPTIONS=\"--max_old_space_size=10240\" && tsc
142 | ```
143 | {% endhint %}
144 |
145 | {% hint style="warning" %}
146 | If you report a OOM error, please provide an easy way to reproduce the issue using:
147 |
148 | * online sandbox
149 | * example repository
150 | {% endhint %}
151 |
152 | ### Not working interpolation values
153 |
154 | `t` function infers interpolation values, but it'll only work if the translation files (resources) are placed in a ts file and using `as const` _(like_ [_this_](https://github.com/i18next/i18next/blob/master/examples/typescript/i18n/en/ns1.ts)_)_ or an [interface in a d.ts file](https://github.com/locize/react-i18next-example-app-ts/blob/main/src/%40types/resources.d.ts) _(can be generated like_ [_this_](https://github.com/locize/react-i18next-example-app-ts/blob/751f704984c206076d08638442ae34b3507aa7ad/package.json#L35)_)_, JSON files don't support `as const` to convert objects to be type literals (yet).
155 |
156 | ### `Type 'HTMLAttributes' is not assignable to type...`
157 |
158 | This happens when [`skipLibCheck`](https://www.typescriptlang.org/tsconfig#skipLibCheck) is disabled. Setting `skipLibCheck` in tsconfig to `true` will remove this issue.
159 |
160 | ### Type error - template literal
161 |
162 | If you face this issue:
163 |
164 | > Argument of type 'string' is not assignable to parameter of type ...
165 |
166 | When using the following approach (template literal with an expression):
167 |
168 | ```typescript
169 | // with i18next
170 | i18next.t(`${expression}.title`);
171 |
172 | // with react-i18next
173 | const { t } = useTranslation();
174 | t(`${expression}.title`);
175 | ```
176 |
177 | Or:
178 |
179 | ```typescript
180 | // with react-i18next
181 | const { t } = useTranslation(`${ns}Default`);
182 | ```
183 |
184 | TypeScript will lose the literal value, and it will infer the `key` as string, which will cause to throw the error above. In this case, you will need to assert the template string `as const`, like this:
185 |
186 | ```typescript
187 | // with i18next
188 | i18next.t(`${expression}.title` as const);
189 |
190 | // with react-i18next
191 | const { t } = useTranslation();
192 | t(`${expression}.title` as const);
193 | ```
194 |
195 | For now, this is the only possible workaround. This is a TypeScript limitation that will be address at some point in the future.
196 |
197 | ### Type error - excessively deep and possibly infinite
198 |
199 | If you face this issue whenever calling the `t` function:
200 |
201 | > TS2589: Type instantiation is excessively deep and possibly infinite.
202 |
203 | That probably means you did not set up your type declaration correctly, so review your configuration or check [here](https://github.com/i18next/react-i18next/issues?q=is%3Aissue+Type+instantiation+is+excessively+deep+and+possibly+infinite) for some similar cases that may help you. If needed, you can always open an issue on Github to get some help from us.
204 |
205 | ### Tagged Template Literal (`react-i18next` only)
206 |
207 | If you are using the tagged template literal syntax for the `t` function, like this:
208 |
209 | ```typescript
210 | t`key1.key2`;
211 | ```
212 |
213 | The `keys` and `return` type inference will not work, because [TemplateStringsArray](https://github.com/microsoft/TypeScript/issues/33304) does not accept generic types yet. You can use Tagged Template Literal syntax, but it will accept any string as argument.
214 |
215 | ### Customize `t` function return when `returnObjects` is set to `true` but `CustomTypeOptions.resources` is not used (>= v23)
216 |
217 | When no `resources` are defined inside `CustomTypeOptions` and `returnObject` options is set to `true` `t` function returns a `$SpecialObject` type:
218 |
219 | ```typescript
220 | type $SpecialObject = object | Array;
221 | ```
222 |
223 | Due to his anatomy it can be easily casted to a better defined type as you can see from the following examples:
224 |
225 | #### Example with object
226 |
227 | ```typescript
228 | const tResult = t('myTypeKey', { returnObjects: true }) as { title: string, text: string };
229 | expectTypeOf(tResult).toEqualTypeOf<{ title: string; text: string }>();
230 | ```
231 |
232 | #### Example with array
233 |
234 | ```typescript
235 | const tResult = t('myTypeKey', { returnObjects: true }) as Array;
236 | expectTypeOf(tResult).toEqualTypeOf>();
237 | ```
238 |
239 | #### Example without casting using type parameters
240 |
241 | ```typescript
242 | type MyCustomReturn = { title:string; text: string };
243 | const tResult = t('myKey', { returnObjects: true });
244 | expectTypeOf(tResult).toEqualTypeOf();
245 | ```
246 |
247 | ## Troubleshooting (< 23)
248 |
249 | {% hint style="info" %}
250 | The following problems should not be present since v23.0.0
251 | {% endhint %}
252 |
253 | ### Slow compilation time
254 |
255 | In order to fully type the `t` function, we recursively map all nested keys from your primary locale files or objects. Depending on the number of keys your project have, the compilation time could be noticeably affected. If this is negatively influencing your productivity, this feature might not be the best choice for you. If needed, you can always open an issue on Github to get some help from us.
256 |
257 | ### Argument of type 'DefaultTFuncReturn' is not assignable to parameter of type xyz
258 |
259 | `t` function can return `null`, this behaviour is [set by default](configuration-options.md#translation-defaults), if you want to change it, set `returnNull` type to `false`.
260 |
261 | ```typescript
262 | // i18next.d.ts
263 | import 'i18next';
264 |
265 | declare module 'i18next' {
266 | interface CustomTypeOptions {
267 | returnNull: false;
268 | ...
269 | }
270 | }
271 | ```
272 |
273 | I also recommend updating your [i18next configuration](configuration-options.md) to behave accordantly:
274 |
275 | ```javascript
276 | i18next.init({
277 | returnNull: false,
278 | // ...
279 | });
280 | ```
281 |
--------------------------------------------------------------------------------
/principles/best-practices.md:
--------------------------------------------------------------------------------
1 | # Best Practices
2 |
3 | > This content is available to you thanks to the contribution of following people:
4 | >
5 | > * [Jenny Reid](https://github.com/jennylreid)
6 |
7 | ### Implications of interpolation for localization
8 |
9 | When translating into other languages, interpolation causes real problems. Fundamentally, what interpolation does is concatenate pieces of text. English sentences split into sentence fragments and programmatically constructed at runtime are difficult and sometimes impossible to translate, unless you have implemented multilingual grammar rules, which is rare.
10 |
11 | Use interpolation sparingly to minimize issues with localization. Interpolation cannot be avoided for values that can only be known at runtime, such as:
12 |
13 | * Time stamps
14 | * User-inputted data
15 |
16 | {% hint style="info" %}
17 | When values are known and available for translation in a resource file, interpolation should be avoided. Use multiple self-contained string values instead.
18 | {% endhint %}
19 |
20 | #### Example
21 |
22 | Suppose you want to use interpolation to replace the value for `{paymentType}` in the following key
23 |
24 | ```
25 | {
26 | "key": "All fees will be charged to the {{paymentType}} on file for this account."
27 | }
28 | ```
29 |
30 | wherein `{paymentType}` could be 'credit card' or 'PayPal account'.
31 |
32 | In German the spelling of the word "the" preceding `{paymentType}` must change depending on which value is passed.
33 |
34 | ```
35 | {
36 | "key": "Alle Beträge werden dem {{paymentType}} für dieses Konto in Rechnung gestellt."
37 | }
38 | ```
39 |
40 | The result is some runtime strings will be broken
41 |
42 | // -> "Alle Beträge werden dem Kreditkarte für dieses Konto in Rechnung gestellt." <- 'dem Kreditkarte' should be 'der Kreditkarte'
43 |
44 | // -> "Alle Beträge werden dem PayPal-Konto für dieses Konto in Rechnung gestellt." <- 'dem PayPal-Konto' is correct
45 |
46 | This is just one simple example of a very complex localization problem.
47 |
48 | Use two separate fully self-contained strings instead:
49 |
50 | ```
51 | {
52 | "key1": "All fees will be charged to the credit card on file for this account."
53 | "key2": "All fees will be charged to the PayPal account on file for this account."
54 |
55 | }
56 | ```
57 |
--------------------------------------------------------------------------------
/principles/fallback.md:
--------------------------------------------------------------------------------
1 | # Fallback
2 |
3 | Doing graceful fallbacks is a core principle of i18next. This enables you to display the most accurate content possible, while not repeating content over and over.
4 |
5 | ## Language fallback
6 |
7 | ### Variant resolving - fallback from dialects or scripts
8 |
9 | By default, if a variant (containing region, script, etc) is not found, i18next will look for the same key in the broader version of that language. With this in mind, a common strategy if you're supporting language variants is to write common text inside the pure language, specifying only what differs in the variants.
10 |
11 | Example:
12 |
13 | ```javascript
14 | // fallback to one language
15 | i18next.init({
16 | lng: "en-GB",
17 | resources: {
18 | "en-GB": {
19 | "translation": {
20 | "i18n": "Internationalisation"
21 | }
22 | },
23 | "en": {
24 | "translation": {
25 | "i18n": "Internationalization",
26 | "i18n_short": "i18n"
27 | }
28 | }
29 | }
30 | }, () => {
31 | i18next.t('i18n'); // -> finds "Internationalisation"
32 | i18next.t('i18n_short'); // -> falls back to "en": "i18n"
33 |
34 | // force using en
35 | i18next.t('i18n', { lng: 'en' }); // -> "Internationalization"
36 | });
37 | ```
38 |
39 | ### Fallback to different languages
40 |
41 | If you can not provide the preferred language for a user, you can specify another language as fallback. This is useful to indicate the main language or, for instance, if you want to keep the fallbacks different per region.
42 |
43 | ```javascript
44 | // fallback to one language
45 | i18next.init({
46 | fallbackLng: 'en'
47 | });
48 |
49 | // fallback ordered
50 | i18next.init({
51 | fallbackLng: ['fr', 'en']
52 | });
53 |
54 | // fallback depending on user language
55 | i18next.init({
56 | fallbackLng: {
57 | 'de-CH': ['fr', 'it'], //French and Italian are also spoken in Switzerland
58 | 'zh-Hant': ['zh-Hans', 'en'],
59 | 'es': ['fr'],
60 | 'default': ['en']
61 | }
62 | });
63 |
64 | // function that returns an array of fallbacks
65 | // your function may also return a string or object as above
66 | i18next.init({
67 | fallbackLng: (code) => {
68 | if (!code || code === 'en') return ['en-US'];
69 | const fallbacks = [code];
70 |
71 | // We maintain en-US and en-AU. Some regions will prefer en-AU.
72 | if (code.startsWith('en-') && !['en-US', 'en-AU'].includes(code)) {
73 | if (['en-GB', 'en-NZ', 'en-IR'].includes(code)) fallbacks.push('en-AU');
74 | else fallbacks.push('en-US');
75 | return fallbacks;
76 | }
77 |
78 | // add pure lang
79 | const langPart = code.split('-')[0];
80 | if (langPart !== code) fallbacks.push(langPart);
81 |
82 | // finally, developer language
83 | fallbacks.push('dev');
84 | return fallbacks;
85 | }
86 | });
87 | ```
88 |
89 | The default is set to `dev` which means developer language. At first this might look strange to set the default to a language, but this enables to set the `saveMissing` feature to send new keys to that developer specific language. From there your translators can modify the texts to a translation file containing, for instance, proper English, including defined terminology. For production use, just set `fallbackLng` to an existing language.
90 |
91 | ## Namespace fallback
92 |
93 | i18next by default loads its translations from one file named `translation`. However, you can configure it to load from multiple files, called [_namespaces_](namespaces.md).
94 |
95 | Besides defining multiple namespaces to load from, you also can set fallback namespaces. Thus, if a key to translate isn't found in the given namespace, it will look it up in the indicated fallbacks.
96 |
97 | app.json
98 |
99 | ```javascript
100 | {
101 | "title": "i18next"
102 | }
103 | ```
104 |
105 | common.json
106 |
107 | ```javascript
108 | {
109 | "button": {
110 | "save": "save"
111 | }
112 | }
113 | ```
114 |
115 | Sample
116 |
117 | ```javascript
118 | i18next.init({
119 | // files to load
120 | ns: ['app', 'common'],
121 |
122 | // default namespace (needs no prefix on calling t)
123 | defaultNS: 'app',
124 |
125 | // fallback, can be a string or an array of namespaces
126 | fallbackNS: 'common'
127 | }, () => {
128 | i18next.t('title') // -> "i18next"
129 |
130 | i18next.t('button.save') // -> "save" (fallback from common)
131 |
132 | // without fallbackNS you would have to prefix namespace
133 | // to access keys in that namespace
134 | // and this is not recommended when used in combination with natural language keys
135 | i18next.t('common:button.save') // -> "save"
136 | // better use the ns option:
137 | i18next.t('button.save', { ns: 'common' }) // -> "save"
138 | });
139 | ```
140 |
141 | ## Key fallback
142 |
143 | ### Key not found
144 |
145 | If a key does not return a value the key acts as fallback:
146 |
147 | ```javascript
148 | i18next.t('notExistingKey'); // -> "notExistingKey"
149 | ```
150 |
151 | So you could configure i18next to have the key being the fallback instead of loading a fallback language:
152 |
153 | de.json
154 |
155 | ```javascript
156 | {
157 | "No one says a key can not be the fallback.": "Niemand sagt ein key kann nicht als Ersatz dienen."
158 | }
159 | ```
160 |
161 | ```javascript
162 | i18next.init({
163 | lng: 'de',
164 |
165 | // allow keys to be phrases having `:`, `.`
166 | nsSeparator: false,
167 | keySeparator: false,
168 |
169 | // do not load a fallback
170 | fallbackLng: false
171 | });
172 |
173 | i18next.t('No one says a key can not be the fallback.')
174 | // -> "Niemand sagt ein key kann nicht als Ersatz dienen."
175 |
176 |
177 | i18next.t('This will be shown if the current loaded translations do not have this.');
178 | // -> "This will be shown if the current loaded translations do not have this."
179 | ```
180 |
181 | While this works and might reduce files to load it makes the management of translations a lot harder as you will need to update changes to fallback values in code and JSON files.
182 |
183 | Possible - but not recommended.
184 |
185 | ### Missing values for existing keys
186 |
187 | In addition to the above, if you want missing values to fallback to the key in cases where the keys (e.g. got extracted by a code parser) exist in your JSON translation file with empty string as value, you also need this setting:
188 |
189 | ```
190 | // allow an empty value to count as invalid (by default is true)
191 | returnEmptyString: false
192 | ```
193 |
194 | ### Calling with fallback keys
195 |
196 | Calling the t function with an array of keys enables you to translate dynamic keys providing a non specific fallback value.
197 |
198 | As a sample think of an error code you get and you like to show a specific warning in some cases:
199 |
200 | translation.json
201 |
202 | ```javascript
203 | {
204 | "error": {
205 | "unspecific": "Something went wrong.",
206 | "404": "The page was not found."
207 | }
208 | }
209 | ```
210 |
211 | Sample
212 |
213 | ```javascript
214 | // const error = '404';
215 | i18next.t([`error.${error}`, 'error.unspecific']) // -> "The page was not found"
216 |
217 | // const error = '502';
218 | i18next.t([`error.${error}`, 'error.unspecific']) // -> "Something went wrong"
219 | ```
220 |
--------------------------------------------------------------------------------
/principles/namespaces.md:
--------------------------------------------------------------------------------
1 | # Namespaces
2 |
3 | Namespaces are a feature in i18next internationalization framework which allows you to separate translations that get loaded into multiple files.
4 |
5 | While in a smaller project it might be reasonable to just put everything in one file you might get at a point where you want to break translations into multiple files. Reasons might be:
6 |
7 | * You start losing the overview having more than 300 segments in a file
8 | * Not every translation needs to be loaded on the first page, speed up load time
9 |
10 | {% hint style="info" %}
11 | 🎓 Check out this topic in the [i18next crash course video](https://youtu.be/SA\_9i4TtxLQ?t=314).
12 | {% endhint %}
13 |
14 | ## semantic reasons
15 |
16 | Often you wish to separate some segments out because they belong together. We do this in most of our projects, eg.:
17 |
18 | * **common.json** -> Things that are reused everywhere, eg. Button labels 'save', 'cancel'
19 | * **validation.json** -> All validation texts
20 | * **glossary.json** -> Words we want to be reused consistently inside texts
21 |
22 | ## technical / editorial reasons
23 |
24 | More often you don't want to load all the translations upfront or at least reduce the amount loaded. This reason often goes hand in hand with the one translation file gets too large and you start losing the overview scrolling through hundreds of text fragments.
25 |
26 | * namespace per view/page
27 | * namespace per application section / feature set (admin area, ...)
28 | * namespace per module which gets lazy loaded (single page applications)
29 |
30 | ## Sample
31 |
32 | ```javascript
33 | i18next.init({
34 | ns: ['common', 'moduleA', 'moduleB'],
35 | defaultNS: 'moduleA'
36 | }, (err, t) => {
37 | i18next.t('myKey'); // key in moduleA namespace (defined default)
38 | i18next.t('common:myKey'); // key in common namespace (not recommended with ns prefix when used in combination with natural language keys)
39 | // better use the ns option:
40 | i18next.t('myKey', { ns: 'common' });
41 | });
42 |
43 | // load additional namespaces after initialization
44 | i18next.loadNamespaces('anotherNamespace', (err, t) => { /* ... */ });
45 | ```
46 |
47 | Check the extended sample on the [getting started](../overview/getting-started.md) page for a running sample.
48 |
--------------------------------------------------------------------------------
/principles/plugins.md:
--------------------------------------------------------------------------------
1 | # Plugins
2 |
3 | i18next [comes with a lot of modules](../overview/plugins-and-utils.md) to enhance the features available. There are modules to:
4 |
5 | * [load resources](https://www.i18next.com/overview/plugins-and-utils#backends), eg. via [http fetch](https://github.com/i18next/i18next-http-backend) or from [filesystem](https://github.com/i18next/i18next-fs-backend) \(Node.js, Deno\)
6 | * [cache resources](../how-to/caching.md) using eg. [i18next-localstorage-backend](https://github.com/i18next/i18next-localstorage-backend)
7 | * [detect user language](https://www.i18next.com/overview/plugins-and-utils#language-detector) by querystring, navigator, cookie, …
8 | * [post processors](https://www.i18next.com/overview/plugins-and-utils#post-processors) to further manipulate values, eg. to add sprintf support
9 |
10 | ```javascript
11 | import i18next from 'i18next';
12 | import Backend from 'i18next-http-backend';
13 | import LanguageDetector from 'i18next-browser-languagedetector';
14 | import sprintf from 'i18next-sprintf-postprocessor';
15 |
16 | i18next
17 | .use(Backend) // or any other backend implementation
18 | .use(LanguageDetector) // or any other implementation
19 | .use(sprintf) // or any other post processor
20 | .init(options);
21 | ```
22 |
23 | For usage details please read the documentation of the plugin \(readme file in the repository or npm website\).
24 |
25 | {% hint style="info" %}
26 | If you're not sure on why you may need such a plugin, have a look at the [First setup help](../overview/first-setup-help.md) page.
27 | {% endhint %}
28 |
29 | {% hint style="success" %}
30 | [Do you like to create your own plugin?](../misc/creating-own-plugins.md)
31 | {% endhint %}
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/principles/translation-resolution.md:
--------------------------------------------------------------------------------
1 | # Translation Resolution
2 |
3 | The process of translating keys is the heart of i18next, and as such this document should serve as a guide to the overall process by which i18next attempts to translate your keys into the appropriate content for a given location, be it on a specific page and/or for a user in a particular region of the world.
4 |
5 | ## Core Elements
6 |
7 | ### Keys
8 |
9 | A key is not unlike a key in any object structure, like JSON or a dictionary in Python. A key is a specific set of text that, when looked up, provides a corresponding value.
10 |
11 | #### Example:
12 |
13 | ```text
14 | "key": "value"
15 | ```
16 |
17 | This example shows the very core concept of what a key is capable of expressing, but the ability to express this formally is very important, as it allows us to expand its utility going forward.
18 |
19 | Keys are a very powerful way of specifying the different forms of an element, be it a piece of text or other forms of content, into its potential variations.
20 |
21 | For more information on all of the different ways keys can be used, please see the documentation for the [translation function](../translation-function/essentials.md).
22 |
23 | ### Languages
24 |
25 | A language is what you would expect: the idiom to be used for translating a key. When we look for a key, we specify a language with it, so that we know which version of the key to use. The important thing to note about this is that _if a key is not found, you can_ [_gracefully fall back to a parent language or a default one_](fallback.md).
26 |
27 | In i18next, a language is a particular value which can be known as a "code". A language code can be expressed in variety of ways, but they generally look something like the following example:
28 |
29 | #### Example:
30 |
31 | ```text
32 | "en-US"
33 | ```
34 |
35 | Long story short, you'll either use a "pure language" code, such as `en` or `de` for English and German, or a language + a variant identification, such as `pt-BR` for the Brazilian Portuguese, `es-419` for Latin American Spanish, or `zh-cmn-Hant-HK` which is Chinese in the Mandarin variation, written in the Traditional script, as used in Hong Kong. For more information on the subject, it is recommended to read up on [IETF Language Codes](https://en.wikipedia.org/wiki/IETF_language_tag).
36 |
37 | ### Namespaces
38 |
39 | A namespace can be thought of as logical groupings of different sets of translations.
40 |
41 | For instance, you might have a 3 sections of your app, each with many individual pages in them, but only 2 sections share similar content. If that's the case, instead of loading all of the keys for all 3 sections, you can instead load keys from a "shared" set of translations and break up the other sections into much smaller sets of keys, loading them as needed.
42 |
43 | In a given namespace you could have a set of languages, each with its own set of keys.
44 |
45 | #### Example
46 |
47 | ```text
48 | "common" // Things that are reused everywhere, like "Confirm" and "Cancel" on buttons
49 | "validation" // All validation text, like "email address not valid" in a form
50 | "glossary" // Words we want to be reused consistently, like key words in your app
51 | ```
52 |
53 | For more information on the concept of namespaces and how you might want to use them, please see their [documentation](namespaces.md).
54 |
55 | ## Resolution Order
56 |
57 | By default, when translating a key, i18next tries the first combination of your **namespace**, **language**, and **key**.
58 |
59 | However, if that does not work, i18next attempts to [gracefully fallback](fallback.md) to a different combination in order to provide the most relevant translation for a piece of content. The core idea is to try to find a key that exists, from _most specific to least specific_. Here is the process that it uses by default:
60 |
61 | #### 1. Similar Keys
62 |
63 | If the specific key is not found, i18next tries to match the key you are looking for with a similar key, looking for a key that best fits the **plural** form, **context**, and **singular** form in that order.
64 |
65 | #### 2. Languages
66 |
67 | If a key is not found, i18next then walks through the list of languages, which consists of the **current language\(s\)** and the **fallback language\(s\)**.
68 |
69 | #### 3. Namespaces
70 |
71 | If no language matches, i18next walks through the list of namespaces, which similarly to languages, consists of the **current namespace\(s\)** and the **fallback namespace\(s\)**.
72 |
73 | #### 4. Fallback Keys
74 |
75 | If that key is still not found, i18n will walk through this process with the **fallback key\(s\)**, if specified.
76 |
77 | #### 5. Key Not Found
78 |
79 | If the key is still not found, i18n will then return the **key itself**, that being the first key specified if you also specified fallback keys.
80 |
81 | For more information on each method of fallback, please see the [fallback documentation](fallback.md).
82 |
83 |
--------------------------------------------------------------------------------
/styles/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i18next/i18next-gitbook/6755a6155fe610a051076a1d86c520cde709b683/styles/README.md
--------------------------------------------------------------------------------
/styles/website.css:
--------------------------------------------------------------------------------
1 | /* header */
2 | h1, h2, h3, h4, h5, h6 {
3 | color: #00796B;
4 | }
5 |
6 | h2, h3, h4, h5, h6 {
7 | color: #00796B;
8 | }
9 |
10 | h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {
11 | position: relative;
12 | text-decoration: none;
13 | color: #00796B;
14 | }
15 |
16 | h1 a {
17 | color: #00796B;
18 | }
19 |
20 | h2 a, h3 a, h4 a, h5 a, h6 a {
21 | color: #00796B;
22 | }
23 |
24 | .markdown-section a, a, a:active, a:hover, a:focus, a:visited {
25 | color: #26A69A;
26 | }
27 |
28 | h2, h3, h4, h5 {
29 | position: relative;
30 | }
31 |
32 | h2 > a:before, h3 > a:before, h4 > a:before, h5 > a:before {
33 | color: #efefef;
34 | position: absolute;
35 | left: -20px;
36 | content: "#";
37 | }
38 |
39 | h2 > a:hover:before, h3 > a:hover:before, h4 > a:hover:before, h5 > a:hover:before {
40 | position: absolute;
41 | left: -20px;
42 | content: "#";
43 | }
44 |
45 | /* active link in summary */
46 | .book-summary ul.summary li.active>a {
47 | color: #26A69A;
48 | }
49 |
50 | /* brand */
51 | .brand-container {
52 | padding: 5px 15px;
53 | }
54 |
55 | /* page */
56 | .page-wrapper {
57 | padding-bottom: 20px;
58 | }
59 |
60 | /* page toc */
61 | .markdown-section > * {
62 | z-index: 1;
63 | }
64 | .markdown-section > ul:first-child {
65 | z-index: 3000;
66 | position: relative;
67 | list-style-type: none;
68 | border: solid 1px #eee;
69 | padding: 10px;
70 | background: #fafafa;
71 | display: inline-block;
72 | min-width: 300px;
73 | float: right;
74 | margin-left: 40px;
75 | }
76 | .book-header {
77 | z-index: 4000;
78 | }
79 |
80 | /* workaround for non working initial top position - initial load scrolls title up 50px */
81 | .book-body {
82 | top: 50px;
83 | }
84 | .body-inner {
85 | min-height: 100%;
86 | }
87 | .page-inner {
88 | margin-top: 0;
89 | }
--------------------------------------------------------------------------------
/translation-function/context.md:
--------------------------------------------------------------------------------
1 | # Context
2 |
3 | By providing a context you can differ translations. Eg. useful to provide gender specific translations.
4 |
5 | {% hint style="info" %}
6 | 🎓 Check out this topic in the [i18next crash course video](https://youtu.be/SA\_9i4TtxLQ?t=653).
7 | {% endhint %}
8 |
9 | ## Basic
10 |
11 | keys
12 |
13 | ```javascript
14 | {
15 | "friend": "A friend",
16 | "friend_male": "A boyfriend",
17 | "friend_female": "A girlfriend"
18 | }
19 | ```
20 |
21 | sample
22 |
23 | ```javascript
24 | i18next.t('friend'); // -> "A friend"
25 | i18next.t('friend', { context: 'male' }); // -> "A boyfriend"
26 | i18next.t('friend', { context: 'female' }); // -> "A girlfriend"
27 | ```
28 |
29 | ## Combining with plurals
30 |
31 | You can pass entire data models in options.
32 |
33 | keys
34 |
35 | ```javascript
36 | {
37 | "friend_male_one": "A boyfriend",
38 | "friend_female_one": "A girlfriend",
39 | "friend_male_other": "{{count}} boyfriends",
40 | "friend_female_other": "{{count}} girlfriends"
41 | }
42 | ```
43 |
44 | sample
45 |
46 | ```javascript
47 | i18next.t('friend', {context: 'male', count: 1}); // -> "A boyfriend"
48 | i18next.t('friend', {context: 'female', count: 1}); // -> "A girlfriend"
49 | i18next.t('friend', {context: 'male', count: 100}); // -> "100 boyfriends"
50 | i18next.t('friend', {context: 'female', count: 100}); // -> "100 girlfriends"
51 | ```
52 |
--------------------------------------------------------------------------------
/translation-function/essentials.md:
--------------------------------------------------------------------------------
1 | # Essentials
2 |
3 | ## Accessing keys
4 |
5 | resources with 2 keys:
6 |
7 | ```javascript
8 | {
9 | "key": "value of key",
10 | "look": {
11 | "deep": "value of look deep"
12 | }
13 | }
14 | ```
15 |
16 | sample
17 |
18 | ```javascript
19 | i18next.t('key');
20 | // -> "value of key"
21 |
22 | i18next.t('look.deep');
23 | // -> "value of look deep"
24 | ```
25 |
26 | ## Passing a default value
27 |
28 | You can pass in a default value for cases the key could not be found in translations like:
29 |
30 | ```javascript
31 | i18next.t('key', 'default value to show');
32 | ```
33 |
34 | {% hint style="info" %}
35 | In case you're using the [saveMissing functionality](../overview/configuration-options.md#missing-keys), it will also pass the defaultValue to your chosen backend, like shown in [this React.js example](https://github.com/locize/react-tutorial).
36 | {% endhint %}
37 |
38 | ## Accessing keys in different namespaces
39 |
40 | Namespaces are a feature in i18next internationalization framework which allows you to separate translations that get loaded into multiple files.
41 |
42 | init
43 |
44 | ```javascript
45 | i18next.init({
46 | ns: ['common', 'moduleA'],
47 | defaultNS: 'moduleA'
48 | });
49 | ```
50 |
51 | moduleA.json
52 |
53 | ```javascript
54 | {
55 | "name": "Module A"
56 | }
57 | ```
58 |
59 | common.json
60 |
61 | ```javascript
62 | {
63 | "button": {
64 | "save": "save"
65 | }
66 | }
67 | ```
68 |
69 | sample
70 |
71 | ```javascript
72 | i18next.t('name');
73 | // -> "Module A"
74 |
75 | // from different namespace (not recommended with namespace prefix when used in combination with natural language keys)
76 | i18next.t('common:button.save') // -> "save"
77 | // better use the ns option:
78 | i18next.t('button.save', { ns: 'common' }) // -> "save"
79 | ```
80 |
81 | ## Multiple fallback keys
82 |
83 | Calling the t function with an array of keys enables you to translate dynamic keys providing a non specific fallback value.
84 |
85 | As a sample think of an error code you get and you like to show a specific warning in some cases:
86 |
87 | keys
88 |
89 | ```javascript
90 | {
91 | "error": {
92 | "unspecific": "Something went wrong.",
93 | "404": "The page was not found."
94 | }
95 | }
96 | ```
97 |
98 | sample
99 |
100 | ```javascript
101 | // const error = '404';
102 | i18next.t([`error.${error}`, 'error.unspecific']); // -> "The page was not found"
103 |
104 | // const error = '502';
105 | i18next.t([`error.${error}`, 'error.unspecific']); // -> "Something went wrong"
106 | ```
107 |
108 | ## Overview options
109 |
110 | `i18next.t(key, options)`
111 |
112 | | option | description |
113 | | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
114 | | defaultValue | defaultValue to return if a translation was not found, you also can define defaults for plurals by adding defaultValue\_other -> \_suffix depends on same [pluralrules](plurals.md). |
115 | | count | count value used for [plurals](plurals.md) |
116 | | context | used for [contexts](context.md) (eg. male / female) |
117 | | replace | object with vars for [interpolation](interpolation.md) - or put them directly in options |
118 | | lng | override language to use |
119 | | lngs | override languages to use |
120 | | fallbackLng | override language to lookup key if not found see [fallbacks](../principles/fallback.md) for details, passing `false` will not do a fallback to any language |
121 | | ns | override namespaces (string or array) |
122 | | keySeparator | override char to separate keys |
123 | | nsSeparator | override char to split namespace from key |
124 | | returnObjects | accessing an object not a translation string (can be set globally too) |
125 | | returnDetails | returns an object that includes information about the used language, namespace, key and value |
126 | | joinArrays | char, eg. '\n' that arrays will be joined by (can be set globally too) |
127 | | postProcess | string or array of postProcessors to apply see [interval plurals](plurals.md) as a sample |
128 | | interpolation | override [interpolation options](interpolation.md) |
129 | | skipInterpolation | skip interpolation and nesting for this call to t function |
130 | | ignoreJSONStructure | if a key is not found as nested key, it will try to lookup as flat key |
131 |
--------------------------------------------------------------------------------
/translation-function/formatting.md:
--------------------------------------------------------------------------------
1 | # Formatting
2 |
3 | Starting with **i18next>=21.3.0** you can use the built-in formatting functions based on the [Intl API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl).
4 |
5 | _You may need to_ [_polyfill_](https://formatjs.io/docs/polyfills/) _the Intl API:_
6 |
7 | * [_Intl.PluralRules_](https://formatjs.io/docs/polyfills/intl-pluralrules)
8 | * [_Intl.RelativeTimeFormat_](https://formatjs.io/docs/polyfills/intl-relativetimeformat)
9 | * [_Intl.ListFormat_](https://formatjs.io/docs/polyfills/intl-listformat)
10 | * [_Intl.DisplayNames_](https://formatjs.io/docs/polyfills/intl-displaynames)
11 | * [_Intl.NumberFormat_](https://formatjs.io/docs/polyfills/intl-numberformat) _(ES2020)_
12 | * [_Intl.Locale_](https://formatjs.io/docs/polyfills/intl-locale)
13 | * [_Intl.getCanonicalLocales_](https://formatjs.io/docs/polyfills/intl-getcanonicallocales)
14 | * [_Intl.DateTimeFormat_](https://formatjs.io/docs/polyfills/intl-datetimeformat) _(ES2020)_
15 |
16 | {% hint style="info" %}
17 | 🎓 Check out this topic in the [i18next crash course video](https://youtu.be/SA_9i4TtxLQ?t=557).
18 | {% endhint %}
19 |
20 | ## Basic usage
21 |
22 | The translation string has the following signature:
23 |
24 | ```json
25 | {
26 | "key": "Some format {{value, formatname}}",
27 | "keyWithOptions": "Some format {{value, formatname(option1Name: option1Value; option2Name: option2Value)}}"
28 | }
29 | ```
30 |
31 | {% hint style="info" %}
32 | Use a "semicolon" delimited list of options.
33 | {% endhint %}
34 |
35 | #### Passing options to the formatting:
36 |
37 | 1. In the translation string using `{{value, formatname(options1: options1Value)}}`
38 | 2. Using the root level options when calling `t('key', { option1: option1Value })`
39 | 3. Using the per value options like: `t('key', { formatParams: { value: { option1: option1Value } })`
40 |
41 | Samples
42 |
43 | ```javascript
44 | // JSON
45 | {
46 | "intlNumber": "Some {{val, number}}",
47 | "intlNumberWithOptions": "Some {{val, number(minimumFractionDigits: 2)}}"
48 | }
49 |
50 | i18next.t('intlNumber', { val: 1000 });
51 | // --> Some 1,000
52 | i18next.t('intlNumber', { val: 1000.1, minimumFractionDigits: 3 });
53 | // --> Some 1,000.100
54 | i18next.t('intlNumber', { val: 1000.1, formatParams: { val: { minimumFractionDigits: 3 } } });
55 | // --> Some 1,000.100
56 | i18next.t('intlNumberWithOptions', { val: 2000 });
57 | // --> Some 2,000.00
58 | i18next.t('intlNumberWithOptions', { val: 2000, minimumFractionDigits: 3 });
59 | // --> Some 2,000.000
60 | ```
61 |
62 | #### Overriding the language to use
63 |
64 | The language can be overridden by passing it in t.options
65 |
66 | ```javascript
67 | i18next.t('intlNumber', { val: 1000.1, lng: 'de' }); // or: i18next.t('intlNumber', { val: 1000.1, locale: 'de' });
68 | i18next.t('intlNumber', { val: 1000.1, formatParams: { val: { lng: 'de' } } }); // or: i18next.t('intlNumber', { val: 1000.1, formatParams: { val: { locale: 'de' } } });
69 | ```
70 |
71 | #### Adding custom format function
72 |
73 | It's rather simple to add own function:
74 |
75 | ```javascript
76 | // after i18next.init(options);
77 | i18next.services.formatter.add('lowercase', (value, lng, options) => {
78 | return value.toLowerCase();
79 | });
80 | i18next.services.formatter.add('underscore', (value, lng, options) => {
81 | return value.replace(/\s+/g, '_');
82 | });
83 | ```
84 |
85 | {% hint style="warning" %}
86 | Make sure you add your custom format function **AFTER** the `i18next.init()` call.
87 | {% endhint %}
88 |
89 | There's also an addCached version for optimized performance:
90 |
91 | ```javascript
92 | i18next.services.formatter.addCached('specialformat', (lng, options) => {
93 | const formatter = new Intl.NumberFormat(lng, options);
94 | return (val) => formatter.format(val);
95 | });
96 | ```
97 |
98 | #### Using multiple formatters
99 |
100 | ```json
101 | {
102 | "key": "Some format {{value, formatter1, formatter2}}"
103 | }
104 | ```
105 |
106 | ## Built-in formats
107 |
108 | ### Number
109 |
110 | ```javascript
111 | // JSON
112 | {
113 | "intlNumber": "Some {{val, number}}",
114 | "intlNumberWithOptions": "Some {{val, number(minimumFractionDigits: 2)}}"
115 | }
116 |
117 | i18next.t('intlNumber', { val: 1000 });
118 | // --> Some 1,000
119 | i18next.t('intlNumber', { val: 1000.1, minimumFractionDigits: 3 });
120 | // --> Some 1,000.100
121 | i18next.t('intlNumber', { val: 1000.1, formatParams: { val: { minimumFractionDigits: 3 } } });
122 | // --> Some 1,000.100
123 | i18next.t('intlNumberWithOptions', { val: 2000 });
124 | // --> Some 2,000.00
125 | i18next.t('intlNumberWithOptions', { val: 2000, minimumFractionDigits: 3 });
126 | // --> Some 2,000.000
127 | ```
128 |
129 | For options see: [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global\_Objects/Intl/NumberFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat)
130 |
131 | ### Currency
132 |
133 | ```javascript
134 | // JSON
135 | {
136 | "intlCurrencyWithOptionsSimplified": "The value is {{val, currency(USD)}}",
137 | "intlCurrencyWithOptions": "The value is {{val, currency(currency: USD)}}",
138 | "twoIntlCurrencyWithUniqueFormatOptions": "The value is {{localValue, currency}} or {{altValue, currency}}",
139 | }
140 |
141 | i18next.t('intlCurrencyWithOptionsSimplified', { val: 2000 });
142 | // --> The value is $2,000.00
143 | i18next.t('intlCurrencyWithOptions', { val: 2300 });
144 | // --> The value is $2,300.00
145 | i18next.t('twoIntlCurrencyWithUniqueFormatOptions',
146 | {
147 | localValue: 12345.67,
148 | altValue: 16543.21,
149 | formatParams: {
150 | localValue: { currency: 'USD', locale: 'en-US' },
151 | altValue: { currency: 'CAD', locale: 'fr-CA' },
152 | },
153 | },);
154 | // --> The value is $12,345.67 or 16 543,21 $ CA
155 | ```
156 |
157 | For options see: [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global\_Objects/Intl/NumberFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat)
158 |
159 | ### DateTime
160 |
161 | ```javascript
162 | // JSON
163 | {
164 | "intlDateTime": "On the {{val, datetime}}",
165 | }
166 |
167 | i18next.t('intlDateTime', { val: new Date(Date.UTC(2012, 11, 20, 3, 0, 0)) });
168 | // --> On the 12/20/2012
169 | i18next.t('intlDateTime',
170 | {
171 | val: new Date(Date.UTC(2012, 11, 20, 3, 0, 0)),
172 | formatParams: {
173 | val: { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' },
174 | },
175 | });
176 | // --> On the Thursday, December 20, 2012
177 | ```
178 |
179 | For options see: [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global\_Objects/Intl/DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat)
180 |
181 | ### RelativeTime
182 |
183 | ```javascript
184 | // JSON
185 | {
186 | "intlRelativeTime": "Lorem {{val, relativetime}}",
187 | "intlRelativeTimeWithOptions": "Lorem {{val, relativetime(quarter)}}",
188 | "intlRelativeTimeWithOptionsExplicit": "Lorem {{val, relativetime(range: quarter; style: narrow;)}}",
189 | }
190 |
191 | i18next.t('intlRelativeTime', { val: 3 });
192 | // --> Lorem in 3 days
193 | i18next.t('intlRelativeTimeWithOptions', { val: -3 });
194 | // --> Lorem 3 quarters ago
195 | i18next.t('intlRelativeTimeWithOptionsExplicit', { val: -3 });
196 | // --> Lorem 3 qtrs. ago
197 | i18next.t('intlRelativeTimeWithOptionsExplicit', { val: -3, style: 'long' });
198 | // --> Lorem 3 quarters ago
199 | ```
200 |
201 | For options see: [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global\_Objects/Intl/RelativeTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat)
202 |
203 | ### List
204 |
205 | ```javascript
206 | // JSON
207 | {
208 | "intlList": "A list of {{val, list}}"
209 | }
210 |
211 | i18next.t('intlList', { val: ['locize', 'i18next', 'awesomeness'] });
212 | // --> A list of locize, i18next, and awesomeness
213 | ```
214 |
215 | For options see: [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global\_Objects/Intl/ListFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat)
216 |
217 | ## Legacy format function i18next<21.3.0
218 |
219 | You can add formatting using [moment.js](http://momentjs.com/) and [numeral.js](http://numeraljs.com/) or the [intl api](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Intl).
220 |
221 | As a sample using momentjs to format dates.
222 |
223 | keys
224 |
225 | ```javascript
226 | {
227 | "key": "The current date is {{date, MM/DD/YYYY}}",
228 | "key2": "{{text, uppercase}} just uppercased"
229 | }
230 | ```
231 |
232 | Init i18next with a format function:
233 |
234 | ```javascript
235 | i18next.init({
236 | interpolation: {
237 | format: function(value, format, lng) {
238 | if (format === 'uppercase') return value.toUpperCase();
239 | if(value instanceof Date) return moment(value).format(format);
240 | return value;
241 | }
242 | }
243 | });
244 | ```
245 |
246 | sample
247 |
248 | ```javascript
249 | i18next.t('key', { date: new Date() });
250 | // -> "The current date is 07/13/2016"
251 |
252 | i18next.t('key2', { text: 'can you hear me' });
253 | // => "CAN YOU HEAR ME just uppercased"
254 | ```
255 |
256 | Keep the language on moment in sync with i18next by listening to the change language event:
257 |
258 | ```javascript
259 | i18next.on('languageChanged', function(lng) {
260 | moment.locale(lng);
261 | });
262 | ```
263 |
264 | ## Additional options
265 |
266 | Prefix/Suffix for interpolation and other options can be overridden in init option:
267 |
268 | sample
269 |
270 | ```javascript
271 | i18next.init({
272 | interpolation: { ... }
273 | });
274 | ```
275 |
276 | | option | default | description |
277 | | --------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
278 | | alwaysFormat | false | used to always call the format function for all interpolated values |
279 | | format | noop function |
Passing this function is considered LEGACY in i18next>=21.3.0
format function function format(value, format, lng, edit) {}
|
280 | | formatSeparator | ',' | used to separate format from interpolation value |
281 |
282 | While there are a lot of options going with the defaults should get you covered.
283 |
--------------------------------------------------------------------------------
/translation-function/interpolation.md:
--------------------------------------------------------------------------------
1 | # Interpolation
2 |
3 | Interpolation is one of the most used functionalities in I18N. It allows integrating dynamic values into your translations.
4 |
5 | Per default, interpolation values get escaped to mitigate XSS attacks.
6 |
7 | {% hint style="info" %}
8 | 🎓 Check out this topic in the [i18next crash course video](https://youtu.be/SA\_9i4TtxLQ?t=433).
9 | {% endhint %}
10 |
11 | If the interpolation functionality provided doesn't suit you, you can use [i18next-sprintf-postProcessor](https://github.com/i18next/i18next-sprintf-postProcessor) for sprintf supported interpolation.
12 |
13 | ## Basic
14 |
15 | Interpolation is one of the most used functionalities in I18N.
16 |
17 | Keys
18 |
19 | Keys, by default, are strings surrounded by curly brackets:
20 |
21 | ```javascript
22 | {
23 | "key": "{{what}} is {{how}}"
24 | }
25 | ```
26 |
27 | Sample
28 |
29 | ```javascript
30 | i18next.t('key', { what: 'i18next', how: 'great' });
31 | // -> "i18next is great"
32 | ```
33 |
34 | ## Working with data models
35 |
36 | You can also pass entire data models as a value for interpolation.
37 |
38 | Keys
39 |
40 | ```javascript
41 | {
42 | "key": "I am {{author.name}}"
43 | }
44 | ```
45 |
46 | Sample
47 |
48 | ```javascript
49 | const author = {
50 | name: 'Jan',
51 | github: 'jamuhl'
52 | };
53 | i18next.t('key', { author });
54 | // -> "I am Jan"
55 | ```
56 |
57 | ## Unescape
58 |
59 | By default, the values get escaped to mitigate XSS attacks. You can toggle escaping off, by either putting `-` before the key, or set the `escapeValue` option to `false` when requesting a translation.
60 |
61 | Keys
62 |
63 | ```javascript
64 | {
65 | "keyEscaped": "no danger {{myVar}}",
66 | "keyUnescaped": "dangerous {{- myVar}}"
67 | }
68 | ```
69 |
70 | Sample
71 |
72 | ```javascript
73 | i18next.t('keyEscaped', { myVar: '' });
74 | // -> "no danger <img />"
75 |
76 | i18next.t('keyUnescaped', { myVar: '' });
77 | // -> "dangerous "
78 |
79 | i18next.t('keyEscaped', { myVar: '', interpolation: { escapeValue: false } });
80 | // -> "no danger " (obviously could be dangerous)
81 | ```
82 |
83 | _Warning:_ If you toggle escaping off, escape any user input yourself!
84 |
85 | ## Additional options
86 |
87 | Prefix/Suffix for interpolation and other options can be overridden in the init options or by passing additional options to the `t` function:
88 |
89 | ```javascript
90 | i18next.init({
91 | interpolation: { ... }
92 | });
93 |
94 | i18next.t('key', {
95 | interpolation: { ... }
96 | });
97 | ```
98 |
99 | | option | default | description |
100 | | ------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
101 | | escape | function | escape function `function escape(str) { return str; }` |
102 | | escapeValue | true | escapes passed in values to avoid XSS injection |
103 | | useRawValueToEscape | false | If true, then value passed into escape function is not casted to string, use with custom escape function that does its own type-checking |
104 | | prefix | "\{{" | prefix for interpolation |
105 | | suffix | "\}}" | suffix for interpolation |
106 |
107 | While there are a lot of options going with the defaults should get you covered.
108 |
109 | ## All interpolation options
110 |
111 | | option | default | description |
112 | | ----------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
113 | | format | noop function | format function, read [formatting](formatting.md) for details |
114 | | formatSeparator | "," | used to separate format from interpolation value |
115 | | escape | function | escape function `function escape(str) { return str; }` |
116 | | escapeValue | true | escape passed in values to avoid XSS injection |
117 | | useRawValueToEscape | false | If true, then value passed into escape function is not casted to string, use with custom escape function that does its own type-checking |
118 | | prefix | "\{{" | prefix for interpolation |
119 | | suffix | "\}}" | suffix for interpolation |
120 | | prefixEscaped | undefined | escaped prefix for interpolation (regexSafe) |
121 | | suffixEscaped | undefined | escaped suffix for interpolation (regexSafe) |
122 | | unescapeSuffix | undefined | suffix to unescaped mode |
123 | | unescapePrefix | "-" | prefix to unescaped mode |
124 | | nestingPrefix | "$t(" | prefix for [nesting](nesting.md) |
125 | | nestingSuffix | ")" | suffix for [nesting](nesting.md) |
126 | | nestingPrefixEscaped | undefined | escaped prefix for nesting (regexSafe) |
127 | | nestingSuffixEscaped | undefined | escaped suffix for nesting (regexSafe) |
128 | | nestingOptionsSeparator | "," | separates the options from nesting key |
129 | | defaultVariables | undefined | global variables to use in interpolation replacements `defaultVariables: { key: "value" }` |
130 | | maxReplaces | 1000 | after how many interpolation runs to break out before throwing a stack overflow |
131 | | skipOnVariables |
true
(was false for <v21.0.0)
|
Will skip to interpolate the variables, example:
t('key', { a: '$t(nested)' })
this will not resolve the nested key and will use$t(nested) as the variable value. Another example: