Reputation: 572
I have a little problem in my application. I use i18next and react-i18next for the translation and have already included it. The whole translation comes from 1 file for each language and that is a mess with over 4000 rows :(
Now I want update this so that i18next would take the translation files placed in the different component-folders and their children-folders.
The folder-structure should look like this after the update:
scr
- components
-- Header
---translations (en/translation.json, de/translation.json)
-- Dashboard
--- translations (en/translation.json, de/translation.json)
--- Menu
---- translations (en/translation.json, de/translation.json)
---- ExampleComponent.tsx
---- ...
--- Cards
---- translations (en/translation.json, de/translation.json)
...
I already figured out how I can handle the automatic export via babel and babel-i18next-plugin with the "namespace"
So, my code (example Menu) would be written like this:
const { t } = useTranslation("Dashboard/Menu")
const explString = t("ExampleComponent.ExampleString","This is an example")
In babel I placed the plugin like this:
[i18next-plugin, {"outputPath": "src/components/{{ns}}/translations/{{locale}}/translation.json"}]
This runs without problems. It takes the namespace as a folder-structure and places the translation-files into the translation-folder including the correct keys.
Now, how I can tell i18next, where to find the translation-files? I could only figure out that I can import the files (file-by-file) inside a resource. I tried backend plugins (html-backend, async-storage-backend, local-storage-backend and filesystem) with
backend: { loadPath: "components/{{ns}}/translations/{{lng}}/translation.json" }
(The i18next.ts is placed inside src/)
and I get the warnings that the keys aren't found.
Also, you can see that I use TypeScript.
In my webpack I tried it with the ts-i18next-loader with this inside the webpack configuration file:
{
test: /\translation.json$/,
exclude: /node_modules/,
loader: 'i18next-ts-loader',
options: {
localeFilesPattern: 'src/components/{{ns}}/translations/{{lng}}/translation.json',
},
},
If I only had 5-6 translation-files for each language / namespace it would not be a problem to put it inside the resource but at the end I have more than 100 files for each language.
Would be nice if anyone had a solution to my problem. If you need any further information I can update the post.
Cheers
Upvotes: 2
Views: 8156
Reputation: 485
npm install i18next-resources-to-backend
i18n
.use(initReactI18next) // passes i18n down to react-i18next
.use(resourcesToBackend((language, namespace, callback) => {
import(`./locales/${language}/${namespace}.json`)
.then((resources) => {
callback(null, resources)
})
.catch((error) => {
console.log(error)
callback(error, null)
})
}))
.init({
// resources,
fallbackLng: 'fr',
lng: 'fr',
interpolation: {
escapeValue: false // react already safes from xss
}
});
Note the additional line I needed compared to adrai answer.
ℹ the translation.json files look like:
{
"hi": "Hello world!"
}
Upvotes: 1
Reputation: 3168
There's an alternative plugin to be used, suggested in the official documentation: https://www.i18next.com/how-to/add-or-load-translations#lazy-load-in-memory-translations
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:
import i18next from 'i18next';
import resourcesToBackend from 'i18next-resources-to-backend';
i18next
.use(resourcesToBackend((language, namespace, callback) => {
import(`./locales/${language}/${namespace}.json`)
.then((resources) => {
callback(null, resources)
})
.catch((error) => {
callback(error, null)
})
}))
.init({ /* other options */ })
Upvotes: 2
Reputation: 572
Found the solution. After i included the "webpack backend for i18next" it solved the problem and the translation gets the correct file.
i18next webpack backend by SimeonC
Upvotes: 0