mirror of
https://github.com/Grasscutters/Cultivation.git
synced 2026-02-04 09:25:16 +01:00
translation system
This commit is contained in:
8
lang/en.json
Normal file
8
lang/en.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"lang_name": "English",
|
||||||
|
"main": {
|
||||||
|
"title": "Cultivation",
|
||||||
|
"launch_button": "Launch",
|
||||||
|
"gc_enable": "Connect via Grasscutter"
|
||||||
|
}
|
||||||
|
}
|
||||||
28
src-tauri/src/lang.rs
Normal file
28
src-tauri/src/lang.rs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn get_lang(window: tauri::Window, lang: String) -> String {
|
||||||
|
let lang = lang.to_lowercase();
|
||||||
|
|
||||||
|
// Send contents of language file back
|
||||||
|
let contents = match std::fs::read_to_string(format!("../lang/{}.json", lang)) {
|
||||||
|
Ok(x) => x,
|
||||||
|
Err(e) => {
|
||||||
|
emit_lang_err(window, format!("Failed to read language file: {}", e));
|
||||||
|
return "".to_string();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn emit_lang_err(window: tauri::Window, msg: std::string::String) {
|
||||||
|
let mut res_hash = std::collections::HashMap::new();
|
||||||
|
|
||||||
|
res_hash.insert(
|
||||||
|
"error".to_string(),
|
||||||
|
msg.to_string()
|
||||||
|
);
|
||||||
|
|
||||||
|
window.emit("lang_error", &res_hash).unwrap();
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ windows_subsystem = "windows"
|
|||||||
use opener;
|
use opener;
|
||||||
|
|
||||||
mod downloader;
|
mod downloader;
|
||||||
|
mod lang;
|
||||||
mod proxy;
|
mod proxy;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@@ -14,7 +15,8 @@ fn main() {
|
|||||||
connect,
|
connect,
|
||||||
disconnect,
|
disconnect,
|
||||||
run_program,
|
run_program,
|
||||||
downloader::download_file
|
downloader::download_file,
|
||||||
|
lang::get_lang
|
||||||
])
|
])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { listen } from '@tauri-apps/api/event'
|
||||||
import './App.css'
|
import './App.css'
|
||||||
import './custom.css'
|
import './custom.css'
|
||||||
|
|
||||||
@@ -47,6 +48,10 @@ class App extends React.Component<IProps, IState> {
|
|||||||
optionsOpen: false,
|
optionsOpen: false,
|
||||||
miniDownloadsOpen: false,
|
miniDownloadsOpen: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
listen('lang_error', (payload) => {
|
||||||
|
console.log(payload)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ import minIcon from '../../resources/icons/min.svg'
|
|||||||
import cogBtn from '../../resources/icons/cog.svg'
|
import cogBtn from '../../resources/icons/cog.svg'
|
||||||
import downBtn from '../../resources/icons/download.svg'
|
import downBtn from '../../resources/icons/download.svg'
|
||||||
|
|
||||||
|
import Tr, { translate } from '../../utils/language'
|
||||||
|
|
||||||
import './TopBar.css'
|
import './TopBar.css'
|
||||||
|
import { listen } from '@tauri-apps/api/event'
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
optFunc: () => void;
|
optFunc: () => void;
|
||||||
@@ -37,7 +40,9 @@ export default class TopBar extends React.Component<IProps, IState> {
|
|||||||
return (
|
return (
|
||||||
<div className="TopBar" data-tauri-drag-region >
|
<div className="TopBar" data-tauri-drag-region >
|
||||||
<div id="title">
|
<div id="title">
|
||||||
<span data-tauri-drag-region>Cultivation</span>
|
<span data-tauri-drag-region>
|
||||||
|
<Tr text="main.title" />
|
||||||
|
</span>
|
||||||
<span data-tauri-drag-region id="version">{this.state?.version}</span>
|
<span data-tauri-drag-region id="version">{this.state?.version}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="TopBtns">
|
<div className="TopBtns">
|
||||||
|
|||||||
88
src/utils/language.ts
Normal file
88
src/utils/language.ts
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
import { invoke } from '@tauri-apps/api'
|
||||||
|
import React from 'react'
|
||||||
|
import { getConfigOption } from './configuration'
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IState {
|
||||||
|
language: string;
|
||||||
|
translated_text: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Tr extends React.Component<IProps, IState> {
|
||||||
|
constructor(props: IProps) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
language: 'en',
|
||||||
|
translated_text: '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const { text } = this.props
|
||||||
|
getConfigOption('language').then((language: string) => {
|
||||||
|
// Get translation file
|
||||||
|
if (!language) language = 'en'
|
||||||
|
|
||||||
|
invoke('get_lang', { lang: language }).then((response) => {
|
||||||
|
const translation_obj = JSON.parse(response as string || '{}')
|
||||||
|
|
||||||
|
console.log(translation_obj)
|
||||||
|
|
||||||
|
// Traversal
|
||||||
|
if (text.includes('.')) {
|
||||||
|
const keys = text.split('.')
|
||||||
|
let translation: string | Record<string, string> = translation_obj
|
||||||
|
|
||||||
|
for (let i = 0; i < keys.length; i++) {
|
||||||
|
if (!translation) {
|
||||||
|
translation = ''
|
||||||
|
} else {
|
||||||
|
translation = typeof translation !== 'string' ? translation[keys[i]] : translation as string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(translation)
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
translated_text: translation as string,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
translated_text: translation_obj[text] || ''
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return this.state.translated_text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function translate(text: string) {
|
||||||
|
const language = await getConfigOption('language') || 'en'
|
||||||
|
const translation_json = JSON.parse(await invoke('get_lang', { lang: language }) || '{}')
|
||||||
|
|
||||||
|
// Traversal
|
||||||
|
if (text.includes('.')) {
|
||||||
|
const keys = text.split('.')
|
||||||
|
let translation = ''
|
||||||
|
|
||||||
|
for (let i = 0; i < keys.length; i++) {
|
||||||
|
if (!translation) {
|
||||||
|
translation = ''
|
||||||
|
} else {
|
||||||
|
translation = translation_json[keys[i]] || ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return translation
|
||||||
|
} else {
|
||||||
|
return translation_json[text] || ''
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user