语言切换知识库 · 00-README(索引)
MiCarSettings「切换系统语言」专题知识库入口。 建库:2026-07-19 | 基线机型:fermi (flavor=xcd, region=cn) 维护方式:分篇 + mermaid +
文件:行号;本文件是导航,详情进各篇。
一句话结论
国内版(
ro.micar.build.region=cn)在「系统→通用」里看不到「系统语言」入口,是产品有意裁剪(UniversalSettingsFragment运行时移除),不是 bug。切语言有三条路:① 彩蛋(关于→连点内核版本 10 次,国内可用、即时生效)② adb(改system_locales+ reboot)③ 海外版才有 UI 入口。核心坑:权威落点是Settings.System.system_locales,persist.sys.locale只是 fallback——只改 prop 重启必被覆盖回旧值。
全景图
flowchart LR subgraph 触发["切换语言的三条路径"] E1["① 彩蛋<br/>关于→内核版本点10次<br/>LanguageUtils.showTipToast<br/>中英互切·即时生效<br/>国内cn可用/ECE隐藏"] E2["② adb<br/>settings put system system_locales<br/>+ reboot<br/>任意机型·需root或debug"] E3["③ UI入口<br/>系统→通用→系统语言<br/>SystemLanguageDialogActivity<br/>仅海外版可见"] end subgraph 归一["全部归一到 framework 单一入口"] LP["com.android.internal.app<br/>LocalePicker.updateLocale<br/>(adb 例外:直接写 system_locales)"] end subgraph 落点["三处存储"] SL["Settings.System.system_locales<br/>★ 权威 · 跨重启"] PP["persist.sys.locale<br/>fallback · 镜像"] CF["运行时 Configuration<br/>派生 · 进程内"] end subgraph 副作用["切换后"] BR["ACTION_LOCALE_CHANGED 广播"] VSM["LocaleChangedReceiver<br/>→ VoiceSearchManager.onLocaleChanged<br/>语音搜索重解析"] end E1 --> LP E3 --> LP LP --> SL LP --> PP LP --> CF E2 --> SL SL -- "reboot后AMS读取" --> CF CF --> BR BR --> VSM style SL fill:#d4edda,stroke:#28a745 style PP fill:#fff3cd,stroke:#ffc107 style E1 fill:#e1f5ff,stroke:#0a6
文档清单
| # | 文档 | 回答的问题 |
|---|---|---|
| 01 | 切换全链路时序 | 用户点「系统语言」后,从 Controller → DialogActivity → Adapter → LocalePicker.updateLocale 的完整时序、状态机、防双击、文案 |
| 02 | Android Locale 体系与落点 | 为什么 setprop persist.sys.locale 改了重启还是中文?三个存储点、framework 链路、优先级决策树(含可验证性说明) |
| 03 | Region 裁剪机制 | 为什么 XCD cn 看不到入口?ro.micar.build.region 判定、国内裁剪 vs ECE 物理裁剪、Flavor/Region 正交 |
| 04 | adb 实操与排查手册 | 命令清单、fermi 实战复盘、4 个入口盘点(含彩蛋)、排查决策树、常见坑 |
| — | _对抗审查记录 | 建库时的对抗审查过程(13 条问题 + 修正),留档供追溯 |
速查:三个关键事实
- 权威 locale 源 =
Settings.System.system_locales(不是persist.sys.locale)。- 切:
adb shell settings put system system_locales en-US && adb reboot - 查(三连,以第三个为准):
adb shell getprop persist.sys.locale adb shell settings get system system_locales adb shell dumpsys activity | grep -oE '\[[a-z]{2}_[A-Z]{2,3}\]' | head -1
- 切:
- 国内/海外判定 =
ro.micar.build.region(cn/global/eu/ece,空也算国内)。adb shell getprop ro.micar.build.region一行查清。 - 国内版也能切语言——彩蛋入口(关于→内核版本点 10 次)走
LanguageUtils.showTipToast→LocalePicker.updateLocale,即时生效、无需 reboot;ECE 版因hiddenFeatures="lemans_ece"隐藏内核条目而点不到。
速查:项目内 4 个切换入口
| 入口 | 文件 | 国内可用 |
|---|---|---|
| ① 设置→通用→系统语言 | SystemLanguagePreferenceController.kt:46 → SystemLanguageDialogActivity.kt:52 | 否(被移除) |
| ② 开机引导选语言 | ProvisionLanguageDialogActivity.kt:100 | 是(provision 拉起) |
| ③ 显示设置老入口 | LanguagePickerPrefController.java:46 | 已废弃(XML 注释停用) |
| ④ 彩蛋:内核版本点 10 次 | KernelVersionPreferenceController.java:80 → LanguageUtils.java:26 | 是(cn 可用,ECE 隐藏) |
边界
覆盖:MiCarSettings 应用内「切换系统语言」的全部代码路径、Locale 落点机制、Flavor/Region 裁剪、adb 调试与排查。
不覆盖(如需请另建专题):
- 各语言字符串资源的翻译完整性(
values-de/fr/...覆盖率) - 多用户/多账号下的 per-user locale 隔离(AOSP 行为,本仓不可验证,见 02 篇 §10)
- OTA 升级时 system_locales 是否被强制回写出厂值(待实测)
- framework 侧
LocalePicker/AMS/SettingsProvider的逐行源码(非本仓,02 篇基于 AOSP 描述)
相关文件清单(核心)
- 入口/弹窗/列表:
settingsPage/settingsSystem/src/main/java/com/android/car/settings/universal/(SystemLanguagePreferenceController.kt/SystemLanguageDialogActivity.kt/SystemLanguageConfig.kt/SystemLanguageAdapter.kt/LocaleInfoWrapper.kt/ProvisionLanguageDialogActivity.kt/UniversalSettingsFragment.java) - 读 locale:
base/settingsBaseLib/src/main/java/com/android/micar/settings/utils/LocaleUtils.kt - 彩蛋:
settingsPage/settingsSystem/.../system/KernelVersionPreferenceController.java+.../utils/LanguageUtils.java - 监听变更:
app/src/main/java/com/android/car/settings/miauto/LocaleChangedReceiver.kt(manifest 注册app/src/main/AndroidManifest.xml:1583-1589) - Region 判定:
base/settingsBaseLib/.../DeviceUtil.java+.../views/MiCarSettings.java - 两套 XML:
settingsPage/settingsSystem/src/main/res/xml/miauto_universal_settings_fragment.xml(主)+_ece.xml(ECE 精简)