feat(i18n): added automatic default launcher language selection

Improved `i18n` mod to list supported languages and some other stuff

As well was added `get_default_lang` function
which will return language key based on current system language.
This function is called at the first launcher start
to update default `launcher.language` config property, so user will immediately
have proper language in initial setup window
This commit is contained in:
Observer KRypt0n_ 2023-02-25 14:24:04 +02:00
parent b7e85b7a8f
commit cbd91c42aa
No known key found for this signature in database
GPG key ID: 844DA47BA25FE1E2
3 changed files with 88 additions and 23 deletions

View file

@ -8,20 +8,9 @@ pub struct Background {
}
pub fn get_uri() -> String {
let mut lang;
unsafe {
lang = crate::i18n::LANG.language.as_str().to_string();
if let Some(region) = crate::i18n::LANG.region {
lang += "-";
lang += &region.as_str().to_ascii_lowercase();
}
}
let uri = concat!("https://sdk-os-static.", "ho", "yo", "verse", ".com/hk4e_global/mdk/launcher/api/content?filter_adv=true&key=gcStgarh&launcher_id=10&language=");
uri.to_owned() + &lang
uri.to_owned() + crate::i18n::get_lang()
}
#[cached::proc_macro::cached(result)]

View file

@ -8,17 +8,88 @@ fluent_templates::static_loader! {
};
}
pub static mut LANG: LanguageIdentifier = langid!("en");
/// Map of supported languages
pub const SUPPORTED_LANGUAGES: &[(&str, LanguageIdentifier)] = &[
("en-us", langid!("en")),
("ru-ru", langid!("ru"))
];
static mut LANG: LanguageIdentifier = langid!("en");
/// Set launcher language
pub fn set_lang<T: AsRef<str>>(lang: T) -> anyhow::Result<()> {
for (key, id) in SUPPORTED_LANGUAGES {
if key == &lang.as_ref() {
unsafe {
LANG = id.to_owned()
}
return Ok(());
}
}
anyhow::bail!("Language {} is not supported", lang.as_ref())
}
/// Get launcher language
pub fn get_lang() -> &'static str {
for (key, lang) in SUPPORTED_LANGUAGES {
if lang == unsafe { &LANG } {
return key;
}
}
unreachable!()
}
/// Get system language or default language if system one is not supported
///
/// Checks env variables in following order:
/// - `LC_ALL`
/// - `LC_MESSAGES`
/// - `LANG`
pub fn get_default_lang() -> String {
let lang = std::env::var("LC_ALL")
.unwrap_or_else(|_| std::env::var("LC_MESSAGES")
.unwrap_or_else(|_| std::env::var("LANG")
.unwrap_or_else(|_| String::from("en_US.UTF-8"))));
let lang = lang.split('.')
.next()
.unwrap_or("en_US")
.replace('_', "-")
.to_ascii_lowercase();
for (key, _) in SUPPORTED_LANGUAGES {
if key == &lang {
return lang;
}
}
String::from("en-us")
}
/// Get translated message by key
///
/// ```no_run
/// println!("Translated message: {}", tr("launch"));
/// ```
#[allow(clippy::expect_fun_call)]
pub fn tr(id: &str) -> String {
unsafe {
LOCALES
.lookup(&LANG, id)
.expect(&format!("Failed to find message with a given id: {id}"))
.expect(&format!("Failed to find message with given id: {id}"))
}
}
/// Get translated message by key with filled arguments
///
/// ```no_run
/// println!("Translated message: {}", tr_args("game-outdated", [
/// ("latest", "3.3.0".into())
/// ]));
/// ```
#[allow(clippy::expect_fun_call)]
pub fn tr_args<I, T>(id: &str, args: I) -> String
where
@ -28,6 +99,6 @@ where
unsafe {
LOCALES
.lookup_with_args(&LANG, id, &std::collections::HashMap::from_iter(args.into_iter()))
.expect(&format!("Failed to find message with a given id: {id}"))
.expect(&format!("Failed to find message with given id: {id}"))
}
}

View file

@ -65,6 +65,13 @@ fn main() {
// This one is kinda critical buy well, I can't do something with it
std::fs::write(FIRST_RUN_FILE.as_path(), "").expect("Failed to create .first-run file");
// Set initial launcher language based on system language
let mut config = config::get().expect("Failed to get config");
config.launcher.language = i18n::get_default_lang();
config::update_raw(config).expect("Failed to update config");
}
// Force debug output
@ -130,7 +137,12 @@ fn main() {
background-size: cover;
}}
", BACKGROUND_FILE.to_string_lossy()));
// Set UI language
i18n::set_lang(config::get().unwrap().launcher.language).expect("Failed to set launcher language");
tracing::info!("Set UI language to {}", i18n::get_lang());
// Run FirstRun window if .first-run file persist
if FIRST_RUN_FILE.exists() {
app.run::<ui::first_run::main::FirstRunApp>(());
@ -138,13 +150,6 @@ fn main() {
// Run the app if everything's ready
else {
// Set UI language
unsafe {
i18n::LANG = config::get().unwrap().launcher.language.parse().unwrap();
tracing::info!("Set UI language to {}", i18n::LANG);
}
app.run::<ui::main::App>(());
}
}