Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .changeset/25502-ai-reset-action-translation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
'@objectstack/service-settings': patch
---

fix: Setup → AI's "Reset to environment defaults" button is now translated in zh-CN, ja-JP and es-ES

Clause-②: no
Metadata-protocol: none

The `ai` settings manifest declares an `action_button` with id `reset`, but no locale bundle carried `settings.ai.actions.reset.label`, so the button rendered in English beside its translated siblings. The bundles now carry it (en, zh-CN, ja-JP, es-ES).

The settings translation coverage test now reads every manifest's `action_button` labels: each shipped non-English locale must carry `settings.<namespace>.actions.<id>.label` for every action button, and no bundle may carry action copy for a button no manifest declares.
1 change: 1 addition & 0 deletions packages/services/service-settings/src/translations/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ export const en: PlatformTranslationData = {
actions: {
test: { label: 'Test connection' },
test_embedder: { label: 'Test embedder' },
reset: { label: 'Reset to environment defaults' },
},
banners: {
log_prompts_warning: { title: 'Prompts may contain PII',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,7 @@ export const esES: PlatformTranslationData = {
actions: {
test: { label: 'Probar conexión' },
test_embedder: { label: 'Probar embedder' },
reset: { label: 'Restablecer a los valores predeterminados del entorno' },
},
banners: {
log_prompts_warning: { title: 'Los prompts pueden contener PII',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ export const jaJP: PlatformTranslationData = {
actions: {
test: { label: '接続テスト' },
test_embedder: { label: 'Embedder をテスト' },
reset: { label: '環境変数のデフォルトにリセット' },
},
banners: {
log_prompts_warning: { title: 'PII 漏えいの可能性',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
*
* This test pins each shipped non-English locale to full coverage of every
* manifest's structural strings — namespace title/description, each group
* title, each field label, and each `info_banner`'s title and text (keyed by
* the banner's `id` under `settings.<namespace>.banners`). Dropdown *option* labels are intentionally
* title, each field label, each `info_banner`'s title and text (keyed by
* the banner's `id` under `settings.<namespace>.banners`), and each
* `action_button`'s label (keyed by the button's `id` under
* `settings.<namespace>.actions`). Dropdown *option* labels are intentionally
* excluded: several must not be "translated" (the `timezone` option "UTC" is a
* code; each `locale` option names its language in that language), and
* option-level parity is filled per-locale on a best-effort basis.
Expand Down Expand Up @@ -56,6 +58,14 @@ function missingFor(data: { settings?: Record<string, any> }, m: SettingsManifes
}
if (tr?.banners?.[s.id]?.title == null) missing.push(`banner:${s.id}.title`);
if (tr?.banners?.[s.id]?.text == null) missing.push(`banner:${s.id}.text`);
} else if (s.type === 'action_button') {
// Same as a banner: an action button is addressed by its `id`, and one
// without an id has no place in the bundle for its label.
if (!s.id) {
missing.push('action without an id');
continue;
}
if (tr?.actions?.[s.id]?.label == null) missing.push(`action:${s.id}`);
} else if (s.key) {
if (tr?.keys?.[s.key]?.label == null) missing.push(`key:${s.key}`);
}
Expand All @@ -64,7 +74,7 @@ function missingFor(data: { settings?: Record<string, any> }, m: SettingsManifes
}

/**
* The other direction: copy for a group, key or banner no manifest declares.
* The other direction: copy for a group, key, banner or action no manifest declares.
* Such an entry renders nowhere, so it survives every review as dead text. The four
* Localization format keys retired by #21958 are the case that named it.
*/
Expand All @@ -80,18 +90,22 @@ function undeclaredIn(data: { settings?: Record<string, any> }): string[] {
const groups = new Set<string>();
const keys = new Set<string>();
const banners = new Set<string>();
const actions = new Set<string>();
for (const s of m.specifiers) {
if (s.type === 'group') {
if (s.id) groups.add(s.id);
} else if (s.type === 'info_banner') {
if (s.id) banners.add(s.id);
} else if (s.type === 'action_button') {
if (s.id) actions.add(s.id);
} else if (s.key) {
keys.add(s.key);
}
}
for (const g of Object.keys(tr?.groups ?? {})) if (!groups.has(g)) extra.push(`${ns}.group:${g}`);
for (const k of Object.keys(tr?.keys ?? {})) if (!keys.has(k)) extra.push(`${ns}.key:${k}`);
for (const b of Object.keys(tr?.banners ?? {})) if (!banners.has(b)) extra.push(`${ns}.banner:${b}`);
for (const a of Object.keys(tr?.actions ?? {})) if (!actions.has(a)) extra.push(`${ns}.action:${a}`);
}
return extra;
}
Expand All @@ -103,15 +117,15 @@ describe('settings translation coverage', () => {

for (const [locale, data] of LOCALES) {
for (const m of manifests) {
it(`${locale} covers settings.${m.namespace} (title / groups / keys / banners)`, () => {
it(`${locale} covers settings.${m.namespace} (title / groups / keys / banners / actions)`, () => {
const missing = missingFor(data, m);
expect(missing, `${locale} missing for ${m.namespace}: ${missing.join(', ')}`).toEqual([]);
});
}
}

for (const [locale, data] of [['en', en], ...LOCALES] as typeof LOCALES) {
it(`${locale} carries no copy for a group, key or banner no manifest declares`, () => {
it(`${locale} carries no copy for a group, key, banner or action no manifest declares`, () => {
const extra = undeclaredIn(data);
expect(extra, `${locale} has undeclared settings copy: ${extra.join(', ')}`).toEqual([]);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,7 @@ export const zhCN: PlatformTranslationData = {
actions: {
test: { label: '测试连接' },
test_embedder: { label: '测试 Embedder' },
reset: { label: '重置为环境变量默认值' },
},
banners: {
log_prompts_warning: { title: 'Prompt 可能含有 PII', text: '可能泄露 PII,合规场景请关闭。' },
Expand Down
Loading