approve: 元景测试环境部署(scene 应用,补齐 env/test.json + 真实部署 + 冒烟)
This commit is contained in:
parent
b2db4764e2
commit
6f270ed663
68
docs/i18n.md
Normal file
68
docs/i18n.md
Normal file
@ -0,0 +1,68 @@
|
||||
# entity 模块 i18n 提取说明(W-03 实体管理)
|
||||
|
||||
本文件是 entity 模块**新文案 i18n 提取清单与引用约定**,覆盖两个新增页面
|
||||
(`wwwroot/index.ui`、`wwwroot/import_page.ui`)及后端错误码/按钮等全部新文案。
|
||||
|
||||
## 1. i18n 文件清单
|
||||
|
||||
| 文件 | 语言 | 内容 |
|
||||
|------|------|------|
|
||||
| `wwwroot/i18n/zh-CN.json` | 简体中文 | 全部 UI 文案 + 错误码文案 + 字典文案 |
|
||||
| `wwwroot/i18n/en-US.json` | 英文 | 与 zh-CN 键一一对应 |
|
||||
|
||||
i18n 文件与页面同置于 `wwwroot/` 下,宿主应用加载时按当前语言读取对应 json,
|
||||
键缺失时回退到 `zh-CN.json`,仍缺失则显示键名本身(不阻塞页面)。
|
||||
|
||||
## 2. 键命名规则(扁平点分,前缀 entity.)
|
||||
|
||||
| 前缀 | 用途 | 示例 |
|
||||
|------|------|------|
|
||||
| `entity.page.*` | 页面标题/副标题 | `entity.page.index.title` |
|
||||
| `entity.btn.*` | 按钮文案 | `entity.btn.add` |
|
||||
| `entity.col.*` | 表格列头 | `entity.col.name` |
|
||||
| `entity.filter.*` | 筛选区标签/占位 | `entity.filter.world_id` |
|
||||
| `entity.form.*` | 新增/编辑表单标签 | `entity.form.code` |
|
||||
| `entity.import.*` | 导入页专用文案 | `entity.import.col.total` |
|
||||
| `entity.msg.*` | 操作提示/消息 | `entity.msg.confirm_delete` |
|
||||
| `entity.dict.*` | 字典下拉(entity_type / entity_status / import_status) | `entity.dict.entity_type.npc` |
|
||||
| `entity.err.*` | 后端错误码→文案映射 | `entity.err.DUPLICATE_CODE` |
|
||||
| `entity.field.*` | 错误码文案中的字段标签占位 | `entity.field.name` |
|
||||
|
||||
## 3. 页面引用方式
|
||||
|
||||
- `index.ui`(实体列表页):标题/按钮/列头/筛选/表单/提示全部使用
|
||||
`entity.page.index.title`、`entity.btn.add`、`entity.col.name` 等键,经宿主
|
||||
i18n 函数取文案,禁止硬编码中文。
|
||||
- `import_page.ui`(实体导入页):使用 `entity.page.import.*`、`entity.import.*`、
|
||||
`entity.btn.*` 键。
|
||||
- 字典下拉(世界/场景/实体类型/状态/导入状态)取值经 `get_search_*.dspy` 返回
|
||||
`[{value,text}]`,其中 `text` 优先取 i18n 文案(`entity.dict.*`),服务端字典
|
||||
值作为兜底。
|
||||
|
||||
## 4. 错误码 → 文案映射约定
|
||||
|
||||
接口统一返回错误结构 `{code, message, field, detail}`。前端展示优先级:
|
||||
1. 取 `entity.err.{code}` 对应 i18n 文案(支持 `{label}`/`{max}` 占位符替换,
|
||||
占位值来自 `field` 对应的 `entity.field.*` 与 `detail`);
|
||||
2. 无映射时回退接口返回的 `message`。
|
||||
|
||||
已提取的错误码(10 个):
|
||||
|
||||
| code | 中文文案 | 英文文案 |
|
||||
|------|----------|----------|
|
||||
| PARAM_REQUIRED | 缺少必要参数 | Missing required parameter |
|
||||
| FIELD_REQUIRED | {label}不能为空 | {label} is required |
|
||||
| FIELD_TOO_LONG | {label}长度不能超过{max} | {label} length cannot exceed {max} |
|
||||
| WORLD_NOT_FOUND | 所属世界不存在 | World not found |
|
||||
| SCENE_NOT_FOUND | 所属场景不存在 | Scene not found |
|
||||
| DUPLICATE_CODE | 实体编码已存在 | Entity code already exists |
|
||||
| PARSE_ERROR | 文件解析失败 | File parse error |
|
||||
| INVALID_JSON | 属性JSON格式错误 | Invalid attributes JSON |
|
||||
| DB_ERROR | 数据库操作失败 | Database operation failed |
|
||||
| NOT_FOUND | 记录不存在 | Record not found |
|
||||
|
||||
## 5. 新增文案流程(维护约定)
|
||||
|
||||
新增任何页面文案/错误码/按钮时:先在 `zh-CN.json` 与 `en-US.json` 同步增加同键
|
||||
条目,再在页面中引用该键。两文件键集合必须保持一致(提交前用脚本比对
|
||||
`jq -S 'keys'` 两文件差异,差异为 0 才允许提交)。
|
||||
96
wwwroot/i18n/en-US.json
Normal file
96
wwwroot/i18n/en-US.json
Normal file
@ -0,0 +1,96 @@
|
||||
{
|
||||
"entity.page.index.title": "Entity Management",
|
||||
"entity.page.index.subtitle": "Entity table CRUD and list query",
|
||||
"entity.page.import.title": "Entity Import",
|
||||
"entity.page.import.subtitle": "Batch import entities from file (JSON Array / JSON Lines / CSV)",
|
||||
"entity.btn.add": "Add",
|
||||
"entity.btn.edit": "Edit",
|
||||
"entity.btn.delete": "Delete",
|
||||
"entity.btn.import": "Import",
|
||||
"entity.btn.refresh": "Refresh",
|
||||
"entity.btn.search": "Search",
|
||||
"entity.btn.reset": "Reset",
|
||||
"entity.btn.save": "Save",
|
||||
"entity.btn.cancel": "Cancel",
|
||||
"entity.btn.confirm": "OK",
|
||||
"entity.btn.choose_file": "Choose File",
|
||||
"entity.btn.start_import": "Start Import",
|
||||
"entity.btn.download_template": "Download Template",
|
||||
"entity.btn.back": "Back",
|
||||
"entity.col.name": "Entity Name",
|
||||
"entity.col.code": "Entity Code",
|
||||
"entity.col.entity_type": "Entity Type",
|
||||
"entity.col.status": "Status",
|
||||
"entity.col.world_id": "World",
|
||||
"entity.col.scene_id": "Scene",
|
||||
"entity.col.attributes_json": "Attributes",
|
||||
"entity.col.created_at": "Created At",
|
||||
"entity.col.updated_at": "Updated At",
|
||||
"entity.col.actions": "Actions",
|
||||
"entity.filter.world_id": "World",
|
||||
"entity.filter.scene_id": "Scene",
|
||||
"entity.filter.entity_type": "Entity Type",
|
||||
"entity.filter.status": "Status",
|
||||
"entity.filter.keyword": "Name/Code Keyword",
|
||||
"entity.filter.placeholder.select": "Select",
|
||||
"entity.filter.placeholder.input": "Input",
|
||||
"entity.form.name": "Entity Name",
|
||||
"entity.form.code": "Entity Code",
|
||||
"entity.form.world_id": "World",
|
||||
"entity.form.scene_id": "Scene",
|
||||
"entity.form.entity_type": "Entity Type",
|
||||
"entity.form.status": "Status",
|
||||
"entity.form.attributes_json": "Attributes (JSON)",
|
||||
"entity.form.placeholder.name": "Enter entity name",
|
||||
"entity.form.placeholder.code": "Enter entity code",
|
||||
"entity.form.placeholder.attributes_json": "e.g. {\"hp\":100,\"atk\":10}",
|
||||
"entity.import.form.world_id": "Target World",
|
||||
"entity.import.form.scene_id": "Target Scene",
|
||||
"entity.import.form.file": "Import File",
|
||||
"entity.import.col.file_name": "File Name",
|
||||
"entity.import.col.total": "Total",
|
||||
"entity.import.col.success": "Success",
|
||||
"entity.import.col.fail": "Fail",
|
||||
"entity.import.col.status": "Import Status",
|
||||
"entity.import.col.created_at": "Imported At",
|
||||
"entity.import.history.title": "Import History",
|
||||
"entity.msg.confirm_delete": "Delete this entity?",
|
||||
"entity.msg.delete_ok": "Deleted successfully",
|
||||
"entity.msg.delete_fail": "Delete failed",
|
||||
"entity.msg.save_ok": "Saved successfully",
|
||||
"entity.msg.save_fail": "Save failed",
|
||||
"entity.msg.importing": "Importing, please wait...",
|
||||
"entity.msg.import_ok": "Import done: {total} total, {success} succeeded, {fail} failed",
|
||||
"entity.msg.import_fail": "Import failed",
|
||||
"entity.msg.file_format_hint": "Supports JSON Array / JSON Lines / CSV (header row)",
|
||||
"entity.msg.file_required": "Please choose an import file first",
|
||||
"entity.msg.no_data": "No data",
|
||||
"entity.msg.loading": "Loading...",
|
||||
"entity.dict.entity_type.npc": "NPC",
|
||||
"entity.dict.entity_type.item": "Item",
|
||||
"entity.dict.entity_type.building": "Building",
|
||||
"entity.dict.entity_type.prop": "Prop",
|
||||
"entity.dict.entity_type.other": "Other",
|
||||
"entity.dict.entity_status.0": "Enabled",
|
||||
"entity.dict.entity_status.1": "Disabled",
|
||||
"entity.dict.import_status.0": "In Progress",
|
||||
"entity.dict.import_status.1": "Success",
|
||||
"entity.dict.import_status.2": "Failed",
|
||||
"entity.err.PARAM_REQUIRED": "Missing required parameter",
|
||||
"entity.err.FIELD_REQUIRED": "{label} is required",
|
||||
"entity.err.FIELD_TOO_LONG": "{label} length cannot exceed {max}",
|
||||
"entity.err.WORLD_NOT_FOUND": "World not found",
|
||||
"entity.err.SCENE_NOT_FOUND": "Scene not found",
|
||||
"entity.err.DUPLICATE_CODE": "Entity code already exists",
|
||||
"entity.err.PARSE_ERROR": "File parse error",
|
||||
"entity.err.INVALID_JSON": "Invalid attributes JSON",
|
||||
"entity.err.DB_ERROR": "Database operation failed",
|
||||
"entity.err.NOT_FOUND": "Record not found",
|
||||
"entity.field.name": "Entity Name",
|
||||
"entity.field.code": "Entity Code",
|
||||
"entity.field.world_id": "World",
|
||||
"entity.field.scene_id": "Scene",
|
||||
"entity.field.entity_type": "Entity Type",
|
||||
"entity.field.status": "Status",
|
||||
"entity.field.attributes_json": "Attributes JSON"
|
||||
}
|
||||
96
wwwroot/i18n/zh-CN.json
Normal file
96
wwwroot/i18n/zh-CN.json
Normal file
@ -0,0 +1,96 @@
|
||||
{
|
||||
"entity.page.index.title": "实体管理",
|
||||
"entity.page.index.subtitle": "实体表(entity)增删改查与列表查询",
|
||||
"entity.page.import.title": "实体导入",
|
||||
"entity.page.import.subtitle": "通过文件批量导入实体(支持 JSON 数组 / JSON Lines / CSV)",
|
||||
"entity.btn.add": "新增",
|
||||
"entity.btn.edit": "编辑",
|
||||
"entity.btn.delete": "删除",
|
||||
"entity.btn.import": "导入",
|
||||
"entity.btn.refresh": "刷新",
|
||||
"entity.btn.search": "查询",
|
||||
"entity.btn.reset": "重置",
|
||||
"entity.btn.save": "保存",
|
||||
"entity.btn.cancel": "取消",
|
||||
"entity.btn.confirm": "确定",
|
||||
"entity.btn.choose_file": "选择文件",
|
||||
"entity.btn.start_import": "开始导入",
|
||||
"entity.btn.download_template": "下载模板",
|
||||
"entity.btn.back": "返回",
|
||||
"entity.col.name": "实体名称",
|
||||
"entity.col.code": "实体编码",
|
||||
"entity.col.entity_type": "实体类型",
|
||||
"entity.col.status": "状态",
|
||||
"entity.col.world_id": "所属世界",
|
||||
"entity.col.scene_id": "所属场景",
|
||||
"entity.col.attributes_json": "属性",
|
||||
"entity.col.created_at": "创建时间",
|
||||
"entity.col.updated_at": "更新时间",
|
||||
"entity.col.actions": "操作",
|
||||
"entity.filter.world_id": "所属世界",
|
||||
"entity.filter.scene_id": "所属场景",
|
||||
"entity.filter.entity_type": "实体类型",
|
||||
"entity.filter.status": "状态",
|
||||
"entity.filter.keyword": "名称/编码关键字",
|
||||
"entity.filter.placeholder.select": "请选择",
|
||||
"entity.filter.placeholder.input": "请输入",
|
||||
"entity.form.name": "实体名称",
|
||||
"entity.form.code": "实体编码",
|
||||
"entity.form.world_id": "所属世界",
|
||||
"entity.form.scene_id": "所属场景",
|
||||
"entity.form.entity_type": "实体类型",
|
||||
"entity.form.status": "状态",
|
||||
"entity.form.attributes_json": "属性(JSON)",
|
||||
"entity.form.placeholder.name": "请输入实体名称",
|
||||
"entity.form.placeholder.code": "请输入实体编码",
|
||||
"entity.form.placeholder.attributes_json": "如 {\"hp\":100,\"atk\":10}",
|
||||
"entity.import.form.world_id": "目标世界",
|
||||
"entity.import.form.scene_id": "目标场景",
|
||||
"entity.import.form.file": "导入文件",
|
||||
"entity.import.col.file_name": "文件名",
|
||||
"entity.import.col.total": "总数",
|
||||
"entity.import.col.success": "成功",
|
||||
"entity.import.col.fail": "失败",
|
||||
"entity.import.col.status": "导入状态",
|
||||
"entity.import.col.created_at": "导入时间",
|
||||
"entity.import.history.title": "导入记录",
|
||||
"entity.msg.confirm_delete": "确认删除该实体?",
|
||||
"entity.msg.delete_ok": "删除成功",
|
||||
"entity.msg.delete_fail": "删除失败",
|
||||
"entity.msg.save_ok": "保存成功",
|
||||
"entity.msg.save_fail": "保存失败",
|
||||
"entity.msg.importing": "导入中,请稍候...",
|
||||
"entity.msg.import_ok": "导入完成:共 {total} 条,成功 {success} 条,失败 {fail} 条",
|
||||
"entity.msg.import_fail": "导入失败",
|
||||
"entity.msg.file_format_hint": "支持 JSON 数组 / JSON Lines / CSV(首行表头)",
|
||||
"entity.msg.file_required": "请先选择导入文件",
|
||||
"entity.msg.no_data": "暂无数据",
|
||||
"entity.msg.loading": "加载中...",
|
||||
"entity.dict.entity_type.npc": "NPC",
|
||||
"entity.dict.entity_type.item": "物品",
|
||||
"entity.dict.entity_type.building": "建筑",
|
||||
"entity.dict.entity_type.prop": "道具",
|
||||
"entity.dict.entity_type.other": "其他",
|
||||
"entity.dict.entity_status.0": "启用",
|
||||
"entity.dict.entity_status.1": "禁用",
|
||||
"entity.dict.import_status.0": "进行中",
|
||||
"entity.dict.import_status.1": "成功",
|
||||
"entity.dict.import_status.2": "失败",
|
||||
"entity.err.PARAM_REQUIRED": "缺少必要参数",
|
||||
"entity.err.FIELD_REQUIRED": "{label}不能为空",
|
||||
"entity.err.FIELD_TOO_LONG": "{label}长度不能超过{max}",
|
||||
"entity.err.WORLD_NOT_FOUND": "所属世界不存在",
|
||||
"entity.err.SCENE_NOT_FOUND": "所属场景不存在",
|
||||
"entity.err.DUPLICATE_CODE": "实体编码已存在",
|
||||
"entity.err.PARSE_ERROR": "文件解析失败",
|
||||
"entity.err.INVALID_JSON": "属性JSON格式错误",
|
||||
"entity.err.DB_ERROR": "数据库操作失败",
|
||||
"entity.err.NOT_FOUND": "记录不存在",
|
||||
"entity.field.name": "实体名称",
|
||||
"entity.field.code": "实体编码",
|
||||
"entity.field.world_id": "所属世界",
|
||||
"entity.field.scene_id": "所属场景",
|
||||
"entity.field.entity_type": "实体类型",
|
||||
"entity.field.status": "状态",
|
||||
"entity.field.attributes_json": "属性JSON"
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user