diff --git a/components/search.tsx b/components/search.tsx
index 8c4bbe8..fc14012 100644
--- a/components/search.tsx
+++ b/components/search.tsx
@@ -5,9 +5,11 @@ import { queryAtom } from "lib/state/query";
import { selectedSuggestionAtom } from "lib/state/suggestionSelection";
import handleEnter from "lib/onesearch/handleEnter";
import { suggestionAtom } from "lib/state/suggestion";
+import { useTranslation } from "react-i18next";
export default function Search(props: { onFocus: () => void }) {
+ const { t } = useTranslation();
const settings = useAtomValue(settingsAtom);
const [query, setQuery] = useAtom(queryAtom);
const [selectedSuggestion, setSelected] = useAtom(selectedSuggestionAtom);
@@ -43,7 +45,7 @@ export default function Search(props: { onFocus: () => void }) {
dark:placeholder:text-slate-400 text-slate-900 dark:text-white"
id="searchBox"
type="text"
- placeholder="placeholder"
+ placeholder={t('search.placeholder')}
onFocus={props.onFocus}
onKeyDown={handleKeydown}
onChange={(e) =>
diff --git a/components/time.tsx b/components/time.tsx
index fb3f9c0..c33a6b1 100644
--- a/components/time.tsx
+++ b/components/time.tsx
@@ -38,7 +38,9 @@ export default function Time(props: {
{formatTime()}{" "}
{new Intl.DateTimeFormat(navigator.language, {
- dateStyle: "medium"
+ year: "numeric",
+ month: "short",
+ day: "numeric"
}).format(currentTime)}
diff --git a/i18n/ar.json b/i18n/ar.json
new file mode 100755
index 0000000..0d329a3
--- /dev/null
+++ b/i18n/ar.json
@@ -0,0 +1,5 @@
+{
+ "search" : {
+ "placeholder" : "ابحث أو اكتب عنوان URL"
+ }
+}
\ No newline at end of file
diff --git a/i18n/de.json b/i18n/de.json
new file mode 100755
index 0000000..47a7c7e
--- /dev/null
+++ b/i18n/de.json
@@ -0,0 +1,5 @@
+{
+ "search" : {
+ "placeholder" : "Suche oder gib eine URL ein"
+ }
+}
\ No newline at end of file
diff --git a/i18n/en.json b/i18n/en.json
new file mode 100755
index 0000000..b03c753
--- /dev/null
+++ b/i18n/en.json
@@ -0,0 +1,5 @@
+{
+ "search" : {
+ "placeholder" : "Search or type a URL"
+ }
+}
\ No newline at end of file
diff --git a/i18n/es.json b/i18n/es.json
new file mode 100755
index 0000000..c79c404
--- /dev/null
+++ b/i18n/es.json
@@ -0,0 +1,5 @@
+{
+ "search" : {
+ "placeholder" : "Buscar o escribir una URL"
+ }
+}
\ No newline at end of file
diff --git a/i18n/fr.json b/i18n/fr.json
new file mode 100755
index 0000000..d9f6e0b
--- /dev/null
+++ b/i18n/fr.json
@@ -0,0 +1,5 @@
+{
+ "search" : {
+ "placeholder" : "Rechercher ou saisir une URL"
+ }
+}
\ No newline at end of file
diff --git a/i18n/it.json b/i18n/it.json
new file mode 100755
index 0000000..23f0358
--- /dev/null
+++ b/i18n/it.json
@@ -0,0 +1,5 @@
+{
+ "search" : {
+ "placeholder" : "Cerca o digita un URL"
+ }
+}
\ No newline at end of file
diff --git a/i18n/ja.json b/i18n/ja.json
new file mode 100755
index 0000000..d3b3714
--- /dev/null
+++ b/i18n/ja.json
@@ -0,0 +1,5 @@
+{
+ "search" : {
+ "placeholder" : "検索またはURLを入力"
+ }
+}
\ No newline at end of file
diff --git a/i18n/ko.json b/i18n/ko.json
new file mode 100755
index 0000000..f93197a
--- /dev/null
+++ b/i18n/ko.json
@@ -0,0 +1,5 @@
+{
+ "search" : {
+ "placeholder" : "검색 또는 URL 입력"
+ }
+}
\ No newline at end of file
diff --git a/i18n/pt.json b/i18n/pt.json
new file mode 100755
index 0000000..2fad8f3
--- /dev/null
+++ b/i18n/pt.json
@@ -0,0 +1,5 @@
+{
+ "search" : {
+ "placeholder" : "Pesquisar ou digitar uma URL"
+ }
+}
\ No newline at end of file
diff --git a/i18n/ru.json b/i18n/ru.json
new file mode 100755
index 0000000..b23cc86
--- /dev/null
+++ b/i18n/ru.json
@@ -0,0 +1,5 @@
+{
+ "search" : {
+ "placeholder" : "Искать или ввести URL"
+ }
+}
\ No newline at end of file
diff --git a/i18n/zh.json b/i18n/zh.json
new file mode 100755
index 0000000..0c7e1d4
--- /dev/null
+++ b/i18n/zh.json
@@ -0,0 +1,5 @@
+{
+ "search" : {
+ "placeholder" : "搜索或输入网址"
+ }
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index dd1c46c..56f1001 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "sparkhome",
"private": false,
- "version": "5.0.0",
+ "version": "5.1.0",
"type": "module",
"scripts": {
"dev": "vite",
@@ -10,9 +10,13 @@
"preview": "vite preview"
},
"dependencies": {
+ "i18next": "^23.11.5",
+ "i18next-browser-languagedetector": "^8.0.0",
+ "i18next-icu": "^2.3.0",
"jotai": "^2.8.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
+ "react-i18next": "^14.1.2",
"react-router": "^6.23.1",
"react-router-dom": "^6.23.1",
"search-engine-autocomplete": "^0.4.3",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 8eaf75d..1d1a8e5 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -8,6 +8,15 @@ importers:
.:
dependencies:
+ i18next:
+ specifier: ^23.11.5
+ version: 23.11.5
+ i18next-browser-languagedetector:
+ specifier: ^8.0.0
+ version: 8.0.0
+ i18next-icu:
+ specifier: ^2.3.0
+ version: 2.3.0(intl-messageformat@10.5.14)
jotai:
specifier: ^2.8.3
version: 2.8.3(@types/react@18.3.3)(react@18.3.1)
@@ -17,9 +26,9 @@ importers:
react-dom:
specifier: ^18.3.1
version: 18.3.1(react@18.3.1)
- react-intl:
- specifier: ^6.6.8
- version: 6.6.8(react@18.3.1)(typescript@5.5.2)
+ react-i18next:
+ specifier: ^14.1.2
+ version: 14.1.2(i18next@23.11.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react-router:
specifier: ^6.23.1
version: 6.23.1(react@18.3.1)
@@ -53,7 +62,7 @@ importers:
version: 7.13.1(eslint@8.57.0)(typescript@5.5.2)
'@vitejs/plugin-react-swc':
specifier: ^3.5.0
- version: 3.7.0(vite@5.3.1)
+ version: 3.7.0(vite@5.3.1(@types/node@20.14.8))
autoprefixer:
specifier: ^10.4.19
version: 10.4.19(postcss@8.4.38)
@@ -77,13 +86,13 @@ importers:
version: 5.5.2
vite:
specifier: ^5.3.1
- version: 5.3.1
+ version: 5.3.1(@types/node@20.14.8)
vite-plugin-pages:
specifier: ^0.32.2
- version: 0.32.2(react-router@6.23.1(react@18.3.1))(vite@5.3.1)
+ version: 0.32.2(react-router@6.23.1(react@18.3.1))(vite@5.3.1(@types/node@20.14.8))
vite-tsconfig-paths:
specifier: ^4.3.2
- version: 4.3.2(typescript@5.5.2)(vite@5.3.1)
+ version: 4.3.2(typescript@5.5.2)(vite@5.3.1(@types/node@20.14.8))
packages:
@@ -91,6 +100,10 @@ packages:
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
engines: {node: '>=10'}
+ '@babel/runtime@7.24.7':
+ resolution: {integrity: sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==}
+ engines: {node: '>=6.9.0'}
+
'@esbuild/aix-ppc64@0.21.5':
resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
engines: {node: '>=12'}
@@ -259,23 +272,9 @@ packages:
'@formatjs/icu-skeleton-parser@1.8.2':
resolution: {integrity: sha512-k4ERKgw7aKGWJZgTarIcNEmvyTVD9FYh0mTrrBMHZ1b8hUu6iOJ4SzsZlo3UNAvHYa+PnvntIwRPt1/vy4nA9Q==}
- '@formatjs/intl-displaynames@6.6.8':
- resolution: {integrity: sha512-Lgx6n5KxN16B3Pb05z3NLEBQkGoXnGjkTBNCZI+Cn17YjHJ3fhCeEJJUqRlIZmJdmaXQhjcQVDp6WIiNeRYT5g==}
-
- '@formatjs/intl-listformat@7.5.7':
- resolution: {integrity: sha512-MG2TSChQJQT9f7Rlv+eXwUFiG24mKSzmF144PLb8m8OixyXqn4+YWU+5wZracZGCgVTVmx8viCf7IH3QXoiB2g==}
-
'@formatjs/intl-localematcher@0.5.4':
resolution: {integrity: sha512-zTwEpWOzZ2CiKcB93BLngUX59hQkuZjT2+SAQEscSm52peDW/getsawMcWF1rGRpMCX6D7nSJA3CzJ8gn13N/g==}
- '@formatjs/intl@2.10.4':
- resolution: {integrity: sha512-56483O+HVcL0c7VucAS2tyH020mt9XTozZO67cwtGg0a7KWDukS/FzW3OnvaHmTHDuYsoPIzO+ZHVfU6fT/bJw==}
- peerDependencies:
- typescript: ^4.7 || 5
- peerDependenciesMeta:
- typescript:
- optional: true
-
'@humanwhocodes/config-array@0.11.14':
resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==}
engines: {node: '>=10.10.0'}
@@ -492,12 +491,12 @@ packages:
'@types/estree@1.0.5':
resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
- '@types/hoist-non-react-statics@3.3.5':
- resolution: {integrity: sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==}
-
'@types/ms@0.7.34':
resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==}
+ '@types/node@20.14.8':
+ resolution: {integrity: sha512-DO+2/jZinXfROG7j7WKFn/3C6nFwxy2lLpgLjEXJz+0XKphZlTLJ14mo8Vfg8X5BWN6XjyESXq+LcYdT7tR3bA==}
+
'@types/prop-types@15.7.12':
resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==}
@@ -965,8 +964,19 @@ packages:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
- hoist-non-react-statics@3.3.2:
- resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
+ html-parse-stringify@3.0.1:
+ resolution: {integrity: sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==}
+
+ i18next-browser-languagedetector@8.0.0:
+ resolution: {integrity: sha512-zhXdJXTTCoG39QsrOCiOabnWj2jecouOqbchu3EfhtSHxIB5Uugnm9JaizenOy39h7ne3+fLikIjeW88+rgszw==}
+
+ i18next-icu@2.3.0:
+ resolution: {integrity: sha512-x+j7kd5nDJCfbU53uwsMfXD7ALPu5uv0bqjAMQ5nVvXRoj1L7gkmswKtM3XDWYo4YUHf1jznlhSdPyy0xEwU+Q==}
+ peerDependencies:
+ intl-messageformat: ^10.3.3
+
+ i18next@23.11.5:
+ resolution: {integrity: sha512-41pvpVbW9rhZPk5xjCX2TPJi2861LEig/YRhUkY+1FQ2IQPS0bKUDYnEqY8XPPbB48h1uIwLnP9iiEfuSl20CA==}
ignore@5.3.1:
resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==}
@@ -1367,17 +1377,18 @@ packages:
peerDependencies:
react: ^18.3.1
- react-intl@6.6.8:
- resolution: {integrity: sha512-M0pkhzcgV31h++2901BiRXWl69hp2zPyLxRrSwRjd1ErXbNoubz/f4M6DrRTd4OiSUrT4ajRQzrmtS5plG4FtA==}
+ react-i18next@14.1.2:
+ resolution: {integrity: sha512-FSIcJy6oauJbGEXfhUgVeLzvWBhIBIS+/9c6Lj4niwKZyGaGb4V4vUbATXSlsHJDXXB+ociNxqFNiFuV1gmoqg==}
peerDependencies:
- react: ^16.6.0 || 17 || 18
- typescript: ^4.7 || 5
+ i18next: '>= 23.2.3'
+ react: '>= 16.8.0'
+ react-dom: '*'
+ react-native: '*'
peerDependenciesMeta:
- typescript:
+ react-dom:
+ optional: true
+ react-native:
optional: true
-
- react-is@16.13.1:
- resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
react-router-dom@6.23.1:
resolution: {integrity: sha512-utP+K+aSTtEdbWpC+4gxhdlPFwuEfDKq8ZrPFU65bbRJY+l706qjR7yaidBpo3MSeA/fzwbXWbKBI6ftOnP3OQ==}
@@ -1403,6 +1414,9 @@ packages:
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
engines: {node: '>=8.10.0'}
+ regenerator-runtime@0.14.1:
+ resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
+
regexp.prototype.flags@1.5.2:
resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==}
engines: {node: '>= 0.4'}
@@ -1569,6 +1583,9 @@ packages:
ufo@1.5.3:
resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==}
+ undici-types@5.26.5:
+ resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
+
update-browserslist-db@1.0.16:
resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==}
hasBin: true
@@ -1641,6 +1658,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'}
+
which-boxed-primitive@1.0.2:
resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
@@ -1685,6 +1706,10 @@ snapshots:
'@alloc/quick-lru@5.2.0': {}
+ '@babel/runtime@7.24.7':
+ dependencies:
+ regenerator-runtime: 0.14.1
+
'@esbuild/aix-ppc64@0.21.5':
optional: true
@@ -1797,34 +1822,10 @@ snapshots:
'@formatjs/ecma402-abstract': 2.0.0
tslib: 2.6.3
- '@formatjs/intl-displaynames@6.6.8':
- dependencies:
- '@formatjs/ecma402-abstract': 2.0.0
- '@formatjs/intl-localematcher': 0.5.4
- tslib: 2.6.3
-
- '@formatjs/intl-listformat@7.5.7':
- dependencies:
- '@formatjs/ecma402-abstract': 2.0.0
- '@formatjs/intl-localematcher': 0.5.4
- tslib: 2.6.3
-
'@formatjs/intl-localematcher@0.5.4':
dependencies:
tslib: 2.6.3
- '@formatjs/intl@2.10.4(typescript@5.5.2)':
- dependencies:
- '@formatjs/ecma402-abstract': 2.0.0
- '@formatjs/fast-memoize': 2.2.0
- '@formatjs/icu-messageformat-parser': 2.7.8
- '@formatjs/intl-displaynames': 6.6.8
- '@formatjs/intl-listformat': 7.5.7
- intl-messageformat: 10.5.14
- tslib: 2.6.3
- optionalDependencies:
- typescript: 5.5.2
-
'@humanwhocodes/config-array@0.11.14':
dependencies:
'@humanwhocodes/object-schema': 2.0.3
@@ -1986,13 +1987,13 @@ snapshots:
'@types/estree@1.0.5': {}
- '@types/hoist-non-react-statics@3.3.5':
- dependencies:
- '@types/react': 18.3.3
- hoist-non-react-statics: 3.3.2
-
'@types/ms@0.7.34': {}
+ '@types/node@20.14.8':
+ dependencies:
+ undici-types: 5.26.5
+ optional: true
+
'@types/prop-types@15.7.12': {}
'@types/react-dom@18.3.0':
@@ -2089,10 +2090,10 @@ snapshots:
'@ungap/structured-clone@1.2.0': {}
- '@vitejs/plugin-react-swc@3.7.0(vite@5.3.1)':
+ '@vitejs/plugin-react-swc@3.7.0(vite@5.3.1(@types/node@20.14.8))':
dependencies:
'@swc/core': 1.6.5
- vite: 5.3.1
+ vite: 5.3.1(@types/node@20.14.8)
transitivePeerDependencies:
- '@swc/helpers'
@@ -2556,9 +2557,21 @@ snapshots:
dependencies:
function-bind: 1.1.2
- hoist-non-react-statics@3.3.2:
+ html-parse-stringify@3.0.1:
dependencies:
- react-is: 16.13.1
+ void-elements: 3.1.0
+
+ i18next-browser-languagedetector@8.0.0:
+ dependencies:
+ '@babel/runtime': 7.24.7
+
+ i18next-icu@2.3.0(intl-messageformat@10.5.14):
+ dependencies:
+ intl-messageformat: 10.5.14
+
+ i18next@23.11.5:
+ dependencies:
+ '@babel/runtime': 7.24.7
ignore@5.3.1: {}
@@ -2902,23 +2915,14 @@ snapshots:
react: 18.3.1
scheduler: 0.23.2
- react-intl@6.6.8(react@18.3.1)(typescript@5.5.2):
+ react-i18next@14.1.2(i18next@23.11.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
- '@formatjs/ecma402-abstract': 2.0.0
- '@formatjs/icu-messageformat-parser': 2.7.8
- '@formatjs/intl': 2.10.4(typescript@5.5.2)
- '@formatjs/intl-displaynames': 6.6.8
- '@formatjs/intl-listformat': 7.5.7
- '@types/hoist-non-react-statics': 3.3.5
- '@types/react': 18.3.3
- hoist-non-react-statics: 3.3.2
- intl-messageformat: 10.5.14
+ '@babel/runtime': 7.24.7
+ html-parse-stringify: 3.0.1
+ i18next: 23.11.5
react: 18.3.1
- tslib: 2.6.3
optionalDependencies:
- typescript: 5.5.2
-
- react-is@16.13.1: {}
+ react-dom: 18.3.1(react@18.3.1)
react-router-dom@6.23.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
@@ -2944,6 +2948,8 @@ snapshots:
dependencies:
picomatch: 2.3.1
+ regenerator-runtime@0.14.1: {}
+
regexp.prototype.flags@1.5.2:
dependencies:
call-bind: 1.0.7
@@ -3139,6 +3145,9 @@ snapshots:
ufo@1.5.3: {}
+ undici-types@5.26.5:
+ optional: true
+
update-browserslist-db@1.0.16(browserslist@4.23.1):
dependencies:
browserslist: 4.23.1
@@ -3155,7 +3164,7 @@ snapshots:
validate-color@2.2.4: {}
- vite-plugin-pages@0.32.2(react-router@6.23.1(react@18.3.1))(vite@5.3.1):
+ vite-plugin-pages@0.32.2(react-router@6.23.1(react@18.3.1))(vite@5.3.1(@types/node@20.14.8)):
dependencies:
'@types/debug': 4.1.12
debug: 4.3.5
@@ -3165,32 +3174,35 @@ snapshots:
json5: 2.2.3
local-pkg: 0.5.0
picocolors: 1.0.1
- vite: 5.3.1
+ vite: 5.3.1(@types/node@20.14.8)
yaml: 2.4.5
optionalDependencies:
react-router: 6.23.1(react@18.3.1)
transitivePeerDependencies:
- supports-color
- vite-tsconfig-paths@4.3.2(typescript@5.5.2)(vite@5.3.1):
+ vite-tsconfig-paths@4.3.2(typescript@5.5.2)(vite@5.3.1(@types/node@20.14.8)):
dependencies:
debug: 4.3.5
globrex: 0.1.2
tsconfck: 3.1.0(typescript@5.5.2)
optionalDependencies:
- vite: 5.3.1
+ vite: 5.3.1(@types/node@20.14.8)
transitivePeerDependencies:
- supports-color
- typescript
- vite@5.3.1:
+ vite@5.3.1(@types/node@20.14.8):
dependencies:
esbuild: 0.21.5
postcss: 8.4.38
rollup: 4.18.0
optionalDependencies:
+ '@types/node': 20.14.8
fsevents: 2.3.3
+ void-elements@3.1.0: {}
+
which-boxed-primitive@1.0.2:
dependencies:
is-bigint: 1.0.4
diff --git a/src/app.tsx b/src/app.tsx
index bec4ca9..ce118cb 100644
--- a/src/app.tsx
+++ b/src/app.tsx
@@ -1,11 +1,74 @@
import { Suspense } from "react";
import { useRoutes } from "react-router-dom";
import routes from "~react-pages";
+import i18n from "i18next";
+import { initReactI18next } from "react-i18next";
+import LanguageDetector from 'i18next-browser-languagedetector';
+import ICU from 'i18next-icu';
+import * as en from "i18n/en.json"
+import * as zh from "i18n/zh.json"
+import * as ja from "i18n/ja.json"
+import * as ar from "i18n/ar.json"
+import * as de from "i18n/de.json"
+import * as es from "i18n/es.json"
+import * as fr from "i18n/fr.json"
+import * as it from "i18n/it.json"
+import * as ko from "i18n/ko.json"
+import * as pt from "i18n/pt.json"
+import * as ru from "i18n/ru.json"
+
+i18n.use(initReactI18next) // passes i18n down to react-i18next
+ .use(LanguageDetector)
+ .use(ICU)
+ .init({
+ resources: {
+ en: {
+ translation: en
+ },
+ zh: {
+ translation: zh
+ },
+ ja: {
+ translation: ja
+ },
+ ar: {
+ translation: ar
+ },
+ de: {
+ translation: de
+ },
+ es: {
+ translation: es
+ },
+ fr: {
+ translation: fr
+ },
+ it: {
+ translation: it
+ },
+ ko: {
+ translation: ko
+ },
+ pt: {
+ translation: pt
+ },
+ ru: {
+ translation: ru
+ }
+ },
+ fallbackLng: "en",
+
+ interpolation: {
+ escapeValue: false // react already safes from xss => https://www.i18next.com/translation-function/interpolation#unescape
+ },
+
+ detection: {
+ order: ['navigator'],
+ caches: []
+ }
+ });
+
export function App() {
- return (
-