@pie-players/pie-players-shared 1.0.0-beta.3 → 1.0.0-beta.5

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.
@@ -31,6 +31,11 @@ export declare const BUNDLED_LOCALES: readonly BundledLocaleCode[];
31
31
  /**
32
32
  * Load one shipped catalog.
33
33
  *
34
+ * `en-US` comes back without a load: it is statically resident, and a host
35
+ * composing this loader into a provider — the generated tier's README pattern,
36
+ * or a pseudo-localization of the English catalog — asks for it by name like
37
+ * any other locale.
38
+ *
34
39
  * Throws for a locale with no shipped catalog; the provider treats that as
35
40
  * "resolve through the fallback chain" rather than an error, so a host locale we
36
41
  * do not ship still renders.
@@ -20,6 +20,7 @@
20
20
  *
21
21
  * @module @pie-players/pie-players-shared/i18n/catalogs
22
22
  */
23
+ import enUS from "./messages/en-US.js";
23
24
  const CATALOG_LOADERS = {
24
25
  "nl-NL": () => import("./messages/nl-NL.js"),
25
26
  };
@@ -33,11 +34,19 @@ export const BUNDLED_LOCALES = ["en-US", "nl-NL"];
33
34
  /**
34
35
  * Load one shipped catalog.
35
36
  *
37
+ * `en-US` comes back without a load: it is statically resident, and a host
38
+ * composing this loader into a provider — the generated tier's README pattern,
39
+ * or a pseudo-localization of the English catalog — asks for it by name like
40
+ * any other locale.
41
+ *
36
42
  * Throws for a locale with no shipped catalog; the provider treats that as
37
43
  * "resolve through the fallback chain" rather than an error, so a host locale we
38
44
  * do not ship still renders.
39
45
  */
40
46
  export async function loadBundledCatalog(locale) {
47
+ if (locale === "en-US") {
48
+ return enUS;
49
+ }
41
50
  const loader = CATALOG_LOADERS[locale];
42
51
  if (!loader) {
43
52
  throw new Error(`No bundled i18n catalog for locale: ${locale}`);
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Content language on the delivery channel.
3
+ *
4
+ * Content language names the language the item's content is written in — a
5
+ * fact about the content, on a separate channel from the interface locale a
6
+ * player publishes to the elements inside it. It reaches the player in
7
+ * `env.locale`, the same channel `env.mode` travels: a delivery fact the
8
+ * container knows and content cannot. Authoring hosts emit it; a host that
9
+ * emits nothing leaves the content unstamped, and nothing is invented — there
10
+ * is no default language for content that names none.
11
+ *
12
+ * The player reflects the resolved language onto its content subtree's root as
13
+ * `lang` and `dir`, so a screen reader takes the content's voice rules and RTL
14
+ * content lays out right to left, independent of the chrome's locale.
15
+ */
16
+ import type { TextDirection } from "./types.js";
17
+ /** `lang` and `dir` for declared content, or `null` when nothing is declared. */
18
+ export interface ContentLanguageAttributes {
19
+ lang: string;
20
+ dir: TextDirection;
21
+ }
22
+ /**
23
+ * `lang` and `dir` for the content an `env` describes, or `null` when it
24
+ * declares no usable language. Reads `env.locale` defensively — `env` is
25
+ * pass-through and load-bearing, so anything may arrive — and never invents a
26
+ * default: undeclared content stays unstamped and inherits whatever its
27
+ * context genuinely provides.
28
+ */
29
+ export declare function contentLanguageAttributes(env: unknown): ContentLanguageAttributes | null;
30
+ /**
31
+ * Stamps `contentLanguageAttributes(env)` onto `target`, removing both
32
+ * attributes when the env declares no language — a model set can drop the
33
+ * language a previous one declared. No-op without a target.
34
+ */
35
+ export declare function stampContentLanguage(target: Element | null | undefined, env: unknown): void;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Content language on the delivery channel.
3
+ *
4
+ * Content language names the language the item's content is written in — a
5
+ * fact about the content, on a separate channel from the interface locale a
6
+ * player publishes to the elements inside it. It reaches the player in
7
+ * `env.locale`, the same channel `env.mode` travels: a delivery fact the
8
+ * container knows and content cannot. Authoring hosts emit it; a host that
9
+ * emits nothing leaves the content unstamped, and nothing is invented — there
10
+ * is no default language for content that names none.
11
+ *
12
+ * The player reflects the resolved language onto its content subtree's root as
13
+ * `lang` and `dir`, so a screen reader takes the content's voice rules and RTL
14
+ * content lays out right to left, independent of the chrome's locale.
15
+ */
16
+ import { canonicalLanguageTag } from "./language-tags.js";
17
+ import { localeDirection } from "./provider.js";
18
+ /**
19
+ * `lang` and `dir` for the content an `env` describes, or `null` when it
20
+ * declares no usable language. Reads `env.locale` defensively — `env` is
21
+ * pass-through and load-bearing, so anything may arrive — and never invents a
22
+ * default: undeclared content stays unstamped and inherits whatever its
23
+ * context genuinely provides.
24
+ */
25
+ export function contentLanguageAttributes(env) {
26
+ const locale = env?.locale;
27
+ if (typeof locale !== "string")
28
+ return null;
29
+ const lang = canonicalLanguageTag(locale);
30
+ if (!lang)
31
+ return null;
32
+ return { lang, dir: localeDirection(lang) };
33
+ }
34
+ /**
35
+ * Stamps `contentLanguageAttributes(env)` onto `target`, removing both
36
+ * attributes when the env declares no language — a model set can drop the
37
+ * language a previous one declared. No-op without a target.
38
+ */
39
+ export function stampContentLanguage(target, env) {
40
+ if (!target)
41
+ return;
42
+ const attributes = contentLanguageAttributes(env);
43
+ if (attributes) {
44
+ target.setAttribute("lang", attributes.lang);
45
+ target.setAttribute("dir", attributes.dir);
46
+ }
47
+ else {
48
+ target.removeAttribute("lang");
49
+ target.removeAttribute("dir");
50
+ }
51
+ }
@@ -28,6 +28,10 @@ import type { I18nConfig, I18nServiceApi } from "./types.js";
28
28
  */
29
29
  export declare function createPieI18n(config?: I18nConfig): I18nServiceApi;
30
30
  export { BUNDLED_LOCALES, loadBundledCatalog } from "./catalogs.js";
31
- export { findBestLanguageMatch, languageTagLookupSequence, languageTagsEqual, normalizeLanguageTag, toLanguageTag, } from "./language-tags.js";
32
- export { DEFAULT_LOCALE, detectBrowserLocale, dynamicMessageKey, getDefaultI18n, localeDirection, resolveInterfaceI18n, SimpleI18n, } from "./provider.js";
31
+ export { canonicalLanguageTag, findBestLanguageMatch, languageTagLookupSequence, languageTagsEqual, normalizeLanguageTag, toLanguageTag, } from "./language-tags.js";
32
+ export { DEFAULT_LOCALE, detectBrowserLocale, dynamicMessageKey, getDefaultI18n, localeDirection, resolveInterfaceI18n, SimpleI18n, stampInterfaceLocale, } from "./provider.js";
33
+ export { type ContentLanguageAttributes, contentLanguageAttributes, stampContentLanguage, } from "./content-language.js";
34
+ export { type InterfaceLocaleLoadErrorModel, reportInterfaceLocaleLoadError, } from "./locale-load-error.js";
35
+ export { PSEUDO_LOCALE_EXPANDED, PSEUDO_LOCALE_RTL, pseudoLocalize, } from "./pseudo.js";
36
+ export type { PseudoLocalizeOptions } from "./pseudo.js";
33
37
  export type { BundledLocaleCode, DynamicMessageKey, I18nConfig, I18nProvider, I18nServiceApi, InterpolationValues, LocaleCode, MessageCatalog, MessageKey, MessageKeyInput, MessageNode, PluralOptions, PluralTranslation, TextDirection, TranslationBundle, } from "./types.js";
@@ -35,5 +35,8 @@ export function createPieI18n(config = {}) {
35
35
  });
36
36
  }
37
37
  export { BUNDLED_LOCALES, loadBundledCatalog } from "./catalogs.js";
38
- export { findBestLanguageMatch, languageTagLookupSequence, languageTagsEqual, normalizeLanguageTag, toLanguageTag, } from "./language-tags.js";
39
- export { DEFAULT_LOCALE, detectBrowserLocale, dynamicMessageKey, getDefaultI18n, localeDirection, resolveInterfaceI18n, SimpleI18n, } from "./provider.js";
38
+ export { canonicalLanguageTag, findBestLanguageMatch, languageTagLookupSequence, languageTagsEqual, normalizeLanguageTag, toLanguageTag, } from "./language-tags.js";
39
+ export { DEFAULT_LOCALE, detectBrowserLocale, dynamicMessageKey, getDefaultI18n, localeDirection, resolveInterfaceI18n, SimpleI18n, stampInterfaceLocale, } from "./provider.js";
40
+ export { contentLanguageAttributes, stampContentLanguage, } from "./content-language.js";
41
+ export { reportInterfaceLocaleLoadError, } from "./locale-load-error.js";
42
+ export { PSEUDO_LOCALE_EXPANDED, PSEUDO_LOCALE_RTL, pseudoLocalize, } from "./pseudo.js";
@@ -57,3 +57,12 @@ export declare function languageTagLookupSequence(tag: string | null | undefined
57
57
  * however they were authored.
58
58
  */
59
59
  export declare function findBestLanguageMatch(requested: string | null | undefined, available: readonly (string | null | undefined)[]): string | undefined;
60
+ /**
61
+ * The canonical form of a usable language tag, or `undefined` for anything a
62
+ * language in use would not be: `es_MX` normalizes to `es-MX`, `NL-nl` to
63
+ * `nl-NL`, and `Spanish` or an empty string are not tags. One rule for every
64
+ * `lang` this repository writes — content and chrome alike — and the same rule
65
+ * the PIE elements apply to `model.language`, so every stamped attribute on a
66
+ * page carries the same shape.
67
+ */
68
+ export declare function canonicalLanguageTag(language: string | null | undefined): string | undefined;
@@ -92,3 +92,24 @@ export function findBestLanguageMatch(requested, available) {
92
92
  }
93
93
  return undefined;
94
94
  }
95
+ /**
96
+ * The canonical form of a usable language tag, or `undefined` for anything a
97
+ * language in use would not be: `es_MX` normalizes to `es-MX`, `NL-nl` to
98
+ * `nl-NL`, and `Spanish` or an empty string are not tags. One rule for every
99
+ * `lang` this repository writes — content and chrome alike — and the same rule
100
+ * the PIE elements apply to `model.language`, so every stamped attribute on a
101
+ * page carries the same shape.
102
+ */
103
+ export function canonicalLanguageTag(language) {
104
+ const tag = toLanguageTag(language).split(/[.@]/)[0];
105
+ // `Intl` accepts any 5-8 letter primary subtag, `Spanish` included; a
106
+ // language in use has an ISO 639 code of two or three letters.
107
+ if (!/^[a-z]{2,3}(-|$)/i.test(tag))
108
+ return undefined;
109
+ try {
110
+ return Intl.getCanonicalLocales(tag)[0];
111
+ }
112
+ catch {
113
+ return undefined;
114
+ }
115
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * The `framework-error` report for a failed interface-locale catalog load.
3
+ *
4
+ * Every locale driver — the toolkit through its error bus, the standalone item
5
+ * player and the reference assembly through this helper — reports the same
6
+ * failure the same way: a `framework-error` DOM event whose detail carries the
7
+ * `i18n-locale-load` kind with `recoverable: true`, because every key still
8
+ * resolves through the English fallback chain and the player renders — in the
9
+ * wrong language, which a host wants to know about.
10
+ *
11
+ * The shape mirrors the toolkit's `FrameworkErrorModel` field for field. It is
12
+ * declared here, narrowly, because the standalone item player does not depend
13
+ * on the toolkit and a type-only import would still drag it into the published
14
+ * declarations; what this module commits to is the fields below, which is what
15
+ * a host reading `.kind` and `.recoverable` consumes.
16
+ */
17
+ export interface InterfaceLocaleLoadErrorModel {
18
+ kind: "i18n-locale-load";
19
+ source: string;
20
+ message: string;
21
+ details: string[];
22
+ recoverable: true;
23
+ scope: "runtime";
24
+ cause?: unknown;
25
+ }
26
+ /**
27
+ * Dispatches the recoverable load-failure report on `target` as a
28
+ * `bubbles`/`composed` `framework-error` event. No-op without a target, so a
29
+ * caller mounted as a plain component rather than an element stays silent.
30
+ *
31
+ * Failed loads are not cached: re-setting the `locale` attribute, or
32
+ * recomposing the `i18n` provider, drives `setLocale` again and so retries.
33
+ */
34
+ export declare function reportInterfaceLocaleLoadError(target: Element | null | undefined, source: string, cause: unknown): void;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Dispatches the recoverable load-failure report on `target` as a
3
+ * `bubbles`/`composed` `framework-error` event. No-op without a target, so a
4
+ * caller mounted as a plain component rather than an element stays silent.
5
+ *
6
+ * Failed loads are not cached: re-setting the `locale` attribute, or
7
+ * recomposing the `i18n` provider, drives `setLocale` again and so retries.
8
+ */
9
+ export function reportInterfaceLocaleLoadError(target, source, cause) {
10
+ if (!target)
11
+ return;
12
+ const message = cause instanceof Error && cause.message.trim().length > 0
13
+ ? cause.message
14
+ : String(cause ?? "Unknown catalog load failure");
15
+ const detail = {
16
+ kind: "i18n-locale-load",
17
+ source,
18
+ message,
19
+ details: [],
20
+ recoverable: true,
21
+ scope: "runtime",
22
+ cause,
23
+ };
24
+ target.dispatchEvent(new CustomEvent("framework-error", {
25
+ detail,
26
+ bubbles: true,
27
+ composed: true,
28
+ }));
29
+ }
@@ -57,6 +57,8 @@ declare const enUS: {
57
57
  apply: string;
58
58
  enabled: string;
59
59
  disabled: string;
60
+ lookUp: string;
61
+ wordOrPhrase: string;
60
62
  closeA11y: string;
61
63
  settingsA11y: string;
62
64
  };
@@ -89,6 +91,14 @@ declare const enUS: {
89
91
  resizeMediaRegion: string;
90
92
  resizeQuestionAndMediaA11y: string;
91
93
  resizePassageAndMediaA11y: string;
94
+ resizePassageAndQuestionA11y: string;
95
+ passageWidthA11y: string;
96
+ /**
97
+ * The section player's navigation live region, announced when the active
98
+ * item changes; `{label}` is the item's own label when it has one.
99
+ */
100
+ questionPositionA11y: string;
101
+ questionPositionLabeledA11y: string;
92
102
  /**
93
103
  * The assessment player's own section-to-section navigation. Its Back and
94
104
  * Next controls take `common.back` / `common.next`.
@@ -139,6 +149,29 @@ declare const enUS: {
139
149
  playbackAdvisory: string;
140
150
  playbackReleased: string;
141
151
  };
152
+ /**
153
+ * `<pie-item-summary>`: an item described as a list row, without loading its
154
+ * elements. The correct marker's glyph is hidden from assistive technology,
155
+ * which reads `correctA11y` instead.
156
+ */
157
+ summary: {
158
+ correctA11y: string;
159
+ answer: string;
160
+ manualScoring: string;
161
+ audio: string;
162
+ video: string;
163
+ };
164
+ /** `<pie-item-list>`. */
165
+ list: {
166
+ /** The row toggle, a disclosure button whose `aria-expanded` carries the state, so its label stays the same either way. */
167
+ expandA11y: string;
168
+ /** Names the block of an entry's search matches below its summary. */
169
+ highlights: string;
170
+ /** The row toggle's tooltip while the row is expanded: collapsing returns it to the summary. */
171
+ collapse: string;
172
+ /** Shown in an expanded row whose player failed to load; the summary keeps showing above it. */
173
+ playerError: string;
174
+ };
142
175
  };
143
176
  /** Toolbar and tool-shell chrome owned by the assessment toolkit. */
144
177
  toolkit: {
@@ -159,17 +192,20 @@ declare const enUS: {
159
192
  moveRightA11y: string;
160
193
  moveUpA11y: string;
161
194
  moveDownA11y: string;
162
- shrinkA11y: string;
163
- growA11y: string;
195
+ narrowerA11y: string;
196
+ widerA11y: string;
197
+ shorterA11y: string;
198
+ tallerA11y: string;
164
199
  centerA11y: string;
165
200
  closeA11y: string;
166
201
  };
167
202
  /**
168
- * The tap controls that move and turn the ruler and protractor without a
203
+ * The tap controls that move, turn and resize a placed tool without a
169
204
  * drag. The move buttons reuse the `window` labels above.
170
205
  */
171
206
  placement: {
172
207
  controlsA11y: string;
208
+ moveAndResizeA11y: string;
173
209
  rotateClockwiseA11y: string;
174
210
  rotateCounterclockwiseA11y: string;
175
211
  };
@@ -209,6 +245,7 @@ declare const enUS: {
209
245
  toolA11y: string;
210
246
  loading: string;
211
247
  providerUnavailable: string;
248
+ initFailed: string;
212
249
  };
213
250
  graph: {
214
251
  name: string;
@@ -302,6 +339,15 @@ declare const enUS: {
302
339
  buttonA11y: string;
303
340
  tooltip: string;
304
341
  toolA11y: string;
342
+ notConfigured: string;
343
+ idleHint: string;
344
+ lookingUp: string;
345
+ noEntryFor: string;
346
+ entriesCount: {
347
+ one: string;
348
+ other: string;
349
+ };
350
+ noEntryStatusFor: string;
305
351
  };
306
352
  pictureDictionary: {
307
353
  name: string;
@@ -309,6 +355,15 @@ declare const enUS: {
309
355
  buttonA11y: string;
310
356
  tooltip: string;
311
357
  toolA11y: string;
358
+ notConfigured: string;
359
+ idleHint: string;
360
+ lookingUp: string;
361
+ noEntryFor: string;
362
+ entriesCount: {
363
+ one: string;
364
+ other: string;
365
+ };
366
+ noEntryStatusFor: string;
312
367
  };
313
368
  /**
314
369
  * The Spanish variants. Named in the interface locale like every other tool label —
@@ -341,10 +396,36 @@ declare const enUS: {
341
396
  windowHeightAnnounce: string;
342
397
  frameHeightAnnounce: string;
343
398
  widthAnnounce: string;
399
+ shorterWindowA11y: string;
400
+ tallerWindowA11y: string;
401
+ shorterFrameA11y: string;
402
+ tallerFrameA11y: string;
403
+ narrowerA11y: string;
404
+ widerA11y: string;
344
405
  applicationA11y: string;
345
406
  resizeWindowFullA11y: string;
346
407
  resizeFrameFullA11y: string;
347
408
  };
409
+ magnification: {
410
+ name: string;
411
+ description: string;
412
+ buttonA11y: string;
413
+ tooltip: string;
414
+ roleA11y: string;
415
+ applicationA11y: string;
416
+ zoomIn: string;
417
+ zoomOut: string;
418
+ zoomLevel: string;
419
+ zoomAnnounce: string;
420
+ close: string;
421
+ resizeA11y: string;
422
+ resizeFullA11y: string;
423
+ sizeAnnounce: string;
424
+ narrowerA11y: string;
425
+ widerA11y: string;
426
+ shorterA11y: string;
427
+ tallerA11y: string;
428
+ };
348
429
  answerEliminator: {
349
430
  name: string;
350
431
  description: string;
@@ -498,6 +579,30 @@ declare const enUS: {
498
579
  toggleEventPanelA11y: string;
499
580
  toggleDatabasePanelA11y: string;
500
581
  toggleInstrumentationPanelA11y: string;
582
+ clear: string;
583
+ pause: string;
584
+ resume: string;
585
+ controllerUnavailable: string;
586
+ noMatchingEvents: string;
587
+ noSectionSessionYet: string;
588
+ eventLevelItem: string;
589
+ eventLevelSection: string;
590
+ instrumentationKindAll: string;
591
+ instrumentationKindEvent: string;
592
+ instrumentationKindError: string;
593
+ instrumentationKindMetric: string;
594
+ instrumentationKindUserContext: string;
595
+ instrumentationKindGlobalAttributes: string;
596
+ instrumentationFieldName: string;
597
+ instrumentationFieldKind: string;
598
+ instrumentationFieldProvider: string;
599
+ instrumentationFieldTimestamp: string;
600
+ instrumentationFieldValue: string;
601
+ instrumentationFieldError: string;
602
+ sessionDbAssessmentId: string;
603
+ sessionDbSectionId: string;
604
+ sessionDbAttemptId: string;
605
+ sessionDbMode: string;
501
606
  /** PNP debugger. */
502
607
  pnp: {
503
608
  title: string;
@@ -517,6 +622,12 @@ declare const enUS: {
517
622
  perToolDecisions: string;
518
623
  policyDiagnostics: string;
519
624
  profileReadOnly: string;
625
+ on: string;
626
+ effective: string;
627
+ needs: string;
628
+ hostSurfaceNotPlaced: string;
629
+ support: string;
630
+ prohibit: string;
520
631
  };
521
632
  /** TTS settings panel. */
522
633
  tts: {
@@ -612,6 +723,16 @@ declare const enUS: {
612
723
  previewHintGoogleSsml: string;
613
724
  previewHintCustom: string;
614
725
  previewHintTracking: string;
726
+ formatMp3: string;
727
+ formatOgg: string;
728
+ formatPcm: string;
729
+ sampleRate8000: string;
730
+ sampleRate16000: string;
731
+ sampleRate22050: string;
732
+ sampleRate24000: string;
733
+ apiEndpointPlaceholder: string;
734
+ languagePlaceholder: string;
735
+ ssml: string;
615
736
  };
616
737
  };
617
738
  };