diff --git a/tools/gframework-config-tool/src/containsSummary.js b/tools/gframework-config-tool/src/containsSummary.js index a6fdbbe4..63a1771f 100644 --- a/tools/gframework-config-tool/src/containsSummary.js +++ b/tools/gframework-config-tool/src/containsSummary.js @@ -39,7 +39,7 @@ function describeContainsSchema(containsSchema, localizer) { /** * Build localized contains-related hint lines for array fields. * - * @param {{contains?: {type?: string, enumValues?: string[], constValue?: string, constDisplayValue?: string, pattern?: string, refTable?: string}, minContains?: number}} propertySchema Array property schema metadata. + * @param {{contains?: {type?: string, enumValues?: string[], constValue?: string, constDisplayValue?: string, pattern?: string, refTable?: string}, minContains?: number, maxContains?: number}} propertySchema Array property schema metadata. * @param {{t: (key: string, params?: Record) => string}} localizer Runtime localizer. * @returns {string[]} Localized contains hint lines. */ @@ -51,7 +51,7 @@ function buildContainsHintLines(propertySchema, localizer) { const effectiveMinContains = typeof propertySchema.minContains === "number" ? propertySchema.minContains : 1; - return [ + const lines = [ localizer.t("webview.hint.contains", { summary: describeContainsSchema(propertySchema.contains, localizer) }), @@ -59,6 +59,14 @@ function buildContainsHintLines(propertySchema, localizer) { value: effectiveMinContains }) ]; + + if (typeof propertySchema.maxContains === "number") { + lines.push(localizer.t("webview.hint.maxContains", { + value: propertySchema.maxContains + })); + } + + return lines; } module.exports = { diff --git a/tools/gframework-config-tool/src/localization.js b/tools/gframework-config-tool/src/localization.js index b2684e9f..736cae20 100644 --- a/tools/gframework-config-tool/src/localization.js +++ b/tools/gframework-config-tool/src/localization.js @@ -247,9 +247,9 @@ const zhCnMessages = { "webview.hint.format": "格式:{value}", "webview.hint.minItems": "最少元素数:{value}", "webview.hint.maxItems": "最多元素数:{value}", - "webview.hint.contains": "Contains 约束:{summary}", - "webview.hint.minContains": "最少 contains 匹配数:{value}", - "webview.hint.maxContains": "最多 contains 匹配数:{value}", + "webview.hint.contains": "Contains 条件:{summary}", + "webview.hint.minContains": "最少匹配数:{value}", + "webview.hint.maxContains": "最多匹配数:{value}", "webview.hint.uniqueItems": "元素必须唯一", "webview.hint.required": "必填字段:{properties}", "webview.hint.itemMinimum": "元素最小值:{value}", @@ -265,7 +265,7 @@ const zhCnMessages = { "webview.hint.minProperties": "最少属性数:{value}", "webview.hint.maxProperties": "最多属性数:{value}", "webview.hint.dependentRequired": "当 {trigger} 出现时:还必须声明 {dependencies}", - "webview.hint.dependentSchemas": "当 {trigger} 出现时:还必须满足 {schema}", + "webview.hint.dependentSchemas": "当 {trigger} 出现时:还必须满足以下条件:{schema}", "webview.hint.allOf": "还必须满足:{schema}", "webview.hint.ifThen": "当满足 {condition} 时:还必须满足 {schema}", "webview.hint.ifElse": "否则(当 {condition} 不匹配时):还必须满足 {schema}", @@ -277,7 +277,7 @@ const zhCnMessages = { [ValidationMessageKeys.allOfViolation]: "对象“{displayPath}”必须满足全部 `allOf` schema,第 {index} 项未匹配。", [ValidationMessageKeys.constMismatch]: "属性“{displayPath}”必须匹配固定值 {value}。", [ValidationMessageKeys.dependentRequiredViolation]: "属性“{triggerProperty}”存在时,必须同时声明属性“{displayPath}”。", - [ValidationMessageKeys.dependentSchemasViolation]: "对象“{displayPath}”在属性“{triggerProperty}”存在时,必须满足对应的 dependent schema。", + [ValidationMessageKeys.dependentSchemasViolation]: "对象“{displayPath}”在属性“{triggerProperty}”存在时,必须满足对应的依赖 schema。", [ValidationMessageKeys.elseViolation]: "对象“{displayPath}”在内联 `if` 条件未命中时,必须满足对应的 `else` schema。", [ValidationMessageKeys.exclusiveMaximumViolation]: "属性“{displayPath}”必须小于 {value}。", [ValidationMessageKeys.exclusiveMinimumViolation]: "属性“{displayPath}”必须大于 {value}。", diff --git a/tools/gframework-config-tool/src/localizationKeys.js b/tools/gframework-config-tool/src/localizationKeys.js index 51699094..a4c8ab5c 100644 --- a/tools/gframework-config-tool/src/localizationKeys.js +++ b/tools/gframework-config-tool/src/localizationKeys.js @@ -1,6 +1,7 @@ const ValidationMessageKeys = Object.freeze({ allOfViolation: "validation.allOfViolation", constMismatch: "validation.constMismatch", + dependentRequiredViolation: "validation.dependentRequiredViolation", dependentSchemasViolation: "validation.dependentSchemasViolation", elseViolation: "validation.elseViolation", enumMismatch: "validation.enumMismatch", diff --git a/tools/gframework-config-tool/test/containsSummary.test.js b/tools/gframework-config-tool/test/containsSummary.test.js index 8d29d7f0..13122cd5 100644 --- a/tools/gframework-config-tool/test/containsSummary.test.js +++ b/tools/gframework-config-tool/test/containsSummary.test.js @@ -51,6 +51,7 @@ test("buildContainsHintLines should use explicit minContains when provided", () const lines = buildContainsHintLines( { minContains: 2, + maxContains: 3, contains: { type: "string", constValue: "\"potion\"", @@ -62,7 +63,8 @@ test("buildContainsHintLines should use explicit minContains when provided", () assert.deepEqual(lines, [ "Contains: string, Const: \"potion\", Ref table: item", - "Min contains: 2" + "Min contains: 2", + "Max contains: 3" ]); }); @@ -93,3 +95,24 @@ test("describeContainsSchema should format pattern-based contains schema in Chin assert.equal(summary, "string, 正则模式:^potion-, 引用表:item"); }); + +test("buildContainsHintLines should use updated Chinese contains hint wording", () => { + const localizer = createLocalizer("zh-cn"); + + const lines = buildContainsHintLines( + { + minContains: 1, + maxContains: 2, + contains: { + type: "string", + enumValues: ["potion", "elixir"] + } + }, + localizer); + + assert.deepEqual(lines, [ + "Contains 条件:string, 允许值:potion, elixir", + "最少匹配数:1", + "最多匹配数:2" + ]); +}); diff --git a/tools/gframework-config-tool/test/localization.test.js b/tools/gframework-config-tool/test/localization.test.js index 52358254..35010a7d 100644 --- a/tools/gframework-config-tool/test/localization.test.js +++ b/tools/gframework-config-tool/test/localization.test.js @@ -70,6 +70,19 @@ test("createLocalizer should expose contains-count validation keys", () => { "属性“dropRates”最多只能包含 1 个匹配 contains 条件的元素。"); }); +test("createLocalizer should resolve dependentRequired through the explicit validation key", () => { + const localizer = createLocalizer("en"); + + assert.equal(ValidationMessageKeys.dependentRequiredViolation, "validation.dependentRequiredViolation"); + assert.equal( + localizer.t(ValidationMessageKeys.dependentRequiredViolation, { + displayPath: "reward.itemCount", + triggerProperty: "reward.itemId" + }), + "Property 'reward.itemCount' is required when sibling property 'reward.itemId' is present."); + assert.equal(localizer.t("undefined"), "undefined"); +}); + test("createLocalizer should expose not validation keys", () => { const englishLocalizer = createLocalizer("en"); const chineseLocalizer = createLocalizer("zh-cn"); @@ -132,7 +145,7 @@ test("createLocalizer should expose dependentSchemas validation keys", () => { trigger: "reward.itemId", schema: "object, 必填字段:itemCount" }), - "当 reward.itemId 出现时:还必须满足 object, 必填字段:itemCount"); + "当 reward.itemId 出现时:还必须满足以下条件:object, 必填字段:itemCount"); assert.equal( englishLocalizer.t(ValidationMessageKeys.dependentSchemasViolation, { displayPath: "reward", @@ -144,7 +157,7 @@ test("createLocalizer should expose dependentSchemas validation keys", () => { displayPath: "reward", triggerProperty: "reward.itemId" }), - "对象“reward”在属性“reward.itemId”存在时,必须满足对应的 dependent schema。"); + "对象“reward”在属性“reward.itemId”存在时,必须满足对应的依赖 schema。"); }); test("createLocalizer should expose allOf validation keys", () => {