euv_ui/hook/i18n/struct.rs
1use super::*;
2
3/// The aggregate i18n state.
4///
5/// Constructed once per app via `App::use_i18n()`, threaded
6/// through any code that needs to render translated text.
7/// Cheap to `Clone` (the internal signal is
8/// `Copy`-by-pointer).
9///
10/// # Storage
11///
12/// Messages are stored in a process-wide
13/// [`I18N_MESSAGES`] `OnceLock<RwLock<HashMap<...>>>` rather
14/// than a per-handle `Signal`. The translation table is
15/// not reactive on its own — only the `locale` field is —
16/// so wrapping the table in a signal forced every `t()`
17/// call to clone the entire `HashMap<String, HashMap<String,
18/// String>>`. Moving the table behind a `OnceLock` means:
19///
20/// - one allocation for the whole process (no per-handle
21/// `Signal::create(HashMap::new())`),
22/// - reads (`t`, `locale_count`, `active_message_count`)
23/// borrow through the read guard with zero clone,
24/// - writes (`add_messages`, `remove_locale`,
25/// `remove_message`) take the write guard once.
26///
27/// `I18n` is `Copy` because every remaining field is a
28/// `Signal`, which is already `Copy` — the registry hands
29/// out cheap `usize` addresses for any `T: Clone + PartialEq
30/// + 'static`.
31impl Copy for I18n {}
32
33/// Process-wide translation table storage.
34///
35/// Backed by [`std::sync::OnceLock`] so the table is
36/// allocated lazily on first write/read and never torn
37/// down. Wrapped in a [`std::sync::RwLock`] because runtime
38/// mutation is supported — `add_messages`,
39/// `remove_locale`, and `remove_message` all write.
40///
41/// On WASM this is single-threaded so the lock is
42/// uncontended; on the native test target it serialises
43/// the rare concurrent test against itself without
44/// affecting functional correctness.
45///
46/// OPT 22 (tail): replaces the previous
47/// `Signal<HashMap<...>>` field on `I18n`. Every `t()` call
48/// used to clone the entire translation table; now the
49/// table lives behind this lock and `t()` borrows through
50/// the read guard.
51pub(crate) static I18N_MESSAGES: OnceLock<RwLock<HashMap<String, HashMap<String, String>>>> =
52 OnceLock::new();
53
54#[derive(Clone, Data, New)]
55pub struct I18n {
56 /// The currently-active locale tag. Setting this
57 /// via `set_locale` triggers a reactive update that
58 /// re-evaluates any reactive `t(...)` read.
59 pub(crate) locale: Signal<String>,
60 /// The locale to fall back to when a key is missing
61 /// in the active locale. Defaults to `"en"`.
62 pub(crate) fallback_locale: Signal<String>,
63}