From 9746be581d457f1f75fb49ddc8798548ec8551eb Mon Sep 17 00:00:00 2001 From: wc24 Date: Sat, 23 May 2026 22:48:10 +0800 Subject: [PATCH] =?UTF-8?q?v0.2.1:=20i18n=20messages=20=E6=94=B9=E6=88=90?= =?UTF-8?q?=E6=B7=B1=E5=90=88=E5=B9=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit initI18n 之前用 spread 浅合并: { ...zh_cn, ...(extra['zh-cn'] || {}) } 业务侧只要定义同名一级键(如 'user'),框架自带 user.* 全部被覆盖, 表现是控制台 [intlify] Not found 'user.operationLog' / 'user.xxx' 之类。 改成递归 deepMerge,框架 locale 在底,业务侧叠在上,同 leaf key 业务覆盖框架。 --- package.json | 2 +- src/VueAdmin.ts | 32 ++++++++++++++++++++++++-------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 971de77..cf96400 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "shrimp-admin", - "version": "0.2.0", + "version": "0.2.1", "private": true, "description": "Shrimp 框架前端 — 消费 ShrimpServer + ShrimpTable 契约的经典 Vue3 + Element Plus 实现", "main": "src/index.ts", diff --git a/src/VueAdmin.ts b/src/VueAdmin.ts index dd36041..df64bb7 100644 --- a/src/VueAdmin.ts +++ b/src/VueAdmin.ts @@ -12,6 +12,22 @@ import { IShrimpResponse, ILabel } from './IShrimpType' import { ShrimpClient, handleShrimpResponse, type IShrimpTipper, type IRouteInfo } from './ShrimpClient' import FieldString from './components/fields/FieldString.vue' +// ============== 工具 ============== + +/** locale 深合并:嵌套对象按 key 递归 merge,非对象值 src 覆盖 dst。仅服务于 i18n messages,没必要拉 lodash。 */ +function deepMerge(dst: Record, src: Record): Record { + const out: Record = { ...dst } + for (const key in src) { + const sv = src[key], dv = out[key] + if (sv && typeof sv === 'object' && !Array.isArray(sv) && dv && typeof dv === 'object' && !Array.isArray(dv)) { + out[key] = deepMerge(dv, sv) + } else { + out[key] = sv + } + } + return out +} + // ============== Options ============== export interface ShrimpAdminConfig { @@ -169,14 +185,14 @@ export class VueAdmin extends ShrimpClient { } initI18n(extraLocales?: Record) { - const merged: Record = { - 'zh-cn': { ...zh_cn, ...(extraLocales?.['zh-cn'] || {}) }, - 'en': { ...en, ...(extraLocales?.['en'] || {}) }, - } - if (extraLocales) { - for (const key in extraLocales) { - if (!(key in merged)) merged[key] = extraLocales[key] - } + // 深合并:框架自带 locale 在底,业务侧叠在上。 + // 旧版用 spread 浅合并,业务侧只要定义了同名一级键(如 user)就会把框架的 user.* 全部替换, + // 表现是控制台 [intlify] Not found 'user.operationLog' key 之类的报错。 + const builtins: Record = { 'zh-cn': zh_cn, 'en': en } + const merged: Record = {} + const langs = new Set([...Object.keys(builtins), ...Object.keys(extraLocales || {})]) + for (const lang of langs) { + merged[lang] = deepMerge(builtins[lang] || {}, extraLocales?.[lang] || {}) } this.i18n = createI18n({ locale: this.localData.get("lang") || 'zh-cn',