From 1c7c3e566c780ae457d376b525ffb8613a903110 Mon Sep 17 00:00:00 2001 From: Aria Moradi Date: Mon, 13 Feb 2023 20:20:08 +0330 Subject: [PATCH] add i18n (#239) --- package.json | 3 ++ public/index.html | 2 +- src/App.tsx | 1 + src/components/navbar/DefaultNavBar.tsx | 5 ++- src/i18n/index.ts | 25 ++++++++++++++ src/i18n/translations.ts | 23 +++++++++++++ src/screens/Library.tsx | 6 ++-- yarn.lock | 46 +++++++++++++++++++++++++ 8 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 src/i18n/index.ts create mode 100644 src/i18n/translations.ts diff --git a/package.json b/package.json index 4ea5907a..86d4d46f 100644 --- a/package.json +++ b/package.json @@ -13,11 +13,14 @@ "@mui/system": "^5.0.6", "axios": "^0.21.1", "file-selector": "^0.2.4", + "i18next": "^22.4.9", + "i18next-browser-languagedetector": "^7.0.1", "p-queue": "^7.2.0", "query-string": "^7.0.1", "react": "^17.0.2", "react-beautiful-dnd": "^13.0.0", "react-dom": "^17.0.2", + "react-i18next": "^12.1.5", "react-lazyload": "^3.2.0", "react-router-dom": "^5.2.0", "react-scripts": "4.0.3", diff --git a/public/index.html b/public/index.html index 1b3eaa39..0b52ddfb 100644 --- a/public/index.html +++ b/public/index.html @@ -1,5 +1,5 @@ - + diff --git a/src/App.tsx b/src/App.tsx index 91a2b076..845bb825 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -27,6 +27,7 @@ import SourceConfigure from 'screens/SourceConfigure'; import SourceMangas from 'screens/SourceMangas'; import Sources from 'screens/Sources'; import Updates from 'screens/Updates'; +import 'i18n'; const App: React.FC = () => ( diff --git a/src/components/navbar/DefaultNavBar.tsx b/src/components/navbar/DefaultNavBar.tsx index 80d69208..fc7f6c2b 100644 --- a/src/components/navbar/DefaultNavBar.tsx +++ b/src/components/navbar/DefaultNavBar.tsx @@ -31,11 +31,13 @@ import { createPortal } from 'react-dom'; import useBackTo from 'util/useBackTo'; import DesktopSideBar from 'components/navbar/navigation/DesktopSideBar'; import MobileBottomBar from 'components/navbar/navigation/MobileBottomBar'; +// import { useTranslation } from 'react-i18next'; +import { t } from 'i18next'; const navbarItems: Array = [ { path: '/library', - title: 'Library', + title: t('DefaultNavBar.navbarItems.Library'), SelectedIconComponent: CollectionsBookmarkIcon, IconComponent: CollectionsOutlinedBookmarkIcon, show: 'both', @@ -85,6 +87,7 @@ const navbarItems: Array = [ ]; export default function DefaultNavBar() { + // const { t } = useTranslation(); const { title, action, override } = useContext(NavBarContext); const backTo = useBackTo(); diff --git a/src/i18n/index.ts b/src/i18n/index.ts new file mode 100644 index 00000000..08d40634 --- /dev/null +++ b/src/i18n/index.ts @@ -0,0 +1,25 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +import { use } from 'i18next'; +import { initReactI18next } from 'react-i18next'; +import resources from 'i18n/translations'; +import LanguageDetector from 'i18next-browser-languagedetector'; + +const i18n = use(initReactI18next) + .use(LanguageDetector) + .init({ + resources, + + fallbackLng: 'en', + interpolation: { + escapeValue: false, + }, + debug: true, + }); + +export default i18n; diff --git a/src/i18n/translations.ts b/src/i18n/translations.ts new file mode 100644 index 00000000..1b352f36 --- /dev/null +++ b/src/i18n/translations.ts @@ -0,0 +1,23 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +const resources = { + en: { + translation: { + 'DefaultNavBar.navbarItems.Library': 'Library', + 'screens/Library/Library': 'Library', + }, + }, + fr: { + translation: { + 'DefaultNavBar.navbarItems.Library': 'fr(Library)', + 'screens/Library/Library': 'fr(Library)', + }, + }, +}; + +export default resources; diff --git a/src/screens/Library.tsx b/src/screens/Library.tsx index 1c20e06a..100c9af4 100644 --- a/src/screens/Library.tsx +++ b/src/screens/Library.tsx @@ -17,15 +17,17 @@ import AppbarSearch from 'components/util/AppbarSearch'; import { useQueryParam, NumberParam } from 'use-query-params'; import { useQuery } from 'util/client'; import UpdateChecker from 'components/library/UpdateChecker'; +import { useTranslation } from 'react-i18next'; export default function Library() { + const { t } = useTranslation(); const [lastLibraryUpdate, setLastLibraryUpdate] = useState(Date.now()); const { data: tabsData, error: tabsError, loading } = useQuery('/api/v1/category'); const tabs = tabsData ?? []; const [tabSearchParam, setTabSearchParam] = useQueryParam('tab', NumberParam); - const activeTab = tabs.find((t) => t.order === tabSearchParam) ?? tabs[0]; + const activeTab = tabs.find((tab) => tab.order === tabSearchParam) ?? tabs[0]; const { data: mangaData, error: mangaError, @@ -37,7 +39,7 @@ export default function Library() { const { setTitle, setAction } = useContext(NavbarContext); useEffect(() => { - setTitle('Library'); + setTitle(t('screens/Library/Library')); setAction( <> diff --git a/yarn.lock b/yarn.lock index 7c7dd9bd..47201b12 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1164,6 +1164,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.19.4", "@babel/runtime@^7.20.6": + version "7.20.13" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.13.tgz#7055ab8a7cff2b8f6058bf6ae45ff84ad2aded4b" + integrity sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA== + dependencies: + regenerator-runtime "^0.13.11" + "@babel/template@^7.10.4", "@babel/template@^7.15.4", "@babel/template@^7.3.3": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.15.4.tgz#51898d35dcf3faa670c4ee6afcfd517ee139f194" @@ -6030,6 +6037,13 @@ html-minifier-terser@^5.0.1: relateurl "^0.2.7" terser "^4.6.3" +html-parse-stringify@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz#dfc1017347ce9f77c8141a507f233040c59c55d2" + integrity sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg== + dependencies: + void-elements "3.1.0" + html-webpack-plugin@4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.5.0.tgz#625097650886b97ea5dae331c320e3238f6c121c" @@ -6148,6 +6162,20 @@ hyphenate-style-name@^1.0.3: resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d" integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ== +i18next-browser-languagedetector@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-7.0.1.tgz#ead34592edc96c6c3a618a51cb57ad027c5b5d87" + integrity sha512-Pa5kFwaczXJAeHE56CHG2aWzFBMJNUNghf0Pm4SwSrEMps/PTKqW90EYWlIvhuYStf3Sn1K0vw+gH3+TLdkH1g== + dependencies: + "@babel/runtime" "^7.19.4" + +i18next@^22.4.9: + version "22.4.9" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-22.4.9.tgz#98c8384c6bd41ff937da98b1e809ba03d3b41053" + integrity sha512-8gWMmUz460KJDQp/ob3MNUX84cVuDRY9PLFPnV8d+Qezz/6dkjxwOaH70xjrCNDO+JrUL25iXfAIN9wUkInNZw== + dependencies: + "@babel/runtime" "^7.20.6" + iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -9676,6 +9704,14 @@ react-error-overlay@^6.0.9: resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a" integrity sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew== +react-i18next@^12.1.5: + version "12.1.5" + resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-12.1.5.tgz#b65f5733dd2f96188a9359c009b7dbe27443f009" + integrity sha512-7PQAv6DA0TcStG96fle+8RfTwxVbHVlZZJPoEszwUNvDuWpGldJmNWa3ZPesEsZQZGF6GkzwvEh6p57qpFD2gQ== + dependencies: + "@babel/runtime" "^7.20.6" + html-parse-stringify "^3.0.1" + react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" @@ -9935,6 +9971,11 @@ regenerator-runtime@^0.11.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== +regenerator-runtime@^0.13.11: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== + regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7: version "0.13.9" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" @@ -11652,6 +11693,11 @@ vm-browserify@^1.0.1: resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== +void-elements@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" + integrity sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w== + w3c-hr-time@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd"