G9: persist Japanese menu language without bundled fonts

This commit is contained in:
midasdf
2026-10-06 16:22:23 +09:00
parent 80c246d843
commit 25233abbcb
10 changed files with 868 additions and 9 deletions
+9
View File
@@ -44,6 +44,8 @@ macro_rules! page {
}
page!(General {
/// Interface language (`en` or `ja`).
language: String = "en".into(),
/// Levels of Undo (1–99).
undo_levels: u32 = 32,
/// Path Point and Handle Size (px).
@@ -415,6 +417,9 @@ impl Prefs {
pub fn normalize(&mut self) {
self.version = PREFS_VERSION;
let g = &mut self.general;
if !matches!(g.language.as_str(), "en" | "ja") {
g.language = "en".into();
}
g.undo_levels = g.undo_levels.clamp(1, 99);
g.path_point_size = g.path_point_size.clamp(3, 20);
g.recent_items = g.recent_items.clamp(1, 30);
@@ -453,6 +458,9 @@ impl Prefs {
/// Set the value at a dotted key. The key must exist and the value must have its type.
pub fn set(&mut self, key: &str, value: Value) -> Result<(), String> {
if key == "general.language" && !matches!(value.as_str(), Some("en" | "ja")) {
return Err("`general.language` expects `en` or `ja`".into());
}
let mut v = serde_json::to_value(&*self).map_err(|e| e.to_string())?;
let ptr = format!("/{}", key.replace('.', "/"));
let slot = v.pointer_mut(&ptr).ok_or_else(|| format!("unknown setting `{key}`"))?;
@@ -877,6 +885,7 @@ pub fn pages() -> Vec<Page> {
id: "general",
title: "General",
items: vec![
s("general.language", "Language", Kind::Choice(&[("English", "en"), ("日本語", "ja")]), true),
s("general.undoLevels", "Levels of Undo", Kind::Int(1, 99, ""), true),
s("general.pathPointSize", "Path Point and Handle Size", Kind::Int(3, 20, "px"), true),
s("general.recentItems", "Recent Projects Shown", Kind::Int(1, 30, ""), true),
+22
View File
@@ -486,3 +486,25 @@ fn memory_tick_never_waits_for_the_system() {
assert!(got.is_some_and(|m| m.total > 0), "the reading arrives in the background");
}
}
#[test]
fn interface_language_is_validated_persisted_and_backward_compatible() {
let store = Arc::new(MemoryConfig::default());
let mut s = Session { config: Some(store.clone()), ..Default::default() };
assert_eq!(s.prefs.general.language, "en");
s.execute("prefs.set", json!({"key": "general.language", "value": "ja"})).unwrap();
assert_eq!(s.execute("prefs.get", json!({"key": "general.language"})).unwrap(), json!("ja"));
let saved = store.read(PREFS_FILE).unwrap();
for bad in [json!("fr"), json!(""), json!(17), json!(null)] {
assert!(s.execute("prefs.set", json!({"key": "general.language", "value": bad})).is_err());
assert_eq!(s.prefs.general.language, "ja");
assert_eq!(store.read(PREFS_FILE).unwrap(), saved);
}
let mut reloaded = Session { config: Some(store), ..Default::default() };
reloaded.load_settings();
assert_eq!(reloaded.prefs.general.language, "ja");
reloaded.execute("prefs.reset", json!({"page": "general"})).unwrap();
assert_eq!(reloaded.prefs.general.language, "en");
assert_eq!(Prefs::from_json(r#"{"general":{"undoLevels":17}}"#).general.language, "en");
assert_eq!(Prefs::from_json(r#"{"general":{"language":"unknown"}}"#).general.language, "en");
}