mirror of
https://github.com/Grasscutters/Cultivation.git
synced 2025-12-12 23:24:35 +01:00
language select
This commit is contained in:
@@ -13,7 +13,8 @@
|
|||||||
"game_exec": "Set Game Executable",
|
"game_exec": "Set Game Executable",
|
||||||
"grasscutter_jar": "Set Grasscutter Jar",
|
"grasscutter_jar": "Set Grasscutter Jar",
|
||||||
"java_path": "Set Custom Java Path",
|
"java_path": "Set Custom Java Path",
|
||||||
"grasscutter_with_game": "Automatically launch Grasscutter with game"
|
"grasscutter_with_game": "Automatically launch Grasscutter with game",
|
||||||
|
"language": "Select Language"
|
||||||
},
|
},
|
||||||
"downloads": {
|
"downloads": {
|
||||||
"grasscutter_stable_data": "Download Grasscutter Stable Data",
|
"grasscutter_stable_data": "Download Grasscutter Stable Data",
|
||||||
|
|||||||
@@ -14,6 +14,32 @@ pub async fn get_lang(window: tauri::Window, lang: String) -> String {
|
|||||||
return contents;
|
return contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn get_languages() -> std::collections::HashMap<String, String> {
|
||||||
|
// for each lang file, set the key as the filename and the value as the lang_name contained in the file
|
||||||
|
let mut languages = std::collections::HashMap::new();
|
||||||
|
|
||||||
|
let mut lang_files = std::fs::read_dir("../lang").unwrap();
|
||||||
|
|
||||||
|
while let Some(entry) = lang_files.next() {
|
||||||
|
let entry = entry.unwrap();
|
||||||
|
let path = entry.path();
|
||||||
|
let filename = path.file_name().unwrap().to_str().unwrap();
|
||||||
|
|
||||||
|
let content = match std::fs::read_to_string(path.to_str().unwrap()) {
|
||||||
|
Ok(x) => x,
|
||||||
|
Err(e) => {
|
||||||
|
println!("Failed to read language file: {}", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
languages.insert(filename.to_string(), content);
|
||||||
|
}
|
||||||
|
|
||||||
|
return languages;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn emit_lang_err(window: tauri::Window, msg: std::string::String) {
|
pub fn emit_lang_err(window: tauri::Window, msg: std::string::String) {
|
||||||
let mut res_hash = std::collections::HashMap::new();
|
let mut res_hash = std::collections::HashMap::new();
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ fn main() {
|
|||||||
get_bg_file,
|
get_bg_file,
|
||||||
downloader::download_file,
|
downloader::download_file,
|
||||||
downloader::stop_download,
|
downloader::stop_download,
|
||||||
lang::get_lang
|
lang::get_lang,
|
||||||
|
lang::get_languages
|
||||||
])
|
])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
|
|||||||
@@ -5,6 +5,23 @@ body {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
width: 217px;
|
||||||
|
border: none;
|
||||||
|
border-bottom: 2px solid #cecece;
|
||||||
|
|
||||||
|
padding-right: 16px;
|
||||||
|
|
||||||
|
text-decoration-color: #000;
|
||||||
|
|
||||||
|
transition: border-bottom-color 0.1s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
select:focus {
|
||||||
|
outline: none;
|
||||||
|
border-bottom-color: #ffd326;
|
||||||
|
}
|
||||||
|
|
||||||
#root, .App {
|
#root, .App {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import DirInput from '../common/DirInput'
|
import DirInput from '../common/DirInput'
|
||||||
import Menu from './Menu'
|
import Menu from './Menu'
|
||||||
import Tr from '../../../utils/language'
|
import Tr, { getLanguages } from '../../../utils/language'
|
||||||
import './Options.css'
|
import './Options.css'
|
||||||
import { setConfigOption, getConfig, getConfigOption } from '../../../utils/configuration'
|
import { setConfigOption, getConfig, getConfigOption } from '../../../utils/configuration'
|
||||||
import Checkbox from '../common/Checkbox'
|
import Checkbox from '../common/Checkbox'
|
||||||
import Divider from './Divider'
|
import Divider from './Divider'
|
||||||
|
import { invoke } from '@tauri-apps/api'
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
closeFn: () => void;
|
closeFn: () => void;
|
||||||
@@ -16,6 +17,7 @@ interface IState {
|
|||||||
grasscutter_path: string
|
grasscutter_path: string
|
||||||
java_path: string
|
java_path: string
|
||||||
grasscutter_with_game: boolean
|
grasscutter_with_game: boolean
|
||||||
|
language_options: { [key: string]: string }[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Options extends React.Component<IProps, IState> {
|
export default class Options extends React.Component<IProps, IState> {
|
||||||
@@ -26,18 +28,21 @@ export default class Options extends React.Component<IProps, IState> {
|
|||||||
game_install_path: '',
|
game_install_path: '',
|
||||||
grasscutter_path: '',
|
grasscutter_path: '',
|
||||||
java_path: '',
|
java_path: '',
|
||||||
grasscutter_with_game: false
|
grasscutter_with_game: false,
|
||||||
|
language_options: []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
async componentDidMount() {
|
||||||
getConfig().then(config => {
|
const config = await getConfig()
|
||||||
this.setState({
|
const languages = await getLanguages()
|
||||||
game_install_path: config.game_install_path || '',
|
|
||||||
grasscutter_path: config.grasscutter_path || '',
|
this.setState({
|
||||||
java_path: config.java_path || '',
|
game_install_path: config.game_install_path || '',
|
||||||
grasscutter_with_game: config.grasscutter_with_game || false
|
grasscutter_path: config.grasscutter_path || '',
|
||||||
})
|
java_path: config.java_path || '',
|
||||||
|
grasscutter_with_game: config.grasscutter_with_game || false,
|
||||||
|
language_options: languages
|
||||||
})
|
})
|
||||||
|
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
@@ -55,6 +60,10 @@ export default class Options extends React.Component<IProps, IState> {
|
|||||||
setConfigOption('java_path', value)
|
setConfigOption('java_path', value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setLanguage(value: string) {
|
||||||
|
setConfigOption('language', value)
|
||||||
|
}
|
||||||
|
|
||||||
async toggleGrasscutterWithGame() {
|
async toggleGrasscutterWithGame() {
|
||||||
setConfigOption('grasscutter_with_game', !(await getConfigOption('grasscutter_with_game')))
|
setConfigOption('grasscutter_with_game', !(await getConfigOption('grasscutter_with_game')))
|
||||||
}
|
}
|
||||||
@@ -100,6 +109,21 @@ export default class Options extends React.Component<IProps, IState> {
|
|||||||
<DirInput onChange={this.setJavaPath} value={this.state?.java_path} extensions={['exe']} />
|
<DirInput onChange={this.setJavaPath} value={this.state?.java_path} extensions={['exe']} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className='OptionSection'>
|
||||||
|
<div className='OptionLabel'>
|
||||||
|
<Tr text="options.language" />
|
||||||
|
</div>
|
||||||
|
<div className='OptionValue'>
|
||||||
|
<select onChange={(event) => {
|
||||||
|
this.setLanguage(event.target.value)
|
||||||
|
}}>
|
||||||
|
{this.state.language_options.map(lang => (
|
||||||
|
<option key={Object.keys(lang)[0]} value={Object.keys(lang)[0]}>{lang[Object.keys(lang)[0]]}</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</Menu>
|
</Menu>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ async function readConfigFile() {
|
|||||||
// Create config file
|
// Create config file
|
||||||
const file: fs.FsTextFileOption = {
|
const file: fs.FsTextFileOption = {
|
||||||
path: configFilePath,
|
path: configFilePath,
|
||||||
contents: '{}'
|
contents: JSON.stringify(defaultConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
await fs.writeFile(file)
|
await fs.writeFile(file)
|
||||||
|
|||||||
@@ -60,6 +60,25 @@ export default class Tr extends React.Component<IProps, IState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getLanguages() {
|
||||||
|
const resp: {
|
||||||
|
[key: string]: string;
|
||||||
|
} = await invoke('get_languages')
|
||||||
|
const lang_list: {
|
||||||
|
[key: string]: string;
|
||||||
|
}[] = []
|
||||||
|
|
||||||
|
Object.keys(resp).forEach(k => {
|
||||||
|
const parsed = JSON.parse(resp[k])
|
||||||
|
|
||||||
|
if (parsed.lang_name) {
|
||||||
|
lang_list.push({ [k.split('.json')[0]]: parsed.lang_name })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return lang_list
|
||||||
|
}
|
||||||
|
|
||||||
export async function translate(text: string) {
|
export async function translate(text: string) {
|
||||||
const language = await getConfigOption('language') || 'en'
|
const language = await getConfigOption('language') || 'en'
|
||||||
const translation_json = JSON.parse(await invoke('get_lang', { lang: language }) || '{}')
|
const translation_json = JSON.parse(await invoke('get_lang', { lang: language }) || '{}')
|
||||||
|
|||||||
Reference in New Issue
Block a user