🌍 Added i18n lib

This commit is contained in:
2024-04-11 09:58:53 -04:00
parent 0024660f2e
commit 6de8517bb5
8 changed files with 121 additions and 16 deletions

View File

@@ -43,6 +43,9 @@
"focus-trap-react": "^10.2.3",
"history": "^5.3.0",
"html-to-text": "^8.1.0",
"i18next": "^23.11.1",
"i18next-browser-languagedetector": "^7.2.1",
"i18next-http-backend": "^2.5.0",
"immer": "^10.0.3",
"jsdoc": "^3.6.10",
"keen-slider": "^6.8.6",
@@ -58,6 +61,7 @@
"react-fast-compare": "^3.2.0",
"react-final-form": "^6.5.9",
"react-final-form-arrays": "^3.1.4",
"react-i18next": "^14.1.0",
"react-loader-spinner": "^4.0.0",
"react-modal": "^3.15.1",
"react-router": "^6.9.0",

View File

@@ -6,6 +6,8 @@ import { Form, Field } from "react-final-form";
import Card from "../shared/Carda";
import ellipsize from "ellipsize";
import { convert } from "html-to-text";
import { useTranslation } from "react-i18next";
import "../../shared/utils/i18n.util"; // Ensure you import your i18n configuration
import PopoverButton from "../shared/PopoverButton";
import dayjs from "dayjs";
import { useMutation, useQuery } from "@tanstack/react-query";
@@ -23,7 +25,7 @@ export const Search = ({}: ISearchProps): ReactElement => {
};
const [comicVineMetadata, setComicVineMetadata] = useState({});
const [selectedResource, setSelectedResource] = useState("volume");
const { t } = useTranslation();
const handleResourceChange = (value) => {
setSelectedResource(value);
};
@@ -293,19 +295,24 @@ export const Search = ({}: ISearchProps): ReactElement => {
)}
{result.start_year && <> ({result.start_year})</>}
</div>
<div className="flex flex-row gap-2">
{/* issue count */}
<div className="my-2">
<span className="inline-flex items-center bg-slate-50 text-slate-800 text-xs font-medium px-2 rounded-md dark:text-slate-900 dark:bg-slate-400">
<span className="pr-1 pt-1">
<i className="icon-[solar--documents-minimalistic-bold-duotone] w-5 h-5"></i>
</span>
{result.count_of_issues && (
<div className="my-2">
<span className="inline-flex items-center bg-slate-50 text-slate-800 text-xs font-medium px-2 rounded-md dark:text-slate-900 dark:bg-slate-400">
<span className="pr-1 pt-1">
<i className="icon-[solar--documents-minimalistic-bold-duotone] w-5 h-5"></i>
</span>
<span className="text-md text-slate-500 dark:text-slate-900">
{result.count_of_issues} issues
<span className="text-md text-slate-500 dark:text-slate-900">
{t("issueWithCount", {
count: result.count_of_issues,
})}
</span>
</span>
</span>
</div>
</div>
)}
{/* type: TPB, one-shot, graphic novel etc. */}
{!isNil(result.description) &&
!isUndefined(result.description) && (
@@ -351,7 +358,14 @@ export const Search = ({}: ISearchProps): ReactElement => {
)}
</p>
<div className="mt-2">
<PopoverButton issuesCount={result.count_of_issues} />
<PopoverButton
content={`Adding this volume will add ${t(
"issueWithCount",
{
count: result.count_of_issues,
},
)} to your wanted list.`}
/>
{/* onClick={() => addToLibrary("comicvine", result) */}
</div>
</div>

View File

@@ -48,7 +48,7 @@ export const SystemSettingsForm = (): ReactElement => {
</article>
<button
className="flex space-x-1 sm:mt-0 sm:flex-row sm:items-center rounded-lg border border-red-400 dark:border-red-200 bg-red-200 px-4 py-2 text-gray-500 hover:bg-transparent hover:text-red-600 focus:outline-none focus:ring active:text-indigo-500"
className="flex space-x-1 sm:mt-0 sm:flex-row sm:items-center rounded-lg border border-red-400 dark:border-red-200 bg-red-200 px-2 py-1 text-gray-500 hover:bg-transparent hover:text-red-600 focus:outline-none focus:ring active:text-indigo-500"
onClick={() => flushDb()}
>
<span className="pt-1 px-1">

View File

@@ -1,7 +1,9 @@
import React, { useState } from "react";
import { useFloating, offset, flip } from "@floating-ui/react-dom";
import { useTranslation } from "react-i18next";
import "../../shared/utils/i18n.util"; // Ensure you import your i18n configuration
const PopoverButton = ({ issuesCount }) => {
const PopoverButton = ({ content }) => {
const [isVisible, setIsVisible] = useState(false);
// Use destructuring to obtain the reference and floating setters, among other values.
const { x, y, refs, strategy, floatingStyles } = useFloating({
@@ -9,6 +11,7 @@ const PopoverButton = ({ issuesCount }) => {
middleware: [offset(8), flip()],
strategy: "absolute",
});
const { t } = useTranslation();
return (
<div>
{/* Apply the reference setter directly to the ref prop */}
@@ -31,8 +34,7 @@ const PopoverButton = ({ issuesCount }) => {
className="text-sm bg-slate-400 p-2 rounded-md"
role="tooltip"
>
Adding this volume will add all {issuesCount} issues to your wanted
list.
{content}
</div>
)}
</div>

View File

@@ -7,6 +7,7 @@ import Settings from "./components/Settings/Settings";
import { ErrorPage } from "./components/shared/ErrorPage";
const rootEl = document.getElementById("root");
const root = createRoot(rootEl);
import i18n from "./shared/utils/i18n.util";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import Import from "./components/Import/Import";
import Dashboard from "./components/Dashboard/Dashboard";

View File

@@ -0,0 +1,4 @@
{
"issueWithCount_one": "{{count}} issue",
"issueWithCount_other": "{{count}} issues"
}

View File

@@ -0,0 +1,25 @@
// i18n.js
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import HttpBackend from "i18next-http-backend";
import LanguageDetector from "i18next-browser-languagedetector";
i18n
// Learn more about options: https://www.i18next.com/overview/configuration-options
.use(HttpBackend) // Load translations over http
.use(LanguageDetector) // Detect language automatically
.use(initReactI18next) // Pass i18n instance to react-i18next
.init({
lng: "en", // Specify the language
fallbackLng: "en",
debug: true,
interpolation: {
escapeValue: false, // Not needed for React
},
backend: {
// path where resources get loaded from
loadPath: "./src/client/locales/en/translation.json",
},
});
export default i18n;

View File

@@ -1024,6 +1024,13 @@
dependencies:
regenerator-runtime "^0.14.0"
"@babel/runtime@^7.23.9":
version "7.24.4"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.4.tgz#de795accd698007a66ba44add6cc86542aff1edd"
integrity sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==
dependencies:
regenerator-runtime "^0.14.0"
"@babel/template@^7.22.15", "@babel/template@^7.23.9", "@babel/template@^7.3.3":
version "7.23.9"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.23.9.tgz#f881d0487cba2828d3259dcb9ef5005a9731011a"
@@ -4719,6 +4726,13 @@ create-jest@^29.7.0:
jest-util "^29.7.0"
prompts "^2.0.1"
cross-fetch@4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-4.0.0.tgz#f037aef1580bb3a1a35164ea2a848ba81b445983"
integrity sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==
dependencies:
node-fetch "^2.6.12"
cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
@@ -6506,6 +6520,13 @@ html-minifier-terser@^6.1.0:
relateurl "^0.2.7"
terser "^5.10.0"
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-tags@^3.1.0:
version "3.3.1"
resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.3.1.tgz#a04026a18c882e4bba8a01a3d39cfe465d40b5ce"
@@ -6574,6 +6595,27 @@ human-signals@^5.0.0:
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28"
integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==
i18next-browser-languagedetector@^7.2.1:
version "7.2.1"
resolved "https://registry.yarnpkg.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-7.2.1.tgz#1968196d437b4c8db847410c7c33554f6c448f6f"
integrity sha512-h/pM34bcH6tbz8WgGXcmWauNpQupCGr25XPp9cZwZInR9XHSjIFDYp1SIok7zSPsTOMxdvuLyu86V+g2Kycnfw==
dependencies:
"@babel/runtime" "^7.23.2"
i18next-http-backend@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/i18next-http-backend/-/i18next-http-backend-2.5.0.tgz#8396a7df30bfe722eff7a65f629df32a61720414"
integrity sha512-Z/aQsGZk1gSxt2/DztXk92DuDD20J+rNudT7ZCdTrNOiK8uQppfvdjq9+DFQfpAnFPn3VZS+KQIr1S/W1KxhpQ==
dependencies:
cross-fetch "4.0.0"
i18next@^23.11.1:
version "23.11.1"
resolved "https://registry.yarnpkg.com/i18next/-/i18next-23.11.1.tgz#8e384b6ad7d6ba70c40cb86e020438251a5ff8b1"
integrity sha512-mXw4A24BiPZKRsbb9ewgSvjYd6fxFCNwJyfK6nYfSTIAX2GkCWcb598m3DFkDZmqADatvuASrKo6qwORz3VwTQ==
dependencies:
"@babel/runtime" "^7.23.2"
iconv-lite@0.4.24:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
@@ -8153,7 +8195,7 @@ node-fetch-native@^1.6.1:
resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.6.1.tgz#f95c74917d3cebc794cdae0cd2a9c7594aad0cb4"
integrity sha512-bW9T/uJDPAJB2YNYEpWzE54U5O3MQidXsOyTfnbKYtTtFexRvGzb1waphBN4ZwP6EcIvYYEOwW0b72BpAqydTw==
node-fetch@^2.0.0:
node-fetch@^2.0.0, node-fetch@^2.6.12:
version "2.7.0"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
@@ -9047,6 +9089,14 @@ react-full-screen@1.1.0:
dependencies:
fscreen "^1.0.2"
react-i18next@^14.1.0:
version "14.1.0"
resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-14.1.0.tgz#44da74fbffd416f5d0c5307ef31735cf10cc91d9"
integrity sha512-3KwX6LHpbvGQ+sBEntjV4sYW3Zovjjl3fpoHbUwSgFHf0uRBcbeCBLR5al6ikncI5+W0EFb71QXZmfop+J6NrQ==
dependencies:
"@babel/runtime" "^7.23.9"
html-parse-stringify "^3.0.1"
react-icons@4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.3.1.tgz#2fa92aebbbc71f43d2db2ed1aed07361124e91ca"
@@ -10682,6 +10732,11 @@ voca@^1.4.0:
resolved "https://registry.yarnpkg.com/voca/-/voca-1.4.1.tgz#9f84939e1aaca80c39158049d3321c67c6d2ed0a"
integrity sha512-NJC/BzESaHT1p4B5k4JykxedeltmNbau4cummStd4RjFojgq/kLew5TzYge9N2geeWyI2w8T30wUET5v+F7ZHA==
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==
walker@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f"