use ely_gpui_component::i18n::I18n; mod analysis; mod calc; mod data; mod doc; mod mark; mod motion; mod office; mod output; mod pdf; mod play; mod refs; mod secure; mod settings; mod show; mod table; mod tools; mod tree; mod tree_ops; mod tree_places; mod web; use gpui::{App, SharedString}; const EN: &[(&str, &str)] = &[ ("menu.app.quit", "Quit {app}"), ("menu.app.switch", "Open Ely App"), ("toast.open", "Open"), ("toast.open_failed", "The file did not open: {error}"), ("menu.app.switch_failed", "{app} did not open: {error}"), ("menu.file", "File"), ("menu.insert", "Insert"), ("command.file.new", "New"), ("command.file.open", "Open…"), ("command.file.save", "Save"), ("command.file.save_as", "Save As…"), ("command.file.rename", "Rename…"), ("command.file.export", "Export…"), ("command.file.print", "Print…"), ("command.blocked.no_document", "No open document"), ("palette.group.file", "File"), ("gallery.ready", "Ready"), ("gallery.nav", "Navigation"), ("gallery.inbox", "Inbox"), ("gallery.archive", "Archive"), ("gallery.props", "Properties"), ("gallery.content", "Content"), ("gallery.mixed", "Mixed"), ("gallery.content_of", "Content of {page}"), ("gallery.rename", "Rename…"), ("gallery.delete", "Delete…"), ("gallery.group.selection", "Selection"), ("gallery.row.format", "Format"), ("gallery.row.pages", "Pages"), ("gallery.empty.pages", "No pages"), ("gallery.task.done", "Export done"), ("gallery.task.cancelled", "Export cancelled"), ("gallery.task.progress", "Export {state} · Cancel"), ("gallery.task.retry", "{error} · Retry"), ("gallery.error.disk_full", "The disk is full"), ("gallery.rename.title", "Rename Page"), ("gallery.rename.submit", "Rename"), ("gallery.rename.empty", "A page needs a name"), ("gallery.rename.placeholder", "Page name"), ( "gallery.rename.failed", "The disk is full; the name was not saved", ), ("gallery.delete.title", "Delete {title}?"), ( "gallery.delete.message", "{title} and its items are gone for good.", ), ("gallery.delete.confirm", "Delete Page"), ]; const ZH_CN: &[(&str, &str)] = &[ ("menu.app.quit", "退出 {app}"), ("menu.app.switch", "打开 Ely 应用"), ("toast.open", "打开"), ("toast.open_failed", "文件没能打开:{error}"), ("menu.app.switch_failed", "{app} 没能打开:{error}"), ("menu.file", "文件"), ("menu.insert", "插入"), ("command.file.new", "新建"), ("command.file.open", "打开…"), ("command.file.save", "保存"), ("command.file.save_as", "另存为…"), ("command.file.rename", "重命名…"), ("command.file.export", "导出…"), ("command.file.print", "打印…"), ("command.blocked.no_document", "没有打开的文档"), ("palette.group.file", "文件"), ("gallery.ready", "就绪"), ("gallery.nav", "导航"), ("gallery.inbox", "收件箱"), ("gallery.archive", "归档"), ("gallery.props", "属性"), ("gallery.content", "内容"), ("gallery.mixed", "混合"), ("gallery.content_of", "{page}的内容"), ("gallery.rename", "重命名…"), ("gallery.delete", "删除…"), ("gallery.group.selection", "所选"), ("gallery.row.format", "格式"), ("gallery.row.pages", "页数"), ("gallery.empty.pages", "没有页面"), ("gallery.task.done", "导出完成"), ("gallery.task.cancelled", "导出已取消"), ("gallery.task.progress", "导出 {state} · 取消"), ("gallery.task.retry", "{error} · 重试"), ("gallery.error.disk_full", "磁盘已满"), ("gallery.rename.title", "重命名页面"), ("gallery.rename.submit", "重命名"), ("gallery.rename.empty", "页面需要名称"), ("gallery.rename.placeholder", "页面名称"), ("gallery.rename.failed", "磁盘已满,名称未保存"), ("gallery.delete.title", "删除{title}?"), ("gallery.delete.message", "{title}及其内容将被永久删除。"), ("gallery.delete.confirm", "删除页面"), ]; /// zh-* maps to zh-CN; anything else to en-US. pub fn resolve(tag: &str) -> &'static str { if tag.to_ascii_lowercase().starts_with("zh") { "zh-CN" } else { "en-US" } } /// Installs the catalogs and resolves the locale. pub fn install(cx: &mut App) { let tag = locale_tag(cx); let locale = resolve(&tag); log::info!("i18n: locale {tag} -> {locale}"); let en: Vec<_> = EN .iter() .chain(office::EN) .chain(doc::EN) .chain(refs::EN) .chain(tools::EN) .chain(table::EN) .chain(calc::EN) .chain(data::EN) .chain(analysis::EN) .chain(output::EN) .chain(show::EN) .chain(motion::EN) .chain(play::EN) .chain(pdf::EN) .chain(secure::EN) .chain(tree::EN) .chain(tree_ops::EN) .chain(tree_places::EN) .chain(web::EN) .chain(mark::EN) .chain(settings::EN) .copied() .collect(); let zh: Vec<_> = ZH_CN .iter() .chain(office::ZH_CN) .chain(doc::ZH_CN) .chain(refs::ZH_CN) .chain(tools::ZH_CN) .chain(table::ZH_CN) .chain(calc::ZH_CN) .chain(data::ZH_CN) .chain(analysis::ZH_CN) .chain(output::ZH_CN) .chain(show::ZH_CN) .chain(motion::ZH_CN) .chain(play::ZH_CN) .chain(pdf::ZH_CN) .chain(secure::ZH_CN) .chain(tree::ZH_CN) .chain(tree_ops::ZH_CN) .chain(tree_places::ZH_CN) .chain(web::ZH_CN) .chain(mark::ZH_CN) .chain(settings::ZH_CN) .copied() .collect(); cx.set_global( I18n::new(locale) .catalog("en-US", &en) .catalog("zh-CN", &zh), ); } /// `ELY_LOCALE`, then the language setting, then the system's. fn locale_tag(cx: &App) -> String { use ely_platform::settings::{Language, word}; match crate::settings::current(cx).language { Language::System => ely_platform::locale::system(), _ if ely_platform::env::value("ELY_LOCALE").is_some() => ely_platform::locale::system(), chosen => word(&Language::ALL, &chosen).into(), } } pub fn text(cx: &App, key: &str, args: &[(&str, &str)]) -> SharedString { cx.global::().text(key, args) } #[cfg(test)] mod tests { use super::resolve; #[test] fn zh_variants_pick_zh_cn_others_pick_en() { for tag in ["zh-CN", "zh-Hans", "zh", "ZH-TW"] { assert_eq!(resolve(tag), "zh-CN", "{tag}"); } for tag in ["en", "en-US", "fr", "ja", "", "x9!"] { assert_eq!(resolve(tag), "en-US", "{tag}"); } } }