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"