mirror of
https://github.com/OSMA-D/osma-app.git
synced 2024-12-05 02:56:23 +03:00
feat: i18n
This commit is contained in:
parent
37c3c3f069
commit
0a1f979891
15 changed files with 314 additions and 16 deletions
191
package-lock.json
generated
191
package-lock.json
generated
|
@ -10,8 +10,11 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@heroicons/react": "^1.0.6",
|
"@heroicons/react": "^1.0.6",
|
||||||
"@tauri-apps/api": "^1.0.2",
|
"@tauri-apps/api": "^1.0.2",
|
||||||
|
"@tauri-apps/tauri-forage": "^1.0.0-beta.2",
|
||||||
|
"i18next": "^21.9.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
"react-i18next": "^11.18.3",
|
||||||
"react-router-dom": "^6.3.0"
|
"react-router-dom": "^6.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -716,6 +719,22 @@
|
||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tauri-apps/tauri-forage": {
|
||||||
|
"version": "1.0.0-beta.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tauri-apps/tauri-forage/-/tauri-forage-1.0.0-beta.2.tgz",
|
||||||
|
"integrity": "sha512-aGObWlY8sgEfImt8+Cv4D+hqWhWB4KwPLVRQTv2uPtHSrXpXrvkJ8vTjy+QsT7tGPyVhcLPBchbyGu0JReErSQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"localforage": "^1.7.3",
|
||||||
|
"ramda": "^0.26.1",
|
||||||
|
"tweetnacl": "^1.0.1",
|
||||||
|
"tweetnacl-util": "^0.15.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.18.1",
|
||||||
|
"npm": ">= 6.13.4",
|
||||||
|
"yarn": ">= 1.21.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/prop-types": {
|
"node_modules/@types/prop-types": {
|
||||||
"version": "15.7.5",
|
"version": "15.7.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
||||||
|
@ -1606,6 +1625,41 @@
|
||||||
"@babel/runtime": "^7.7.6"
|
"@babel/runtime": "^7.7.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/html-parse-stringify": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==",
|
||||||
|
"dependencies": {
|
||||||
|
"void-elements": "3.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/i18next": {
|
||||||
|
"version": "21.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/i18next/-/i18next-21.9.0.tgz",
|
||||||
|
"integrity": "sha512-B+6/yd7rCpJidyPuBaEApUECx7G8Ai6+tqYhrChsY4MmQqJhG7qJ4eT6Lm1OnRhieVelEtfxh4aAQktdNVZtDA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://locize.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://locize.com/i18next.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.17.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/immediate": {
|
||||||
|
"version": "3.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
||||||
|
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
|
||||||
|
},
|
||||||
"node_modules/is-binary-path": {
|
"node_modules/is-binary-path": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||||
|
@ -1689,6 +1743,14 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lie": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==",
|
||||||
|
"dependencies": {
|
||||||
|
"immediate": "~3.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lilconfig": {
|
"node_modules/lilconfig": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz",
|
||||||
|
@ -1698,6 +1760,14 @@
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/localforage": {
|
||||||
|
"version": "1.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
|
||||||
|
"integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==",
|
||||||
|
"dependencies": {
|
||||||
|
"lie": "3.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/loose-envify": {
|
"node_modules/loose-envify": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||||
|
@ -1992,6 +2062,11 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ramda": {
|
||||||
|
"version": "0.26.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz",
|
||||||
|
"integrity": "sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ=="
|
||||||
|
},
|
||||||
"node_modules/react": {
|
"node_modules/react": {
|
||||||
"version": "18.2.0",
|
"version": "18.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
|
||||||
|
@ -2015,6 +2090,27 @@
|
||||||
"react": "^18.2.0"
|
"react": "^18.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-i18next": {
|
||||||
|
"version": "11.18.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.18.3.tgz",
|
||||||
|
"integrity": "sha512-EttTX31HbqzZymUM3SIrMPuvamfSXFZVsDHm/ZAqoDfTLjhzlwyxqfbDNxcKNAGOi2mjZaXfR7hSNMlvLNpB/g==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.14.5",
|
||||||
|
"html-parse-stringify": "^3.0.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"i18next": ">= 19.0.0",
|
||||||
|
"react": ">= 16.8.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-native": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-refresh": {
|
"node_modules/react-refresh": {
|
||||||
"version": "0.14.0",
|
"version": "0.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
|
||||||
|
@ -2268,6 +2364,16 @@
|
||||||
"node": ">=8.0"
|
"node": ">=8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tweetnacl": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw=="
|
||||||
|
},
|
||||||
|
"node_modules/tweetnacl-util": {
|
||||||
|
"version": "0.15.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz",
|
||||||
|
"integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw=="
|
||||||
|
},
|
||||||
"node_modules/update-browserslist-db": {
|
"node_modules/update-browserslist-db": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz",
|
||||||
|
@ -2341,6 +2447,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/void-elements": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/xtend": {
|
"node_modules/xtend": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||||
|
@ -2819,6 +2933,17 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"@tauri-apps/tauri-forage": {
|
||||||
|
"version": "1.0.0-beta.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tauri-apps/tauri-forage/-/tauri-forage-1.0.0-beta.2.tgz",
|
||||||
|
"integrity": "sha512-aGObWlY8sgEfImt8+Cv4D+hqWhWB4KwPLVRQTv2uPtHSrXpXrvkJ8vTjy+QsT7tGPyVhcLPBchbyGu0JReErSQ==",
|
||||||
|
"requires": {
|
||||||
|
"localforage": "^1.7.3",
|
||||||
|
"ramda": "^0.26.1",
|
||||||
|
"tweetnacl": "^1.0.1",
|
||||||
|
"tweetnacl-util": "^0.15.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/prop-types": {
|
"@types/prop-types": {
|
||||||
"version": "15.7.5",
|
"version": "15.7.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
||||||
|
@ -3370,6 +3495,27 @@
|
||||||
"@babel/runtime": "^7.7.6"
|
"@babel/runtime": "^7.7.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"html-parse-stringify": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==",
|
||||||
|
"requires": {
|
||||||
|
"void-elements": "3.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"i18next": {
|
||||||
|
"version": "21.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/i18next/-/i18next-21.9.0.tgz",
|
||||||
|
"integrity": "sha512-B+6/yd7rCpJidyPuBaEApUECx7G8Ai6+tqYhrChsY4MmQqJhG7qJ4eT6Lm1OnRhieVelEtfxh4aAQktdNVZtDA==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.17.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"immediate": {
|
||||||
|
"version": "3.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
||||||
|
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
|
||||||
|
},
|
||||||
"is-binary-path": {
|
"is-binary-path": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||||
|
@ -3426,12 +3572,28 @@
|
||||||
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
|
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"lie": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==",
|
||||||
|
"requires": {
|
||||||
|
"immediate": "~3.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"lilconfig": {
|
"lilconfig": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz",
|
||||||
"integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==",
|
"integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"localforage": {
|
||||||
|
"version": "1.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
|
||||||
|
"integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==",
|
||||||
|
"requires": {
|
||||||
|
"lie": "3.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"loose-envify": {
|
"loose-envify": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||||
|
@ -3609,6 +3771,11 @@
|
||||||
"integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
|
"integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"ramda": {
|
||||||
|
"version": "0.26.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz",
|
||||||
|
"integrity": "sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ=="
|
||||||
|
},
|
||||||
"react": {
|
"react": {
|
||||||
"version": "18.2.0",
|
"version": "18.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
|
||||||
|
@ -3626,6 +3793,15 @@
|
||||||
"scheduler": "^0.23.0"
|
"scheduler": "^0.23.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-i18next": {
|
||||||
|
"version": "11.18.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.18.3.tgz",
|
||||||
|
"integrity": "sha512-EttTX31HbqzZymUM3SIrMPuvamfSXFZVsDHm/ZAqoDfTLjhzlwyxqfbDNxcKNAGOi2mjZaXfR7hSNMlvLNpB/g==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.14.5",
|
||||||
|
"html-parse-stringify": "^3.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-refresh": {
|
"react-refresh": {
|
||||||
"version": "0.14.0",
|
"version": "0.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
|
||||||
|
@ -3807,6 +3983,16 @@
|
||||||
"is-number": "^7.0.0"
|
"is-number": "^7.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"tweetnacl": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw=="
|
||||||
|
},
|
||||||
|
"tweetnacl-util": {
|
||||||
|
"version": "0.15.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz",
|
||||||
|
"integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw=="
|
||||||
|
},
|
||||||
"update-browserslist-db": {
|
"update-browserslist-db": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz",
|
||||||
|
@ -3836,6 +4022,11 @@
|
||||||
"rollup": "^2.75.6"
|
"rollup": "^2.75.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"void-elements": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w=="
|
||||||
|
},
|
||||||
"xtend": {
|
"xtend": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||||
|
|
|
@ -12,8 +12,10 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@heroicons/react": "^1.0.6",
|
"@heroicons/react": "^1.0.6",
|
||||||
"@tauri-apps/api": "^1.0.2",
|
"@tauri-apps/api": "^1.0.2",
|
||||||
|
"i18next": "^21.9.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
"react-i18next": "^11.18.3",
|
||||||
"react-router-dom": "^6.3.0"
|
"react-router-dom": "^6.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use crate::AppData;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use crate::{AppData, Language};
|
||||||
use reqwest::blocking::*;
|
use reqwest::blocking::*;
|
||||||
use tauri::{App, State};
|
use tauri::{App, State};
|
||||||
|
|
||||||
|
@ -26,3 +28,17 @@ pub fn check_auth(state: State<AppData>) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn change_lng(state: State<Mutex<Language>>, lng: String) {
|
||||||
|
let mut state = state.lock().unwrap();
|
||||||
|
*state = Language { lng };
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn get_lng(state: State<Mutex<Language>>) -> String {
|
||||||
|
match state.lock() {
|
||||||
|
Ok(val) => val.lng.clone(),
|
||||||
|
Err(_) => "ru".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,21 +3,30 @@
|
||||||
windows_subsystem = "windows"
|
windows_subsystem = "windows"
|
||||||
)]
|
)]
|
||||||
|
|
||||||
use std::fs;
|
use std::{fs, sync::Mutex};
|
||||||
|
|
||||||
mod types;
|
mod types;
|
||||||
use types::*;
|
use types::*;
|
||||||
|
|
||||||
mod commands;
|
mod commands;
|
||||||
fn main() {
|
fn main() {
|
||||||
let options = fs::read_to_string("options.json").unwrap_or("{\"jwt\":null}".to_string());
|
let options = {
|
||||||
tauri::Builder::default()
|
let op = fs::read_to_string("options.json").unwrap_or("{\"jwt\":null}".to_string());
|
||||||
.manage(
|
serde_json::from_str::<AppData>(&op).unwrap_or(AppData {
|
||||||
serde_json::from_str::<AppData>(&options).unwrap_or(AppData {
|
|
||||||
jwt: "null".to_string(),
|
jwt: "null".to_string(),
|
||||||
}),
|
lng: "en".to_string(),
|
||||||
)
|
})
|
||||||
.invoke_handler(tauri::generate_handler![commands::check_auth])
|
};
|
||||||
|
tauri::Builder::default()
|
||||||
|
.manage(Mutex::new(Language {
|
||||||
|
lng: options.lng.clone(),
|
||||||
|
}))
|
||||||
|
.manage(options)
|
||||||
|
.invoke_handler(tauri::generate_handler![
|
||||||
|
commands::check_auth,
|
||||||
|
commands::change_lng,
|
||||||
|
commands::get_lng
|
||||||
|
])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running osma app");
|
.expect("error while running osma app");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize, Clone)]
|
||||||
pub struct AppData {
|
pub struct AppData {
|
||||||
pub jwt: String,
|
pub jwt: String,
|
||||||
|
pub lng: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Language {
|
||||||
|
pub lng: String,
|
||||||
}
|
}
|
||||||
|
|
37
src/App.jsx
37
src/App.jsx
|
@ -2,8 +2,29 @@ import "./components/menu";
|
||||||
import Menu from "./components/menu";
|
import Menu from "./components/menu";
|
||||||
import { Routes, Route } from "react-router-dom";
|
import { Routes, Route } from "react-router-dom";
|
||||||
import CheckAuth from "./pages/checkAuth";
|
import CheckAuth from "./pages/checkAuth";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import { invoke } from "@tauri-apps/api/tauri";
|
||||||
|
|
||||||
|
let lngs = ["en", "ru"];
|
||||||
function App() {
|
function App() {
|
||||||
|
const { i18n } = useTranslation();
|
||||||
|
|
||||||
|
let setLng = async () => {
|
||||||
|
let lng = await invoke("get_lng");
|
||||||
|
if (lng == i18n.language) return;
|
||||||
|
i18n.changeLanguage(lng);
|
||||||
|
};
|
||||||
|
|
||||||
|
let changeLng = async (lang) => {
|
||||||
|
let lng = await invoke("change_lng", { lng: lang });
|
||||||
|
i18n.changeLanguage(lang);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setLng();
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-5 gap-10 text-black dark:text-white">
|
<div className="grid grid-cols-1 lg:grid-cols-5 gap-10 text-black dark:text-white">
|
||||||
<Menu />
|
<Menu />
|
||||||
|
@ -24,7 +45,21 @@ function App() {
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="options"
|
path="options"
|
||||||
element={<div className="col-span-4">Options page</div>}
|
element={
|
||||||
|
<div className="col-span-4">
|
||||||
|
{lngs.map((val) => {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
className="bg-zinc-500 p-5 m-5 rounded-3xl"
|
||||||
|
onClick={() => changeLng(val)}
|
||||||
|
key={val}
|
||||||
|
>
|
||||||
|
{val}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
function Button(props) {
|
function Button(props) {
|
||||||
return (
|
return (
|
||||||
<a href={props.href} className={props.className}>
|
<a href={props.href} className={props.className} onClick={props.onClick}>
|
||||||
<div className="transition-transform w-48 ease-[cubic-bezier(.69,.58,.32,1.69)] delay-60 hover:scale-105 p-2 pl-6 text-lg bg-zinc-100 hover:bg-zinc-300 dark:bg-zinc-600 dark:hover:bg-zinc-800 rounded-2xl">
|
<div className="transition-transform w-48 ease-[cubic-bezier(.69,.58,.32,1.69)] delay-60 hover:scale-105 p-2 pl-6 text-lg bg-zinc-100 hover:bg-zinc-300 dark:bg-zinc-600 dark:hover:bg-zinc-800 rounded-2xl">
|
||||||
{props.children}
|
{props.children}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,20 +5,23 @@ import {
|
||||||
ArrowCircleDownIcon,
|
ArrowCircleDownIcon,
|
||||||
CogIcon,
|
CogIcon,
|
||||||
} from "@heroicons/react/outline";
|
} from "@heroicons/react/outline";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
function Menu() {
|
function Menu() {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid grid-cols-1 gap-3 m-4">
|
<div className="grid grid-cols-1 gap-3 m-4">
|
||||||
<Button href="/main">
|
<Button href="/main">
|
||||||
<IconWithButton icon={<MenuIcon className="h-7 w-7" />}>
|
<IconWithButton icon={<MenuIcon className="h-7 w-7" />}>
|
||||||
Main
|
{t("main")}
|
||||||
</IconWithButton>
|
</IconWithButton>
|
||||||
</Button>
|
</Button>
|
||||||
<Button href="/library">
|
<Button href="/library">
|
||||||
<IconWithButton
|
<IconWithButton
|
||||||
icon={<ArchiveIcon className="transform translate-z-0 h-7 w-7" />}
|
icon={<ArchiveIcon className="transform translate-z-0 h-7 w-7" />}
|
||||||
>
|
>
|
||||||
Library
|
{t("library")}
|
||||||
</IconWithButton>
|
</IconWithButton>
|
||||||
</Button>
|
</Button>
|
||||||
<Button href="/downloads">
|
<Button href="/downloads">
|
||||||
|
@ -27,14 +30,14 @@ function Menu() {
|
||||||
<ArrowCircleDownIcon className="transform translate-z-0 h-7 w-7" />
|
<ArrowCircleDownIcon className="transform translate-z-0 h-7 w-7" />
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Downloads
|
{t("downloads")}
|
||||||
</IconWithButton>
|
</IconWithButton>
|
||||||
</Button>
|
</Button>
|
||||||
<Button href="/options">
|
<Button href="/options">
|
||||||
<IconWithButton
|
<IconWithButton
|
||||||
icon={<CogIcon className="transform translate-z-0 h-7 w-7" />}
|
icon={<CogIcon className="transform translate-z-0 h-7 w-7" />}
|
||||||
>
|
>
|
||||||
Options
|
{t("options")}
|
||||||
</IconWithButton>
|
</IconWithButton>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
12
src/i18n.js
Normal file
12
src/i18n.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import i18next from "i18next";
|
||||||
|
import { initReactI18next } from "react-i18next";
|
||||||
|
import { en, ru } from "./locales/all";
|
||||||
|
|
||||||
|
i18next.use(initReactI18next).init({
|
||||||
|
fallbackLng: "en",
|
||||||
|
debug: true,
|
||||||
|
resources: {
|
||||||
|
en,
|
||||||
|
ru,
|
||||||
|
},
|
||||||
|
});
|
4
src/locales/all.js
Normal file
4
src/locales/all.js
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
import en from "./en";
|
||||||
|
import ru from "./ru";
|
||||||
|
|
||||||
|
export { en, ru };
|
10
src/locales/en.js
Normal file
10
src/locales/en.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
const en = {
|
||||||
|
translation: {
|
||||||
|
main: "Main",
|
||||||
|
downloads: "Downloads",
|
||||||
|
library: "Library",
|
||||||
|
options: "Options",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default en;
|
10
src/locales/ru.js
Normal file
10
src/locales/ru.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
const en = {
|
||||||
|
translation: {
|
||||||
|
main: "Главная",
|
||||||
|
downloads: "Загрузки",
|
||||||
|
library: "Библиотека",
|
||||||
|
options: "Настройки",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default en;
|
|
@ -3,6 +3,7 @@ import ReactDOM from "react-dom/client";
|
||||||
import App from "./App";
|
import App from "./App";
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
import { BrowserRouter } from "react-router-dom";
|
import { BrowserRouter } from "react-router-dom";
|
||||||
|
import "./i18n";
|
||||||
|
|
||||||
ReactDOM.createRoot(document.getElementById("root")).render(
|
ReactDOM.createRoot(document.getElementById("root")).render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
|
|
0
src/pages/auth.jsx
Normal file
0
src/pages/auth.jsx
Normal file
Loading…
Add table
Reference in a new issue