app_lib/
app_i18n.rs

1//! App UI strings for i18n: seeded into SQLite (`app_i18n` table) from `i18n/app_i18n_en.json`
2//! (toasts, menus, tray, HTML `data-i18n*`, dialogs). Locales `cs`, `da`, `de`, `es`, `es-419`, `sv`, `fr`, `nl`, `pt`, `pt-BR`, `it`, `el`, `pl`, `ru`, `zh`, `ja`, `ko`, `fi`, `nb`, `tr`, `hu`, `ro`, `uk`, `vi`, `id`, `hi` add rows with the same keys.
3
4use rusqlite::{params, Connection};
5use std::collections::HashMap;
6
7static SEED_JSON_EN: &str = include_str!("../../i18n/app_i18n_en.json");
8static SEED_JSON_DE: &str = include_str!("../../i18n/app_i18n_de.json");
9static SEED_JSON_ES: &str = include_str!("../../i18n/app_i18n_es.json");
10static SEED_JSON_ES_419: &str = include_str!("../../i18n/app_i18n_es_419.json");
11static SEED_JSON_SV: &str = include_str!("../../i18n/app_i18n_sv.json");
12static SEED_JSON_FR: &str = include_str!("../../i18n/app_i18n_fr.json");
13static SEED_JSON_PT: &str = include_str!("../../i18n/app_i18n_pt.json");
14static SEED_JSON_PT_BR: &str = include_str!("../../i18n/app_i18n_pt_br.json");
15static SEED_JSON_NL: &str = include_str!("../../i18n/app_i18n_nl.json");
16static SEED_JSON_IT: &str = include_str!("../../i18n/app_i18n_it.json");
17static SEED_JSON_EL: &str = include_str!("../../i18n/app_i18n_el.json");
18static SEED_JSON_PL: &str = include_str!("../../i18n/app_i18n_pl.json");
19static SEED_JSON_RU: &str = include_str!("../../i18n/app_i18n_ru.json");
20static SEED_JSON_ZH: &str = include_str!("../../i18n/app_i18n_zh.json");
21static SEED_JSON_JA: &str = include_str!("../../i18n/app_i18n_ja.json");
22static SEED_JSON_KO: &str = include_str!("../../i18n/app_i18n_ko.json");
23static SEED_JSON_FI: &str = include_str!("../../i18n/app_i18n_fi.json");
24static SEED_JSON_DA: &str = include_str!("../../i18n/app_i18n_da.json");
25static SEED_JSON_NB: &str = include_str!("../../i18n/app_i18n_nb.json");
26static SEED_JSON_TR: &str = include_str!("../../i18n/app_i18n_tr.json");
27static SEED_JSON_CS: &str = include_str!("../../i18n/app_i18n_cs.json");
28static SEED_JSON_HU: &str = include_str!("../../i18n/app_i18n_hu.json");
29static SEED_JSON_RO: &str = include_str!("../../i18n/app_i18n_ro.json");
30static SEED_JSON_UK: &str = include_str!("../../i18n/app_i18n_uk.json");
31static SEED_JSON_VI: &str = include_str!("../../i18n/app_i18n_vi.json");
32static SEED_JSON_ID: &str = include_str!("../../i18n/app_i18n_id.json");
33static SEED_JSON_HI: &str = include_str!("../../i18n/app_i18n_hi.json");
34
35/// Insert default locale rows (`INSERT OR REPLACE` on `(key, locale)` primary key) on every
36/// migration so shipped `i18n/app_i18n_*.json` values stay current. There is no separate UI to
37/// edit `app_i18n` rows; the catalog is the source of truth.
38pub fn seed_defaults(conn: &Connection) -> Result<(), String> {
39    seed_locale(conn, "en", SEED_JSON_EN)?;
40    seed_locale(conn, "de", SEED_JSON_DE)?;
41    seed_locale(conn, "es", SEED_JSON_ES)?;
42    seed_locale(conn, "es-419", SEED_JSON_ES_419)?;
43    seed_locale(conn, "sv", SEED_JSON_SV)?;
44    seed_locale(conn, "fr", SEED_JSON_FR)?;
45    seed_locale(conn, "pt", SEED_JSON_PT)?;
46    seed_locale(conn, "pt-BR", SEED_JSON_PT_BR)?;
47    seed_locale(conn, "nl", SEED_JSON_NL)?;
48    seed_locale(conn, "it", SEED_JSON_IT)?;
49    seed_locale(conn, "el", SEED_JSON_EL)?;
50    seed_locale(conn, "pl", SEED_JSON_PL)?;
51    seed_locale(conn, "ru", SEED_JSON_RU)?;
52    seed_locale(conn, "zh", SEED_JSON_ZH)?;
53    seed_locale(conn, "ja", SEED_JSON_JA)?;
54    seed_locale(conn, "ko", SEED_JSON_KO)?;
55    seed_locale(conn, "fi", SEED_JSON_FI)?;
56    seed_locale(conn, "da", SEED_JSON_DA)?;
57    seed_locale(conn, "nb", SEED_JSON_NB)?;
58    seed_locale(conn, "tr", SEED_JSON_TR)?;
59    seed_locale(conn, "cs", SEED_JSON_CS)?;
60    seed_locale(conn, "hu", SEED_JSON_HU)?;
61    seed_locale(conn, "ro", SEED_JSON_RO)?;
62    seed_locale(conn, "uk", SEED_JSON_UK)?;
63    seed_locale(conn, "vi", SEED_JSON_VI)?;
64    seed_locale(conn, "id", SEED_JSON_ID)?;
65    seed_locale(conn, "hi", SEED_JSON_HI)?;
66    Ok(())
67}
68
69fn seed_locale(conn: &Connection, locale: &str, json: &str) -> Result<(), String> {
70    let map: HashMap<String, String> = serde_json::from_str(json).map_err(|e| e.to_string())?;
71    let mut stmt = conn
72        .prepare_cached("INSERT OR REPLACE INTO app_i18n (key, locale, value) VALUES (?1, ?2, ?3)")
73        .map_err(|e| e.to_string())?;
74    for (k, v) in map {
75        stmt.execute(params![k, locale, v])
76            .map_err(|e| e.to_string())?;
77    }
78    Ok(())
79}
80
81/// Merge English with `locale` (falls back to English for missing keys).
82pub fn load_merged(conn: &Connection, locale: &str) -> Result<HashMap<String, String>, String> {
83    let mut out: HashMap<String, String> = HashMap::new();
84    let mut stmt = conn
85        .prepare("SELECT key, value FROM app_i18n WHERE locale = 'en'")
86        .map_err(|e| e.to_string())?;
87    let rows = stmt
88        .query_map([], |row| {
89            Ok((row.get::<_, String>(0)?, row.get::<_, String>(1)?))
90        })
91        .map_err(|e| e.to_string())?;
92    for row in rows {
93        let (k, v) = row.map_err(|e| e.to_string())?;
94        out.insert(k, v);
95    }
96    if locale == "en" || locale.is_empty() {
97        return Ok(out);
98    }
99    let mut stmt = conn
100        .prepare("SELECT key, value FROM app_i18n WHERE locale = ?1")
101        .map_err(|e| e.to_string())?;
102    let rows = stmt
103        .query_map(params![locale], |row| {
104            Ok((row.get::<_, String>(0)?, row.get::<_, String>(1)?))
105        })
106        .map_err(|e| e.to_string())?;
107    for row in rows {
108        let (k, v) = row.map_err(|e| e.to_string())?;
109        out.insert(k, v);
110    }
111    Ok(out)
112}
113
114#[cfg(test)]
115mod tests {
116    use super::{
117        load_merged, SEED_JSON_CS, SEED_JSON_DA, SEED_JSON_DE, SEED_JSON_EL, SEED_JSON_EN,
118        SEED_JSON_ES, SEED_JSON_ES_419, SEED_JSON_FI, SEED_JSON_FR, SEED_JSON_HU, SEED_JSON_IT,
119        SEED_JSON_JA, SEED_JSON_KO, SEED_JSON_NB, SEED_JSON_NL, SEED_JSON_PL, SEED_JSON_PT,
120        SEED_JSON_PT_BR, SEED_JSON_RO, SEED_JSON_RU, SEED_JSON_SV, SEED_JSON_TR, SEED_JSON_UK,
121        SEED_JSON_VI, SEED_JSON_ID, SEED_JSON_HI, SEED_JSON_ZH,
122    };
123    use regex::Regex;
124    use rusqlite::Connection;
125    use std::collections::{HashMap, HashSet};
126
127    /// Keys passed to `t("…", …)` in `native_menu.rs` — English seed must define each.
128    const NATIVE_MENU_BAR_KEYS: &[&str] = &[
129        "menu.about",
130        "menu.app",
131        "menu.check_updates",
132        "menu.clear_favorites",
133        "menu.clear_history",
134        "menu.clear_kvr",
135        "menu.cmd_palette",
136        "menu.data",
137        "menu.dep_graph",
138        "menu.docs",
139        "menu.edit",
140        "menu.expand_player",
141        "menu.export_daw",
142        "menu.export_plugins",
143        "menu.export_presets",
144        "menu.export_samples",
145        "menu.file",
146        "menu.find",
147        "menu.find_duplicates",
148        "menu.github",
149        "menu.help",
150        "menu.help_overlay",
151        "menu.import_daw",
152        "menu.import_plugins",
153        "menu.import_presets",
154        "menu.import_samples",
155        "menu.next_track",
156        "menu.play_pause",
157        "menu.playback",
158        "menu.preferences",
159        "menu.prev_track",
160        "menu.reset_all_scans",
161        "menu.reset_columns",
162        "menu.reset_tabs",
163        "menu.scan",
164        "menu.scan_all",
165        "menu.scan_daw",
166        "menu.scan_plugins",
167        "menu.scan_presets",
168        "menu.scan_samples",
169        "menu.stop_all",
170        "menu.stop_playback",
171        "menu.tab_daw",
172        "menu.tab_audio_engine",
173        "menu.tab_favorites",
174        "menu.tab_files",
175        "menu.tab_history",
176        "menu.tab_notes",
177        "menu.tab_plugins",
178        "menu.tab_presets",
179        "menu.tab_samples",
180        "menu.tab_settings",
181        "menu.toggle_crt",
182        "menu.toggle_loop",
183        "menu.toggle_mute",
184        "menu.toggle_shuffle",
185        "menu.toggle_theme",
186        "menu.tools",
187        "menu.view",
188        "menu.window",
189    ];
190
191    /// Keys passed to `t("tray.…", …)` for the system tray in `tray_menu.rs` (+ dynamic strings from `audio.js`).
192    const TRAY_KEYS: &[&str] = &[
193        "tray.show",
194        "tray.scan_all",
195        "tray.stop_all",
196        "tray.previous_track",
197        "tray.play_pause",
198        "tray.next_track",
199        "tray.quit",
200        "tray.tooltip",
201        "tray.popover_idle",
202        "tray.status_playing",
203        "tray.status_paused",
204    ];
205
206    fn key_matches_catalog_prefix(k: &str) -> bool {
207        ["menu.", "tray.", "confirm.", "toast.", "help.", "ui."]
208            .iter()
209            .any(|p| k.starts_with(p))
210    }
211
212    fn setup_minimal_i18n(conn: &Connection) {
213        conn.execute_batch(
214            "CREATE TABLE app_i18n (
215                key TEXT NOT NULL,
216                locale TEXT NOT NULL,
217                value TEXT NOT NULL,
218                PRIMARY KEY (key, locale)
219            );",
220        )
221        .expect("create app_i18n");
222        conn.execute(
223            "INSERT INTO app_i18n (key, locale, value) VALUES ('k1', 'en', 'english')",
224            [],
225        )
226        .expect("insert k1 en");
227        conn.execute(
228            "INSERT INTO app_i18n (key, locale, value) VALUES ('k2', 'en', 'only-en')",
229            [],
230        )
231        .expect("insert k2 en");
232        conn.execute(
233            "INSERT INTO app_i18n (key, locale, value) VALUES ('k1', 'fr', 'french')",
234            [],
235        )
236        .expect("insert k1 fr");
237    }
238
239    #[test]
240    fn load_merged_fr_overrides_shared_key_keeps_en_only_keys() {
241        let conn = Connection::open_in_memory().expect("in memory");
242        setup_minimal_i18n(&conn);
243        let m = load_merged(&conn, "fr").expect("merged fr");
244        assert_eq!(m.get("k1").map(String::as_str), Some("french"));
245        assert_eq!(m.get("k2").map(String::as_str), Some("only-en"));
246    }
247
248    #[test]
249    fn load_merged_en_and_empty_locale_skip_overlay() {
250        let conn = Connection::open_in_memory().expect("in memory");
251        setup_minimal_i18n(&conn);
252        for loc in ["en", ""] {
253            let m = load_merged(&conn, loc).expect("merged");
254            assert_eq!(m.get("k1").map(String::as_str), Some("english"));
255            assert_eq!(m.get("k2").map(String::as_str), Some("only-en"));
256        }
257    }
258
259    #[test]
260    fn load_merged_unknown_locale_yields_english_base_only() {
261        let conn = Connection::open_in_memory().expect("in memory");
262        setup_minimal_i18n(&conn);
263        let m = load_merged(&conn, "xx").expect("merged xx");
264        assert_eq!(m.get("k1").map(String::as_str), Some("english"));
265        assert_eq!(m.get("k2").map(String::as_str), Some("only-en"));
266    }
267
268    #[test]
269    fn load_merged_overlay_empty_string_replaces_english_value() {
270        let conn = Connection::open_in_memory().expect("in memory");
271        conn.execute_batch(
272            "CREATE TABLE app_i18n (
273                key TEXT NOT NULL,
274                locale TEXT NOT NULL,
275                value TEXT NOT NULL,
276                PRIMARY KEY (key, locale)
277            );",
278        )
279        .expect("create app_i18n");
280        conn.execute(
281            "INSERT INTO app_i18n (key, locale, value) VALUES ('k1', 'en', 'english')",
282            [],
283        )
284        .expect("insert k1 en");
285        conn.execute(
286            "INSERT INTO app_i18n (key, locale, value) VALUES ('k1', 'de', '')",
287            [],
288        )
289        .expect("insert k1 de empty");
290        let m = load_merged(&conn, "de").expect("merged de");
291        assert_eq!(m.get("k1").map(String::as_str), Some(""));
292    }
293
294    #[test]
295    fn seed_json_en_parses() {
296        let map: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
297        assert!(
298            map.len() > 100,
299            "English seed should contain a large string table"
300        );
301        assert!(map.contains_key("menu.scan_all"));
302    }
303
304    #[test]
305    fn seed_json_de_menu_scan_all_differs_from_en() {
306        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
307        let de: HashMap<String, String> = serde_json::from_str(SEED_JSON_DE).expect("de json");
308        assert_ne!(
309            en.get("menu.scan_all"),
310            de.get("menu.scan_all"),
311            "German seed should translate menu.scan_all (same key, different value)"
312        );
313    }
314
315    #[test]
316    fn seed_json_es_menu_scan_all_differs_from_en() {
317        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
318        let es: HashMap<String, String> = serde_json::from_str(SEED_JSON_ES).expect("es json");
319        assert_ne!(
320            en.get("menu.scan_all"),
321            es.get("menu.scan_all"),
322            "Spanish seed should translate menu.scan_all (same key, different value)"
323        );
324    }
325
326    #[test]
327    fn seed_json_es_419_menu_scan_all_differs_from_en() {
328        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
329        let es_419: HashMap<String, String> =
330            serde_json::from_str(SEED_JSON_ES_419).expect("es-419 json");
331        assert_ne!(
332            en.get("menu.scan_all"),
333            es_419.get("menu.scan_all"),
334            "Latin American Spanish seed should translate menu.scan_all (same key, different value)"
335        );
336    }
337
338    #[test]
339    fn seed_json_sv_menu_scan_all_differs_from_en() {
340        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
341        let sv: HashMap<String, String> = serde_json::from_str(SEED_JSON_SV).expect("sv json");
342        assert_ne!(
343            en.get("menu.scan_all"),
344            sv.get("menu.scan_all"),
345            "Swedish seed should translate menu.scan_all (same key, different value)"
346        );
347    }
348
349    #[test]
350    fn seed_json_fr_menu_scan_all_differs_from_en() {
351        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
352        let fr: HashMap<String, String> =
353            serde_json::from_str(include_str!("../../i18n/app_i18n_fr.json")).expect("fr json");
354        assert_ne!(
355            en.get("menu.scan_all"),
356            fr.get("menu.scan_all"),
357            "French seed should translate menu.scan_all (same key, different value)"
358        );
359    }
360
361    #[test]
362    fn seed_json_pt_menu_scan_all_differs_from_en() {
363        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
364        let pt: HashMap<String, String> = serde_json::from_str(SEED_JSON_PT).expect("pt json");
365        assert_ne!(
366            en.get("menu.scan_all"),
367            pt.get("menu.scan_all"),
368            "Portuguese seed should translate menu.scan_all (same key, different value)"
369        );
370    }
371
372    #[test]
373    fn seed_json_pt_br_menu_scan_all_differs_from_en() {
374        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
375        let pt_br: HashMap<String, String> =
376            serde_json::from_str(SEED_JSON_PT_BR).expect("pt-BR json");
377        assert_ne!(
378            en.get("menu.scan_all"),
379            pt_br.get("menu.scan_all"),
380            "Brazilian Portuguese seed should translate menu.scan_all (same key, different value)"
381        );
382    }
383
384    #[test]
385    fn seed_json_nl_menu_scan_all_differs_from_en() {
386        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
387        let nl: HashMap<String, String> = serde_json::from_str(SEED_JSON_NL).expect("nl json");
388        assert_ne!(
389            en.get("menu.scan_all"),
390            nl.get("menu.scan_all"),
391            "Dutch seed should translate menu.scan_all (same key, different value)"
392        );
393    }
394
395    #[test]
396    fn seed_json_it_menu_scan_all_differs_from_en() {
397        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
398        let it: HashMap<String, String> = serde_json::from_str(SEED_JSON_IT).expect("it json");
399        assert_ne!(
400            en.get("menu.scan_all"),
401            it.get("menu.scan_all"),
402            "Italian seed should translate menu.scan_all (same key, different value)"
403        );
404    }
405
406    #[test]
407    fn seed_json_el_menu_scan_all_differs_from_en() {
408        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
409        let el: HashMap<String, String> = serde_json::from_str(SEED_JSON_EL).expect("el json");
410        assert_ne!(
411            en.get("menu.scan_all"),
412            el.get("menu.scan_all"),
413            "Greek seed should translate menu.scan_all (same key, different value)"
414        );
415    }
416
417    #[test]
418    fn seed_json_pl_menu_scan_all_differs_from_en() {
419        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
420        let pl: HashMap<String, String> = serde_json::from_str(SEED_JSON_PL).expect("pl json");
421        assert_ne!(
422            en.get("menu.scan_all"),
423            pl.get("menu.scan_all"),
424            "Polish seed should translate menu.scan_all (same key, different value)"
425        );
426    }
427
428    #[test]
429    fn seed_json_ru_menu_scan_all_differs_from_en() {
430        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
431        let ru: HashMap<String, String> = serde_json::from_str(SEED_JSON_RU).expect("ru json");
432        assert_ne!(
433            en.get("menu.scan_all"),
434            ru.get("menu.scan_all"),
435            "Russian seed should translate menu.scan_all (same key, different value)"
436        );
437    }
438
439    #[test]
440    fn seed_json_zh_menu_scan_all_differs_from_en() {
441        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
442        let zh: HashMap<String, String> = serde_json::from_str(SEED_JSON_ZH).expect("zh json");
443        assert_ne!(
444            en.get("menu.scan_all"),
445            zh.get("menu.scan_all"),
446            "Chinese seed should translate menu.scan_all (same key, different value)"
447        );
448    }
449
450    #[test]
451    fn seed_json_ja_menu_scan_all_differs_from_en() {
452        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
453        let ja: HashMap<String, String> = serde_json::from_str(SEED_JSON_JA).expect("ja json");
454        assert_ne!(
455            en.get("menu.scan_all"),
456            ja.get("menu.scan_all"),
457            "Japanese seed should translate menu.scan_all (same key, different value)"
458        );
459    }
460
461    #[test]
462    fn seed_json_ko_menu_scan_all_differs_from_en() {
463        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
464        let ko: HashMap<String, String> = serde_json::from_str(SEED_JSON_KO).expect("ko json");
465        assert_ne!(
466            en.get("menu.scan_all"),
467            ko.get("menu.scan_all"),
468            "Korean seed should translate menu.scan_all (same key, different value)"
469        );
470    }
471
472    #[test]
473    fn seed_json_fi_menu_scan_all_differs_from_en() {
474        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
475        let fi: HashMap<String, String> = serde_json::from_str(SEED_JSON_FI).expect("fi json");
476        assert_ne!(
477            en.get("menu.scan_all"),
478            fi.get("menu.scan_all"),
479            "Finnish seed should translate menu.scan_all (same key, different value)"
480        );
481    }
482
483    #[test]
484    fn seed_json_da_menu_scan_all_differs_from_en() {
485        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
486        let da: HashMap<String, String> = serde_json::from_str(SEED_JSON_DA).expect("da json");
487        assert_ne!(
488            en.get("menu.scan_all"),
489            da.get("menu.scan_all"),
490            "Danish seed should translate menu.scan_all (same key, different value)"
491        );
492    }
493
494    #[test]
495    fn seed_json_nb_menu_scan_all_differs_from_en() {
496        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
497        let nb: HashMap<String, String> = serde_json::from_str(SEED_JSON_NB).expect("nb json");
498        assert_ne!(
499            en.get("menu.scan_all"),
500            nb.get("menu.scan_all"),
501            "Norwegian seed should translate menu.scan_all (same key, different value)"
502        );
503    }
504
505    #[test]
506    fn seed_json_tr_menu_scan_all_differs_from_en() {
507        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
508        let tr: HashMap<String, String> = serde_json::from_str(SEED_JSON_TR).expect("tr json");
509        assert_ne!(
510            en.get("menu.scan_all"),
511            tr.get("menu.scan_all"),
512            "Turkish seed should translate menu.scan_all (same key, different value)"
513        );
514    }
515
516    #[test]
517    fn seed_json_cs_menu_scan_all_differs_from_en() {
518        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
519        let cs: HashMap<String, String> = serde_json::from_str(SEED_JSON_CS).expect("cs json");
520        assert_ne!(
521            en.get("menu.scan_all"),
522            cs.get("menu.scan_all"),
523            "Czech seed should translate menu.scan_all (same key, different value)"
524        );
525    }
526
527    #[test]
528    fn seed_json_hu_menu_scan_all_differs_from_en() {
529        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
530        let hu: HashMap<String, String> = serde_json::from_str(SEED_JSON_HU).expect("hu json");
531        assert_ne!(
532            en.get("menu.scan_all"),
533            hu.get("menu.scan_all"),
534            "Hungarian seed should translate menu.scan_all (same key, different value)"
535        );
536    }
537
538    #[test]
539    fn seed_json_ro_menu_scan_all_differs_from_en() {
540        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
541        let ro: HashMap<String, String> = serde_json::from_str(SEED_JSON_RO).expect("ro json");
542        assert_ne!(
543            en.get("menu.scan_all"),
544            ro.get("menu.scan_all"),
545            "Romanian seed should translate menu.scan_all (same key, different value)"
546        );
547    }
548
549    #[test]
550    fn seed_json_uk_menu_scan_all_differs_from_en() {
551        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
552        let uk: HashMap<String, String> = serde_json::from_str(SEED_JSON_UK).expect("uk json");
553        assert_ne!(
554            en.get("menu.scan_all"),
555            uk.get("menu.scan_all"),
556            "Ukrainian seed should translate menu.scan_all (same key, different value)"
557        );
558    }
559
560    #[test]
561    fn seed_json_vi_menu_scan_all_differs_from_en() {
562        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
563        let vi: HashMap<String, String> = serde_json::from_str(SEED_JSON_VI).expect("vi json");
564        assert_ne!(
565            en.get("menu.scan_all"),
566            vi.get("menu.scan_all"),
567            "Vietnamese seed should translate menu.scan_all (same key, different value)"
568        );
569    }
570
571    #[test]
572    fn seed_json_id_menu_scan_all_differs_from_en() {
573        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
574        let id: HashMap<String, String> = serde_json::from_str(SEED_JSON_ID).expect("id json");
575        assert_ne!(
576            en.get("menu.scan_all"),
577            id.get("menu.scan_all"),
578            "Indonesian seed should translate menu.scan_all (same key, different value)"
579        );
580    }
581
582    #[test]
583    fn seed_json_hi_menu_scan_all_differs_from_en() {
584        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
585        let hi: HashMap<String, String> = serde_json::from_str(SEED_JSON_HI).expect("hi json");
586        assert_ne!(
587            en.get("menu.scan_all"),
588            hi.get("menu.scan_all"),
589            "Hindi seed should translate menu.scan_all (same key, different value)"
590        );
591    }
592
593    #[test]
594    fn seed_json_de_tray_play_pause_differs_from_en() {
595        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
596        let de: HashMap<String, String> = serde_json::from_str(SEED_JSON_DE).expect("de json");
597        assert_ne!(
598            en.get("tray.play_pause"),
599            de.get("tray.play_pause"),
600            "German seed should translate tray.play_pause (same key, different value)"
601        );
602    }
603
604    #[test]
605    fn seed_json_es_tray_play_pause_differs_from_en() {
606        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
607        let es: HashMap<String, String> = serde_json::from_str(SEED_JSON_ES).expect("es json");
608        assert_ne!(
609            en.get("tray.play_pause"),
610            es.get("tray.play_pause"),
611            "Spanish seed should translate tray.play_pause (same key, different value)"
612        );
613    }
614
615    #[test]
616    fn seed_json_es_419_tray_play_pause_differs_from_en() {
617        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
618        let es_419: HashMap<String, String> =
619            serde_json::from_str(SEED_JSON_ES_419).expect("es-419 json");
620        assert_ne!(
621            en.get("tray.play_pause"),
622            es_419.get("tray.play_pause"),
623            "Latin American Spanish seed should translate tray.play_pause (same key, different value)"
624        );
625    }
626
627    #[test]
628    fn seed_json_sv_tray_play_pause_differs_from_en() {
629        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
630        let sv: HashMap<String, String> = serde_json::from_str(SEED_JSON_SV).expect("sv json");
631        assert_ne!(
632            en.get("tray.play_pause"),
633            sv.get("tray.play_pause"),
634            "Swedish seed should translate tray.play_pause (same key, different value)"
635        );
636    }
637
638    #[test]
639    fn seed_json_fr_tray_play_pause_differs_from_en() {
640        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
641        let fr: HashMap<String, String> = serde_json::from_str(SEED_JSON_FR).expect("fr json");
642        assert_ne!(
643            en.get("tray.play_pause"),
644            fr.get("tray.play_pause"),
645            "French seed should translate tray.play_pause (same key, different value)"
646        );
647    }
648
649    #[test]
650    fn seed_json_pt_tray_play_pause_differs_from_en() {
651        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
652        let pt: HashMap<String, String> = serde_json::from_str(SEED_JSON_PT).expect("pt json");
653        assert_ne!(
654            en.get("tray.play_pause"),
655            pt.get("tray.play_pause"),
656            "Portuguese seed should translate tray.play_pause (same key, different value)"
657        );
658    }
659
660    #[test]
661    fn seed_json_pt_br_tray_play_pause_differs_from_en() {
662        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
663        let pt_br: HashMap<String, String> =
664            serde_json::from_str(SEED_JSON_PT_BR).expect("pt-BR json");
665        assert_ne!(
666            en.get("tray.play_pause"),
667            pt_br.get("tray.play_pause"),
668            "Brazilian Portuguese seed should translate tray.play_pause (same key, different value)"
669        );
670    }
671
672    #[test]
673    fn seed_json_nl_tray_play_pause_differs_from_en() {
674        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
675        let nl: HashMap<String, String> = serde_json::from_str(SEED_JSON_NL).expect("nl json");
676        assert_ne!(
677            en.get("tray.play_pause"),
678            nl.get("tray.play_pause"),
679            "Dutch seed should translate tray.play_pause (same key, different value)"
680        );
681    }
682
683    #[test]
684    fn seed_json_it_tray_play_pause_differs_from_en() {
685        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
686        let it: HashMap<String, String> = serde_json::from_str(SEED_JSON_IT).expect("it json");
687        assert_ne!(
688            en.get("tray.play_pause"),
689            it.get("tray.play_pause"),
690            "Italian seed should translate tray.play_pause (same key, different value)"
691        );
692    }
693
694    #[test]
695    fn seed_json_el_tray_play_pause_differs_from_en() {
696        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
697        let el: HashMap<String, String> = serde_json::from_str(SEED_JSON_EL).expect("el json");
698        assert_ne!(
699            en.get("tray.play_pause"),
700            el.get("tray.play_pause"),
701            "Greek seed should translate tray.play_pause (same key, different value)"
702        );
703    }
704
705    #[test]
706    fn seed_json_pl_tray_play_pause_differs_from_en() {
707        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
708        let pl: HashMap<String, String> = serde_json::from_str(SEED_JSON_PL).expect("pl json");
709        assert_ne!(
710            en.get("tray.play_pause"),
711            pl.get("tray.play_pause"),
712            "Polish seed should translate tray.play_pause (same key, different value)"
713        );
714    }
715
716    #[test]
717    fn seed_json_ru_tray_play_pause_differs_from_en() {
718        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
719        let ru: HashMap<String, String> = serde_json::from_str(SEED_JSON_RU).expect("ru json");
720        assert_ne!(
721            en.get("tray.play_pause"),
722            ru.get("tray.play_pause"),
723            "Russian seed should translate tray.play_pause (same key, different value)"
724        );
725    }
726
727    #[test]
728    fn seed_json_zh_tray_play_pause_differs_from_en() {
729        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
730        let zh: HashMap<String, String> = serde_json::from_str(SEED_JSON_ZH).expect("zh json");
731        assert_ne!(
732            en.get("tray.play_pause"),
733            zh.get("tray.play_pause"),
734            "Chinese seed should translate tray.play_pause (same key, different value)"
735        );
736    }
737
738    #[test]
739    fn seed_json_ja_tray_play_pause_differs_from_en() {
740        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
741        let ja: HashMap<String, String> = serde_json::from_str(SEED_JSON_JA).expect("ja json");
742        assert_ne!(
743            en.get("tray.play_pause"),
744            ja.get("tray.play_pause"),
745            "Japanese seed should translate tray.play_pause (same key, different value)"
746        );
747    }
748
749    #[test]
750    fn seed_json_ko_tray_play_pause_differs_from_en() {
751        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
752        let ko: HashMap<String, String> = serde_json::from_str(SEED_JSON_KO).expect("ko json");
753        assert_ne!(
754            en.get("tray.play_pause"),
755            ko.get("tray.play_pause"),
756            "Korean seed should translate tray.play_pause (same key, different value)"
757        );
758    }
759
760    #[test]
761    fn seed_json_fi_tray_play_pause_differs_from_en() {
762        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
763        let fi: HashMap<String, String> = serde_json::from_str(SEED_JSON_FI).expect("fi json");
764        assert_ne!(
765            en.get("tray.play_pause"),
766            fi.get("tray.play_pause"),
767            "Finnish seed should translate tray.play_pause (same key, different value)"
768        );
769    }
770
771    #[test]
772    fn seed_json_da_tray_play_pause_differs_from_en() {
773        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
774        let da: HashMap<String, String> = serde_json::from_str(SEED_JSON_DA).expect("da json");
775        assert_ne!(
776            en.get("tray.play_pause"),
777            da.get("tray.play_pause"),
778            "Danish seed should translate tray.play_pause (same key, different value)"
779        );
780    }
781
782    #[test]
783    fn seed_json_nb_tray_play_pause_differs_from_en() {
784        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
785        let nb: HashMap<String, String> = serde_json::from_str(SEED_JSON_NB).expect("nb json");
786        assert_ne!(
787            en.get("tray.play_pause"),
788            nb.get("tray.play_pause"),
789            "Norwegian seed should translate tray.play_pause (same key, different value)"
790        );
791    }
792
793    #[test]
794    fn seed_json_tr_tray_play_pause_differs_from_en() {
795        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
796        let tr: HashMap<String, String> = serde_json::from_str(SEED_JSON_TR).expect("tr json");
797        assert_ne!(
798            en.get("tray.play_pause"),
799            tr.get("tray.play_pause"),
800            "Turkish seed should translate tray.play_pause (same key, different value)"
801        );
802    }
803
804    #[test]
805    fn seed_json_cs_tray_play_pause_differs_from_en() {
806        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
807        let cs: HashMap<String, String> = serde_json::from_str(SEED_JSON_CS).expect("cs json");
808        assert_ne!(
809            en.get("tray.play_pause"),
810            cs.get("tray.play_pause"),
811            "Czech seed should translate tray.play_pause (same key, different value)"
812        );
813    }
814
815    #[test]
816    fn seed_json_hu_tray_play_pause_differs_from_en() {
817        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
818        let hu: HashMap<String, String> = serde_json::from_str(SEED_JSON_HU).expect("hu json");
819        assert_ne!(
820            en.get("tray.play_pause"),
821            hu.get("tray.play_pause"),
822            "Hungarian seed should translate tray.play_pause (same key, different value)"
823        );
824    }
825
826    #[test]
827    fn seed_json_ro_tray_play_pause_differs_from_en() {
828        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
829        let ro: HashMap<String, String> = serde_json::from_str(SEED_JSON_RO).expect("ro json");
830        assert_ne!(
831            en.get("tray.play_pause"),
832            ro.get("tray.play_pause"),
833            "Romanian seed should translate tray.play_pause (same key, different value)"
834        );
835    }
836
837    #[test]
838    fn seed_json_uk_tray_play_pause_differs_from_en() {
839        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
840        let uk: HashMap<String, String> = serde_json::from_str(SEED_JSON_UK).expect("uk json");
841        assert_ne!(
842            en.get("tray.play_pause"),
843            uk.get("tray.play_pause"),
844            "Ukrainian seed should translate tray.play_pause (same key, different value)"
845        );
846    }
847
848    #[test]
849    fn seed_json_vi_tray_play_pause_differs_from_en() {
850        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
851        let vi: HashMap<String, String> = serde_json::from_str(SEED_JSON_VI).expect("vi json");
852        assert_ne!(
853            en.get("tray.play_pause"),
854            vi.get("tray.play_pause"),
855            "Vietnamese seed should translate tray.play_pause (same key, different value)"
856        );
857    }
858
859    #[test]
860    fn seed_json_id_tray_play_pause_differs_from_en() {
861        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
862        let id: HashMap<String, String> = serde_json::from_str(SEED_JSON_ID).expect("id json");
863        assert_ne!(
864            en.get("tray.play_pause"),
865            id.get("tray.play_pause"),
866            "Indonesian seed should translate tray.play_pause (same key, different value)"
867        );
868    }
869
870    #[test]
871    fn seed_json_hi_tray_play_pause_differs_from_en() {
872        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
873        let hi: HashMap<String, String> = serde_json::from_str(SEED_JSON_HI).expect("hi json");
874        assert_ne!(
875            en.get("tray.play_pause"),
876            hi.get("tray.play_pause"),
877            "Hindi seed should translate tray.play_pause (same key, different value)"
878        );
879    }
880
881    #[test]
882    fn seed_json_de_tray_stop_all_differs_from_en() {
883        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
884        let de: HashMap<String, String> = serde_json::from_str(SEED_JSON_DE).expect("de json");
885        assert_ne!(
886            en.get("tray.stop_all"),
887            de.get("tray.stop_all"),
888            "German seed should translate tray.stop_all (same key, different value)"
889        );
890    }
891
892    #[test]
893    fn seed_json_es_tray_stop_all_differs_from_en() {
894        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
895        let es: HashMap<String, String> = serde_json::from_str(SEED_JSON_ES).expect("es json");
896        assert_ne!(
897            en.get("tray.stop_all"),
898            es.get("tray.stop_all"),
899            "Spanish seed should translate tray.stop_all (same key, different value)"
900        );
901    }
902
903    #[test]
904    fn seed_json_es_419_tray_stop_all_differs_from_en() {
905        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
906        let es_419: HashMap<String, String> =
907            serde_json::from_str(SEED_JSON_ES_419).expect("es-419 json");
908        assert_ne!(
909            en.get("tray.stop_all"),
910            es_419.get("tray.stop_all"),
911            "Latin American Spanish seed should translate tray.stop_all (same key, different value)"
912        );
913    }
914
915    #[test]
916    fn seed_json_sv_tray_stop_all_differs_from_en() {
917        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
918        let sv: HashMap<String, String> = serde_json::from_str(SEED_JSON_SV).expect("sv json");
919        assert_ne!(
920            en.get("tray.stop_all"),
921            sv.get("tray.stop_all"),
922            "Swedish seed should translate tray.stop_all (same key, different value)"
923        );
924    }
925
926    #[test]
927    fn seed_json_fr_tray_stop_all_differs_from_en() {
928        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
929        let fr: HashMap<String, String> = serde_json::from_str(SEED_JSON_FR).expect("fr json");
930        assert_ne!(
931            en.get("tray.stop_all"),
932            fr.get("tray.stop_all"),
933            "French seed should translate tray.stop_all (same key, different value)"
934        );
935    }
936
937    #[test]
938    fn seed_json_pt_tray_stop_all_differs_from_en() {
939        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
940        let pt: HashMap<String, String> = serde_json::from_str(SEED_JSON_PT).expect("pt json");
941        assert_ne!(
942            en.get("tray.stop_all"),
943            pt.get("tray.stop_all"),
944            "Portuguese seed should translate tray.stop_all (same key, different value)"
945        );
946    }
947
948    #[test]
949    fn seed_json_pt_br_tray_stop_all_differs_from_en() {
950        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
951        let pt_br: HashMap<String, String> =
952            serde_json::from_str(SEED_JSON_PT_BR).expect("pt-BR json");
953        assert_ne!(
954            en.get("tray.stop_all"),
955            pt_br.get("tray.stop_all"),
956            "Brazilian Portuguese seed should translate tray.stop_all (same key, different value)"
957        );
958    }
959
960    #[test]
961    fn seed_json_nl_tray_stop_all_differs_from_en() {
962        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
963        let nl: HashMap<String, String> = serde_json::from_str(SEED_JSON_NL).expect("nl json");
964        assert_ne!(
965            en.get("tray.stop_all"),
966            nl.get("tray.stop_all"),
967            "Dutch seed should translate tray.stop_all (same key, different value)"
968        );
969    }
970
971    #[test]
972    fn seed_json_it_tray_stop_all_differs_from_en() {
973        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
974        let it: HashMap<String, String> = serde_json::from_str(SEED_JSON_IT).expect("it json");
975        assert_ne!(
976            en.get("tray.stop_all"),
977            it.get("tray.stop_all"),
978            "Italian seed should translate tray.stop_all (same key, different value)"
979        );
980    }
981
982    #[test]
983    fn seed_json_el_tray_stop_all_differs_from_en() {
984        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
985        let el: HashMap<String, String> = serde_json::from_str(SEED_JSON_EL).expect("el json");
986        assert_ne!(
987            en.get("tray.stop_all"),
988            el.get("tray.stop_all"),
989            "Greek seed should translate tray.stop_all (same key, different value)"
990        );
991    }
992
993    #[test]
994    fn seed_json_pl_tray_stop_all_differs_from_en() {
995        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
996        let pl: HashMap<String, String> = serde_json::from_str(SEED_JSON_PL).expect("pl json");
997        assert_ne!(
998            en.get("tray.stop_all"),
999            pl.get("tray.stop_all"),
1000            "Polish seed should translate tray.stop_all (same key, different value)"
1001        );
1002    }
1003
1004    #[test]
1005    fn seed_json_ru_tray_stop_all_differs_from_en() {
1006        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1007        let ru: HashMap<String, String> = serde_json::from_str(SEED_JSON_RU).expect("ru json");
1008        assert_ne!(
1009            en.get("tray.stop_all"),
1010            ru.get("tray.stop_all"),
1011            "Russian seed should translate tray.stop_all (same key, different value)"
1012        );
1013    }
1014
1015    #[test]
1016    fn seed_json_zh_tray_stop_all_differs_from_en() {
1017        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1018        let zh: HashMap<String, String> = serde_json::from_str(SEED_JSON_ZH).expect("zh json");
1019        assert_ne!(
1020            en.get("tray.stop_all"),
1021            zh.get("tray.stop_all"),
1022            "Chinese seed should translate tray.stop_all (same key, different value)"
1023        );
1024    }
1025
1026    #[test]
1027    fn seed_json_ja_tray_stop_all_differs_from_en() {
1028        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1029        let ja: HashMap<String, String> = serde_json::from_str(SEED_JSON_JA).expect("ja json");
1030        assert_ne!(
1031            en.get("tray.stop_all"),
1032            ja.get("tray.stop_all"),
1033            "Japanese seed should translate tray.stop_all (same key, different value)"
1034        );
1035    }
1036
1037    #[test]
1038    fn seed_json_ko_tray_stop_all_differs_from_en() {
1039        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1040        let ko: HashMap<String, String> = serde_json::from_str(SEED_JSON_KO).expect("ko json");
1041        assert_ne!(
1042            en.get("tray.stop_all"),
1043            ko.get("tray.stop_all"),
1044            "Korean seed should translate tray.stop_all (same key, different value)"
1045        );
1046    }
1047
1048    #[test]
1049    fn seed_json_fi_tray_stop_all_differs_from_en() {
1050        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1051        let fi: HashMap<String, String> = serde_json::from_str(SEED_JSON_FI).expect("fi json");
1052        assert_ne!(
1053            en.get("tray.stop_all"),
1054            fi.get("tray.stop_all"),
1055            "Finnish seed should translate tray.stop_all (same key, different value)"
1056        );
1057    }
1058
1059    #[test]
1060    fn seed_json_da_tray_stop_all_differs_from_en() {
1061        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1062        let da: HashMap<String, String> = serde_json::from_str(SEED_JSON_DA).expect("da json");
1063        assert_ne!(
1064            en.get("tray.stop_all"),
1065            da.get("tray.stop_all"),
1066            "Danish seed should translate tray.stop_all (same key, different value)"
1067        );
1068    }
1069
1070    #[test]
1071    fn seed_json_nb_tray_stop_all_differs_from_en() {
1072        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1073        let nb: HashMap<String, String> = serde_json::from_str(SEED_JSON_NB).expect("nb json");
1074        assert_ne!(
1075            en.get("tray.stop_all"),
1076            nb.get("tray.stop_all"),
1077            "Norwegian seed should translate tray.stop_all (same key, different value)"
1078        );
1079    }
1080
1081    #[test]
1082    fn seed_json_tr_tray_stop_all_differs_from_en() {
1083        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1084        let tr: HashMap<String, String> = serde_json::from_str(SEED_JSON_TR).expect("tr json");
1085        assert_ne!(
1086            en.get("tray.stop_all"),
1087            tr.get("tray.stop_all"),
1088            "Turkish seed should translate tray.stop_all (same key, different value)"
1089        );
1090    }
1091
1092    #[test]
1093    fn seed_json_cs_tray_stop_all_differs_from_en() {
1094        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1095        let cs: HashMap<String, String> = serde_json::from_str(SEED_JSON_CS).expect("cs json");
1096        assert_ne!(
1097            en.get("tray.stop_all"),
1098            cs.get("tray.stop_all"),
1099            "Czech seed should translate tray.stop_all (same key, different value)"
1100        );
1101    }
1102
1103    #[test]
1104    fn seed_json_hu_tray_stop_all_differs_from_en() {
1105        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1106        let hu: HashMap<String, String> = serde_json::from_str(SEED_JSON_HU).expect("hu json");
1107        assert_ne!(
1108            en.get("tray.stop_all"),
1109            hu.get("tray.stop_all"),
1110            "Hungarian seed should translate tray.stop_all (same key, different value)"
1111        );
1112    }
1113
1114    #[test]
1115    fn seed_json_ro_tray_stop_all_differs_from_en() {
1116        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1117        let ro: HashMap<String, String> = serde_json::from_str(SEED_JSON_RO).expect("ro json");
1118        assert_ne!(
1119            en.get("tray.stop_all"),
1120            ro.get("tray.stop_all"),
1121            "Romanian seed should translate tray.stop_all (same key, different value)"
1122        );
1123    }
1124
1125    #[test]
1126    fn seed_json_uk_tray_stop_all_differs_from_en() {
1127        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1128        let uk: HashMap<String, String> = serde_json::from_str(SEED_JSON_UK).expect("uk json");
1129        assert_ne!(
1130            en.get("tray.stop_all"),
1131            uk.get("tray.stop_all"),
1132            "Ukrainian seed should translate tray.stop_all (same key, different value)"
1133        );
1134    }
1135
1136    #[test]
1137    fn seed_json_vi_tray_stop_all_differs_from_en() {
1138        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1139        let vi: HashMap<String, String> = serde_json::from_str(SEED_JSON_VI).expect("vi json");
1140        assert_ne!(
1141            en.get("tray.stop_all"),
1142            vi.get("tray.stop_all"),
1143            "Vietnamese seed should translate tray.stop_all (same key, different value)"
1144        );
1145    }
1146
1147    #[test]
1148    fn seed_json_id_tray_stop_all_differs_from_en() {
1149        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1150        let id: HashMap<String, String> = serde_json::from_str(SEED_JSON_ID).expect("id json");
1151        assert_ne!(
1152            en.get("tray.stop_all"),
1153            id.get("tray.stop_all"),
1154            "Indonesian seed should translate tray.stop_all (same key, different value)"
1155        );
1156    }
1157
1158    #[test]
1159    fn seed_json_hi_tray_stop_all_differs_from_en() {
1160        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1161        let hi: HashMap<String, String> = serde_json::from_str(SEED_JSON_HI).expect("hi json");
1162        assert_ne!(
1163            en.get("tray.stop_all"),
1164            hi.get("tray.stop_all"),
1165            "Hindi seed should translate tray.stop_all (same key, different value)"
1166        );
1167    }
1168
1169    #[test]
1170    fn seed_json_de_tray_show_differs_from_en() {
1171        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1172        let de: HashMap<String, String> = serde_json::from_str(SEED_JSON_DE).expect("de json");
1173        assert_ne!(
1174            en.get("tray.show"),
1175            de.get("tray.show"),
1176            "German seed should translate tray.show (same key, different value)"
1177        );
1178    }
1179
1180    #[test]
1181    fn seed_json_es_tray_show_differs_from_en() {
1182        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1183        let es: HashMap<String, String> = serde_json::from_str(SEED_JSON_ES).expect("es json");
1184        assert_ne!(
1185            en.get("tray.show"),
1186            es.get("tray.show"),
1187            "Spanish seed should translate tray.show (same key, different value)"
1188        );
1189    }
1190
1191    #[test]
1192    fn seed_json_es_419_tray_show_differs_from_en() {
1193        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1194        let es_419: HashMap<String, String> =
1195            serde_json::from_str(SEED_JSON_ES_419).expect("es-419 json");
1196        assert_ne!(
1197            en.get("tray.show"),
1198            es_419.get("tray.show"),
1199            "Latin American Spanish seed should translate tray.show (same key, different value)"
1200        );
1201    }
1202
1203    #[test]
1204    fn seed_json_sv_tray_show_differs_from_en() {
1205        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1206        let sv: HashMap<String, String> = serde_json::from_str(SEED_JSON_SV).expect("sv json");
1207        assert_ne!(
1208            en.get("tray.show"),
1209            sv.get("tray.show"),
1210            "Swedish seed should translate tray.show (same key, different value)"
1211        );
1212    }
1213
1214    #[test]
1215    fn seed_json_fr_tray_show_differs_from_en() {
1216        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1217        let fr: HashMap<String, String> = serde_json::from_str(SEED_JSON_FR).expect("fr json");
1218        assert_ne!(
1219            en.get("tray.show"),
1220            fr.get("tray.show"),
1221            "French seed should translate tray.show (same key, different value)"
1222        );
1223    }
1224
1225    #[test]
1226    fn seed_json_pt_tray_show_differs_from_en() {
1227        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1228        let pt: HashMap<String, String> = serde_json::from_str(SEED_JSON_PT).expect("pt json");
1229        assert_ne!(
1230            en.get("tray.show"),
1231            pt.get("tray.show"),
1232            "Portuguese seed should translate tray.show (same key, different value)"
1233        );
1234    }
1235
1236    #[test]
1237    fn seed_json_pt_br_tray_show_differs_from_en() {
1238        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1239        let pt_br: HashMap<String, String> =
1240            serde_json::from_str(SEED_JSON_PT_BR).expect("pt-BR json");
1241        assert_ne!(
1242            en.get("tray.show"),
1243            pt_br.get("tray.show"),
1244            "Brazilian Portuguese seed should translate tray.show (same key, different value)"
1245        );
1246    }
1247
1248    #[test]
1249    fn seed_json_nl_tray_show_differs_from_en() {
1250        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1251        let nl: HashMap<String, String> = serde_json::from_str(SEED_JSON_NL).expect("nl json");
1252        assert_ne!(
1253            en.get("tray.show"),
1254            nl.get("tray.show"),
1255            "Dutch seed should translate tray.show (same key, different value)"
1256        );
1257    }
1258
1259    #[test]
1260    fn seed_json_it_tray_show_differs_from_en() {
1261        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1262        let it: HashMap<String, String> = serde_json::from_str(SEED_JSON_IT).expect("it json");
1263        assert_ne!(
1264            en.get("tray.show"),
1265            it.get("tray.show"),
1266            "Italian seed should translate tray.show (same key, different value)"
1267        );
1268    }
1269
1270    #[test]
1271    fn seed_json_el_tray_show_differs_from_en() {
1272        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1273        let el: HashMap<String, String> = serde_json::from_str(SEED_JSON_EL).expect("el json");
1274        assert_ne!(
1275            en.get("tray.show"),
1276            el.get("tray.show"),
1277            "Greek seed should translate tray.show (same key, different value)"
1278        );
1279    }
1280
1281    #[test]
1282    fn seed_json_pl_tray_show_differs_from_en() {
1283        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1284        let pl: HashMap<String, String> = serde_json::from_str(SEED_JSON_PL).expect("pl json");
1285        assert_ne!(
1286            en.get("tray.show"),
1287            pl.get("tray.show"),
1288            "Polish seed should translate tray.show (same key, different value)"
1289        );
1290    }
1291
1292    #[test]
1293    fn seed_json_ru_tray_show_differs_from_en() {
1294        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1295        let ru: HashMap<String, String> = serde_json::from_str(SEED_JSON_RU).expect("ru json");
1296        assert_ne!(
1297            en.get("tray.show"),
1298            ru.get("tray.show"),
1299            "Russian seed should translate tray.show (same key, different value)"
1300        );
1301    }
1302
1303    #[test]
1304    fn seed_json_zh_tray_show_differs_from_en() {
1305        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1306        let zh: HashMap<String, String> = serde_json::from_str(SEED_JSON_ZH).expect("zh json");
1307        assert_ne!(
1308            en.get("tray.show"),
1309            zh.get("tray.show"),
1310            "Chinese seed should translate tray.show (same key, different value)"
1311        );
1312    }
1313
1314    #[test]
1315    fn seed_json_ja_tray_show_differs_from_en() {
1316        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1317        let ja: HashMap<String, String> = serde_json::from_str(SEED_JSON_JA).expect("ja json");
1318        assert_ne!(
1319            en.get("tray.show"),
1320            ja.get("tray.show"),
1321            "Japanese seed should translate tray.show (same key, different value)"
1322        );
1323    }
1324
1325    #[test]
1326    fn seed_json_ko_tray_show_differs_from_en() {
1327        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1328        let ko: HashMap<String, String> = serde_json::from_str(SEED_JSON_KO).expect("ko json");
1329        assert_ne!(
1330            en.get("tray.show"),
1331            ko.get("tray.show"),
1332            "Korean seed should translate tray.show (same key, different value)"
1333        );
1334    }
1335
1336    #[test]
1337    fn seed_json_fi_tray_show_differs_from_en() {
1338        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1339        let fi: HashMap<String, String> = serde_json::from_str(SEED_JSON_FI).expect("fi json");
1340        assert_ne!(
1341            en.get("tray.show"),
1342            fi.get("tray.show"),
1343            "Finnish seed should translate tray.show (same key, different value)"
1344        );
1345    }
1346
1347    #[test]
1348    fn seed_json_da_tray_show_differs_from_en() {
1349        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1350        let da: HashMap<String, String> = serde_json::from_str(SEED_JSON_DA).expect("da json");
1351        assert_ne!(
1352            en.get("tray.show"),
1353            da.get("tray.show"),
1354            "Danish seed should translate tray.show (same key, different value)"
1355        );
1356    }
1357
1358    #[test]
1359    fn seed_json_nb_tray_show_differs_from_en() {
1360        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1361        let nb: HashMap<String, String> = serde_json::from_str(SEED_JSON_NB).expect("nb json");
1362        assert_ne!(
1363            en.get("tray.show"),
1364            nb.get("tray.show"),
1365            "Norwegian seed should translate tray.show (same key, different value)"
1366        );
1367    }
1368
1369    #[test]
1370    fn seed_json_tr_tray_show_differs_from_en() {
1371        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1372        let tr: HashMap<String, String> = serde_json::from_str(SEED_JSON_TR).expect("tr json");
1373        assert_ne!(
1374            en.get("tray.show"),
1375            tr.get("tray.show"),
1376            "Turkish seed should translate tray.show (same key, different value)"
1377        );
1378    }
1379
1380    #[test]
1381    fn seed_json_cs_tray_show_differs_from_en() {
1382        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1383        let cs: HashMap<String, String> = serde_json::from_str(SEED_JSON_CS).expect("cs json");
1384        assert_ne!(
1385            en.get("tray.show"),
1386            cs.get("tray.show"),
1387            "Czech seed should translate tray.show (same key, different value)"
1388        );
1389    }
1390
1391    #[test]
1392    fn seed_json_hu_tray_show_differs_from_en() {
1393        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1394        let hu: HashMap<String, String> = serde_json::from_str(SEED_JSON_HU).expect("hu json");
1395        assert_ne!(
1396            en.get("tray.show"),
1397            hu.get("tray.show"),
1398            "Hungarian seed should translate tray.show (same key, different value)"
1399        );
1400    }
1401
1402    #[test]
1403    fn seed_json_ro_tray_show_differs_from_en() {
1404        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1405        let ro: HashMap<String, String> = serde_json::from_str(SEED_JSON_RO).expect("ro json");
1406        assert_ne!(
1407            en.get("tray.show"),
1408            ro.get("tray.show"),
1409            "Romanian seed should translate tray.show (same key, different value)"
1410        );
1411    }
1412
1413    #[test]
1414    fn seed_json_uk_tray_show_differs_from_en() {
1415        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1416        let uk: HashMap<String, String> = serde_json::from_str(SEED_JSON_UK).expect("uk json");
1417        assert_ne!(
1418            en.get("tray.show"),
1419            uk.get("tray.show"),
1420            "Ukrainian seed should translate tray.show (same key, different value)"
1421        );
1422    }
1423
1424    #[test]
1425    fn seed_json_vi_tray_show_differs_from_en() {
1426        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1427        let vi: HashMap<String, String> = serde_json::from_str(SEED_JSON_VI).expect("vi json");
1428        assert_ne!(
1429            en.get("tray.show"),
1430            vi.get("tray.show"),
1431            "Vietnamese seed should translate tray.show (same key, different value)"
1432        );
1433    }
1434
1435    #[test]
1436    fn seed_json_id_tray_show_differs_from_en() {
1437        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1438        let id: HashMap<String, String> = serde_json::from_str(SEED_JSON_ID).expect("id json");
1439        assert_ne!(
1440            en.get("tray.show"),
1441            id.get("tray.show"),
1442            "Indonesian seed should translate tray.show (same key, different value)"
1443        );
1444    }
1445
1446    #[test]
1447    fn seed_json_hi_tray_show_differs_from_en() {
1448        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1449        let hi: HashMap<String, String> = serde_json::from_str(SEED_JSON_HI).expect("hi json");
1450        assert_ne!(
1451            en.get("tray.show"),
1452            hi.get("tray.show"),
1453            "Hindi seed should translate tray.show (same key, different value)"
1454        );
1455    }
1456
1457    #[test]
1458    fn seed_json_de_menu_scan_daw_differs_from_en() {
1459        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1460        let de: HashMap<String, String> = serde_json::from_str(SEED_JSON_DE).expect("de json");
1461        assert_ne!(
1462            en.get("menu.scan_daw"),
1463            de.get("menu.scan_daw"),
1464            "German seed should translate menu.scan_daw (same key, different value)"
1465        );
1466    }
1467
1468    #[test]
1469    fn seed_json_es_menu_scan_daw_differs_from_en() {
1470        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1471        let es: HashMap<String, String> = serde_json::from_str(SEED_JSON_ES).expect("es json");
1472        assert_ne!(
1473            en.get("menu.scan_daw"),
1474            es.get("menu.scan_daw"),
1475            "Spanish seed should translate menu.scan_daw (same key, different value)"
1476        );
1477    }
1478
1479    #[test]
1480    fn seed_json_es_419_menu_scan_daw_differs_from_en() {
1481        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1482        let es_419: HashMap<String, String> =
1483            serde_json::from_str(SEED_JSON_ES_419).expect("es-419 json");
1484        assert_ne!(
1485            en.get("menu.scan_daw"),
1486            es_419.get("menu.scan_daw"),
1487            "Latin American Spanish seed should translate menu.scan_daw (same key, different value)"
1488        );
1489    }
1490
1491    #[test]
1492    fn seed_json_sv_menu_scan_daw_differs_from_en() {
1493        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1494        let sv: HashMap<String, String> = serde_json::from_str(SEED_JSON_SV).expect("sv json");
1495        assert_ne!(
1496            en.get("menu.scan_daw"),
1497            sv.get("menu.scan_daw"),
1498            "Swedish seed should translate menu.scan_daw (same key, different value)"
1499        );
1500    }
1501
1502    #[test]
1503    fn seed_json_fr_menu_scan_daw_differs_from_en() {
1504        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1505        let fr: HashMap<String, String> = serde_json::from_str(SEED_JSON_FR).expect("fr json");
1506        assert_ne!(
1507            en.get("menu.scan_daw"),
1508            fr.get("menu.scan_daw"),
1509            "French seed should translate menu.scan_daw (same key, different value)"
1510        );
1511    }
1512
1513    #[test]
1514    fn seed_json_pt_menu_scan_daw_differs_from_en() {
1515        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1516        let pt: HashMap<String, String> = serde_json::from_str(SEED_JSON_PT).expect("pt json");
1517        assert_ne!(
1518            en.get("menu.scan_daw"),
1519            pt.get("menu.scan_daw"),
1520            "Portuguese seed should translate menu.scan_daw (same key, different value)"
1521        );
1522    }
1523
1524    #[test]
1525    fn seed_json_pt_br_menu_scan_daw_differs_from_en() {
1526        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1527        let pt_br: HashMap<String, String> =
1528            serde_json::from_str(SEED_JSON_PT_BR).expect("pt-BR json");
1529        assert_ne!(
1530            en.get("menu.scan_daw"),
1531            pt_br.get("menu.scan_daw"),
1532            "Brazilian Portuguese seed should translate menu.scan_daw (same key, different value)"
1533        );
1534    }
1535
1536    #[test]
1537    fn seed_json_nl_menu_scan_daw_differs_from_en() {
1538        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1539        let nl: HashMap<String, String> = serde_json::from_str(SEED_JSON_NL).expect("nl json");
1540        assert_ne!(
1541            en.get("menu.scan_daw"),
1542            nl.get("menu.scan_daw"),
1543            "Dutch seed should translate menu.scan_daw (same key, different value)"
1544        );
1545    }
1546
1547    #[test]
1548    fn seed_json_it_menu_scan_daw_differs_from_en() {
1549        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1550        let it: HashMap<String, String> = serde_json::from_str(SEED_JSON_IT).expect("it json");
1551        assert_ne!(
1552            en.get("menu.scan_daw"),
1553            it.get("menu.scan_daw"),
1554            "Italian seed should translate menu.scan_daw (same key, different value)"
1555        );
1556    }
1557
1558    #[test]
1559    fn seed_json_el_menu_scan_daw_differs_from_en() {
1560        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1561        let el: HashMap<String, String> = serde_json::from_str(SEED_JSON_EL).expect("el json");
1562        assert_ne!(
1563            en.get("menu.scan_daw"),
1564            el.get("menu.scan_daw"),
1565            "Greek seed should translate menu.scan_daw (same key, different value)"
1566        );
1567    }
1568
1569    #[test]
1570    fn seed_json_pl_menu_scan_daw_differs_from_en() {
1571        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1572        let pl: HashMap<String, String> = serde_json::from_str(SEED_JSON_PL).expect("pl json");
1573        assert_ne!(
1574            en.get("menu.scan_daw"),
1575            pl.get("menu.scan_daw"),
1576            "Polish seed should translate menu.scan_daw (same key, different value)"
1577        );
1578    }
1579
1580    #[test]
1581    fn seed_json_ru_menu_scan_daw_differs_from_en() {
1582        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1583        let ru: HashMap<String, String> = serde_json::from_str(SEED_JSON_RU).expect("ru json");
1584        assert_ne!(
1585            en.get("menu.scan_daw"),
1586            ru.get("menu.scan_daw"),
1587            "Russian seed should translate menu.scan_daw (same key, different value)"
1588        );
1589    }
1590
1591    #[test]
1592    fn seed_json_zh_menu_scan_daw_differs_from_en() {
1593        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1594        let zh: HashMap<String, String> = serde_json::from_str(SEED_JSON_ZH).expect("zh json");
1595        assert_ne!(
1596            en.get("menu.scan_daw"),
1597            zh.get("menu.scan_daw"),
1598            "Chinese seed should translate menu.scan_daw (same key, different value)"
1599        );
1600    }
1601
1602    #[test]
1603    fn seed_json_ja_menu_scan_daw_differs_from_en() {
1604        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1605        let ja: HashMap<String, String> = serde_json::from_str(SEED_JSON_JA).expect("ja json");
1606        assert_ne!(
1607            en.get("menu.scan_daw"),
1608            ja.get("menu.scan_daw"),
1609            "Japanese seed should translate menu.scan_daw (same key, different value)"
1610        );
1611    }
1612
1613    #[test]
1614    fn seed_json_ko_menu_scan_daw_differs_from_en() {
1615        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1616        let ko: HashMap<String, String> = serde_json::from_str(SEED_JSON_KO).expect("ko json");
1617        assert_ne!(
1618            en.get("menu.scan_daw"),
1619            ko.get("menu.scan_daw"),
1620            "Korean seed should translate menu.scan_daw (same key, different value)"
1621        );
1622    }
1623
1624    #[test]
1625    fn seed_json_fi_menu_scan_daw_differs_from_en() {
1626        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1627        let fi: HashMap<String, String> = serde_json::from_str(SEED_JSON_FI).expect("fi json");
1628        assert_ne!(
1629            en.get("menu.scan_daw"),
1630            fi.get("menu.scan_daw"),
1631            "Finnish seed should translate menu.scan_daw (same key, different value)"
1632        );
1633    }
1634
1635    #[test]
1636    fn seed_json_da_menu_scan_daw_differs_from_en() {
1637        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1638        let da: HashMap<String, String> = serde_json::from_str(SEED_JSON_DA).expect("da json");
1639        assert_ne!(
1640            en.get("menu.scan_daw"),
1641            da.get("menu.scan_daw"),
1642            "Danish seed should translate menu.scan_daw (same key, different value)"
1643        );
1644    }
1645
1646    #[test]
1647    fn seed_json_nb_menu_scan_daw_differs_from_en() {
1648        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1649        let nb: HashMap<String, String> = serde_json::from_str(SEED_JSON_NB).expect("nb json");
1650        assert_ne!(
1651            en.get("menu.scan_daw"),
1652            nb.get("menu.scan_daw"),
1653            "Norwegian seed should translate menu.scan_daw (same key, different value)"
1654        );
1655    }
1656
1657    #[test]
1658    fn seed_json_tr_menu_scan_daw_differs_from_en() {
1659        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1660        let tr: HashMap<String, String> = serde_json::from_str(SEED_JSON_TR).expect("tr json");
1661        assert_ne!(
1662            en.get("menu.scan_daw"),
1663            tr.get("menu.scan_daw"),
1664            "Turkish seed should translate menu.scan_daw (same key, different value)"
1665        );
1666    }
1667
1668    #[test]
1669    fn seed_json_cs_menu_scan_daw_differs_from_en() {
1670        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1671        let cs: HashMap<String, String> = serde_json::from_str(SEED_JSON_CS).expect("cs json");
1672        assert_ne!(
1673            en.get("menu.scan_daw"),
1674            cs.get("menu.scan_daw"),
1675            "Czech seed should translate menu.scan_daw (same key, different value)"
1676        );
1677    }
1678
1679    #[test]
1680    fn seed_json_hu_menu_scan_daw_differs_from_en() {
1681        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1682        let hu: HashMap<String, String> = serde_json::from_str(SEED_JSON_HU).expect("hu json");
1683        assert_ne!(
1684            en.get("menu.scan_daw"),
1685            hu.get("menu.scan_daw"),
1686            "Hungarian seed should translate menu.scan_daw (same key, different value)"
1687        );
1688    }
1689
1690    #[test]
1691    fn seed_json_ro_menu_scan_daw_differs_from_en() {
1692        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1693        let ro: HashMap<String, String> = serde_json::from_str(SEED_JSON_RO).expect("ro json");
1694        assert_ne!(
1695            en.get("menu.scan_daw"),
1696            ro.get("menu.scan_daw"),
1697            "Romanian seed should translate menu.scan_daw (same key, different value)"
1698        );
1699    }
1700
1701    #[test]
1702    fn seed_json_uk_menu_scan_daw_differs_from_en() {
1703        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1704        let uk: HashMap<String, String> = serde_json::from_str(SEED_JSON_UK).expect("uk json");
1705        assert_ne!(
1706            en.get("menu.scan_daw"),
1707            uk.get("menu.scan_daw"),
1708            "Ukrainian seed should translate menu.scan_daw (same key, different value)"
1709        );
1710    }
1711
1712    #[test]
1713    fn seed_json_vi_menu_scan_daw_differs_from_en() {
1714        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1715        let vi: HashMap<String, String> = serde_json::from_str(SEED_JSON_VI).expect("vi json");
1716        assert_ne!(
1717            en.get("menu.scan_daw"),
1718            vi.get("menu.scan_daw"),
1719            "Vietnamese seed should translate menu.scan_daw (same key, different value)"
1720        );
1721    }
1722
1723    #[test]
1724    fn seed_json_id_menu_scan_daw_differs_from_en() {
1725        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1726        let id: HashMap<String, String> = serde_json::from_str(SEED_JSON_ID).expect("id json");
1727        assert_ne!(
1728            en.get("menu.scan_daw"),
1729            id.get("menu.scan_daw"),
1730            "Indonesian seed should translate menu.scan_daw (same key, different value)"
1731        );
1732    }
1733
1734    #[test]
1735    fn seed_json_hi_menu_scan_daw_differs_from_en() {
1736        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1737        let hi: HashMap<String, String> = serde_json::from_str(SEED_JSON_HI).expect("hi json");
1738        assert_ne!(
1739            en.get("menu.scan_daw"),
1740            hi.get("menu.scan_daw"),
1741            "Hindi seed should translate menu.scan_daw (same key, different value)"
1742        );
1743    }
1744
1745    /// Mirrors `test/i18n-anchor-keys.test.js`: for every `menu.` / `tray.` / `confirm.` /
1746    /// `toast.` / `help.` / `ui.` key where **all** non-English seeds differ from English, assert
1747    /// each locale row is not a verbatim copy of `en`.
1748    #[test]
1749    fn seed_json_safe_catalog_keys_all_locales_differ_from_en() {
1750        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1751        let locales: [(&str, &str); 26] = [
1752            ("de", SEED_JSON_DE),
1753            ("es", SEED_JSON_ES),
1754            ("es-419", SEED_JSON_ES_419),
1755            ("sv", SEED_JSON_SV),
1756            ("fr", SEED_JSON_FR),
1757            ("nl", SEED_JSON_NL),
1758            ("pt", SEED_JSON_PT),
1759            ("pt-BR", SEED_JSON_PT_BR),
1760            ("it", SEED_JSON_IT),
1761            ("el", SEED_JSON_EL),
1762            ("pl", SEED_JSON_PL),
1763            ("ru", SEED_JSON_RU),
1764            ("zh", SEED_JSON_ZH),
1765            ("ja", SEED_JSON_JA),
1766            ("ko", SEED_JSON_KO),
1767            ("fi", SEED_JSON_FI),
1768            ("da", SEED_JSON_DA),
1769            ("nb", SEED_JSON_NB),
1770            ("tr", SEED_JSON_TR),
1771            ("cs", SEED_JSON_CS),
1772            ("hu", SEED_JSON_HU),
1773            ("ro", SEED_JSON_RO),
1774            ("uk", SEED_JSON_UK),
1775            ("vi", SEED_JSON_VI),
1776            ("id", SEED_JSON_ID),
1777            ("hi", SEED_JSON_HI),
1778        ];
1779        let maps: Vec<(&str, HashMap<String, String>)> = locales
1780            .iter()
1781            .map(|(loc, json)| (*loc, serde_json::from_str(json).expect(loc)))
1782            .collect();
1783
1784        for (k, en_val) in &en {
1785            if !key_matches_catalog_prefix(k) {
1786                continue;
1787            }
1788            if en_val.trim().is_empty() {
1789                continue;
1790            }
1791            let all_differ = maps.iter().all(|(_, m)| match m.get(k) {
1792                Some(v) => v != en_val,
1793                None => false,
1794            });
1795            if !all_differ {
1796                continue;
1797            }
1798            for (loc, m) in &maps {
1799                assert_ne!(
1800                    m.get(k),
1801                    Some(en_val),
1802                    "locale {loc} key {k} must not copy English verbatim"
1803                );
1804            }
1805        }
1806    }
1807
1808    #[test]
1809    fn seed_json_all_locales_share_exact_key_set() {
1810        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1811        let keys_en: HashSet<_> = en.keys().cloned().collect();
1812        for (loc, json) in [
1813            ("de", SEED_JSON_DE),
1814            ("es", SEED_JSON_ES),
1815            ("es-419", SEED_JSON_ES_419),
1816            ("sv", SEED_JSON_SV),
1817            ("fr", SEED_JSON_FR),
1818            ("nl", SEED_JSON_NL),
1819            ("pt", SEED_JSON_PT),
1820            ("pt-BR", SEED_JSON_PT_BR),
1821            ("it", SEED_JSON_IT),
1822            ("el", SEED_JSON_EL),
1823            ("pl", SEED_JSON_PL),
1824            ("ru", SEED_JSON_RU),
1825            ("zh", SEED_JSON_ZH),
1826            ("ja", SEED_JSON_JA),
1827            ("ko", SEED_JSON_KO),
1828            ("fi", SEED_JSON_FI),
1829            ("da", SEED_JSON_DA),
1830            ("nb", SEED_JSON_NB),
1831            ("tr", SEED_JSON_TR),
1832            ("cs", SEED_JSON_CS),
1833            ("hu", SEED_JSON_HU),
1834            ("ro", SEED_JSON_RO),
1835            ("uk", SEED_JSON_UK),
1836            ("vi", SEED_JSON_VI),
1837            ("id", SEED_JSON_ID),
1838            ("hi", SEED_JSON_HI),
1839        ] {
1840            let m: HashMap<String, String> = serde_json::from_str(json).expect(loc);
1841            let keys: HashSet<_> = m.keys().cloned().collect();
1842            assert_eq!(
1843                keys_en, keys,
1844                "locale {loc} must define the same keys as en (missing or extra keys)"
1845            );
1846        }
1847    }
1848
1849    #[test]
1850    fn seed_json_no_empty_values_any_locale() {
1851        for (loc, json) in [
1852            ("en", SEED_JSON_EN),
1853            ("de", SEED_JSON_DE),
1854            ("es", SEED_JSON_ES),
1855            ("es-419", SEED_JSON_ES_419),
1856            ("sv", SEED_JSON_SV),
1857            ("fr", SEED_JSON_FR),
1858            ("nl", SEED_JSON_NL),
1859            ("pt", SEED_JSON_PT),
1860            ("pt-BR", SEED_JSON_PT_BR),
1861            ("it", SEED_JSON_IT),
1862            ("el", SEED_JSON_EL),
1863            ("pl", SEED_JSON_PL),
1864            ("ru", SEED_JSON_RU),
1865            ("zh", SEED_JSON_ZH),
1866            ("ja", SEED_JSON_JA),
1867            ("ko", SEED_JSON_KO),
1868            ("fi", SEED_JSON_FI),
1869            ("da", SEED_JSON_DA),
1870            ("nb", SEED_JSON_NB),
1871            ("tr", SEED_JSON_TR),
1872            ("cs", SEED_JSON_CS),
1873            ("hu", SEED_JSON_HU),
1874            ("ro", SEED_JSON_RO),
1875            ("uk", SEED_JSON_UK),
1876            ("vi", SEED_JSON_VI),
1877            ("id", SEED_JSON_ID),
1878            ("hi", SEED_JSON_HI),
1879        ] {
1880            let m: HashMap<String, String> = serde_json::from_str(json).expect(loc);
1881            for (k, v) in &m {
1882                assert!(
1883                    !v.trim().is_empty(),
1884                    "empty or whitespace-only value for key {k:?} in locale {loc}"
1885                );
1886            }
1887        }
1888    }
1889
1890    /// `appFmt` / `toastFmt` replace `{token}` using the **English** token names passed from JS
1891    /// (`ipc.js`). `de`, `el`, `fi`, `fr`, `it`, `nl`, `pl`, `pt`, `pt-BR`, `ru`, `sv`, `zh`, `ja`, `ko`, and `hi` seeds keep the same `{name}`, `{n}`, … substrings as English.
1892    /// Spanish (`es` / `es-419`) still has many legacy localized placeholder spellings in `toast.*`
1893    /// — covered separately via `seed_json_es_critical_prefixes_match_en_placeholders` and
1894    /// `seed_json_es_419_critical_prefixes_match_en_placeholders`.
1895    fn assert_seed_placeholders_match_en(en: &HashMap<String, String>, loc: &str, json: &str) {
1896        let re = Regex::new(r"\{[a-zA-Z_][a-zA-Z0-9_]*\}").expect("placeholder regex");
1897        let m: HashMap<String, String> = serde_json::from_str(json).expect(loc);
1898        for (k, en_val) in en {
1899            let placeholders: HashSet<String> = re
1900                .find_iter(en_val)
1901                .map(|x| x.as_str().to_string())
1902                .collect();
1903            if placeholders.is_empty() {
1904                continue;
1905            }
1906            let v = m
1907                .get(k)
1908                .unwrap_or_else(|| panic!("key {k} missing in {loc}"));
1909            for p in &placeholders {
1910                assert!(
1911                    v.contains(p.as_str()),
1912                    "key {k} locale {loc}: value must contain placeholder {p} (English: {en_val:?})"
1913                );
1914            }
1915        }
1916    }
1917
1918    #[test]
1919    fn seed_json_appfmt_placeholders_preserved_de_el_es_es_419_fi_fr_it_nl_pl_pt_pt_br_ru_sv_zh_ja_ko_da_nb_tr_cs_hu_ro_uk_vi_id_hi(
1920    ) {
1921        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1922        for (loc, json) in [
1923            ("de", SEED_JSON_DE),
1924            ("el", SEED_JSON_EL),
1925            ("es", SEED_JSON_ES),
1926            ("es-419", SEED_JSON_ES_419),
1927            ("fr", SEED_JSON_FR),
1928            ("it", SEED_JSON_IT),
1929            ("nl", SEED_JSON_NL),
1930            ("pl", SEED_JSON_PL),
1931            ("pt", SEED_JSON_PT),
1932            ("pt-BR", SEED_JSON_PT_BR),
1933            ("ru", SEED_JSON_RU),
1934            ("sv", SEED_JSON_SV),
1935            ("zh", SEED_JSON_ZH),
1936            ("ja", SEED_JSON_JA),
1937            ("ko", SEED_JSON_KO),
1938            ("fi", SEED_JSON_FI),
1939            ("da", SEED_JSON_DA),
1940            ("nb", SEED_JSON_NB),
1941            ("tr", SEED_JSON_TR),
1942            ("cs", SEED_JSON_CS),
1943            ("hu", SEED_JSON_HU),
1944            ("ro", SEED_JSON_RO),
1945            ("uk", SEED_JSON_UK),
1946            ("vi", SEED_JSON_VI),
1947            ("id", SEED_JSON_ID),
1948            ("hi", SEED_JSON_HI),
1949        ] {
1950            assert_seed_placeholders_match_en(&en, loc, json);
1951        }
1952    }
1953
1954    #[test]
1955    fn seed_json_es_critical_prefixes_match_en_placeholders() {
1956        let re = Regex::new(r"\{[a-zA-Z_][a-zA-Z0-9_]*\}").expect("placeholder regex");
1957        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1958        let es: HashMap<String, String> = serde_json::from_str(SEED_JSON_ES).expect("es json");
1959        for (k, en_val) in &en {
1960            let is_critical = k.starts_with("menu.")
1961                || k.starts_with("ui.palette.")
1962                || k.starts_with("ui.sp_")
1963                || k.starts_with("confirm.");
1964            if !is_critical {
1965                continue;
1966            }
1967            let placeholders: HashSet<String> = re
1968                .find_iter(en_val)
1969                .map(|x| x.as_str().to_string())
1970                .collect();
1971            if placeholders.is_empty() {
1972                continue;
1973            }
1974            let v = es.get(k).expect("es must define same keys as en");
1975            for p in &placeholders {
1976                assert!(
1977                    v.contains(p.as_str()),
1978                    "key {k} locale es: value must contain placeholder {p} (English: {en_val:?})"
1979                );
1980            }
1981        }
1982    }
1983
1984    #[test]
1985    fn seed_json_es_419_critical_prefixes_match_en_placeholders() {
1986        let re = Regex::new(r"\{[a-zA-Z_][a-zA-Z0-9_]*\}").expect("placeholder regex");
1987        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
1988        let es_419: HashMap<String, String> =
1989            serde_json::from_str(SEED_JSON_ES_419).expect("es-419 json");
1990        for (k, en_val) in &en {
1991            let is_critical = k.starts_with("menu.")
1992                || k.starts_with("ui.palette.")
1993                || k.starts_with("ui.sp_")
1994                || k.starts_with("confirm.");
1995            if !is_critical {
1996                continue;
1997            }
1998            let placeholders: HashSet<String> = re
1999                .find_iter(en_val)
2000                .map(|x| x.as_str().to_string())
2001                .collect();
2002            if placeholders.is_empty() {
2003                continue;
2004            }
2005            let v = es_419.get(k).expect("es-419 must define same keys as en");
2006            for p in &placeholders {
2007                assert!(
2008                    v.contains(p.as_str()),
2009                    "key {k} locale es-419: value must contain placeholder {p} (English: {en_val:?})"
2010                );
2011            }
2012        }
2013    }
2014
2015    #[test]
2016    fn seed_json_en_defines_all_native_menu_bar_keys() {
2017        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
2018        for key in NATIVE_MENU_BAR_KEYS {
2019            assert!(
2020                en.get(*key).map(|s| !s.trim().is_empty()).unwrap_or(false),
2021                "English seed missing native menu bar key {key} (sync with native_menu.rs)"
2022            );
2023        }
2024    }
2025
2026    #[test]
2027    fn seed_json_en_defines_all_tray_keys() {
2028        let en: HashMap<String, String> = serde_json::from_str(SEED_JSON_EN).expect("en json");
2029        for key in TRAY_KEYS {
2030            assert!(
2031                en.get(*key).map(|s| !s.trim().is_empty()).unwrap_or(false),
2032                "English seed missing tray key {key} (sync with tray_menu.rs)"
2033            );
2034        }
2035    }
2036}