{"record":{"id":"7068641814b1043a","repo":"jlcodes99/cockpit-tools","slug":"error","errorCode":null,"errorMessage":"解析语言文件失败 {}: {}","messagePattern":"解析语言文件失败 (.+?): (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src-tauri/src/modules/i18n.rs","lineNumber":33,"sourceCode":"            (\"fr\", include_str!(\"../../../src/locales/fr.json\")),\n            (\"id\", include_str!(\"../../../src/locales/id.json\")),\n            (\"it\", include_str!(\"../../../src/locales/it.json\")),\n            (\"ja\", include_str!(\"../../../src/locales/ja.json\")),\n            (\"ko\", include_str!(\"../../../src/locales/ko.json\")),\n            (\"pl\", include_str!(\"../../../src/locales/pl.json\")),\n            (\"pt-br\", include_str!(\"../../../src/locales/pt-br.json\")),\n            (\"ru\", include_str!(\"../../../src/locales/ru.json\")),\n            (\"tr\", include_str!(\"../../../src/locales/tr.json\")),\n            (\"vi\", include_str!(\"../../../src/locales/vi.json\")),\n            (\"zh-cn\", include_str!(\"../../../src/locales/zh-CN.json\")),\n            (\"zh-tw\", include_str!(\"../../../src/locales/zh-tw.json\")),\n        ];\n\n        locale_files\n            .into_iter()\n            .map(|(locale, content)| {\n                let parsed = serde_json::from_str::<Value>(content)\n                    .unwrap_or_else(|err| panic!(\"解析语言文件失败 {}: {}\", locale, err));\n                (locale, parsed)\n            })\n            .collect()\n    });\n\nfn normalize_locale(locale: &str) -> String {\n    locale.trim().replace('_', \"-\").to_lowercase()\n}\n\nfn locale_candidates(locale: &str) -> Vec<String> {\n    let normalized = normalize_locale(locale);\n    if normalized.is_empty() {\n        return vec![\"en-us\".to_string(), \"en\".to_string()];\n    }\n\n    let mut candidates = vec![normalized.clone()];\n\n    let mut prefix_matches: Vec<&str> = LOCALES","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/jlcodes99/cockpit-tools/blob/1ed8b77992d62ca81fabf744deb0839ad361d5bf/src-tauri/src/modules/i18n.rs#L15-L51","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n.unwrap_or_else(|err| panic!(\"解析语言文件失败 {}: {}\", locale, err));\n// after\n.unwrap_or_else(|err| {\n    log::error!(\"解析语言文件失败 {}: {}\", locale, err);\n    serde_json::json!({})\n});","handlingStrategy":"validation","validationCode":"# CI check before building\nfor f in src-tauri/locales/*.json; do jq -e . \"$f\" > /dev/null || { echo \"invalid JSON: $f\"; exit 1; }; done","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["rust","i18n","json","panic","startup"],"backgroundTag":"invalid-locale-json","analyzedSha":"1ed8b77992d62ca81fabf744deb0839ad361d5bf","analyzedAt":"2026-09-05T09:51:41.178Z","contentChangedAt":"2026-09-05T09:51:41.178Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}