# 多语言 + 多布局 + 默认皮肤联动技术分析与架构方案 ## 1. 需求摘要 你最终要的功能是: 1. 用户在主 App 切换国家/语言。 2. 如果该语言有多个键盘布局(如西班牙语 QWERTY / AZERTY / QWERTZ),点击语言后进入布局选择页。 3. 选择布局时,页面展示该语言对应键盘布局预览。 4. 切换语言时,自动下发该国家默认皮肤(例如英文 -> 西班牙语,自动应用西班牙默认皮肤)。 ## 2. 现有代码现状分析 ### 2.1 多语言系统(已具备基础能力) 1. 语言管理集中在 `KBLocalizationManager`,支持运行时切换、App 与扩展共享。 2. 当前默认支持语言只有 `en` 和 `zh-Hans`。 3. 主 App 启动时会设置 `supportedLanguageCodes`。 关键代码位置: 1. `/Users/mac/Desktop/项目/公司/KeyBoard/Shared/KBLocalizationManager.h` 2. `/Users/mac/Desktop/项目/公司/KeyBoard/Shared/KBLocalizationManager.m` 3. `/Users/mac/Desktop/项目/公司/KeyBoard/keyBoard/AppDelegate.m` 当前限制: 1. 语言常量只有 `KBLanguageCodeEnglish`、`KBLanguageCodeSimplifiedChinese`。 2. `Localizable.strings` 目前只有 `en`、`zh-Hans` 两套。 3. 工程 `knownRegions` 仅包含 `en`、`zh-Hans`、`Base`。 --- ### 2.2 键盘布局系统(已具备 JSON 驱动,但尚未按“语言+变体”建模) 1. 扩展键盘布局配置由 `kb_keyboard_layout_config.json` 驱动。 2. `KBKeyboardView` 通过 `KBKeyboardLayoutConfig` 读取 `letters / numbers / symbolsMore` 布局并构建按键。 3. 当前布局名是固定三套,不带语言维度。 关键代码位置: 1. `/Users/mac/Desktop/项目/公司/KeyBoard/CustomKeyboard/Model/KBKeyboardLayoutConfig.h` 2. `/Users/mac/Desktop/项目/公司/KeyBoard/CustomKeyboard/Model/KBKeyboardLayoutConfig.m` 3. `/Users/mac/Desktop/项目/公司/KeyBoard/CustomKeyboard/Resource/kb_keyboard_layout_config.json` 4. `/Users/mac/Desktop/项目/公司/KeyBoard/CustomKeyboard/View/KBKeyboardView.m` 当前限制: 1. `KBKeyboardView` 当前布局选择逻辑只区分字母/数字/符号页,不区分输入语言。 2. `buildKeysForLettersLayout` 里仍保留了 QWERTY 兜底硬编码路径。 --- ### 2.3 主 App 设置入口(可扩展) 1. `KBPersonInfoVC` 是现有“设置”页面,可作为语言入口的落点。 2. 该页面当前有三行:昵称、性别、用户 ID。 关键代码位置: 1. `/Users/mac/Desktop/项目/公司/KeyBoard/keyBoard/Class/Me/VC/KBPersonInfoVC.m` 2. `/Users/mac/Desktop/项目/公司/KeyBoard/keyBoard/Class/Me/V/KBPersonInfoItemCell.m` 结论: 1. 最小侵入方案是直接在 `KBPersonInfoVC` 增加“Language / Keyboard Layout”行和跳转逻辑,不需要额外改主流程导航。 --- ### 2.4 皮肤系统(已具备跨进程下发能力) 1. `KBSkinManager` 负责应用主题并通过 Darwin 通知同步到扩展。 2. `KBSkinInstallBridge` 负责发布“待安装皮肤请求”、扩展侧消费并应用。 3. 扩展 `KeyboardViewController+Theme` 已监听并消费皮肤安装通知,且有默认皮肤兜底逻辑。 关键代码位置: 1. `/Users/mac/Desktop/项目/公司/KeyBoard/Shared/KBSkinManager.m` 2. `/Users/mac/Desktop/项目/公司/KeyBoard/Shared/KBSkinInstallBridge.m` 3. `/Users/mac/Desktop/项目/公司/KeyBoard/CustomKeyboard/KeyboardViewControllerHelp/KeyboardViewController+Theme.m` 当前限制: 1. `pendingRequest` 只有单槽位(同一时刻只能保留一条待消费皮肤请求)。 2. 默认皮肤逻辑目前由扩展按系统明暗自动判断,不包含“按语言自动默认皮肤”策略。 --- ### 2.5 与新语言相关的隐含影响点 1. 联想词引擎与 trailing-word 提取仅识别 `a-z`,会影响西语/葡语重音字母。 2. 部分 locale 转换逻辑仍是二分(中文/英文),例如 `KBMyVM` 的 `fetchCancelAccountWarningWithCompletion`。 3. 个别网络模块存在硬编码 `Accept-Language`。 关键代码位置: 1. `/Users/mac/Desktop/项目/公司/KeyBoard/CustomKeyboard/Manager/KBSuggestionEngine.m` 2. `/Users/mac/Desktop/项目/公司/KeyBoard/CustomKeyboard/KeyboardViewControllerHelp/KeyboardViewController+Suggestions.m` 3. `/Users/mac/Desktop/项目/公司/KeyBoard/keyBoard/Class/Me/VM/KBMyVM.m` 4. `/Users/mac/Desktop/项目/公司/KeyBoard/CustomKeyboard/Network/NetworkStreamHandler.m` ## 3. 目标架构(核心原则) ## 3.1 核心原则 1. **展示语言** 与 **输入语言/布局** 解耦。 2. 语言切换是“偏好中心事件”,布局与皮肤都由该事件驱动。 3. 皮肤优先级明确,避免覆盖用户主动选择。 4. 保持现有 JSON 布局机制,不推翻 `KBKeyboardView` 主体。 ## 3.2 模块划分 建议新增以下共享模块(放 `Shared`,主 App 与扩展都可用): 1. `KBInputLanguageProfileManager` 2. `KBKeyboardLayoutPreferenceManager` 3. `KBDefaultSkinPolicyManager` ### 3.2.1 KBInputLanguageProfileManager(语言元数据中心) 职责: 1. 维护每个语言的能力描述(是否多布局、默认布局、默认皮肤 ID、布局列表)。 2. 提供给主 App 设置页和扩展布局解析器统一读取。 建议数据模型(JSON/Plist 均可): 1. `languageCode` 2. `displayNameKey` 3. `supportsMultipleLayouts` 4. `layoutVariants` 5. `defaultLayoutVariant` 6. `defaultSkinId` 7. `defaultSkinZipName` 示例(结构示意): ```json { "es": { "supportsMultipleLayouts": true, "layoutVariants": ["qwerty", "azerty", "qwertz"], "defaultLayoutVariant": "qwerty", "defaultSkinId": "lang_es_default", "defaultSkinZipName": "lang_es_default" }, "pt": { "supportsMultipleLayouts": false, "layoutVariants": ["qwerty"], "defaultLayoutVariant": "qwerty", "defaultSkinId": "lang_pt_default", "defaultSkinZipName": "lang_pt_default" } } ``` ### 3.2.2 KBKeyboardLayoutPreferenceManager(语言/布局偏好持久化) 职责: 1. 存储用户当前输入语言与布局变体。 2. 提供“切换语言后自动决定下一步”的能力。 3. App 与扩展通过 App Group 共享。 建议存储键(App Group): 1. `KBPref_InputLanguageCode` 2. `KBPref_LayoutVariantByLanguage`(字典) 3. `KBPref_CurrentLayoutVariant` 4. `KBPref_UpdatedAt` 通知建议: 1. 进程内通知:`KBKeyboardPreferenceDidChangeNotification` 2. Darwin 通知:`com.loveKey.nyx.keyboard.preference.changed` ### 3.2.3 KBDefaultSkinPolicyManager(默认皮肤策略) 职责: 1. 在语言切换时决定是否自动套用默认皮肤。 2. 防止覆盖用户主动自定义皮肤。 建议策略: 1. 记录 `skinSource`:`language_default` / `user_selected` / `shop_downloaded` / `system_default`。 2. 仅当当前皮肤来源是 `language_default` 或 `system_default` 时,语言切换可自动覆盖。 3. 若当前皮肤来源为 `user_selected`,默认不自动覆盖,除非产品要求强制覆盖。 ## 4. 主流程设计 ## 4.1 主 App:语言切换流程 1. 用户在设置页选择语言(例如西班牙语)。 2. 写入 `KBLocalizationManager`(UI 文案语言切换)。 3. 查询 `KBInputLanguageProfileManager`: 4. 若 `supportsMultipleLayouts = YES`,跳转布局选择页。 5. 若 `supportsMultipleLayouts = NO`,直接写默认布局并结束。 6. 布局选择完成后,写 `KBKeyboardLayoutPreferenceManager`。 7. 触发默认皮肤策略,必要时发布皮肤安装请求给扩展。 ## 4.2 主 App:布局选择页(新页面) 页面职责: 1. 展示该语言可选布局(西班牙语 3 选 1)。 2. 展示对应键盘预览(可复用 `kb_keyboard_layout_config.json` 生成静态预览,或使用简化绘制)。 3. 点击保存后写偏好并返回。 建议页面命名: 1. `KBKeyboardLayoutSelectVC` ## 4.3 键盘扩展:偏好生效流程 1. `viewWillAppear` 读取共享偏好(现有已读取语言,可在此处同时读取布局偏好)。 2. `KBKeyboardView` 通过 Resolver 决定当前要用的 `letters layout name`。 3. 调用 `reloadKeys` 重建按键。 4. 若收到偏好变更通知(进程内/Darwin),动态刷新当前键盘。 ## 4.4 皮肤联动流程 1. 主 App 语言切换后,根据 profile 取 `defaultSkinId/defaultSkinZipName`。 2. 调用 `KBSkinInstallBridge publishBundleSkinRequestWithId` 发布请求。 3. 扩展侧现有 Darwin observer 会消费请求并应用皮肤。 4. 键盘立即主题刷新(现有链路已具备)。 ## 5. 键盘布局建模升级方案 ## 5.1 JSON 扩展方式 不改 `KBKeyboardLayoutConfig` 的基础结构,只扩展 `layouts` 命名约定: 1. `letters_es_qwerty` 2. `letters_es_azerty` 3. `letters_es_qwertz` 4. `letters_pt_qwerty` 5. `letters_id_qwerty` 6. `letters_zh_hant_qwerty`(若繁体沿用 QWERTY) 数字与符号可先复用: 1. `numbers` 2. `symbolsMore` ## 5.2 Resolver 规则 新增 `KBKeyboardLayoutResolver`: 1. 输入参数:`languageCode + layoutVariant + panelType` 2. 输出布局名: 3. 字母面板:`letters__` 4. 数字/符号:先复用现有 `numbers/symbolsMore` 回退链: 1. `letters__` 2. `letters__qwerty` 3. `letters` 4. legacy(当前已存在) ## 6. UI 与交互建议(结合现有代码) ## 6.1 设置入口落点 直接在 `KBPersonInfoVC` 的 section0 新增两行: 1. `Language` 2. `Keyboard Layout`(仅多布局语言显示,单布局语言可隐藏或置灰显示默认值) 优势: 1. 改动集中在已有设置页,不新增复杂入口链路。 2. 能快速验证需求闭环。 ## 6.2 预览实现建议 1. 第一阶段:静态预览图(开发快,风险低)。 2. 第二阶段:用同一份 layout JSON 动态绘制预览(与真实键盘一致性最高)。 ## 7. 风险与约束 1. `KBSkinInstallBridge` 的 pending request 是单槽位,语言切换与商城皮肤下载并发时可能互相覆盖。 2. 当前扩展默认皮肤逻辑会在某些时机自动执行,需要避免与你的“语言默认皮肤”策略冲突。 3. 联想词和字符识别是英文字母集合,西语/葡语输入体验会受影响。 4. locale 透传接口当前存在中文/英文二分逻辑,新增语言后需统一改造为映射表。 ## 8. 分阶段实施计划 ## 阶段 A:基础设施 1. 扩展 `KBLocalizationManager` 支持 `es / pt / zh-Hant / id`。 2. 增加 4 套本地化资源并加入工程 region。 3. 新建 `KBInputLanguageProfileManager` 与配置文件。 ## 阶段 B:设置页与偏好持久化 1. 新建 `KBKeyboardLayoutPreferenceManager`。 2. 在 `KBPersonInfoVC` 增加语言入口。 3. 新建布局选择页与预览页。 ## 阶段 C:扩展键盘接入 1. 新建 `KBKeyboardLayoutResolver`。 2. `KBKeyboardView` 切换为按 Resolver 选布局名。 3. 为西班牙语补三套 `letters` 布局定义。 ## 阶段 D:默认皮肤联动 1. 新建 `KBDefaultSkinPolicyManager`。 2. 语言切换后根据 profile 下发默认皮肤请求。 3. 引入 `skinSource` 防止覆盖用户自定义皮肤。 ## 阶段 E:体验完善 1. 联想词与字符集支持重音字符。 2. 统一 locale 映射(网络、订阅文案、接口参数)。 3. 并发请求队列化(解决 pending 单槽位冲突)。 ## 9. 测试建议 1. 切换语言后 UI 文案是否全量生效(主 App + 扩展)。 2. 西班牙语三布局切换是否即时生效。 3. 语言切换时默认皮肤是否按策略生效。 4. 用户自定义皮肤是否不会被错误覆盖。 5. 扩展冷启动、前后台、键盘切换场景下偏好一致性。 6. App Group 不可用/完全访问关闭时的降级行为。 ## 10. 我建议的落地架构结论 1. 保留现有三大基座:`KBLocalizationManager`、`KBKeyboardLayoutConfig`、`KBSkinInstallBridge`。 2. 新增“语言 profile + 偏好管理 + 皮肤策略”三层,作为编排层。 3. 先打通“西班牙语多布局”闭环,再批量扩展到葡语/繁体/印尼语。 4. 先保证正确性与一致性,再优化联想词与并发策略。