Android 语言切换:硬编码 UI 文本修复实录

Android App 语言切换功能已实现(BaseApplication + attachBaseContext 管道正常),但界面文本硬编码为英文,导致切换语言后 UI 仍显示英文。本文记录 presentation layer 的修复过程。

问题背景

[!bug] 症状描述
语言切换后,底部 Tab 仍然显示 HOMEME,”我的”页面仍然显示 SettingsAbout Us 等英文文本。但 AppLanguage 日志显示 stored=zh applied=zh,说明语言切换的核心管道没有问题。

根因:布局文件(XML)和 Kotlin 代码中存在大量硬编码英文字符串,未使用 @string 资源引用,导致语言切换后文本不跟随。

硬编码文本 vs 资源引用对比
图 1:硬编码文本(左)与资源引用(右)对比


技术分析

Android i18n 架构

Android 的多语言支持依赖 strings.xml 资源文件。正确的实现方式是:

1
2
3
4
5
<!-- values/strings.xml -->
<string name="mine_settings">Settings</string>

<!-- values-zh/strings.xml -->
<string name="mine_settings">设置</string>

在布局文件中引用:

1
<TextView android:text="@string/mine_settings" />

在 Kotlin 代码中引用:

1
text = getString(R.string.mine_settings)

硬编码文本的两大来源

来源 文件 影响
布局文件 fragment_mine.xmlactivity_main.xml 静态文本,XML 中直接写死
Kotlin 代码 MainActivity.ktHistoryActivity.ktSettingActivity.kt 运行时动态设置的文本

修复方案

[!tip] 修复策略
保持 BaseApplication + attachBaseContext 语言管道不变,聚焦 presentation layer:添加 32 个本地化字符串资源,替换 8 个布局文件 + 3 个 Kotlin 文件中的硬编码文本。

i18n 修复三步流程
图 2:修复流程——添加资源 → 替换 XML → 替换 Kotlin 代码

Step 1:添加字符串资源

新增 32 个字符串资源键,覆盖所有硬编码文本:

资源文件 新增键数
values/strings.xml 32 键(英文默认值)
values-zh/strings.xml 32 键(中文翻译)
values-en/strings.xml 32 键(英文镜像)

核心资源键示例

1
2
3
4
5
6
7
8
9
10
<!-- Main Tab -->
<string name="main_tab_home">HOME</string>
<string name="main_tab_me">ME</string>

<!-- Mine Fragment -->
<string name="mine_reading_novels">Novel being read</string>
<string name="mine_settings">Settings</string>

<!-- Settings Activity -->
<string name="settings_clear_cache_confirm">Are you sure you want to clear the local cache?</string>

Step 2:替换布局文件硬编码文本

文件 替换数量
fragment_mine.xml 10 处
activity_main.xml 1 处
tab_item_badge.xml 1 处
fragment_msg.xml 1 处
activity_about.xml 1 处
activity_histery.xml 2 处
activity_contact.xml 2 处
activity_setting.xml 7 处

修改示例fragment_mine.xml):

1
2
3
4
5
<!-- 修改前 -->
<TextView android:text="Settings" ... />

<!-- 修改后 -->
<TextView android:text="@string/mine_settings" ... />

Step 3:替换 Kotlin 运行时硬编码文本

MainActivity.kt —— Tab 标签列表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 修改前
private var mStringList = mutableListOf("HOME","Classification", "","Message", "ME")

// 修改后
lateinit var mTabTitles: List<String>

override fun initView() {
mTabTitles = listOf(
getString(R.string.main_tab_home),
getString(R.string.main_tab_classification),
"",
getString(R.string.main_tab_message),
getString(R.string.main_tab_me)
)
}

HistoryActivity.kt —— Toast 和 Toolbar 文本:

1
2
3
4
5
6
7
// 修改前
toastSuccess("Deleted successfully")
mDataBinding.toolbar.getRightText().text = "Edit"

// 修改后
toastSuccess(getString(R.string.history_delete_success))
mDataBinding.toolbar.getRightText().text = getString(R.string.history_edit)

SettingActivity.kt —— 对话框文本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 修改前
pop.showLogoPop(
"Are you sure you want to clear the local cache?",
"Cancel",
"Confirm",
...
)

// 修改后
pop.showLogoPop(
getString(R.string.settings_clear_cache_confirm),
getString(R.string.common_cancel),
getString(R.string.common_confirm),
...
)

验证结果

构建验证

1
2
.\gradlew.bat --no-daemon :app:compileDebugKotlin
# BUILD SUCCESSFUL

USB 真机验证

日志验证(确认语言已正确应用):

1
2
AppLanguage: SettingActivity stored=zh applied=zh
AppLanguage: MainActivity stored=zh applied=zh

UI Dump 验证(确认中文文本正确显示):

1
2
3
4
<!-- 切换为中文后 -->
我的 / 阅读中的小说 / 已读完小说 / 我的 OKEX 金币 / 推荐奖励
会员中心 / 浏览历史 / 关于我们 / 联系客服 / 设置
首页 / 分类 / 书库 / 消息

真机测试中文 UI 验证
图 3:真机测试——中文文本正确显示


修改文件汇总

文件 改动类型 说明
app/src/main/res/values/strings.xml 新增 32 个英文资源键
app/src/main/res/values-zh/strings.xml 新增 32 个中文翻译
app/src/main/res/values-en/strings.xml 新增 32 个英文镜像
fragment_mine.xml 修改 10 处文本替换
activity_main.xml 修改 1 处文本替换
tab_item_badge.xml 修改 1 处文本替换
fragment_msg.xml 修改 1 处文本替换
activity_about.xml 修改 1 处文本替换
activity_histery.xml 修改 2 处文本替换
activity_contact.xml 修改 2 处文本替换
activity_setting.xml 修改 7 处文本替换
MainActivity.kt 修改 Tab 标签运行时本地化
HistoryActivity.kt 修改 Toast/Toolbar 本地化
SettingActivity.kt 修改 对话框文本本地化

经验总结

[!warning] 注意事项

  • XML 布局文件中的文本也要走资源引用,不能直接写死英文
  • Kotlin 代码中动态设置的文本List/Array 等初始化必须使用 getString(R.string.xxx),而非直接硬编码
  • 资源键命名规范{页面}_{功能}_{描述},如 mine_settingshistory_delete_success

相关文档

  • [[语言切换硬编码UI文本修复/需求分析]](Obsidian 内部链接)
  • [[语言切换硬编码UI文本修复/实现方案]]

本文使用 Hexo + icarus 主题构建,配图由 MiniMax Image-01 生成。