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
22 changes: 22 additions & 0 deletions .changeset/i18n-merge-consequence-documented.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
---
"@objectstack/cli": patch
---

docs(cli): document the i18n merge consequence for a corrected source string (#9672)

`os i18n extract` merges against committed bundles by default so a re-run never
wipes a hand translation, and `--fill=default` only fills gaps. That means a
source label/description that is later **corrected** does not propagate into a
locale that already holds a translation of the old text — a present-but-stale
string is not a gap, so it is left as-is. This was always the behaviour and
remains unchanged; it was simply undocumented where the next reader looks.

Two places now say so: the merge-options comment in `os i18n extract`'s command
implementation, and the header comment written into every generated
`<locale>.objects.generated.ts` / `<locale>.metadata-forms.generated.ts` bundle.
Committed bundles across the repo are regenerated so their header matches the
new template (translated content is unchanged).

`check:i18n`'s bundle-drift verdict still proves generated output matches the
schema; it does not compare a translated value against its source's meaning
(that remains an open appetite question, tracked separately — see #9672).
10 changes: 10 additions & 0 deletions packages/cli/src/commands/i18n/extract.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -136,6 +136,16 @@ export default class I18nExtract extends Command {
locales,
fill: flags.fill as FillStrategy,
filter,
// Merge (the default) never overwrites an existing non-default-locale
// entry, so correcting a source label/description does not propagate
// into a locale that already holds a translation of the old text —
// a present-but-stale string is not a gap, only a missing one is. This
// is deliberate, not an oversight: the alternative, --no-merge, wipes
// every hand translation in the bundle, not just the ones the schema
// changed. The maintenance path is a translator re-editing the leaf in
// place (the generated bundle header names it); nothing here or in
// `os i18n check` distinguishes that deliberate edit from a leaf
// nobody has looked at since the source moved.
mergeExisting: !flags['no-merge'],
});

Expand Down
6 changes: 6 additions & 0 deletions packages/cli/src/utils/i18n-extract.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1173,6 +1173,12 @@ export function renderTranslationModule(
`Auto-generated by 'os i18n extract' for locale '${options.locale}'.`,
'Edit translations in place; re-run extract (with --merge) to fill new gaps.',
'Do not hand-edit the structure — only the leaf string values.',
'Merge only fills gaps: correcting a source label/description does not',
'push the correction into a leaf here that already holds a translation —',
'a present-but-stale string is not a gap, so it is left as-is. Re-translate',
'it by hand when its source changes; nothing here or in `os i18n check`',
'tells a leaf a translator updated on purpose from one nobody has looked',
'at since the source moved.',
];

const lines: string[] = [];
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'en'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'en'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'es-ES'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'es-ES'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'ja-JP'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'ja-JP'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'zh-CN'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'zh-CN'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'en'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'es-ES'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'ja-JP'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'zh-CN'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'en'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'es-ES'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'ja-JP'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'zh-CN'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'en'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'es-ES'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'ja-JP'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'zh-CN'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'en'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'es-ES'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'ja-JP'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,12 @@
* Auto-generated by 'os i18n extract' for locale 'zh-CN'.
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
* Do not hand-edit the structure — only the leaf string values.
* Merge only fills gaps: correcting a source label/description does not
* push the correction into a leaf here that already holds a translation —
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
* it by hand when its source changes; nothing here or in `os i18n check`
* tells a leaf a translator updated on purpose from one nobody has looked
* at since the source moved.
*/

import type { TranslationData } from '@objectstack/spec/system';
Expand Down
Loading
Loading