Skip to main content

typub_ui/
i18n.rs

1use std::sync::RwLock;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub enum Locale {
5    Zh,
6    En,
7}
8
9static LOCALE: RwLock<Option<Locale>> = RwLock::new(None);
10
11fn detect_locale() -> Locale {
12    let locale_str = std::env::var("LC_ALL")
13        .ok()
14        .filter(|s| !s.is_empty())
15        .or_else(|| std::env::var("LANG").ok().filter(|s| !s.is_empty()))
16        .unwrap_or_default();
17
18    if locale_str.to_lowercase().starts_with("zh") {
19        Locale::Zh
20    } else {
21        Locale::En
22    }
23}
24
25pub fn locale() -> Locale {
26    if let Ok(guard) = LOCALE.read()
27        && let Some(loc) = *guard
28    {
29        return loc;
30    }
31
32    let detected = detect_locale();
33    if let Ok(mut guard) = LOCALE.write()
34        && guard.is_none()
35    {
36        *guard = Some(detected);
37    }
38    detected
39}
40
41#[doc(hidden)]
42pub fn set_locale(loc: Locale) {
43    if let Ok(mut guard) = LOCALE.write() {
44        *guard = Some(loc);
45    }
46}
47
48pub fn t(key: &str) -> &'static str {
49    let loc = locale();
50    match (loc, key) {
51        (Locale::Zh, "copy_button") => "复制内容",
52        (Locale::Zh, "open_editor") => "打开编辑器",
53        (Locale::Zh, "copy_success") => "已复制到剪贴板!",
54        (Locale::Zh, "copy_failed") => "复制失败,请手动选择内容复制",
55        (Locale::Zh, "slides_ready") => "张图片已准备好上传",
56        (Locale::Zh, "preview_suffix") => "预览",
57
58        (Locale::En, "copy_button") => "Copy",
59        (Locale::En, "open_editor") => "Open Editor",
60        (Locale::En, "copy_success") => "Copied!",
61        (Locale::En, "copy_failed") => "Copy failed. Please select and copy manually.",
62        (Locale::En, "slides_ready") => "slides ready for upload",
63        (Locale::En, "preview_suffix") => "Preview",
64
65        _ => "[missing translation]",
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    #![allow(clippy::expect_used)]
72
73    use super::*;
74
75    #[test]
76    fn test_t_returns_translation() {
77        let result = t("copy_button");
78        assert!(!result.is_empty());
79        assert!(result == "复制内容" || result == "Copy");
80    }
81
82    #[test]
83    fn test_t_unknown_key_returns_placeholder() {
84        assert_eq!(t("unknown_key_xyz"), "[missing translation]");
85    }
86}