@pie-players/pie-i18n-generated 0.0.0-stage → 1.0.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +272 -2
  3. package/dist/index.d.ts +61 -0
  4. package/dist/index.js +178 -0
  5. package/dist/message-catalog.d.ts +28 -0
  6. package/dist/message-catalog.js +11 -0
  7. package/dist/messages/am.js +678 -0
  8. package/dist/messages/ar.js +690 -0
  9. package/dist/messages/bn.js +662 -0
  10. package/dist/messages/cy.js +690 -0
  11. package/dist/messages/de.js +688 -0
  12. package/dist/messages/el.js +661 -0
  13. package/dist/messages/en-AU.js +656 -0
  14. package/dist/messages/en-GB.js +655 -0
  15. package/dist/messages/es.js +659 -0
  16. package/dist/messages/fa.js +664 -0
  17. package/dist/messages/fil.js +690 -0
  18. package/dist/messages/fr.js +668 -0
  19. package/dist/messages/he.js +669 -0
  20. package/dist/messages/hmn.js +660 -0
  21. package/dist/messages/ht.js +683 -0
  22. package/dist/messages/it.js +703 -0
  23. package/dist/messages/ja.js +652 -0
  24. package/dist/messages/km.js +658 -0
  25. package/dist/messages/ko.js +652 -0
  26. package/dist/messages/lo.js +659 -0
  27. package/dist/messages/ne.js +682 -0
  28. package/dist/messages/nl-NL.js +668 -0
  29. package/dist/messages/pa.js +663 -0
  30. package/dist/messages/pl.js +675 -0
  31. package/dist/messages/pt.js +666 -0
  32. package/dist/messages/ro.js +668 -0
  33. package/dist/messages/ru.js +689 -0
  34. package/dist/messages/so.js +679 -0
  35. package/dist/messages/sv.js +661 -0
  36. package/dist/messages/th-TH.js +652 -0
  37. package/dist/messages/tr.js +659 -0
  38. package/dist/messages/uk.js +675 -0
  39. package/dist/messages/ur.js +661 -0
  40. package/dist/messages/vi.js +652 -0
  41. package/dist/messages/zh-Hant.js +655 -0
  42. package/dist/messages/zh.js +653 -0
  43. package/package.json +49 -5
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 PIE Framework contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,273 @@
1
- # Temporary Holding Version
1
+ # @pie-players/pie-i18n-generated
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Machine-generated, **unreviewed** interface locale catalogs for PIE players —
4
+ the optional tier beneath the reviewed catalogs that
5
+ [`@pie-players/pie-players-shared/i18n`](../players-shared/src/i18n/README.md)
6
+ ships. Every catalog here is generated from the English source against a
7
+ per-locale terminology brief, is provenance-marked, and is **not** presented
8
+ as reviewed: the coverage number certifies structure (keys, placeholders,
9
+ plural shape, freshness), never translation quality.
10
+
11
+ Installing this package changes nothing on its own. A host opts in per
12
+ deployment by wiring the loaders into the provider; a host that never sets a
13
+ generated locale fetches nothing, because every catalog is a lazy chunk
14
+ behind a static `import()` map and the default locale (`en-US`) is statically
15
+ resident in `players-shared` and never hits a loader at all.
16
+
17
+ The package depends on nothing: it is catalog data, and the provider it plugs
18
+ into comes with the players, which install `@pie-players/pie-players-shared`.
19
+
20
+ ## Wiring
21
+
22
+ ```ts
23
+ import {
24
+ BUNDLED_LOCALES,
25
+ createPieI18n,
26
+ loadBundledCatalog,
27
+ } from "@pie-players/pie-players-shared/i18n";
28
+ import {
29
+ GENERATED_LOCALES,
30
+ loadGeneratedCatalog,
31
+ } from "@pie-players/pie-i18n-generated";
32
+
33
+ const i18n = createPieI18n({
34
+ availableLocales: [...BUNDLED_LOCALES, ...GENERATED_LOCALES],
35
+ // Bundled first: a reviewed catalog silently wins over a generated one for
36
+ // the same tag, so promoting a locale out of this package into the
37
+ // reviewed set needs no host action.
38
+ loadCatalog: (locale) =>
39
+ loadBundledCatalog(locale).catch(() => loadGeneratedCatalog(locale)),
40
+ });
41
+
42
+ // Hand the provider to the player; the element's `locale` names the locale
43
+ // and is the only thing that drives it. Built without `locale` on purpose:
44
+ // the factory names a tag without loading its catalog.
45
+ document.querySelector("pie-section-player-splitpane").runtime = { i18n };
46
+ ```
47
+
48
+ ```html
49
+ <pie-section-player-splitpane locale="th-TH" …></pie-section-player-splitpane>
50
+ ```
51
+
52
+ Hosts may also override individual strings of a generated catalog the same
53
+ way they override reviewed ones: `customMessages` is consulted ahead of any
54
+ loaded catalog.
55
+
56
+ ## Locales
57
+
58
+ | Tag | Status | Brief | Generated |
59
+ | --- | --- | --- | --- |
60
+ | `th-TH` | reviewed (agent pass in lieu of a native reader, 2026-11-03) | [`briefs/th-TH.md`](./briefs/th-TH.md) | 2026-10-19 |
61
+ | `en-GB` | reviewed (agent verification pass, 2026-11-03; delta locale) | [`briefs/en-GB.md`](./briefs/en-GB.md) | 2026-10-19 |
62
+ | `en-AU` | reviewed (agent verification pass, 2026-11-03; delta locale) | [`briefs/en-AU.md`](./briefs/en-AU.md) | 2026-10-19 |
63
+ | `es` | reviewed (agent pass in lieu of a native reader, 2026-11-03; Latin-American neutral; serves `es*`) | [`briefs/es.md`](./briefs/es.md) | 2026-10-19 |
64
+ | `fr` | reviewed (agent pass in lieu of a native reader, 2026-11-03; France flavour; serves `fr*`) | [`briefs/fr.md`](./briefs/fr.md) | 2026-10-19 |
65
+ | `ar` | reviewed (agent pass in lieu of a native reader, 2026-11-04, after the RTL layout audit below landed; MSA; serves `ar*`; RTL) | [`briefs/ar.md`](./briefs/ar.md) | 2026-10-19 |
66
+ | `pt` | reviewed (agent pass in lieu of a native reader, 2026-11-03; Brazilian; serves `pt*`) | [`briefs/pt.md`](./briefs/pt.md) | 2026-10-19 |
67
+ | `ko` | reviewed (agent pass in lieu of a native reader, 2026-11-03) | [`briefs/ko.md`](./briefs/ko.md) | 2026-10-19 |
68
+ | `ja` | reviewed (agent pass in lieu of a native reader, 2026-11-03) | [`briefs/ja.md`](./briefs/ja.md) | 2026-10-19 |
69
+ | `zh` | reviewed (agent pass in lieu of a native reader, 2026-11-03; Simplified; serves `zh`, `zh-CN`, `zh-SG`; Traditional hosts supply `customMessages`) | [`briefs/zh.md`](./briefs/zh.md) | 2026-10-19 |
70
+ | `cy` | reviewed (agent pass in lieu of a native reader, 2026-11-03; serves `cy`, `cy-GB`; six CLDR plural categories) | [`briefs/cy.md`](./briefs/cy.md) | 2026-10-19 |
71
+ | `sv` | reviewed (agent pass in lieu of a native reader, 2026-11-03; serves `sv`, `sv-SE`, `sv-FI`) | [`briefs/sv.md`](./briefs/sv.md) | 2026-10-19 |
72
+ | `ro` | reviewed (agent pass in lieu of a native reader, 2026-11-03; serves `ro`, `ro-RO`, `ro-MD`; three CLDR plural categories, `other` takes `de`) | [`briefs/ro.md`](./briefs/ro.md) | 2026-10-19 |
73
+ | `vi` | reviewed (agent pass in lieu of a native reader, 2026-11-03; serves `vi`, `vi-VN`; one CLDR plural category) | [`briefs/vi.md`](./briefs/vi.md) | 2026-11-03 |
74
+ | `nl-NL` | reviewed (**native-speaker audit** — the framework's audit language; carried over from `players-shared`'s bundled set on 2026-11-04, verbatim) | [`briefs/nl-NL.md`](./briefs/nl-NL.md) | 2026-10-18 |
75
+ | `de` | reviewed (agent generation-and-review pass in lieu of a native reader, 2026-11-04; international deployment set; serves `de`, `de-AT`, `de-CH`) | [`briefs/de.md`](./briefs/de.md) | 2026-11-04 |
76
+ | `it` | reviewed (agent generation-and-review pass in lieu of a native reader, 2026-11-04; international deployment set; serves `it`) | [`briefs/it.md`](./briefs/it.md) | 2026-11-04 |
77
+ | `pl` | reviewed (agent generation-and-review pass in lieu of a native reader, 2026-11-04; international deployment set; serves `pl`; four CLDR plural categories) | [`briefs/pl.md`](./briefs/pl.md) | 2026-11-04 |
78
+ | `tr` | reviewed (agent generation-and-review pass in lieu of a native reader, 2026-11-04; international deployment set; serves `tr`, `tr-CY`) | [`briefs/tr.md`](./briefs/tr.md) | 2026-11-04 |
79
+ | `uk` | reviewed (agent generation-and-review pass in lieu of a native reader, 2026-11-04; international deployment set; serves `uk`; four CLDR plural categories) | [`briefs/uk.md`](./briefs/uk.md) | 2026-11-04 |
80
+ | `el` | reviewed (agent generation-and-review pass in lieu of a native reader, 2026-11-04; international deployment set; serves `el`, `el-CY`) | [`briefs/el.md`](./briefs/el.md) | 2026-11-04 |
81
+ | `ru` | reviewed (agent generation-and-review pass in lieu of a native reader, 2026-11-04; big-US wave; four CLDR plural categories) | [`briefs/ru.md`](./briefs/ru.md) | 2026-11-04 |
82
+ | `fil` | reviewed (agent generation-and-review pass in lieu of a native reader, 2026-11-04; big-US wave; the `tl` tag aliases this catalog) | [`briefs/fil.md`](./briefs/fil.md) | 2026-11-04 |
83
+ | `tl` | alias of `fil` (US systems label the language Tagalog) | [`briefs/fil.md`](./briefs/fil.md) | 2026-11-04 |
84
+ | `ht` | reviewed (agent generation-and-review pass in lieu of a native reader, 2026-11-04; big-US wave) | [`briefs/ht.md`](./briefs/ht.md) | 2026-11-04 |
85
+ | `ur` | reviewed (agent generation-and-review pass in lieu of a native reader, 2026-11-04; second RTL wave — inherits the audited RTL layout contract) | [`briefs/ur.md`](./briefs/ur.md) | 2026-11-04 |
86
+ | `fa` | reviewed (agent generation-and-review pass in lieu of a native reader, 2026-11-04; second RTL wave) | [`briefs/fa.md`](./briefs/fa.md) | 2026-11-04 |
87
+ | `he` | reviewed (agent generation-and-review pass in lieu of a native reader, 2026-11-04; second RTL wave; CLDR `two` category) | [`briefs/he.md`](./briefs/he.md) | 2026-11-04 |
88
+ | `zh-Hant` | reviewed (agent generation-and-review pass in lieu of a native reader, 2026-11-04; Taiwan-register Traditional — regional tag, bare `zh` stays Simplified) | [`briefs/zh-Hant.md`](./briefs/zh-Hant.md) | 2026-11-04 |
89
+ | `so` | reviewed (agent pass, 2026-11-04; state/regional wave — terminology partially standardized, **native review strongly advised**) | [`briefs/so.md`](./briefs/so.md) | 2026-11-04 |
90
+ | `hmn` | reviewed (agent pass, 2026-11-04; state/regional wave — White Hmong RPA, CLDR-undersourced, **native review strongly advised**) | [`briefs/hmn.md`](./briefs/hmn.md) | 2026-11-04 |
91
+ | `km` | reviewed (agent pass, 2026-11-04; state/regional wave — Khmer script, **native review strongly advised**) | [`briefs/km.md`](./briefs/km.md) | 2026-11-04 |
92
+ | `lo` | reviewed (agent pass, 2026-11-04; state/regional wave — Lao script, **native review strongly advised**) | [`briefs/lo.md`](./briefs/lo.md) | 2026-11-04 |
93
+ | `bn` | reviewed (agent pass, 2026-11-04; state/regional wave — Bengali script, **native review strongly advised**) | [`briefs/bn.md`](./briefs/bn.md) | 2026-11-04 |
94
+ | `pa` | reviewed (agent pass, 2026-11-04; state/regional wave — Gurmukhi script, **native review strongly advised**) | [`briefs/pa.md`](./briefs/pa.md) | 2026-11-04 |
95
+ | `ne` | reviewed (agent pass, 2026-11-04; state/regional wave — Devanagari script, **native review strongly advised**) | [`briefs/ne.md`](./briefs/ne.md) | 2026-11-04 |
96
+ | `am` | reviewed (agent pass, 2026-11-04; state/regional wave — Ethiopic script, **native review strongly advised**) | [`briefs/am.md`](./briefs/am.md) | 2026-11-04 |
97
+
98
+ Locale tags are chosen for variant reach: bare tags (`es`, `fr`, `ar`) let
99
+ `es-MX`, `fr-CA` and `ar-SA` widen onto them through RFC 4647 lookup, while
100
+ `en-GB`/`en-AU` are regional on purpose so bare `en` keeps resolving to the
101
+ bundled English.
102
+
103
+ Provenance — the exact `en-US` source hash each catalog was generated from,
104
+ the generating model and date — is recorded in
105
+ [`catalog-manifest.json`](./catalog-manifest.json).
106
+
107
+ The `calibration/` directory holds a pipeline measurement against the one
108
+ locale that has audited ground truth (Dutch), not a shippable catalog. See
109
+ [`calibration/nl-NL-calibration.md`](./calibration/nl-NL-calibration.md) for
110
+ what the pipeline does and does not deliver, and what that means for reviewing
111
+ a generated locale.
112
+
113
+ ## Checks
114
+
115
+ ```bash
116
+ bun run check:i18n-generated
117
+ ```
118
+
119
+ runs `scripts/check-catalogs.ts`, which fails on:
120
+
121
+ - **staleness** — per the locale's status: a `generated` locale whose recorded
122
+ `en-US` hash no longer matches the current English source (its untranslated
123
+ keys would silently fall back to English); a `reviewed` locale whose English
124
+ snapshot no longer matches current English, listing exactly the keys whose
125
+ English moved;
126
+ - **key drift** — a missing key, or a key English no longer defines;
127
+ - **placeholder drift** — a lost `{name}` slot or an invented one, in string
128
+ or plural-group leaves;
129
+ - **plural shape** — a missing plural group, or a group without `other`;
130
+ - **manifest disagreement** — a locale present in the loader map but not the
131
+ manifest, or the reverse.
132
+
133
+ The check runs in the repository's pre-commit and CI gates: changing English
134
+ fails the gate until the affected catalogs are regenerated — wholesale for
135
+ `generated` locales, surgically for `reviewed` ones.
136
+
137
+ ## The review lifecycle
138
+
139
+ **Agent passes in lieu of native readers.** On 2026-11-03 `es`, `en-GB` and
140
+ `en-AU` were promoted on agent passes: no native readers were available, the
141
+ maintainer accepted agent review for them, and each manifest entry's
142
+ `reviewedBy` records exactly that. `reviewed` still means *a pass happened and
143
+ its work is anchored* — the pass's nature lives in the manifest, the native
144
+ pass remains open work, and because regeneration is surgical from here, a
145
+ later native pass corrects in place instead of starting over.
146
+
147
+ A locale moves through two statuses, recorded in `catalog-manifest.json`, and
148
+ what regeneration may touch follows from the status:
149
+
150
+ **`generated` — machine output, no reader behind it.** Regeneration is
151
+ wholesale, and losing nothing makes that safe:
152
+
153
+ 1. Read `briefs/<locale>.md`, then regenerate `src/messages/<locale>.ts` from
154
+ the current `packages/players-shared/src/i18n/messages/en-US.ts`, keeping
155
+ every `{placeholder}` slot and the plural-group shape.
156
+ 2. Update `catalog-manifest.json`: the new `source.hash` (sha256 over the
157
+ JSON serialization of the `en-US` default export), and the locale's
158
+ `generatedAt` and `model`.
159
+ 3. Run `bun run check:i18n-generated` until it passes.
160
+
161
+ **Taking a review pass** promotes the locale in place, and this is the step
162
+ that makes iteration to audited quality a ratchet instead of a treadmill:
163
+
164
+ 1. A native reader goes through the catalog — the calibration report's
165
+ finding list is the checklist — correcting the file in place.
166
+ 2. Flip the locale's `status` to `reviewed` in the manifest, add `reviewedAt`
167
+ (and a `reviewedBy` note if wanted), and keep `sourceHash` as the
168
+ generation it started from.
169
+ 3. Run `bun run scripts/write-english-snapshot.ts <locale>`, which anchors
170
+ the corrections to the English they were reviewed against
171
+ (`src/messages/<locale>.english-snapshot.json`).
172
+ 4. `bun run check:i18n-generated` passes again — and from now on, changing a
173
+ translated string is preserved work: only keys whose *English* changed
174
+ ever need regenerating.
175
+
176
+ **`reviewed` — regeneration is surgical, never wholesale.** When the gate
177
+ lists keys whose English moved:
178
+
179
+ 1. Regenerate **only the listed keys**, against the brief and the new English
180
+ strings. Every translation the gate does not name stays exactly as the
181
+ review left it.
182
+ 2. Refresh the anchor:
183
+ `bun run scripts/write-english-snapshot.ts <locale>`.
184
+ 3. `bun run check:i18n-generated` until it passes.
185
+
186
+ Wholesale regeneration of a `reviewed` locale discards review work; do it
187
+ only deliberately, by flipping the status back to `generated` first.
188
+
189
+ ## The RTL layout audit (`ar`)
190
+
191
+ Status: **landed 2026-11-04**, and `ar`'s promotion followed it. This section
192
+ is the audit's record; the checks it added run in the suite.
193
+
194
+ `ar` is the framework's first right-to-left interface locale, and the audit
195
+ that gated its review pass was a layout audit, not a translation one: a native
196
+ reviewer certifying strings that render mirrored would certify the wrong
197
+ product. `direction` derives from `Intl.Locale.prototype.textInfo` and the
198
+ shell stamps `lang`/`dir` on its own host
199
+ ([adoption record](../../docs/architecture/i18n-interface-locale-adoption.md)).
200
+
201
+ `packages/section-player/tests/section-player-rtl-layout.spec.ts` holds seven
202
+ rendered cases against the `ar` demo
203
+ (`/interface-locale?locale=ar`), run outside the sandbox per the repository's
204
+ Playwright rules:
205
+
206
+ 1. **Card header** (pre-existing): the item toolbar hugs the trailing edge,
207
+ under a forced `dir` and under the real `ar` stamps.
208
+ 2. **Card footer**: the check-answer button mirrors under the same
209
+ `margin-inline-start` trailing-edge rule (`/item-session-control`, forced
210
+ `dir` — the rule reads inherited direction, and case 1 proves the stamping
211
+ path end to end).
212
+ 3. **Split-pane layout**: pane *order* flips — passages pane leads in LTR,
213
+ trails in RTL; containment stays with the scroll contract.
214
+ 4. **Toolbar pane**: the shell's toolbar pane hugs the trailing viewport edge
215
+ and follows the direction (right under LTR, left under `ar`); the vertical
216
+ tool column's reading order is direction-independent by design and is
217
+ pinned as stable.
218
+ 5. **Tool windows at `document.body`**: the graph shell's contents mirror
219
+ (title leads from the right under `ar`) while its screen position and size
220
+ stay put — the adoption record's free-window rule.
221
+ 6. **Metrics**: no chrome control clips (`scrollWidth` past the box) and no
222
+ horizontal page overflow appears under `ar`; the sweep covers the chrome
223
+ subtrees through the custom elements' open shadow roots and excludes the
224
+ item players' content roots, which are the content-language channel.
225
+ 7. **Text-level rendered inspection** (recorded, not asserted): a full-page
226
+ screenshot of the `ar` demo was inspected — Arabic labels sit at the
227
+ trailing edges with Western digits per the brief, English content keeps
228
+ its own LTR inside the content root's `dir="auto"`, and no punctuation
229
+ strands on the wrong side of an embedded Latin run in the rendered chrome.
230
+
231
+ **Defect found and repaired by the audit**: the toolbar pane's divider was a
232
+ physical `border-left`/`border-right`
233
+ (`SectionPlayerShell.svelte`), so under RTL the divider rendered on the
234
+ pane's outer screen edge instead of the content side. It now uses
235
+ `border-inline-start`/`border-inline-end`, and case 4's pane-flip assertion
236
+ pins the geometry.
237
+
238
+ **Recorded without assertions** — the surfaces the section demo cannot
239
+ exercise: the toolbar scrolls rather than collapsing into an overflow menu
240
+ when it overflows, and its tooltips are the browser's `title` rendering, so
241
+ neither has an assertion to carry; Back/Next navigation chrome belongs to the
242
+ assessment player (the reference assembly), not this building block; the
243
+ standalone item player (`<pie-item-player>` on its own) has no locale-driven
244
+ demo route, so its chrome mirror is covered only at the stamp level (the
245
+ interface-locale spec asserts its content-root stamps) — a follow-up demo
246
+ route would close that.
247
+
248
+ ## Adding a locale
249
+
250
+ Add `briefs/<locale>.md` (register, glossary, untranslated product names —
251
+ the th-TH brief is the template), translate `en-US` under it into
252
+ `src/messages/<locale>.ts`, then register the tag in both `GENERATED_LOCALES`
253
+ (`src/index.ts`) and `catalog-manifest.json`. The static `import()` map keeps
254
+ each locale its own lazy chunk, exactly as `players-shared`'s `catalogs.ts`
255
+ does.
256
+
257
+ ## Promoting a locale to the reviewed set
258
+
259
+ A locale that has been through a review pass above can go further — into the
260
+ audited set `players-shared` itself ships — and hosts need no migration
261
+ either way:
262
+
263
+ 1. A native speaker with domain context reviews the catalog — the
264
+ calibration report's finding list is the review checklist.
265
+ 2. Move the corrected catalog into
266
+ `packages/players-shared/src/i18n/messages/<locale>.ts`, add the tag to
267
+ `BundledLocaleCode`, `catalogs.ts` and `COMPLETE_LOCALES` per that
268
+ package's README, and give it a changeset.
269
+ 3. Delete the catalog from this package and the tag from the loader map and
270
+ manifest.
271
+
272
+ Because hosts compose the loaders bundled-first, the reviewed catalog wins
273
+ from the moment it ships, whether or not the host has removed this package.
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Generated interface catalogs for PIE Players — the optional locale tier.
3
+ *
4
+ * Every catalog here is machine-generated against the terminology brief named
5
+ * in `catalog-manifest.json` and is **not reviewed** by a native speaker. The
6
+ * reviewed catalogs ship from `@pie-players/pie-players-shared/i18n`; this
7
+ * package is pure data a host opts into by installing it and wiring it into
8
+ * the provider alongside the bundled loaders:
9
+ *
10
+ * ```ts
11
+ * import {
12
+ * BUNDLED_LOCALES,
13
+ * createPieI18n,
14
+ * loadBundledCatalog,
15
+ * } from "@pie-players/pie-players-shared/i18n";
16
+ * import {
17
+ * GENERATED_LOCALES,
18
+ * loadGeneratedCatalog,
19
+ * } from "@pie-players/pie-i18n-generated";
20
+ *
21
+ * // Built without `locale`: the factory names a tag without loading its
22
+ * // catalog. The element's `locale` attribute drives the provider.
23
+ * const i18n = createPieI18n({
24
+ * availableLocales: [...BUNDLED_LOCALES, ...GENERATED_LOCALES],
25
+ * // Bundled first: a reviewed catalog silently wins over a generated one
26
+ * // for the same tag, which is what makes promotion from generated to
27
+ * // reviewed a no-op for a wired host.
28
+ * loadCatalog: (locale) =>
29
+ * loadBundledCatalog(locale).catch(() => loadGeneratedCatalog(locale)),
30
+ * });
31
+ * // <pie-item-player locale="th-TH"> with `player.i18n = i18n`
32
+ * ```
33
+ *
34
+ * Nothing here loads unless a host asks for a generated locale: the loaders
35
+ * are never invoked for the default `en-US` (statically resident in
36
+ * `players-shared`), and each locale stays its own lazy chunk because `tsc`
37
+ * emits these `import()` calls verbatim — the same property
38
+ * `players-shared`'s `catalogs.ts` relies on.
39
+ *
40
+ * Provenance per locale — source hash, brief, model, generation date — lives
41
+ * in `catalog-manifest.json`. `scripts/check-catalogs.ts` fails when a catalog
42
+ * drifts from the English source or from its brief's structural rules.
43
+ *
44
+ * @module @pie-players/pie-i18n-generated
45
+ */
46
+ import type { MessageCatalog } from "./message-catalog.js";
47
+ /**
48
+ * Every locale tag this package ships a generated catalog for.
49
+ *
50
+ * `en-GB` and `en-AU` are regional on purpose: bare `en` must keep resolving
51
+ * to the statically bundled English, never to a regional variant.
52
+ */
53
+ export declare const GENERATED_LOCALES: readonly string[];
54
+ /**
55
+ * Load one generated catalog.
56
+ *
57
+ * Throws for a locale with no generated catalog; the provider treats that as
58
+ * "resolve through the fallback chain" rather than an error, mirroring
59
+ * `loadBundledCatalog`.
60
+ */
61
+ export declare function loadGeneratedCatalog(locale: string): Promise<MessageCatalog>;
package/dist/index.js ADDED
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Generated interface catalogs for PIE Players — the optional locale tier.
3
+ *
4
+ * Every catalog here is machine-generated against the terminology brief named
5
+ * in `catalog-manifest.json` and is **not reviewed** by a native speaker. The
6
+ * reviewed catalogs ship from `@pie-players/pie-players-shared/i18n`; this
7
+ * package is pure data a host opts into by installing it and wiring it into
8
+ * the provider alongside the bundled loaders:
9
+ *
10
+ * ```ts
11
+ * import {
12
+ * BUNDLED_LOCALES,
13
+ * createPieI18n,
14
+ * loadBundledCatalog,
15
+ * } from "@pie-players/pie-players-shared/i18n";
16
+ * import {
17
+ * GENERATED_LOCALES,
18
+ * loadGeneratedCatalog,
19
+ * } from "@pie-players/pie-i18n-generated";
20
+ *
21
+ * // Built without `locale`: the factory names a tag without loading its
22
+ * // catalog. The element's `locale` attribute drives the provider.
23
+ * const i18n = createPieI18n({
24
+ * availableLocales: [...BUNDLED_LOCALES, ...GENERATED_LOCALES],
25
+ * // Bundled first: a reviewed catalog silently wins over a generated one
26
+ * // for the same tag, which is what makes promotion from generated to
27
+ * // reviewed a no-op for a wired host.
28
+ * loadCatalog: (locale) =>
29
+ * loadBundledCatalog(locale).catch(() => loadGeneratedCatalog(locale)),
30
+ * });
31
+ * // <pie-item-player locale="th-TH"> with `player.i18n = i18n`
32
+ * ```
33
+ *
34
+ * Nothing here loads unless a host asks for a generated locale: the loaders
35
+ * are never invoked for the default `en-US` (statically resident in
36
+ * `players-shared`), and each locale stays its own lazy chunk because `tsc`
37
+ * emits these `import()` calls verbatim — the same property
38
+ * `players-shared`'s `catalogs.ts` relies on.
39
+ *
40
+ * Provenance per locale — source hash, brief, model, generation date — lives
41
+ * in `catalog-manifest.json`. `scripts/check-catalogs.ts` fails when a catalog
42
+ * drifts from the English source or from its brief's structural rules.
43
+ *
44
+ * @module @pie-players/pie-i18n-generated
45
+ */
46
+ /**
47
+ * An explicit static map rather than a bundler macro, for the same reason
48
+ * `catalogs.ts` gives: `tsc` emits the `import()` calls verbatim, so `dist`
49
+ * evaluates under every ESM runtime, and every bundler keeps each locale its
50
+ * own chunk. String-keyed: the generated set is open, and a host adding a
51
+ * locale adds one line here alongside the file.
52
+ */
53
+ const GENERATED_CATALOG_LOADERS = {
54
+ "th-TH": () => import("./messages/th-TH.js"),
55
+ "en-GB": () => import("./messages/en-GB.js"),
56
+ "en-AU": () => import("./messages/en-AU.js"),
57
+ // Bare tags on purpose: the provider's RFC 4647 lookup plus
58
+ // primary-subtag widening lands `es-MX`, `es-419`, `fr-CA`, `pt-BR` and
59
+ // `ar-SA` on these, and a host wanting a different national flavour
60
+ // overrides per key through `customMessages`. `zh` is Simplified Chinese
61
+ // and catches `zh-CN`/`zh-SG`; Traditional-Chinese hosts supply their own
62
+ // messages.
63
+ es: () => import("./messages/es.js"),
64
+ fr: () => import("./messages/fr.js"),
65
+ ar: () => import("./messages/ar.js"),
66
+ pt: () => import("./messages/pt.js"),
67
+ ko: () => import("./messages/ko.js"),
68
+ ja: () => import("./messages/ja.js"),
69
+ zh: () => import("./messages/zh.js"),
70
+ // Bare tags: `cy-GB` widens to `cy`, `sv-SE`/`sv-FI` to `sv`, and
71
+ // `ro-RO`/`ro-MD` to `ro`.
72
+ cy: () => import("./messages/cy.js"),
73
+ sv: () => import("./messages/sv.js"),
74
+ ro: () => import("./messages/ro.js"),
75
+ // Bare tag: `vi-VN` widens to `vi`.
76
+ vi: () => import("./messages/vi.js"),
77
+ // Regional on purpose, like en-GB/en-AU: the framework's audit language,
78
+ // native-speaker-reviewed, carried over from players-shared's bundled set
79
+ // on 2026-11-04. A bare `nl` widens onto it through the host's composed
80
+ // availableLocales, and its absence from the bundled set means a host that
81
+ // never wires this package never fetches it.
82
+ "nl-NL": () => import("./messages/nl-NL.js"),
83
+ // Bare tags: `de-AT`/`de-CH` widen to `de`, `tr` covers `tr-TR`, `el` covers
84
+ // Greece and Cyprus, `uk` covers Ukrainian everywhere.
85
+ de: () => import("./messages/de.js"),
86
+ it: () => import("./messages/it.js"),
87
+ pl: () => import("./messages/pl.js"),
88
+ tr: () => import("./messages/tr.js"),
89
+ uk: () => import("./messages/uk.js"),
90
+ el: () => import("./messages/el.js"),
91
+ // The big-US wave: `ru` carries the Slavic four-category set; `ht` is
92
+ // Haitian Creole; `fil` is Filipino — one catalog. A host labeling delivery
93
+ // Tagalog names `fil` (the modern stack name) or aliases `tl` in its own
94
+ // composition; this package ships the single authored catalog.
95
+ ru: () => import("./messages/ru.js"),
96
+ fil: () => import("./messages/fil.js"),
97
+ ht: () => import("./messages/ht.js"),
98
+ // The second RTL wave: the framework's RTL layout contract is audited and
99
+ // pinned by section-player's geometry spec (see the ar locale), so these
100
+ // inherit a verified mirroring path. `he` carries a CLDR `two` category.
101
+ ur: () => import("./messages/ur.js"),
102
+ fa: () => import("./messages/fa.js"),
103
+ he: () => import("./messages/he.js"),
104
+ // Regional on purpose, like nl-NL: Taiwan-register Traditional Chinese.
105
+ // Bare `zh` stays Simplified; `zh-TW`/`zh-HK` widen onto this.
106
+ "zh-Hant": () => import("./messages/zh-Hant.js"),
107
+ // The state/regional US wave: mostly one/other or other-only plurals, and
108
+ // several non-Latin scripts (Khmer, Lao, Bengali, Gurmukhi, Ethiopic,
109
+ // Devanagari; White Hmong in RPA Latin). Briefs flag where assessment
110
+ // terminology is not standardized — native review strongly advised.
111
+ so: () => import("./messages/so.js"),
112
+ hmn: () => import("./messages/hmn.js"),
113
+ km: () => import("./messages/km.js"),
114
+ lo: () => import("./messages/lo.js"),
115
+ bn: () => import("./messages/bn.js"),
116
+ pa: () => import("./messages/pa.js"),
117
+ ne: () => import("./messages/ne.js"),
118
+ am: () => import("./messages/am.js"),
119
+ };
120
+ /**
121
+ * Every locale tag this package ships a generated catalog for.
122
+ *
123
+ * `en-GB` and `en-AU` are regional on purpose: bare `en` must keep resolving
124
+ * to the statically bundled English, never to a regional variant.
125
+ */
126
+ export const GENERATED_LOCALES = [
127
+ "th-TH",
128
+ "en-GB",
129
+ "en-AU",
130
+ "es",
131
+ "fr",
132
+ "ar",
133
+ "pt",
134
+ "ko",
135
+ "ja",
136
+ "zh",
137
+ "cy",
138
+ "sv",
139
+ "ro",
140
+ "vi",
141
+ "nl-NL",
142
+ "de",
143
+ "it",
144
+ "pl",
145
+ "tr",
146
+ "uk",
147
+ "el",
148
+ "ru",
149
+ "fil",
150
+ "ht",
151
+ "ur",
152
+ "fa",
153
+ "he",
154
+ "zh-Hant",
155
+ "so",
156
+ "hmn",
157
+ "km",
158
+ "lo",
159
+ "bn",
160
+ "pa",
161
+ "ne",
162
+ "am",
163
+ ];
164
+ /**
165
+ * Load one generated catalog.
166
+ *
167
+ * Throws for a locale with no generated catalog; the provider treats that as
168
+ * "resolve through the fallback chain" rather than an error, mirroring
169
+ * `loadBundledCatalog`.
170
+ */
171
+ export async function loadGeneratedCatalog(locale) {
172
+ const loader = GENERATED_CATALOG_LOADERS[locale];
173
+ if (!loader) {
174
+ throw new Error(`No generated i18n catalog for locale: ${locale}`);
175
+ }
176
+ const module = await loader();
177
+ return module.default;
178
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * The shape of a locale catalog, as `@pie-players/pie-players-shared/i18n`
3
+ * defines `MessageCatalog`.
4
+ *
5
+ * Restated here because the generated catalogs are pure data: a declaration that
6
+ * named players-shared would make every host that installs them install it for
7
+ * one type. `test/message-catalog-contract.test.ts` fails the typecheck when the
8
+ * two stop accepting each other, which is what lets a host hand
9
+ * `loadGeneratedCatalog` straight to the provider's `loadCatalog`.
10
+ */
11
+ /** A plural group; `other` is the one category every language has. */
12
+ interface PluralTranslation {
13
+ zero?: string;
14
+ one?: string;
15
+ two?: string;
16
+ few?: string;
17
+ many?: string;
18
+ other: string;
19
+ }
20
+ /** A catalog node: a leaf string, a plural group, or a namespace. */
21
+ type MessageNode = string | PluralTranslation | {
22
+ [key: string]: MessageNode;
23
+ };
24
+ /** A whole catalog, as one locale module default-exports it. */
25
+ export type MessageCatalog = {
26
+ [key: string]: MessageNode;
27
+ };
28
+ export {};
@@ -0,0 +1,11 @@
1
+ /**
2
+ * The shape of a locale catalog, as `@pie-players/pie-players-shared/i18n`
3
+ * defines `MessageCatalog`.
4
+ *
5
+ * Restated here because the generated catalogs are pure data: a declaration that
6
+ * named players-shared would make every host that installs them install it for
7
+ * one type. `test/message-catalog-contract.test.ts` fails the typecheck when the
8
+ * two stop accepting each other, which is what lets a host hand
9
+ * `loadGeneratedCatalog` straight to the provider's `loadCatalog`.
10
+ */
11
+ export {};