@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.
- package/LICENSE +21 -0
- package/README.md +272 -2
- package/dist/index.d.ts +61 -0
- package/dist/index.js +178 -0
- package/dist/message-catalog.d.ts +28 -0
- package/dist/message-catalog.js +11 -0
- package/dist/messages/am.js +678 -0
- package/dist/messages/ar.js +690 -0
- package/dist/messages/bn.js +662 -0
- package/dist/messages/cy.js +690 -0
- package/dist/messages/de.js +688 -0
- package/dist/messages/el.js +661 -0
- package/dist/messages/en-AU.js +656 -0
- package/dist/messages/en-GB.js +655 -0
- package/dist/messages/es.js +659 -0
- package/dist/messages/fa.js +664 -0
- package/dist/messages/fil.js +690 -0
- package/dist/messages/fr.js +668 -0
- package/dist/messages/he.js +669 -0
- package/dist/messages/hmn.js +660 -0
- package/dist/messages/ht.js +683 -0
- package/dist/messages/it.js +703 -0
- package/dist/messages/ja.js +652 -0
- package/dist/messages/km.js +658 -0
- package/dist/messages/ko.js +652 -0
- package/dist/messages/lo.js +659 -0
- package/dist/messages/ne.js +682 -0
- package/dist/messages/nl-NL.js +668 -0
- package/dist/messages/pa.js +663 -0
- package/dist/messages/pl.js +675 -0
- package/dist/messages/pt.js +666 -0
- package/dist/messages/ro.js +668 -0
- package/dist/messages/ru.js +689 -0
- package/dist/messages/so.js +679 -0
- package/dist/messages/sv.js +661 -0
- package/dist/messages/th-TH.js +652 -0
- package/dist/messages/tr.js +659 -0
- package/dist/messages/uk.js +675 -0
- package/dist/messages/ur.js +661 -0
- package/dist/messages/vi.js +652 -0
- package/dist/messages/zh-Hant.js +655 -0
- package/dist/messages/zh.js +653 -0
- 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
|
-
#
|
|
1
|
+
# @pie-players/pie-i18n-generated
|
|
2
2
|
|
|
3
|
-
|
|
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.
|
package/dist/index.d.ts
ADDED
|
@@ -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 {};
|