use json_gettext::{get_text, static_json_gettext_build, JSONGetText};
use once_cell::sync::{Lazy, OnceCell};
use std::sync::RwLock;
pub static LOCALIZATION_CTX: Lazy<JSONGetText<'static>> = Lazy::new(|| {
static_json_gettext_build!(
"en_US",
"en_US",
"locale/en_US.json",
"da_DK",
"locale/da_DK.json",
"de_DE",
"locale/de_DE.json",
"fr_FR",
"locale/fr_FR.json",
"ru_RU",
"locale/ru_RU.json",
"se_SE",
"locale/se_SE.json",
"es_ES",
"locale/es_ES.json",
"cs_CZ",
"locale/cs_CZ.json",
"hu_HU",
"locale/hu_HU.json",
"nb_NO",
"locale/nb_NO.json",
"sk_SK",
"locale/sk_SK.json",
"tr_TR",
"locale/tr_TR.json",
"pt_PT",
"locale/pt_PT.json",
"uk_UA",
"locale/uk_UA.json"
)
.unwrap()
});
pub static LANG: OnceCell<RwLock<&'static str>> = OnceCell::new();
pub fn localized_string(key: &str) -> String {
let lang = LANG.get().expect("LANG not set").read().unwrap();
if let Some(text) = get_text!(LOCALIZATION_CTX, *lang, key) {
let text = text.to_string();
if text.is_empty() {
key.to_owned()
} else {
text
}
} else {
key.to_owned()
}
}
pub fn localized_timeago_formatter() -> timeago::Formatter<Box<dyn timeago::Language>> {
let lang = LANG.get().expect("LANG not set").read().unwrap();
let isolang = isolang::Language::from_locale(&lang).unwrap();
if let Some(timeago_lang) = timeago::from_isolang(isolang) {
timeago::Formatter::with_language(timeago_lang)
} else {
timeago::Formatter::with_language(Box::new(timeago::English))
}
}
#[cfg(test)]
mod test {
use serde::Deserialize;
use std::fs;
use std::path::PathBuf;
#[test]
fn test_valid_locales() {
let cargo_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let locale_dir = cargo_dir.join("locale");
let dir_entries = fs::read_dir(&locale_dir).unwrap();
for entry in dir_entries.filter_map(Result::ok) {
let path = entry.path();
let file = fs::File::open(path).unwrap();
let locale: Locale = serde_json::from_reader(&file).unwrap();
dbg!(&locale);
}
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "kebab-case")]
struct Locale {
addon: String,
about: String,
addons: String,
addons_loaded: String,
ajour: String,
all_categories: String,
alternate_row_colors: String,
aura: String,
author: String,
authors: String,
backup: String,
backup_description: String,
backup_latest: String,
backup_never: String,
backup_now: String,
backup_progress: String,
catalog: String,
changelog: String,
changelog_for: String,
changelog_press_full_changelog: String,
channel: String,
columns: String,
completed: String,
delete: String,
delete_saved_variables: String,
description: String,
downloading: String,
game_version: String,
failed: String,
full_changelog: String,
global_release_channel: String,
hashing: String,
hide_addons: String,
ignore: String,
ignored: String,
install: String,
install_for_flavor: String,
install_from_url: String,
install_from_url_description: String,
install_from_url_example: String,
installed: String,
language: String,
latest_release: String,
loading: String,
loading_catalog: String,
local: String,
my_addons: String,
my_weakauras: String,
new_update_available: String,
no_addon_description: String,
no_addons_for_flavor: String,
no_changelog: String,
no_directory: String,
no_known_weakauras: String,
num_downloads: String,
open_data_directory: String,
parsing_addons: String,
parsing_weakauras: String,
patreon: String,
patreon_http: String,
refresh: String,
release_channel_no_release: String,
remote: String,
remote_release_channel: String,
reset_columns: String,
retry: String,
search_for_addon: String,
scale: String,
select_account: String,
select_directory: String,
settings: String,
setup_ajour_description: String,
setup_ajour_title: String,
setup_weakauras_description: String,
setup_weakauras_title: String,
source: String,
status: String,
summary: String,
theme: String,
ui: String,
unavailable: String,
unignore: String,
unknown: String,
unpacking: String,
update: String,
update_all: String,
ajour_update_channel: String,
updating: String,
weakaura_update_available: String,
weakaura_updates_queued: String,
weakauras_loaded: String,
website: String,
website_http: String,
welcome_to_ajour_description: String,
woops: String,
wow_directory: String,
wtf: String,
channel_default: String,
channel_stable: String,
channel_beta: String,
channel_alpha: String,
catalog_results: String,
error_fetch_changelog: String,
error_parse_addons: String,
error_download_addon: String,
error_unpack_addon: String,
error_backup_folders: String,
error_update_ajour: String,
error_remove_cache: String,
error_list_accounts: String,
error_parse_weakauras: String,
error_update_weakauras: String,
error_update_ajour_permission: String,
categories: String,
select_catalog_source_picklist: String,
select_catalog_source_title: String,
select_catalog_source_description: String,
}
}