'Using react-i18next as a translation provider for React Admin
I am trying to use react-i18next as a translation provider for react-admin. React-admin provides documentation on how to setup a custom translation provider.
This was easy enough to follow and I created one for i18next:
export const i18nProvider = {
translate: (key, { _, smart_count, ...rest } = {}) => {
return i18n.t(key, {
defaultValue: _,
count: smart_count,
...rest,
});
},
changeLocale: (locale) => i18n.changeLanguage(locale),
getLocale: () => i18n.language,
};
The problem I am having is that react-i18next uses suspense to load the translations, and this behavior does not seem to work when calling the i18n.t
function directly like this, rather than through a hook:
import React, { Suspense } from 'react';
import { useTranslation } from 'react-i18next';
function MyComponent() {
const { t, i18n } = useTranslation();
return <h1>{t('Welcome to React')}</h1>
}
// i18n translations might still be loaded by the http backend
// use react's Suspense
export default function App() {
return (
<Suspense fallback="loading">
<MyComponent />
</Suspense>
);
}
What ends up happening is that the i18n.t function is called before the translation is loaded, and ends up not showing the translations.
Is there a better approach to integrate react-i18next with react admin?
Solution 1:[1]
Instantiate i18n and simply import it when mounting your app
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import frTranslations from '~/locales/fr.json';
i18n
// pass the i18n instance to react-i18next.
.use(initReactI18next)
// init i18next
// for all options read: https://www.i18next.com/overview/configuration-options
.init({
fallbackLng: 'fr',
resources: {
fr: { translation: frTranslations },
},
});
export default i18n;
import App from './App';
import './i18n';
ReactDOM.render(<App />, document.getElementById('root'));
Then you can use it like you do
import { useTranslation } from 'react-i18next';
function SearchFilter(props) {
const { t } = useTranslation();
...
}
Solution 2:[2]
You need to read react-i18n and react-admin translation to know the basics.
Make a json file from react-admin available locales, choose one and locate the translation file. In my case the translation file is index.js, the content is translated and stored in public/locales/zh-tw/translation.json
. Make sure to include the ra:
json key.
Step to walkthrough this solution:
yarn add [email protected] [email protected]
- In project dir
cd node_modules && ln -s ../public public
to import a translation file, e.g.public/locales/zh-tw/translation.json
- Create
src/i18n.js
and add:
import i18n from "i18next";
import {initReactI18next} from "react-i18next";
import chineseTranslation from 'public/locales/zh-tw/translation.json';
// the translations
const resources = {
"zh-TW": {
translation: chineseTranslation
}
};
i18n
.use(initReactI18next) // passes i18n down to react-i18next
.init({
resources,
lng: "zh-TW",
// keySeparator: false, // we do not use keys in form messages.welcome
interpolation: {
escapeValue: false // react already safes from xss
}
});
export default i18n;
- In
src/index.js
addimport './i18n';
- In your
src/App.jsx
, apply the following:
import {Admin, Resource, ListGuesser} from "react-admin";
import * as React from "react";
import polyglotI18nProvider from 'ra-i18n-polyglot';
import chineseTranslation from 'public/locales/zh-tw/translation.json';
// @ts-ignore
const i18nProvider = polyglotI18nProvider((_) => chineseTranslation);
const LandingPage = () => (
<Admin i18nProvider={i18nProvider}>
<Resource name="users" list={ListGuesser}/>
</Admin>
);
export default LandingPage;
I am using typescript for react-admin, so I added //@ts-ignore
to get rid of compile error.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Striped |
Solution 2 |