Files
ElyOffice/crates/ely-ui/src/i18n.rs
T
ZacharyZhang-NY b7fca0146d Ely Office: six offline-first desktop apps in Rust and GPUI
ElyDoc, ElyTable, ElyShow (LibreOfficeKit), ElyPDF (MuPDF), ElyTree (Git),
ElyMark (Milkdown and CodeMirror in CEF). ElyMail and ElyAgent follow.
2026-10-08 21:20:08 -04:00

220 lines
6.7 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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::<I18n>().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}");
}
}
}