Test / test (pull_request) Successful in 1m12s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GT37Z1Xtfd9pUuQtMTg6Yt
143 lines
5.8 KiB
Rust
143 lines
5.8 KiB
Rust
//! 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", "sign_out") => "Sign out",
|
|
("en", "nothing_here_yet") => "Nothing here yet.",
|
|
("en", "upload_failed") => "The file could not be sent, so nothing was. Try again, or with a smaller file.",
|
|
("en", "current_file") => "Now:",
|
|
("en", "keep_file") => "Choose a new one to replace it, or leave it as it is.",
|
|
("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",
|
|
("en", "down_to") => "Back to ",
|
|
("en", "suggest_edit") => "Suggest a change to this page",
|
|
("en", "suggest_edit_help") => "You are listed as responsible for this question. Say what should change, and it goes to the people who keep the site.",
|
|
("en", "suggest_edit_send") => "Send the suggestion",
|
|
("en", "suggest_edit_sent") => "Thank you - your suggestion is sent.",
|
|
("en", "suggestions_yours") => "What you have suggested here",
|
|
("en", "suggestion_open") => "Sent",
|
|
("en", "suggestion_discussed") => "Being looked at",
|
|
("en", "suggestion_done") => "Done",
|
|
("en", "suggestion_declined") => "Not done",
|
|
("en", "the_start") => "the start",
|
|
|
|
("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", "sign_out") => "Logg ut",
|
|
("no", "nothing_here_yet") => "Ingenting her ennå.",
|
|
("no", "upload_failed") => "Filen kom ikke fram, så ingenting ble sendt. Prøv igjen, eller med en mindre fil.",
|
|
("no", "current_file") => "Nå:",
|
|
("no", "keep_file") => "Velg en ny for å bytte, eller la den være.",
|
|
("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",
|
|
("no", "down_to") => "Tilbake til ",
|
|
("no", "suggest_edit") => "Foreslå en endring på denne siden",
|
|
("no", "suggest_edit_help") => "Du står oppført som ansvarlig for dette spørsmålet. Skriv hva som bør endres, så går det til dem som har siden.",
|
|
("no", "suggest_edit_send") => "Send forslaget",
|
|
("no", "suggest_edit_sent") => "Takk - forslaget er sendt.",
|
|
("no", "suggestions_yours") => "Det du har foreslått her",
|
|
("no", "suggestion_open") => "Sendt",
|
|
("no", "suggestion_discussed") => "Blir sett på",
|
|
("no", "suggestion_done") => "Gjort",
|
|
("no", "suggestion_declined") => "Ikke gjort",
|
|
("no", "the_start") => "starten",
|
|
|
|
_ => 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",
|
|
"sign_out",
|
|
"nothing_here_yet",
|
|
"upload_failed",
|
|
"current_file",
|
|
"keep_file",
|
|
"nothing_here",
|
|
"back_to_start",
|
|
"done",
|
|
"follows_answer",
|
|
"owners_only",
|
|
"announcements",
|
|
"down_to",
|
|
"the_start",
|
|
"suggest_edit",
|
|
"suggest_edit_help",
|
|
"suggest_edit_send",
|
|
"suggest_edit_sent",
|
|
"suggestions_yours",
|
|
"suggestion_open",
|
|
"suggestion_discussed",
|
|
"suggestion_done",
|
|
"suggestion_declined",
|
|
] {
|
|
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");
|
|
}
|
|
}
|