use ratatui::style::{Modifier, Style};
use ratatui::text::{Line, Span};
use crate::localization::MessageId;
use crate::palette;
use crate::tui::app::App;
pub const LANGUAGE_OPTIONS: &[(char, &str, &str, &str)] = &[
('1', "auto", "Auto-detect", "(LC_ALL / LANG)"),
('2', "en", "English", ""),
('3', "ja", "日本語", "(Japanese)"),
('4', "zh-Hans", "简体中文", "(Simplified Chinese)"),
('5', "zh-Hant", "繁體中文", "(Traditional Chinese)"),
('6', "pt-BR", "Português (Brasil)", "(Brazilian Portuguese)"),
(
'7',
"es-419",
"Español (Latinoamérica)",
"(Latin American Spanish)",
),
('8', "vi", "Tiếng Việt", "(Vietnamese)"),
('9', "ko", "한국어", "(Korean)"),
];
pub fn lines(app: &App) -> Vec<Line<'static>> {
let current_owned = app.current_locale_tag();
let current = current_owned.as_str();
let mut out: Vec<Line<'static>> = vec![
Line::from(Span::styled(
app.tr(MessageId::OnboardLanguageTitle).to_string(),
Style::default()
.fg(palette::WHALE_INFO)
.add_modifier(Modifier::BOLD),
)),
Line::from(""),
Line::from(Span::styled(
app.tr(MessageId::OnboardLanguageBlurb).to_string(),
Style::default().fg(palette::TEXT_MUTED),
)),
Line::from(""),
];
for (hotkey, tag, native, english) in LANGUAGE_OPTIONS {
let is_current = current == *tag;
let bullet = if is_current { "●" } else { "○" };
let bullet_color = if is_current {
palette::WHALE_ACCENT_PRIMARY
} else {
palette::TEXT_MUTED
};
let mut spans: Vec<Span<'static>> = vec![
Span::styled(format!(" {bullet} "), Style::default().fg(bullet_color)),
Span::styled(
format!("[{hotkey}] "),
Style::default()
.fg(palette::TEXT_PRIMARY)
.add_modifier(Modifier::BOLD),
),
Span::styled(
native.to_string(),
Style::default().fg(palette::TEXT_PRIMARY),
),
];
if !english.is_empty() {
spans.push(Span::styled(
format!(" {english}"),
Style::default().fg(palette::TEXT_MUTED),
));
}
out.push(Line::from(spans));
}
out.push(Line::from(""));
out.push(Line::from(Span::styled(
app.tr(MessageId::OnboardLanguageFooter).to_string(),
Style::default().fg(palette::TEXT_MUTED),
)));
out
}
#[cfg(test)]
mod tests {
use super::*;
use crate::localization::Locale;
#[test]
fn picker_offers_every_shipped_locale() {
let offered: Vec<&str> = LANGUAGE_OPTIONS.iter().map(|(_, tag, _, _)| *tag).collect();
assert!(
offered.contains(&"auto"),
"picker must keep the auto-detect entry"
);
for locale in Locale::shipped() {
let tag = locale.tag();
assert!(
offered.contains(&tag),
"shipped locale {tag} is not offered in the language picker"
);
}
}
#[test]
fn picker_hotkeys_are_contiguous_digits() {
for (idx, (hotkey, tag, _, _)) in LANGUAGE_OPTIONS.iter().enumerate() {
let expected = char::from_digit((idx + 1) as u32, 10).expect("digit");
assert_eq!(
*hotkey, expected,
"option {tag} should use hotkey {expected}, not {hotkey}"
);
}
}
}