From 774c01d9b770edf7a0e240ad7efefb258906fb4c Mon Sep 17 00:00:00 2001 From: maxim Date: Wed, 19 Feb 2025 14:17:48 +0300 Subject: [PATCH] enable `i18n` support for `russian-only` --- package.json | 2 ++ pnpm-lock.yaml | 55 +++++++++++++++++++++++++++++++++ src/App.tsx | 2 ++ src/i18nProvider.ts | 24 ++++++++++++++ src/locales/ru/translation.json | 18 +++++++++++ 5 files changed, 101 insertions(+) create mode 100644 src/i18nProvider.ts create mode 100644 src/locales/ru/translation.json diff --git a/package.json b/package.json index c0c1641..5b9e402 100644 --- a/package.json +++ b/package.json @@ -19,9 +19,11 @@ "@refinedev/react-router": "^1.0.0", "@refinedev/simple-rest": "^5.0.1", "axios": "^1.7.9", + "i18next": "^24.2.2", "react": "^18.0.0", "react-dom": "^18.0.0", "react-hook-form": "^7.30.0", + "react-i18next": "^15.4.1", "react-router": "^7.0.2" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bc57bdd..47ce003 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -53,6 +53,9 @@ importers: axios: specifier: ^1.7.9 version: 1.7.9 + i18next: + specifier: ^24.2.2 + version: 24.2.2(typescript@5.7.3) react: specifier: ^18.0.0 version: 18.3.1 @@ -62,6 +65,9 @@ importers: react-hook-form: specifier: ^7.30.0 version: 7.54.2(react@18.3.1) + react-i18next: + specifier: ^15.4.1 + version: 15.4.1(i18next@24.2.2(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-router: specifier: ^7.0.2 version: 7.1.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -1800,6 +1806,9 @@ packages: resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} engines: {node: ^16.14.0 || >=18.0.0} + html-parse-stringify@3.0.1: + resolution: {integrity: sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==} + htmlparser2@8.0.2: resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} @@ -1819,6 +1828,14 @@ packages: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} + i18next@24.2.2: + resolution: {integrity: sha512-NE6i86lBCKRYZa5TaUDkU5S4HFgLIEJRLr3Whf2psgaxBleQ2LC1YW1Vc+SCgkAW7VEzndT6al6+CzegSUHcTQ==} + peerDependencies: + typescript: ^5 + peerDependenciesMeta: + typescript: + optional: true + iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -2540,6 +2557,19 @@ packages: peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 + react-i18next@15.4.1: + resolution: {integrity: sha512-ahGab+IaSgZmNPYXdV1n+OYky95TGpFwnKRflX/16dY04DsYYKHtVLjeny7sBSCREEcoMbAgSkFiGLF5g5Oofw==} + peerDependencies: + i18next: '>= 23.2.3' + react: '>= 16.8.0' + react-dom: '*' + react-native: '*' + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} @@ -3050,6 +3080,10 @@ packages: terser: optional: true + void-elements@3.1.0: + resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==} + engines: {node: '>=0.10.0'} + warn-once@0.1.1: resolution: {integrity: sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q==} @@ -5072,6 +5106,10 @@ snapshots: dependencies: lru-cache: 10.4.3 + html-parse-stringify@3.0.1: + dependencies: + void-elements: 3.1.0 + htmlparser2@8.0.2: dependencies: domelementtype: 2.3.0 @@ -5108,6 +5146,12 @@ snapshots: human-signals@2.1.0: {} + i18next@24.2.2(typescript@5.7.3): + dependencies: + '@babel/runtime': 7.26.0 + optionalDependencies: + typescript: 5.7.3 + iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 @@ -5835,6 +5879,15 @@ snapshots: dependencies: react: 18.3.1 + react-i18next@15.4.1(i18next@24.2.2(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + '@babel/runtime': 7.26.0 + html-parse-stringify: 3.0.1 + i18next: 24.2.2(typescript@5.7.3) + react: 18.3.1 + optionalDependencies: + react-dom: 18.3.1(react@18.3.1) + react-is@16.13.1: {} react-is@17.0.2: {} @@ -6329,6 +6382,8 @@ snapshots: '@types/node': 18.19.71 fsevents: 2.3.3 + void-elements@3.1.0: {} + warn-once@0.1.1: {} wcwidth@1.0.1: diff --git a/src/App.tsx b/src/App.tsx index 20eaf7d..ce50955 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -15,6 +15,7 @@ import {Login} from './pages/login' import {Register} from './pages/register' import {ForgotPassword} from './pages/forgotPassword' import {authProvider} from './authProvider' +import {i18nProvider} from './i18nProvider' import {CountryList, CountryCreate, CountryEdit, CountryShow} from './pages/country' import {CityList, CityCreate, CityEdit, CityShow} from './pages/city' @@ -43,6 +44,7 @@ function App() { notificationProvider={useNotificationProvider} routerProvider={routerBindings} authProvider={authProvider} + i18nProvider={i18nProvider} resources={[ { name: 'country', diff --git a/src/i18nProvider.ts b/src/i18nProvider.ts new file mode 100644 index 0000000..353c255 --- /dev/null +++ b/src/i18nProvider.ts @@ -0,0 +1,24 @@ +import i18n from 'i18next' +import {initReactI18next} from 'react-i18next' +import {I18nProvider} from '@refinedev/core' + +import translationRU from './locales/ru/translation.json' + +i18n.use(initReactI18next).init({ + resources: { + ru: { + translation: translationRU, + }, + }, + lng: 'ru', + fallbackLng: 'ru', + interpolation: { + escapeValue: false, + }, +}) + +export const i18nProvider: I18nProvider = { + translate: (key, options) => i18n.t(key, options) as string, + changeLocale: (locale: string) => i18n.changeLanguage(locale), + getLocale: () => i18n.language, +} diff --git a/src/locales/ru/translation.json b/src/locales/ru/translation.json new file mode 100644 index 0000000..048037f --- /dev/null +++ b/src/locales/ru/translation.json @@ -0,0 +1,18 @@ +{ + "actions": { + "create": "Создать", + "show": "Просмотр", + "edit": "Редактировать", + "delete": "Удалить", + "save": "Сохранить" + }, + "buttons": { + "edit": "Редактировать", + "refresh": "Обновить", + "delete": "Удалить", + "save": "Сохранить", + "submit": "Отправить", + "create": "Создать", + "logout": "Выход" + } +}