Skip to content

Commit ab159a9

Browse files
i18n(service-realtime): ship the presence object in all eleven platform languages (#30536)
<!-- claude-projects-attribution: {"github_login":"os-bill"} --> _Requested by **Bill** · [project thread](https://claude.ai/code/project/chan_016iMXWSZDzqWRWvWzdNo8wg?thread=cmsg_016iMXWSZDzqWRWvWzdNo8wgBxjikPH2bUin9o95gbAxsx)_ domain:server#2 · os-bill · session_01Utp6Cai5CRdAs4u9gTipWU Refs #30512 — package 1 of 11 (`@objectstack/service-realtime`). The card stays open: the last PR of the series flips the bundle check to the platform locale table. Clause-②: no Metadata-protocol: none ## 维护者速读 - **改了什么:** 在线状态对象(`sys_presence`)的名称、字段、选项和帮助文字补上 7 种语言:繁体中文、阿拉伯语、法语、巴西葡萄牙语、俄语、德语、韩语,加上原有 4 种共 11 种,与平台语言表一致。 - **为什么改:** 平台语言表(#29428 裁决 F)要求每个界面都带齐 11 种语言;这是第 3 期按包补齐的第一个包,最小的一个(25 条)。 - **风险与回滚:** 只加翻译数据,不动代码逻辑、schema 或接口;原有 4 种语言文件一字未改。回滚即撤 PR。 - **先看:** `src/translations/index.ts`(新语言按表标签注册,zh-CN 排在 zh-Hant 前)、`scripts/i18n-extract.config.ts`(提取命令加 7 个标签),再抽看 `ar.objects.generated.ts`。 - **两分钟验证:** `node scripts/check-i18n-bundles.mjs --filter=realtime` 应输出 `in sync (21 bundle(s))` 并退出 0。 - **需要你做的:** 无,席位落地。 ## What changes - Seven new locales for `sys_presence`, registered under the platform locale table's tags: `zh-Hant`, `ar`, `fr`, `pt-BR`, `ru`, `de`, `ko`. Each is a `TAG.objects.generated.ts` with all 25 leaves and a `TAG.source-hashes.generated.ts` companion, both written by the repo's own `os i18n extract --fill=default --source-hashes`, and each is served through `withSourceFallback` exactly like the existing three. - The extract command in `scripts/i18n-extract.config.ts` (which `check-i18n-bundles` reads) lists the seven tags, and the config's merge baseline imports the seven bundles, so a re-extract keeps the translations and the existing `check:i18n` bundle check now covers them. - `index.ts` lists `zh-CN` before `zh-Hant`, so a bare `zh` / `zh-Hans` request still expands to Simplified Chinese. - Existing `zh-CN` / `ja-JP` / `es-ES` files are untouched (no rename, no content change: the re-extract wrote them byte-identical). - `bundle-ownership.test.ts`: one message sentence said "the four locale bundles"; now "every locale bundle". ## Acceptance notes - **Quality bar (#17508 / PR #19345):** every leaf is written for the reader, placeholders and code spans byte-identical (checked mechanically: same key set as `en`, same backtick spans and `{…}` tokens per leaf). Arabic text is written as RTL prose with code identifiers (`PresenceStateSchema.metadata`) left in Latin script. - **Leaves equal to English, on purpose:** words that are the native word in that language — `fr` `Session`, `Mobile`; `pt-BR` `Status`, `Online`, `Offline`, `Desktop`, `Tablet`; `de` `Status`, `Online`, `Offline`, `Desktop`, `Tablet`. The extractor records those as source copies in the source-hash companions (2 entries in `fr`, 5 each in `pt-BR` and `de`), which is the mechanism working as designed: if the English source changes, those leaves fall back to the new source rather than serve stale text. - Not changed, noted: the existing `zh-CN` / `ja-JP` / `es-ES` bundles still carry `display_title.label` / `.help` as English copies (two source-hash entries each). Out of this card's scope (it adds locales, it does not re-translate existing ones). ## Verification <details><summary>Package suite, typecheck, build (verify lock)</summary> ``` pnpm --filter @objectstack/service-realtime build && test && typecheck Test Files 5 passed (5) Tests 35 passed (35) os-verify-lock: VERDICT command-exit 0 ``` </details> <details><summary>Bundle check covers the new locales (red when one leaf is removed)</summary> ``` node scripts/check-i18n-bundles.mjs --filter=realtime services/service-realtime in sync (21 bundle(s)) check-i18n-bundles: OK (1 package(s) — all bundles in sync, no undeclared authoring keys). EXIT 0 # one-off: delete `device.options.other` from ko.objects.generated.ts, re-run, restore from HEAD services/service-realtime DRIFTED (2) EXIT 1 # restored: git diff HEAD empty node scripts/check-i18n-stale-fill.mjs check-i18n-stale-fill: OK (11 bundle set(s) — no new stale fills, 0 baselined). EXIT 0 ``` </details> <details><summary>Derived gate families at head 28ebd23 (dispatch-gates --commands, reconciled with --ran)</summary> ``` dispatch-gates --ran: 62 derived famil(ies) accounted for — 61 run, 1 NOT-MEASURED (1 DERIVED from a recorded exit 3). NOT MEASURED: node scripts/check-plugin-teardown-shape.mjs --self-test — exit 3, prerequisite: this shallow clone cannot read the self-test's pinned positive-control commit; CI runs it on a full checkout. Not read by anything this PR changes. every other family exit 0, including pnpm check:i18n (all 10 bundle sets) and pnpm check:i18n-stale-fill eslint --no-inline-config on the changed .ts files: exit 0 · check-nul-bytes: exit 0 changed lines 733 (+731 / -2), 18 files: under the 3000-line human-merge threshold ``` Full record: the seat's project folder, `server-seat2/30512/gates-realtime-ran.txt`. </details> Dogfood: not run — content-only package PR, no `!` in the title and no `(narrowing)` arm (dispatch order: package suite + `check:i18n` + typecheck suffice). --- _Generated by [Claude Code](https://claude.ai/code/session_01Utp6Cai5CRdAs4u9gTipWU)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent b4f4781 commit ab159a9

18 files changed

Lines changed: 731 additions & 2 deletions
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@objectstack/service-realtime': patch
3+
---
4+
5+
i18n(service-realtime): the presence object's labels, help and option names ship in all eleven platform languages
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
`sys_presence` now carries Traditional Chinese (`zh-Hant`), Arabic (`ar`), French (`fr`), Brazilian Portuguese (`pt-BR`), Russian (`ru`), German (`de`) and Korean (`ko`) beside the existing `en`, `zh-CN`, `ja-JP` and `es-ES`, so a reader in one of those languages sees the object's labels in their own language instead of English. Each new locale is registered under its platform-table tag and carries its source-hash companion, and the package's extract command lists the seven tags, so the existing `check:i18n` bundle check covers them. Part of #30512.

‎packages/services/service-realtime/scripts/i18n-extract.config.ts‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* strings were seeded from @objectstack/platform-objects.)
99
*
1010
* os i18n extract packages/services/service-realtime/scripts/i18n-extract.config.ts \
11-
* --locales=zh-CN,ja-JP,es-ES --fill=default --objects-only --no-metadata-forms \
11+
* --locales=zh-CN,ja-JP,es-ES,zh-Hant,ar,fr,pt-BR,ru,de,ko --fill=default --objects-only --no-metadata-forms \
1212
* --source-hashes \
1313
* --out=packages/services/service-realtime/src/translations
1414
*
@@ -42,6 +42,13 @@ import { enObjects } from '../src/translations/en.objects.generated.js';
4242
import { zhCNObjects } from '../src/translations/zh-CN.objects.generated.js';
4343
import { jaJPObjects } from '../src/translations/ja-JP.objects.generated.js';
4444
import { esESObjects } from '../src/translations/es-ES.objects.generated.js';
45+
import { zhHantObjects } from '../src/translations/zh-Hant.objects.generated.js';
46+
import { arObjects } from '../src/translations/ar.objects.generated.js';
47+
import { frObjects } from '../src/translations/fr.objects.generated.js';
48+
import { ptBRObjects } from '../src/translations/pt-BR.objects.generated.js';
49+
import { ruObjects } from '../src/translations/ru.objects.generated.js';
50+
import { deObjects } from '../src/translations/de.objects.generated.js';
51+
import { koObjects } from '../src/translations/ko.objects.generated.js';
4552

4653
/**
4754
* The annotation is load-bearing, not decoration (#10868). `defineStack`
@@ -64,6 +71,13 @@ const config: ObjectStackDefinition = defineStack({
6471
{ 'zh-CN': { objects: zhCNObjects } },
6572
{ 'ja-JP': { objects: jaJPObjects } },
6673
{ 'es-ES': { objects: esESObjects } },
74+
{ 'zh-Hant': { objects: zhHantObjects } },
75+
{ 'ar': { objects: arObjects } },
76+
{ 'fr': { objects: frObjects } },
77+
{ 'pt-BR': { objects: ptBRObjects } },
78+
{ 'ru': { objects: ruObjects } },
79+
{ 'de': { objects: deObjects } },
80+
{ 'ko': { objects: koObjects } },
6781
],
6882
});
6983

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
/**
4+
* Auto-generated by 'os i18n extract' for locale 'ar'.
5+
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
6+
* Do not hand-edit the structure — only the leaf string values.
7+
* Merge only fills gaps: correcting a source label/description does not
8+
* push the correction into a leaf here that already holds a translation —
9+
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
10+
* it by hand when its source changes; nothing here or in `os i18n check`
11+
* tells a leaf a translator updated on purpose from one nobody has looked
12+
* at since the source moved.
13+
*/
14+
15+
import type { TranslationData } from '@objectstack/spec/system';
16+
17+
export const arObjects: NonNullable<TranslationData['objects']> = {
18+
sys_presence: {
19+
label: "الحضور",
20+
pluralLabel: "حالات الحضور",
21+
description: "تتبّع حضور المستخدمين ونشاطهم في الوقت الفعلي",
22+
fields: {
23+
id: {
24+
label: "معرّف الحضور"
25+
},
26+
display_title: {
27+
label: "العنوان",
28+
help: "عنوان السجل: المستخدم وحالة حضوره (يُحسب عند القراءة)"
29+
},
30+
created_at: {
31+
label: "تاريخ الإنشاء"
32+
},
33+
updated_at: {
34+
label: "تاريخ التحديث"
35+
},
36+
user_id: {
37+
label: "المستخدم"
38+
},
39+
session_id: {
40+
label: "الجلسة"
41+
},
42+
status: {
43+
label: "الحالة",
44+
options: {
45+
online: "متصل",
46+
away: "بعيد",
47+
busy: "مشغول",
48+
offline: "غير متصل"
49+
}
50+
},
51+
last_seen: {
52+
label: "آخر ظهور"
53+
},
54+
current_location: {
55+
label: "الموقع الحالي"
56+
},
57+
device: {
58+
label: "الجهاز",
59+
options: {
60+
desktop: "سطح المكتب",
61+
mobile: "الهاتف المحمول",
62+
tablet: "الجهاز اللوحي",
63+
other: "أخرى"
64+
}
65+
},
66+
custom_status: {
67+
label: "الحالة المخصّصة"
68+
},
69+
metadata: {
70+
label: "البيانات الوصفية",
71+
help: "بيانات وصفية عشوائية بصيغة JSON مرتبطة بحالة الحضور (تطابق PresenceStateSchema.metadata)."
72+
}
73+
}
74+
}
75+
};
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
/**
4+
* Auto-generated by 'os i18n extract' for locale 'ar'. Do not hand-edit.
5+
*
6+
* Each entry is the digest of the SOURCE REVISION that this locale's leaf at
7+
* that path is still a byte copy of — provenance for the generated half of the
8+
* bundles (commit 09b4f4e4e): a leaf whose digest no longer matches its source is stale and serves the source text instead.
9+
*
10+
* An entry exists only while the leaf IS such a copy. Re-translate the leaf in
11+
* `<locale>.objects.generated.ts` and the next extract drops its entry by
12+
* itself — the table makes no claim about text a translator wrote. A path with
13+
* no entry is LEGACY-TRUSTED and never reported stale.
14+
*
15+
* ⚠️ Do not "fix" a staleness report by editing this file. Refreshing a digest
16+
* records that the current text was copied from the current source, which is
17+
* the false claim the mechanism exists to detect. Fix the TRANSLATION.
18+
*/
19+
20+
export const arGeneratedSourceHashes: Readonly<Record<string, string>> = {
21+
};

‎packages/services/service-realtime/src/translations/bundle-ownership.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ describe('objects translation bundle ownership (ADR-0029 D8)', () => {
2727
strays,
2828
`bundle carries objects this package's extract config does not own: ${strays.join(', ')} — ` +
2929
'their curated translations would be silently deleted on the next `os i18n extract`. ' +
30-
'Remove the dead block from the four locale bundles, or add the object to the extract config + this list.',
30+
'Remove the dead block from every locale bundle, or add the object to the extract config + this list.',
3131
).toEqual([]);
3232
});
3333

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
/**
4+
* Auto-generated by 'os i18n extract' for locale 'de'.
5+
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
6+
* Do not hand-edit the structure — only the leaf string values.
7+
* Merge only fills gaps: correcting a source label/description does not
8+
* push the correction into a leaf here that already holds a translation —
9+
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
10+
* it by hand when its source changes; nothing here or in `os i18n check`
11+
* tells a leaf a translator updated on purpose from one nobody has looked
12+
* at since the source moved.
13+
*/
14+
15+
import type { TranslationData } from '@objectstack/spec/system';
16+
17+
export const deObjects: NonNullable<TranslationData['objects']> = {
18+
sys_presence: {
19+
label: "Anwesenheit",
20+
pluralLabel: "Anwesenheiten",
21+
description: "Echtzeit-Verfolgung von Anwesenheit und Aktivität der Benutzer",
22+
fields: {
23+
id: {
24+
label: "Anwesenheits-ID"
25+
},
26+
display_title: {
27+
label: "Titel",
28+
help: "Datensatztitel: der Benutzer und sein Anwesenheitsstatus (beim Lesen berechnet)"
29+
},
30+
created_at: {
31+
label: "Erstellt am"
32+
},
33+
updated_at: {
34+
label: "Aktualisiert am"
35+
},
36+
user_id: {
37+
label: "Benutzer"
38+
},
39+
session_id: {
40+
label: "Sitzung"
41+
},
42+
status: {
43+
label: "Status",
44+
options: {
45+
online: "Online",
46+
away: "Abwesend",
47+
busy: "Beschäftigt",
48+
offline: "Offline"
49+
}
50+
},
51+
last_seen: {
52+
label: "Zuletzt gesehen"
53+
},
54+
current_location: {
55+
label: "Aktueller Ort"
56+
},
57+
device: {
58+
label: "Gerät",
59+
options: {
60+
desktop: "Desktop",
61+
mobile: "Mobilgerät",
62+
tablet: "Tablet",
63+
other: "Sonstiges"
64+
}
65+
},
66+
custom_status: {
67+
label: "Benutzerdefinierter Status"
68+
},
69+
metadata: {
70+
label: "Metadaten",
71+
help: "Beliebige JSON-Metadaten zum Anwesenheitsstatus (entspricht PresenceStateSchema.metadata)."
72+
}
73+
}
74+
}
75+
};
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
/**
4+
* Auto-generated by 'os i18n extract' for locale 'de'. Do not hand-edit.
5+
*
6+
* Each entry is the digest of the SOURCE REVISION that this locale's leaf at
7+
* that path is still a byte copy of — provenance for the generated half of the
8+
* bundles (commit 09b4f4e4e): a leaf whose digest no longer matches its source is stale and serves the source text instead.
9+
*
10+
* An entry exists only while the leaf IS such a copy. Re-translate the leaf in
11+
* `<locale>.objects.generated.ts` and the next extract drops its entry by
12+
* itself — the table makes no claim about text a translator wrote. A path with
13+
* no entry is LEGACY-TRUSTED and never reported stale.
14+
*
15+
* ⚠️ Do not "fix" a staleness report by editing this file. Refreshing a digest
16+
* records that the current text was copied from the current source, which is
17+
* the false claim the mechanism exists to detect. Fix the TRANSLATION.
18+
*/
19+
20+
export const deGeneratedSourceHashes: Readonly<Record<string, string>> = {
21+
"objects.sys_presence.fields.device.options.desktop": "cc1bf941a947048d",
22+
"objects.sys_presence.fields.device.options.tablet": "7a8f4fab8baceb72",
23+
"objects.sys_presence.fields.status.label": "64a420165247654b",
24+
"objects.sys_presence.fields.status.options.offline": "322a7ca59145b5d8",
25+
"objects.sys_presence.fields.status.options.online": "ac0927911fe6b7c1",
26+
};
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
/**
4+
* Auto-generated by 'os i18n extract' for locale 'fr'.
5+
* Edit translations in place; re-run extract (with --merge) to fill new gaps.
6+
* Do not hand-edit the structure — only the leaf string values.
7+
* Merge only fills gaps: correcting a source label/description does not
8+
* push the correction into a leaf here that already holds a translation —
9+
* a present-but-stale string is not a gap, so it is left as-is. Re-translate
10+
* it by hand when its source changes; nothing here or in `os i18n check`
11+
* tells a leaf a translator updated on purpose from one nobody has looked
12+
* at since the source moved.
13+
*/
14+
15+
import type { TranslationData } from '@objectstack/spec/system';
16+
17+
export const frObjects: NonNullable<TranslationData['objects']> = {
18+
sys_presence: {
19+
label: "Présence",
20+
pluralLabel: "Présences",
21+
description: "Suivi en temps réel de la présence et de l’activité des utilisateurs",
22+
fields: {
23+
id: {
24+
label: "ID de présence"
25+
},
26+
display_title: {
27+
label: "Titre",
28+
help: "Titre de l’enregistrement : l’utilisateur et son état de présence (calculé à la lecture)"
29+
},
30+
created_at: {
31+
label: "Créé le"
32+
},
33+
updated_at: {
34+
label: "Mis à jour le"
35+
},
36+
user_id: {
37+
label: "Utilisateur"
38+
},
39+
session_id: {
40+
label: "Session"
41+
},
42+
status: {
43+
label: "Statut",
44+
options: {
45+
online: "En ligne",
46+
away: "Absent",
47+
busy: "Occupé",
48+
offline: "Hors ligne"
49+
}
50+
},
51+
last_seen: {
52+
label: "Vu pour la dernière fois"
53+
},
54+
current_location: {
55+
label: "Emplacement actuel"
56+
},
57+
device: {
58+
label: "Appareil",
59+
options: {
60+
desktop: "Ordinateur",
61+
mobile: "Mobile",
62+
tablet: "Tablette",
63+
other: "Autre"
64+
}
65+
},
66+
custom_status: {
67+
label: "Statut personnalisé"
68+
},
69+
metadata: {
70+
label: "Métadonnées",
71+
help: "Métadonnées JSON arbitraires associées à l’état de présence (correspond à PresenceStateSchema.metadata)."
72+
}
73+
}
74+
}
75+
};
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
/**
4+
* Auto-generated by 'os i18n extract' for locale 'fr'. Do not hand-edit.
5+
*
6+
* Each entry is the digest of the SOURCE REVISION that this locale's leaf at
7+
* that path is still a byte copy of — provenance for the generated half of the
8+
* bundles (commit 09b4f4e4e): a leaf whose digest no longer matches its source is stale and serves the source text instead.
9+
*
10+
* An entry exists only while the leaf IS such a copy. Re-translate the leaf in
11+
* `<locale>.objects.generated.ts` and the next extract drops its entry by
12+
* itself — the table makes no claim about text a translator wrote. A path with
13+
* no entry is LEGACY-TRUSTED and never reported stale.
14+
*
15+
* ⚠️ Do not "fix" a staleness report by editing this file. Refreshing a digest
16+
* records that the current text was copied from the current source, which is
17+
* the false claim the mechanism exists to detect. Fix the TRANSLATION.
18+
*/
19+
20+
export const frGeneratedSourceHashes: Readonly<Record<string, string>> = {
21+
"objects.sys_presence.fields.device.options.mobile": "b93f18e1a3526425",
22+
"objects.sys_presence.fields.session_id.label": "2650b5c24a1853d7",
23+
};

‎packages/services/service-realtime/src/translations/index.ts‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,23 @@ import { enObjects } from './en.objects.generated.js';
1616
import { zhCNObjects } from './zh-CN.objects.generated.js';
1717
import { jaJPObjects } from './ja-JP.objects.generated.js';
1818
import { esESObjects } from './es-ES.objects.generated.js';
19+
import { zhHantObjects } from './zh-Hant.objects.generated.js';
20+
import { arObjects } from './ar.objects.generated.js';
21+
import { frObjects } from './fr.objects.generated.js';
22+
import { ptBRObjects } from './pt-BR.objects.generated.js';
23+
import { ruObjects } from './ru.objects.generated.js';
24+
import { deObjects } from './de.objects.generated.js';
25+
import { koObjects } from './ko.objects.generated.js';
1926
import { zhCNGeneratedSourceHashes } from './zh-CN.source-hashes.generated.js';
2027
import { jaJPGeneratedSourceHashes } from './ja-JP.source-hashes.generated.js';
2128
import { esESGeneratedSourceHashes } from './es-ES.source-hashes.generated.js';
29+
import { zhHantGeneratedSourceHashes } from './zh-Hant.source-hashes.generated.js';
30+
import { arGeneratedSourceHashes } from './ar.source-hashes.generated.js';
31+
import { frGeneratedSourceHashes } from './fr.source-hashes.generated.js';
32+
import { ptBRGeneratedSourceHashes } from './pt-BR.source-hashes.generated.js';
33+
import { ruGeneratedSourceHashes } from './ru.source-hashes.generated.js';
34+
import { deGeneratedSourceHashes } from './de.source-hashes.generated.js';
35+
import { koGeneratedSourceHashes } from './ko.source-hashes.generated.js';
2236

2337
/**
2438
* ## The provenance companions are READ here, not merely recorded
@@ -54,4 +68,11 @@ export const RealtimeTranslations: TranslationBundle = {
5468
'zh-CN': withSourceFallback({ objects: zhCNObjects }, enSource, undefined, zhCNGeneratedSourceHashes),
5569
'ja-JP': withSourceFallback({ objects: jaJPObjects }, enSource, undefined, jaJPGeneratedSourceHashes),
5670
'es-ES': withSourceFallback({ objects: esESObjects }, enSource, undefined, esESGeneratedSourceHashes),
71+
'zh-Hant': withSourceFallback({ objects: zhHantObjects }, enSource, undefined, zhHantGeneratedSourceHashes),
72+
'ar': withSourceFallback({ objects: arObjects }, enSource, undefined, arGeneratedSourceHashes),
73+
'fr': withSourceFallback({ objects: frObjects }, enSource, undefined, frGeneratedSourceHashes),
74+
'pt-BR': withSourceFallback({ objects: ptBRObjects }, enSource, undefined, ptBRGeneratedSourceHashes),
75+
'ru': withSourceFallback({ objects: ruObjects }, enSource, undefined, ruGeneratedSourceHashes),
76+
'de': withSourceFallback({ objects: deObjects }, enSource, undefined, deGeneratedSourceHashes),
77+
'ko': withSourceFallback({ objects: koObjects }, enSource, undefined, koGeneratedSourceHashes),
5778
};

0 commit comments

Comments
 (0)