本文档聚焦 Sources/STLocalizable 目录,按功能拆解本地化模块的职责、调用关系和接入方式,便于在业务中稳定使用语言切换能力。
STLocalizableProtocol.swift:定义可本地化视图协议STLocalizationManager.swift:语言包选择、持久化、字符串读取、通知分发、启动恢复STViewControllerLocalization.swift:STBaseViewController层面的本地化刷新整合
统一约束“哪些视图支持运行时语言切换刷新”,避免业务层通过类型判断逐个手动刷新。
- 协议:
STLocalizable - 方法:
st_updateLocalizedText() - 设计方式:由
STLabel、STBtn、STTextField等封装控件显式实现
- 组件实现
STLocalizable。 - 在
st_updateLocalizedText()内部重新根据 key 拉取文案并更新 UI。 - 语言切换后由控制器递归遍历视图树触发刷新。
对应文件:STLocalizationManager.swift
- 结构体:
STSupportedLanguage - 字段:
languageCode、displayName、locale - 能力:
getAvailableLanguages()扫描Bundle.main下的.lproj(排除Base.lproj)并排序返回 - 注意:该方法包含文件 I/O,调用方应缓存结果,避免高频扫描
Bundle.st_localizedString(key:tableName:):优先使用当前自定义语言包,否则回退到Bundle.mainString.localized/String.localized(tableName:):字符串快捷调用
Bundle.st_setCustomLanguage(_:):切换语言代码(例如zh-Hans、en)Bundle.st_setSupportedLanguage(_:):用STSupportedLanguage对象切换Bundle.st_clearCustomLanguage():清除自定义语言并恢复“跟随系统”Bundle.st_getCurrentLanguage()/st_getCurrentLanguageObject():获取当前自定义语言Bundle.st_getSystemLanguage():读取系统首选语言Bundle.st_isLanguageAvailable(_:):校验目标语言包是否存在
- 通知名:
Notification.Name.stLanguageDidChange - 触发时机:
- 设置自定义语言成功后发送
- 清除自定义语言后发送
object约定:- 设置语言时为
languageCode - 清除语言时为
nil
- 设置语言时为
- 入口:
Bundle.st_configureLocalization() - 推荐时机:
application(_:didFinishLaunchingWithOptions:) - 行为顺序:
- 安装
Bundle.localizedString方法替换(仅一次) - 恢复上次保存的自定义语言(若可用)
- 若无有效持久化值,则按系统语言匹配可用语言
- 若仍未匹配到,则回退到可用语言列表首项
- 安装
- 模块通过
method_exchangeImplementations替换Bundle.localizedString(forKey:value:table:) - 仅对
Bundle.main生效 - 自定义语言包通过 Associated Object 挂在
Bundle.main上 - 目的:保证包含
NSLocalizedString在内的主 bundle 字符串读取都自动走当前语言包
对应文件:STViewControllerLocalization.swift
- 扩展对象:
STBaseViewController - 核心方法:
st_updateLocalizedTexts() - 刷新内容:
- 导航标题(
titleLabel.text) navigationItem.prompt- 当前页面视图树内所有实现了
STLocalizable的视图
- 导航标题(
- 使用 Associated Object 记录原始 key:
st_vcTitleKeyst_navPromptKey
- 目的:避免语言切换后把“已翻译字符串”当成下一次翻译 key,导致二次切换失效
- 私有方法
updateLocalizedTextsInView(_:)递归遍历view.subviews - 对命中
STLocalizable的视图调用st_updateLocalizedText() - 这样可覆盖页面中已挂载的控件层级
- 在 App 启动阶段调用
Bundle.st_configureLocalization()。 - 页面继承
STBaseViewController,确保接入语言切换通知链路。 - 自定义控件实现
STLocalizable,并在st_updateLocalizedText()中按 key 刷新文案。 - 业务切换语言时统一调用
Bundle.st_setCustomLanguage(_:)或Bundle.st_setSupportedLanguage(_:)。 - 若要恢复系统语言,调用
Bundle.st_clearCustomLanguage()。
st_setCustomLanguage(_:)传入不存在的语言包时会打印告警并直接返回,不会发送变更通知。- 可用语言扫描依赖
Bundle.main的.lproj,如果业务资源放在其他 bundle,需要额外扩展策略。 - 该模块默认表名是
Localizable,如业务使用多表,应显式传入tableName。 - 语言切换后的 UI 刷新依赖页面和控件实现约定;未实现
STLocalizable的视图不会自动更新文本。