Files
his/md/architecture/MULTILANG_I18N_DESIGN.md
chenqi 83f340b6bb feat(i18n): 实现门诊增强和门诊财务国际化功能
- 在门诊增强页面添加表格列的国际化标签
- 在门诊增强页面添加操作按钮的国际化文本
- 在门诊财务日结结算页面实现表单字段的国际化
- 在门诊财务日结结算页面实现表格列标题的国际化
- 在门诊财务日结结算页面添加操作按钮的国际化
- 集成 vue-i18n 并在组件中使用国际化方法
- 更新日结详情提示消息为国际化文本
- 实现导出文件名和成功消息的国际化
2026-06-28 06:58:53 +08:00

654 lines
22 KiB
Markdown

# HealthLink-HIS 多语言(i18n)技术方案
> **文档类型**: 架构设计
> **版本**: V1.0
> **日期**: 2026-06-24
> **作者**: zhugeliang(架构师)
> **状态**: 待确认
---
## 一、现状分析
### 1.1 后端现状
| 项目 | 值 |
|------|------|
| Spring Boot 版本 | 4.0.6 |
| 已有 i18n 基础 | `I18nConfig` (SessionLocaleResolver + LocaleChangeInterceptor, lang参数) |
| 已有 i18n 资源 | `i18n/messages.properties` + `i18n/messages_zh_CN.properties` (56行) |
| MessageUtils | 已封装 `MessageUtils.message(code, args)` 静态方法 |
| 消息键体系 | `PromptMsgConstant` (150+ key, 10个模块接口) |
| 硬编码中文错误 | **~851处** `R.fail("中文")` 散落在各 Controller/AppService |
| 数据库枚举值 | 状态值以数字存储, 前端映射显示 |
**核心问题**:
- 后端已有 i18n 基础设施, 但只用了 ~56 条消息, 远不够覆盖
- 大量业务错误消息硬编码为中文字符串 (`R.fail("中文")`)
- `PromptMsgConstant` 有 150+ 消息键, 但只有 zh_CN 翻译
### 1.2 前端现状
| 项目 | 值 |
|------|------|
| 技术栈 | Vue 3 + Vite + Element Plus + Pinia |
| 页面数量 | ~200+ `.vue` 文件 |
| ElMessage/ElNotification 调用 | **~2109处** (仅 views/) |
| 路由标题 | `meta.title` 硬编码中文 |
| 侧边栏/菜单 | `meta.title` 从数据库动态加载 |
| 布局组件 | Navbar/Sidebar/Settings 中有硬编码中文 |
| Element Plus 组件 | el-dialog title, el-button label, el-table column label 等 |
| 已有 i18n 方案 | **无** (未安装 vue-i18n) |
**核心问题**:
- 零 i18n 基础, 所有中文硬编码在 .vue 文件中
- Element Plus 自身也是中文 (需配置 locale)
- 菜单标题来自数据库, 需要数据库层面的多语言支持
### 1.3 移动端现状
| 项目 | 值 |
|------|------|
| 技术栈 | Vue 3 + Vite + Element Plus |
| 页面数量 | 14 个 .vue 文件 |
| 已有 i18n 方案 | **无** |
---
## 二、方案设计
### 2.1 总体架构
```
┌─────────────────────────────────────┐
│ 语言选择器 (全局) │
│ Cookie/Session 存储当前语言 │
└──────────┬──────────────────────────┘
┌────────────────┼────────────────┐
▼ ▼ ▼
┌───────────┐ ┌──────────────┐ ┌──────────────┐
│ zh_CN (默认)│ │ en_US (英语) │ │ vi_VN (越南语) │
└───────────┘ └──────────────┘ └──────────────┘
│ │ │
┌─────┴────────────────┴────────────────┴─────┐
│ │
┌────┴────┐ ┌──────┴──────┐
│ 前端 i18n │ │ 后端 i18n │
│ vue-i18n │ │ MessageSource│
└────┬────┘ └──────┬──────┘
│ │
▼ ▼
JSON 语言包文件 Properties 资源文件
(src/locales/) (i18n/messages_*.properties)
```
### 2.2 核心技术选型
#### 前端
| 方案 | 选择 | 理由 |
|------|------|------|
| i18n 库 | **vue-i18n v9** | Vue 3 官方推荐, 生态成熟, 与 Element Plus 完美集成 |
| 语言包格式 | **JSON** | 易编辑、易翻译、易从数据库导出、易做 CI/CD 检查 |
| 语言切换 | **Cookie** | 持久化, 刷新不丢失, 与后端 SessionLocaleResolver 保持一致 |
| Element Plus | **动态切换 locale** | `el-config-provider` + `setLocale` API |
#### 后端
| 方案 | 选择 | 理由 |
|------|------|------|
| i18n 引擎 | **Spring MessageSource (已有)** | 无需新增依赖, 已有 `I18nConfig` + `MessageUtils` |
| 资源文件格式 | **Properties** | Spring Boot 原生支持, 已有基础 |
| 语言切换 | **Cookie/Header (新增)** | 保持向后兼容, 同时支持 `lang` query param |
#### 数据库 (菜单/字典多语言)
| 方案 | 选择 | 理由 |
|------|------|------|
| 菜单多语言 | **新建 `sys_menu_i18n` 表** | 不修改已有 `sys_menu` 表结构, 零侵入 |
| 字典多语言 | **新建 `sys_dict_type_i18n` + `sys_dict_data_i18n` 表** | 字典数据量大, 独立表便于管理 |
| 业务数据多语言 | **暂不支持** | 患者名、诊断名等业务数据不需多语言 |
---
## 三、详细设计
### 3.1 前端实现
#### 3.1.1 目录结构
```
healthlink-his-ui/src/
├── locales/ # 语言包目录
│ ├── index.js # vue-i18n 配置 + 导出
│ ├── zh_CN.js # 简体中文 (基于现有硬编码提取)
│ ├── en_US.js # English
│ └── vi_VN.js # Tiếng Việt
├── plugins/
│ └── i18n.js # vue-i18n 插件初始化
├── store/modules/
│ ├── app.js # ← 新增: language 状态
│ └── settings.js # ← 新增: language 配置
├── layout/
│ └── components/
│ └── LanguageSwitcher.vue # 新增: 语言切换下拉组件
├── utils/
│ └── request.js # ← 修改: 请求头带 Accept-Language
└── ...views/** # ← 批量修改: 硬编码中文 → $t('key')
```
#### 3.1.2 语言包结构设计
```javascript
// locales/zh_CN.js 结构示例
export default {
// 系统通用
common: {
confirm: '确认',
cancel: '取消',
save: '保存',
delete: '删除',
edit: '编辑',
add: '新增',
search: '搜索',
export: '导出',
import: '导入',
reset: '重置',
submit: '提交',
close: '关闭',
tip: '提示',
success: '操作成功',
fail: '操作失败',
loading: '加载中...',
noData: '暂无数据',
},
// 登录/认证
auth: {
login: '登录',
username: '用户名',
password: '密码',
captcha: '验证码',
loginSuccess: '登录成功',
logout: '退出登录',
tokenExpired: '登录已过期,请重新登录',
},
// 系统管理
system: {
userManage: '用户管理',
roleManage: '角色管理',
menuManage: '菜单管理',
deptManage: '部门管理',
dictManage: '字典管理',
},
// 门诊挂号
registration: {
outpatientReg: '门诊挂号',
patientSearch: '患者检索',
registerSuccess: '挂号成功',
refund: '退号',
refundSuccess: '退号成功',
},
// 消息提示 (对应后端 PromptMsgConstant)
msgs: {
addSuccess: '{0}添加成功',
saveSuccess: '{0}保存成功',
deleteSuccess: '{0}删除成功',
operationSuccess: '{0}操作成功',
alreadyExists: '{0}已经存在',
operationFailed: '操作失败,请联系管理员',
dataDeletedByOthers: '操作失败,该数据已被他人删除,请刷新后重试',
dataModifiedByOthers: '操作失败,该数据已被他人更改,请刷新后重试',
noDuplicateSubmit: '请勿重复提交',
querySuccess: '查询成功',
},
// 菜单标题 (与 sys_menu 的 menu_name 对应, 用于前端硬编码部分)
menus: {
dashboard: '首页',
patientManage: '患者管理',
registration: '挂号收费',
outpatient: '门诊管理',
inpatient: '住院管理',
pharmacy: '药品管理',
// ... 所有菜单项
},
// Element Plus 组件
element: {
pagination: {
total: '共 {total} 条',
pageSize: '每页 {pageSize} 条',
validator: '每页 {n} 条,至少 1 条',
},
table: {
emptyText: '暂无数据',
},
dialog: {
confirm: '确定',
cancel: '取消',
},
upload: {
exceedSize: '上传文件大小超出限制',
fileNameExceedLength: '上传的文件名最长 {0} 个字符',
},
},
}
```
#### 3.1.3 前端改造策略
**Phase 1 — 基础设施 (不破坏现有功能)**
1. 安装 `vue-i18n@9`
2. 创建 `locales/` 目录和 `zh_CN.js` (先搬运现有中文)
3. 配置 `plugins/i18n.js`
4. 修改 `main.js` 引入 i18n
5. 修改 `request.js` 添加 `Accept-Language` 请求头
6. 新增 `LanguageSwitcher.vue` 组件
7. 修改 `app.js` store 增加 `language` 状态
**Phase 2 — 核心页面改造 (逐步推进)**
8. 登录页 `views/login.vue` → 全部 $t()
9. 布局组件 `layout/**` → 全部 $t()
10. 系统管理模块 `views/system/**` → 全部 $t()
11. 门诊模块 `views/charge/**`, `views/doctorstation/**` → 全部 $t()
12. 住院模块 `views/inpatientNurse/**` → 全部 $t()
13. 药品模块 `views/drug/**`, `views/pharmacy*/**` → 全部 $t()
14. 其余模块依次推进
**Phase 3 — 辅助功能**
15. Element Plus 组件语言包切换
16. 路由 meta.title 多语言化
17. 表单校验提示国际化 (Element Plus form rules)
#### 3.1.4 语言切换流程
```
用户点击 LanguageSwitcher
Cookie.set('language', 'en_US')
Pinia store.app.language = 'en_US'
vue-i18n.global.locale.value = 'en_US'
Element Plus setLocale(en)
Axios 请求头: Accept-Language: en-US
页面响应式更新 (所有 $t() 自动重新渲染)
```
### 3.2 后端实现
#### 3.2.1 资源文件扩展
```
healthlink-his-application/src/main/resources/i18n/
├── messages.properties # 默认 (英文 fallback)
├── messages_zh_CN.properties # 中文 (现有, 扩充)
├── messages_en_US.properties # 英文 (新建)
└── messages_vi_VN.properties # 越南语 (新建)
```
#### 3.2.2 消息分类体系
```
# 1. 系统通用 (已有, 扩充)
apl.common.M00001 = {0} added successfully
apl.common.M00002 = {0} saved successfully
...
# 2. 用户认证
auth.login.success = Login successful
auth.user.not.exists = User does not exist / Incorrect password
auth.password.retry.limit.count = Password entered incorrectly {0} times
...
# 3. 文件上传
upload.exceed.maxSize = Upload file size exceeds limit
...
# 4. 权限
no.permission = You do not have permission for [{0}]
...
# 5. 挂号收费 (registration/payment)
apl.payment.M00001 = Actual payment amount does not match expected
apl.payment.M00003 = Please select a payment method
...
# 6. 药品管理 (pharmacy)
apl.pharmacy.outOfStock = Insufficient inventory for {0}
apl.pharmacy.dispenseSuccess = Dispensing successful
...
# 7. 住院管理 (inpatient)
...
# 8. 检查检验 (check/lab)
...
# 9. 手术麻醉 (surgery/anesthesia)
...
# 10. 电子病历 (emr)
...
# 11. 护理管理 (nursing)
...
# 12. 医保 (yb)
...
```
#### 3.2.3 硬编码消息迁移策略
**优先级 P0 — 高频路径** (登录、挂号、退号、缴费、退药)
- `SysLoginService.java` — 登录相关 ~6处
- `OutpatientRegistrationAppServiceImpl.java` — 挂号/退号 ~10处
- `PaymentRecServiceImpl.java` — 收费/退费 ~30处
**优先级 P1 — 核心业务** (药品、住院、手术、EMR)
- 药房 dispensense/approval ~50处
- 住院登记/结算 ~20处
- 手术管理 ~15处
- EMR 病程记录 ~10处
**优先级 P2 — 其他模块**
- 其余 ~700处按模块逐步迁移
**迁移方式**:
```java
// Before:
return R.fail("请选择调配药师");
// After:
return R.fail(MessageUtils.message("apl.pharmacy.selectDispenser"));
```
#### 3.2.4 语言检测优先级
```
1. Cookie "language" (最高优先级, 持久化)
2. HTTP Header "Accept-Language"
3. Query Param "lang" (已有, 向后兼容)
4. Session 中保存的语言
5. 默认 Locale.SIMPLIFIED_CHINESE
```
新增 `LanguageCookieLocaleResolver` 继承 `SessionLocaleResolver`:
```java
@Bean
public LocaleResolver localeResolver() {
CookieLocaleResolver clr = new CookieLocaleResolver("lang");
clr.setDefaultLocale(Constants.DEFAULT_LOCALE);
clr.setCookieMaxAge(Duration.ofDays(365));
return clr;
}
```
### 3.3 数据库多语言
#### 3.3.1 sys_menu_i18n 表
```sql
CREATE TABLE IF NOT EXISTS sys_menu_i18n (
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
menu_id BIGINT NOT NULL REFERENCES sys_menu(menu_id),
lang_code VARCHAR(10) NOT NULL, -- 'zh_CN', 'en_US', 'vi_VN'
menu_name VARCHAR(100) NOT NULL,
UNIQUE(menu_id, lang_code)
);
COMMENT ON TABLE sys_menu_i18n IS '菜单多语言表';
COMMENT ON COLUMN sys_menu_i18n.menu_id IS '关联 sys_menu.menu_id';
COMMENT ON COLUMN sys_menu_i18n.lang_code IS '语言代码';
COMMENT ON COLUMN sys_menu_i18n.menu_name IS '菜单名称(多语言)';
```
**查询逻辑**:
```sql
-- 优先取当前语言, 回退到中文, 再回退到默认
SELECT COALESCE(
(SELECT menu_name FROM sys_menu_i18n WHERE menu_id = m.menu_id AND lang_code = 'en_US'),
(SELECT menu_name FROM sys_menu_i18n WHERE menu_id = m.menu_id AND lang_code = 'zh_CN'),
m.menu_name
) AS menu_name
FROM sys_menu m;
```
#### 3.3.2 sys_dict_data_i18n 表
```sql
CREATE TABLE IF NOT EXISTS sys_dict_data_i18n (
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
dict_code BIGINT NOT NULL,
dict_sort INT NOT NULL,
lang_code VARCHAR(10) NOT NULL,
dict_label VARCHAR(100) NOT NULL,
dict_value VARCHAR(100) NOT NULL,
css_class VARCHAR(100),
list_class VARCHAR(100),
is_default CHAR(1) DEFAULT 'N',
UNIQUE(dict_code, dict_sort, lang_code)
);
COMMENT ON TABLE sys_dict_data_i18n IS '字典数据多语言表';
```
#### 3.3.3 字典类型 i18n
```sql
CREATE TABLE IF NOT EXISTS sys_dict_type_i18n (
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
dict_id BIGINT NOT NULL REFERENCES sys_dict_type(dict_id),
lang_code VARCHAR(10) NOT NULL,
dict_name VARCHAR(100) NOT NULL,
dict_type VARCHAR(100) NOT NULL,
UNIQUE(dict_id, lang_code)
);
COMMENT ON TABLE sys_dict_type_i18n IS '字典类型多语言表';
```
---
## 四、实施计划
### Sprint 1: 基础设施搭建 (预计 2-3 天)
| 任务 | 模块 | 工作量 | 负责人 |
|------|------|--------|--------|
| T1.1 安装 vue-i18n@9 | 前端 | 0.5h | 赵云 |
| T1.2 创建 locales/ 目录结构 + zh_CN.js | 前端 | 2h | 赵云 |
| T1.3 配置 plugins/i18n.js + main.js 集成 | 前端 | 1h | 赵云 |
| T1.4 扩展后端 messages_zh_CN.properties | 后端 | 2h | 关羽 |
| T1.5 创建 messages_en_US.properties (翻译 P0 消息) | 后端 | 3h | 关羽 |
| T1.6 创建 messages_vi_VN.properties (翻译 P0 消息) | 后端 | 3h | 关羽 |
| T1.7 改造 I18nConfig 支持 Cookie + Header | 后端 | 1h | 关羽 |
| T1.8 新增 LanguageSwitcher.vue 组件 | 前端 | 1h | 赵云 |
| T1.9 修改 request.js 添加 Accept-Language | 前端 | 0.5h | 赵云 |
| T1.10 编译验证 + 冒烟测试 | 全栈 | 1h | 张飞 |
**产出**: 语言切换功能可用, 登录页/布局组件中英文切换
### Sprint 2: 核心模块国际化 (预计 3-4 天)
| 任务 | 模块 | 工作量 | 负责人 |
|------|------|--------|--------|
| T2.1 登录页 login.vue 全部 $t() | 前端 | 2h | 赵云 |
| T2.2 布局组件 (Navbar/Sidebar/Settings) 全部 $t() | 前端 | 3h | 赵云 |
| T2.3 Element Plus 组件语言包切换 | 前端 | 2h | 赵云 |
| T2.4 系统管理模块 views/system/** 全部 $t() | 前端 | 4h | 赵云 |
| T2.5 后端 P0 消息全部翻译 (auth/payment/upload/permission) | 后端 | 3h | 关羽 |
| T2.6 后端硬编码迁移 P0 (SysLoginService, Registration, Payment) | 后端 | 4h | 关羽 |
| T2.7 Flyway 迁移: sys_menu_i18n + sys_dict_*_i18n 表 | DBA | 1h | 荀彧 |
| T2.8 菜单/字典 Service 层支持多语言查询 | 后端 | 3h | 关羽 |
| T2.9 编译验证 + 冒烟测试 | 全栈 | 1h | 张飞 |
**产出**: 系统管理 + 登录 + 布局 中英文/越语可用
### Sprint 3: 业务模块国际化 (预计 5-7 天)
| 任务 | 模块 | 工作量 | 负责人 |
|------|------|--------|--------|
| T3.1 门诊模块 (charge/doctorstation) 全部 $t() | 前端 | 6h | 赵云 |
| T3.2 门诊模块后端硬编码迁移 | 后端 | 4h | 关羽 |
| T3.3 门诊模块消息翻译 (en_US + vi_VN) | 后端 | 4h | 关羽 |
| T3.4 住院模块 (inpatientNurse) 全部 $t() | 前端 | 5h | 赵云 |
| T3.5 住院模块后端硬编码迁移 | 后端 | 3h | 关羽 |
| T3.6 住院模块消息翻译 (en_US + vi_VN) | 后端 | 3h | 关羽 |
| T3.7 药品模块 (drug/pharmacy) 全部 $t() | 前端 | 5h | 赵云 |
| T3.8 药品模块后端硬编码迁移 | 后端 | 4h | 关羽 |
| T3.9 药品模块消息翻译 (en_US + vi_VN) | 后端 | 3h | 关羽 |
| T3.10 EMR/病历模块 全部 $t() | 前端 | 4h | 赵云 |
| T3.11 EMR 后端硬编码迁移 | 后端 | 2h | 关羽 |
| T3.12 EMR 消息翻译 (en_US + vi_VN) | 后端 | 2h | 关羽 |
| T3.13 其余模块 (检验/检查/手术/护理/质控...) 全部 $t() | 前端 | 10h | 赵云 |
| T3.14 其余模块后端硬编码迁移 | 后端 | 8h | 关羽 |
| T3.15 其余模块消息翻译 (en_US + vi_VN) | 后端 | 8h | 关羽 |
| T3.16 路由 meta.title 多语言化 | 前端 | 2h | 赵云 |
| T3.17 表单校验提示国际化 | 前端 | 2h | 赵云 |
| T3.18 编译验证 + 全模块冒烟测试 | 全栈 | 2h | 张飞 |
**产出**: 全模块中英文/越语可用
### Sprint 4: 移动端 + 验收 (预计 2-3 天)
| 任务 | 模块 | 工作量 | 负责人 |
|------|------|--------|--------|
| T4.1 移动端 healthlink-his-mobile 安装 vue-i18n | 移动端 | 0.5h | 赵云 |
| T4.2 移动端 14 个页面全部 $t() | 移动端 | 4h | 赵云 |
| T4.3 移动端语言切换器 | 移动端 | 1h | 赵云 |
| T4.4 全模块端到端测试 (中文→英文→越语) | 测试 | 2h | 张飞 |
| T4.5 性能测试 (语言切换不卡顿) | 测试 | 1h | 张飞 |
| T4.6 验收 + 文档更新 | 华佗 | 1h | 华佗 |
---
## 五、工作量估算
| 阶段 | 前端 | 后端 | DBA | 测试 | 总计 |
|------|------|------|-----|------|------|
| Sprint 1 | 5h | 10h | 0 | 0 | 15h |
| Sprint 2 | 12h | 11h | 1h | 0 | 24h |
| Sprint 3 | 37h | 29h | 0 | 0 | 66h |
| Sprint 4 | 6h | 0 | 0 | 3h | 9h |
| **合计** | **60h** | **50h** | **1h** | **3h** | **~114h (约 2-3 周)** |
---
## 六、风险与应对
| 风险 | 影响 | 应对 |
|------|------|------|
| 2109+ 处前端硬编码修改量大 | 前端工作量大 | 分批推进, 优先核心模块, 非核心可延后 |
| 851+ 处后端硬编码迁移 | 后端工作量大 | 按模块优先级分批迁移, P0→P1→P2 |
| 数据库菜单/字典数据量大 | 迁移困难 | 提供 SQL 脚本自动从现有数据初始化 |
| 翻译质量 (越南语) | 用户体验差 | 先机器翻译, 上线后逐步人工校对 |
| 语言包文件过大 | 加载性能 | 按需加载 (lazy load), 分包加载 |
| 第三方组件未国际化 | 部分中文残留 | Element Plus 已支持, 其他按需处理 |
| 动态路由菜单多语言 | 需改后端 | 菜单查询 SQL 增加 COALESCE 回退逻辑 |
---
## 七、扩展性设计
### 7.1 新增语言只需 3 步
1. 创建 `locales/{langCode}.js` (前端) + `messages_{langCode}.properties` (后端)
2.`locales/index.js` 注册新语言
3.`I18nConfig` 中确认默认值 (无需改动)
### 7.2 翻译管理工具 (可选增强)
后续可接入:
- **Crowdin / Lokalise**: 在线翻译协作平台
- **xliff-js**: 导出/导入 XLIFF 格式
- 自定义脚本: 从 `.vue` 文件自动提取所有中文, 生成翻译模板
### 7.3 数据库多语言扩展
如需其他业务表多语言 (如科室名称、诊断名称), 可按相同模式扩展:
```sql
-- 通用多语言表模板
CREATE TABLE {table}_i18n (
id BIGINT PRIMARY KEY,
source_id BIGINT NOT NULL,
lang_code VARCHAR(10) NOT NULL,
field_name VARCHAR(100) NOT NULL,
field_value TEXT NOT NULL,
UNIQUE(source_id, lang_code, field_name)
);
```
---
## 八、验证标准
### 8.1 功能验证
- [ ] 语言切换器正常显示 (中/英/越)
- [ ] 切换后页面所有中文文本变为对应语言
- [ ] 刷新页面后语言设置保持 (Cookie)
- [ ] Element Plus 组件 (分页/弹窗/表格/表单) 均为对应语言
- [ ] 后端 API 返回的错误消息为当前语言
- [ ] 登录页、系统管理、门诊、住院、药品、EMR 等核心模块全部覆盖
- [ ] 移动端 14 个页面全部支持多语言
### 8.2 兼容性验证
- [ ] 不传 lang 参数时默认中文 (向后兼容)
- [ ] 现有前端页面不因 i18n 改造而样式错乱
- [ ] 数据库菜单查询多语言回退正常 (无翻译 → 显示中文 → 显示默认)
- [ ] 编译无 ERROR, 无新增 WARNING
### 8.3 性能验证
- [ ] 语言切换响应 < 100ms
- [ ] 首屏加载时间增加 < 50KB (gzip)
- [ ] 无明显内存泄漏
---
## 九、附录
### A. 前端需提取的中文文本类型
1. **ElMessage** 提示文本 (~2109处)
2. **ElMessageBox** 确认/提示文本
3. **el-dialog** title 属性
4. **el-button** 文本内容
5. **el-table** column label
6. **el-form** label / placeholder / 校验提示
7. **路由 meta.title** (部分硬编码)
8. **布局组件** 中的固定文本 (Sidebar/Navbar/Settings)
9. **Element Plus** 自身组件文本 (pagination/table/dialog)
10. **页面标题** h1/h2
### B. 后端需迁移的硬编码消息类型
1. **R.fail("中文")** 业务错误 (~851处)
2. **R.ok(data, "中文")** 成功消息 (~150处, 已有 PromptMsgConstant 覆盖)
3. **Service 层抛出的 ServiceException** 异常消息
4. **日志中的中文** 可选, 生产日志建议英文
### C. 消息键命名规范
```
{模块}.{子类}.{编号}
示例:
apl.common.M00001 → APL 通用消息
auth.login.success → 认证-登录-成功
payment.collect.fail → 收费-缴费-失败
pharmacy.dispense.select_pharmacist → 药品-发药-选择药师
registration.refund.success → 挂号-退号-成功
```