jlcodes99/cockpit-tools · critical
解析语言文件失败 {}: {}
Error message
解析语言文件失败 {}: {} What it means
A startup panic in the Rust i18n module: one of the bundled locale JSON files failed `serde_json::from_str::<Value>` parsing, so the loader calls `panic!("解析语言文件失败 {locale}: {err}")`. Since this runs while building the embedded translations map, the whole process aborts at startup with the locale name and the serde error appended to the message (the `{}` in the template are the actual values).
Source
Thrown at src-tauri/src/modules/i18n.rs:33
("fr", include_str!("../../../src/locales/fr.json")),
("id", include_str!("../../../src/locales/id.json")),
("it", include_str!("../../../src/locales/it.json")),
("ja", include_str!("../../../src/locales/ja.json")),
("ko", include_str!("../../../src/locales/ko.json")),
("pl", include_str!("../../../src/locales/pl.json")),
("pt-br", include_str!("../../../src/locales/pt-br.json")),
("ru", include_str!("../../../src/locales/ru.json")),
("tr", include_str!("../../../src/locales/tr.json")),
("vi", include_str!("../../../src/locales/vi.json")),
("zh-cn", include_str!("../../../src/locales/zh-CN.json")),
("zh-tw", include_str!("../../../src/locales/zh-tw.json")),
];
locale_files
.into_iter()
.map(|(locale, content)| {
let parsed = serde_json::from_str::<Value>(content)
.unwrap_or_else(|err| panic!("解析语言文件失败 {}: {}", locale, err));
(locale, parsed)
})
.collect()
});
fn normalize_locale(locale: &str) -> String {
locale.trim().replace('_', "-").to_lowercase()
}
fn locale_candidates(locale: &str) -> Vec<String> {
let normalized = normalize_locale(locale);
if normalized.is_empty() {
return vec!["en-us".to_string(), "en".to_string()];
}
let mut candidates = vec![normalized.clone()];
let mut prefix_matches: Vec<&str> = LOCALESView on GitHub (pinned to 1ed8b77992)
Solutions
- Read the serde error in the panic message — it names the exact line/column in the locale file — and fix the JSON syntax there.
- Validate all locale files with a JSON linter (`jq . src-tauri/locales/*.json`) before rebuilding.
- Restore the affected locale file from version control if the edit was accidental.
- Replace the panic with a logged fallback so a bad locale degrades instead of crashing startup.
Example fix
// before
.unwrap_or_else(|err| panic!("解析语言文件失败 {}: {}", locale, err));
// after
.unwrap_or_else(|err| {
log::error!("解析语言文件失败 {}: {}", locale, err);
serde_json::json!({})
}); Defensive patterns
Strategy: validation
Validate before calling
# CI check before building
for f in src-tauri/locales/*.json; do jq -e . "$f" > /dev/null || { echo "invalid JSON: $f"; exit 1; }; done Prevention
- Lint all locale JSON files in CI (jq / serde_json round-trip test).
- Never hand-edit locale files without validating; use a translation tool that emits valid JSON.
- Add a unit test that parses every embedded locale at test time so panics surface before release.
- Strip BOM and merge-conflict markers from translation files.
When it happens
Trigger: Embedding or editing a locale JSON file (e.g. zh-CN.json, en.json) with a syntax error — trailing comma, unquoted key, BOM, or non-JSON content — so `serde_json::from_str` fails when `load_locale_files` collects the map.
Common situations: A translator edited a language file by hand and broke the JSON; a build script embedded a partially written file; file encoding changed to UTF-8 with BOM; a merge conflict marker (<<<<<<<) was left inside a locale file.
Related errors
- 默认 OAuth client 配置无效
- 无效的 Auth URL
- expected launch path must exist
- [SyncSettings] 保存合并后的配置失败: {}
- 加载账号失败: {}
AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05).
Data as JSON: /api/errors/7068641814b1043a.
Report an issue: GitHub.