//! Chrome-string translations, selected by `site.yaml`'s `lang`. //! //! Content carries its own language; this covers only the strings the //! portal itself speaks around it ("Asked by", the nav lead, the //! not-found page...). Unknown languages and unknown keys fall back //! to English, so a typo degrades to the default instead of a blank. /// Translate `key` for `lang`. `en` is the reference table; every /// other language falls through to it for keys it doesn't carry. pub fn t(lang: &str, key: &str) -> &'static str { if let Some(s) = lookup(lang, key) { return s; } lookup("en", key).unwrap_or(key_missing(key)) } fn lookup(lang: &str, key: &str) -> Option<&'static str> { Some(match (lang, key) { ("en", "also_worth_asking") => "Also worth asking", ("en", "asked_by") => "Asked by ", ("en", "contact_them") => "contact them", ("en", "if_stuck") => " if you get stuck.", ("en", "send") => "Send", ("en", "sign_in") => "Sign in", ("en", "nothing_here_yet") => "Nothing here yet.", ("en", "nothing_here") => "Nothing here", ("en", "back_to_start") => "back to the start", ("en", "done") => "Done.", ("en", "follows_answer") => { "This page follows from an answer you don't seem to carry yet." } ("en", "owners_only") => { "This part of the site is for organizational owners — sign in with that account to take a look." } ("en", "announcements") => "Announcements", ("no", "also_worth_asking") => "Også verdt å spørre", ("no", "asked_by") => "Stilt av ", ("no", "contact_them") => "ta kontakt", ("no", "if_stuck") => " om du står fast.", ("no", "send") => "Send", ("no", "sign_in") => "Logg inn", ("no", "nothing_here_yet") => "Ingenting her ennå.", ("no", "nothing_here") => "Ingenting her", ("no", "back_to_start") => "tilbake til start", ("no", "done") => "Ferdig.", ("no", "follows_answer") => { "Denne siden følger av et svar du ikke ser ut til å bære ennå." } ("no", "owners_only") => { "Denne delen av siden er for organisasjonens eiere — logg inn med den kontoen for å ta en titt." } ("no", "announcements") => "Kunngjøringer", _ => return None, }) } /// A missing key is a programmer error; render the key itself so it /// is findable, never a panic in a view. fn key_missing(key: &str) -> &'static str { // Leak is bounded: keys are a small fixed set of literals. Box::leak(key.to_string().into_boxed_str()) } #[cfg(test)] mod tests { use super::*; #[test] fn norwegian_covers_the_english_table() { for key in [ "also_worth_asking", "asked_by", "contact_them", "if_stuck", "send", "sign_in", "nothing_here_yet", "nothing_here", "back_to_start", "done", "follows_answer", "owners_only", "announcements", ] { assert!(lookup("en", key).is_some(), "en missing {key}"); assert!(lookup("no", key).is_some(), "no missing {key}"); } } #[test] fn unknown_language_falls_back_to_english() { assert_eq!(t("de", "sign_in"), "Sign in"); assert_eq!(t("en", "sign_in"), "Sign in"); } }