language select

This commit is contained in:
SpikeHD
2022-05-16 20:14:54 -07:00
parent b8c195675c
commit 51dfef5616
7 changed files with 101 additions and 13 deletions

View File

@@ -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",

View File

@@ -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();

View File

@@ -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");

View File

@@ -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%;
} }

View File

@@ -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>
) )
} }

View File

@@ -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)

View 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 }) || '{}')