mirror of
https://github.com/OSMA-D/osma-app.git
synced 2024-11-05 21:24:04 +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": {
|
||||
"@heroicons/react": "^1.0.6",
|
||||
"@tauri-apps/api": "^1.0.2",
|
||||
"@tauri-apps/tauri-forage": "^1.0.0-beta.2",
|
||||
"i18next": "^21.9.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-i18next": "^11.18.3",
|
||||
"react-router-dom": "^6.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -716,6 +719,22 @@
|
|||
"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": {
|
||||
"version": "15.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
||||
|
@ -1606,6 +1625,41 @@
|
|||
"@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": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||
|
@ -1689,6 +1743,14 @@
|
|||
"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": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz",
|
||||
|
@ -1698,6 +1760,14 @@
|
|||
"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": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
|
@ -1992,6 +2062,11 @@
|
|||
"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": {
|
||||
"version": "18.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
|
||||
|
@ -2015,6 +2090,27 @@
|
|||
"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": {
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
|
||||
|
@ -2268,6 +2364,16 @@
|
|||
"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": {
|
||||
"version": "1.0.5",
|
||||
"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": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
|
@ -2819,6 +2933,17 @@
|
|||
"dev": 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": {
|
||||
"version": "15.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
||||
|
@ -3370,6 +3495,27 @@
|
|||
"@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": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||
|
@ -3426,12 +3572,28 @@
|
|||
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
|
||||
"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": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz",
|
||||
"integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==",
|
||||
"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": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
|
@ -3609,6 +3771,11 @@
|
|||
"integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
|
||||
"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": {
|
||||
"version": "18.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
|
||||
|
@ -3626,6 +3793,15 @@
|
|||
"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": {
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
|
||||
|
@ -3807,6 +3983,16 @@
|
|||
"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": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz",
|
||||
|
@ -3836,6 +4022,11 @@
|
|||
"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": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
|
|
|
@ -12,8 +12,10 @@
|
|||
"dependencies": {
|
||||
"@heroicons/react": "^1.0.6",
|
||||
"@tauri-apps/api": "^1.0.2",
|
||||
"i18next": "^21.9.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-i18next": "^11.18.3",
|
||||
"react-router-dom": "^6.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use crate::AppData;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use crate::{AppData, Language};
|
||||
use reqwest::blocking::*;
|
||||
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"
|
||||
)]
|
||||
|
||||
use std::fs;
|
||||
use std::{fs, sync::Mutex};
|
||||
|
||||
mod types;
|
||||
use types::*;
|
||||
|
||||
mod commands;
|
||||
fn main() {
|
||||
let options = fs::read_to_string("options.json").unwrap_or("{\"jwt\":null}".to_string());
|
||||
let options = {
|
||||
let op = fs::read_to_string("options.json").unwrap_or("{\"jwt\":null}".to_string());
|
||||
serde_json::from_str::<AppData>(&op).unwrap_or(AppData {
|
||||
jwt: "null".to_string(),
|
||||
lng: "en".to_string(),
|
||||
})
|
||||
};
|
||||
tauri::Builder::default()
|
||||
.manage(
|
||||
serde_json::from_str::<AppData>(&options).unwrap_or(AppData {
|
||||
jwt: "null".to_string(),
|
||||
}),
|
||||
)
|
||||
.invoke_handler(tauri::generate_handler![commands::check_auth])
|
||||
.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!())
|
||||
.expect("error while running osma app");
|
||||
}
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[derive(Deserialize, Clone)]
|
||||
pub struct AppData {
|
||||
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 { Routes, Route } from "react-router-dom";
|
||||
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() {
|
||||
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 (
|
||||
<div className="grid grid-cols-1 lg:grid-cols-5 gap-10 text-black dark:text-white">
|
||||
<Menu />
|
||||
|
@ -24,7 +45,21 @@ function App() {
|
|||
/>
|
||||
<Route
|
||||
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>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
function Button(props) {
|
||||
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">
|
||||
{props.children}
|
||||
</div>
|
||||
|
|
|
@ -5,20 +5,23 @@ import {
|
|||
ArrowCircleDownIcon,
|
||||
CogIcon,
|
||||
} from "@heroicons/react/outline";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
function Menu() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-1 gap-3 m-4">
|
||||
<Button href="/main">
|
||||
<IconWithButton icon={<MenuIcon className="h-7 w-7" />}>
|
||||
Main
|
||||
{t("main")}
|
||||
</IconWithButton>
|
||||
</Button>
|
||||
<Button href="/library">
|
||||
<IconWithButton
|
||||
icon={<ArchiveIcon className="transform translate-z-0 h-7 w-7" />}
|
||||
>
|
||||
Library
|
||||
{t("library")}
|
||||
</IconWithButton>
|
||||
</Button>
|
||||
<Button href="/downloads">
|
||||
|
@ -27,14 +30,14 @@ function Menu() {
|
|||
<ArrowCircleDownIcon className="transform translate-z-0 h-7 w-7" />
|
||||
}
|
||||
>
|
||||
Downloads
|
||||
{t("downloads")}
|
||||
</IconWithButton>
|
||||
</Button>
|
||||
<Button href="/options">
|
||||
<IconWithButton
|
||||
icon={<CogIcon className="transform translate-z-0 h-7 w-7" />}
|
||||
>
|
||||
Options
|
||||
{t("options")}
|
||||
</IconWithButton>
|
||||
</Button>
|
||||
</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 "./index.css";
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
import "./i18n";
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")).render(
|
||||
<React.StrictMode>
|
||||
|
|
0
src/pages/auth.jsx
Normal file
0
src/pages/auth.jsx
Normal file
Loading…
Reference in a new issue