@longsightgroup/qti3-player 0.4.0 → 0.5.4
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/README.md +146 -13
- package/dist/content/content-dom.d.ts +11 -0
- package/dist/content/content-dom.d.ts.map +1 -0
- package/dist/content/content-dom.js +262 -0
- package/dist/content/content-dom.js.map +1 -0
- package/dist/content/content-renderer.d.ts +17 -0
- package/dist/content/content-renderer.d.ts.map +1 -0
- package/dist/content/content-renderer.js +82 -0
- package/dist/content/content-renderer.js.map +1 -0
- package/dist/controls/remove-button.d.ts +3 -0
- package/dist/controls/remove-button.d.ts.map +1 -0
- package/dist/controls/remove-button.js +12 -0
- package/dist/controls/remove-button.js.map +1 -0
- package/dist/index.d.ts +13 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/interactions/choice-interaction.d.ts +4 -0
- package/dist/interactions/choice-interaction.d.ts.map +1 -0
- package/dist/interactions/choice-interaction.js +81 -0
- package/dist/interactions/choice-interaction.js.map +1 -0
- package/dist/interactions/drawing-interaction.d.ts +6 -0
- package/dist/interactions/drawing-interaction.d.ts.map +1 -0
- package/dist/interactions/drawing-interaction.js +401 -0
- package/dist/interactions/drawing-interaction.js.map +1 -0
- package/dist/interactions/end-attempt-interaction.d.ts +4 -0
- package/dist/interactions/end-attempt-interaction.d.ts.map +1 -0
- package/dist/interactions/end-attempt-interaction.js +13 -0
- package/dist/interactions/end-attempt-interaction.js.map +1 -0
- package/dist/interactions/gap-match-interaction.d.ts +4 -0
- package/dist/interactions/gap-match-interaction.d.ts.map +1 -0
- package/dist/interactions/gap-match-interaction.js +277 -0
- package/dist/interactions/gap-match-interaction.js.map +1 -0
- package/dist/interactions/graphic-associate-interaction.d.ts +4 -0
- package/dist/interactions/graphic-associate-interaction.d.ts.map +1 -0
- package/dist/interactions/graphic-associate-interaction.js +297 -0
- package/dist/interactions/graphic-associate-interaction.js.map +1 -0
- package/dist/interactions/graphic-context.d.ts +3 -0
- package/dist/interactions/graphic-context.d.ts.map +1 -0
- package/dist/interactions/graphic-context.js +35 -0
- package/dist/interactions/graphic-context.js.map +1 -0
- package/dist/interactions/hotspot-interaction.d.ts +4 -0
- package/dist/interactions/hotspot-interaction.d.ts.map +1 -0
- package/dist/interactions/hotspot-interaction.js +68 -0
- package/dist/interactions/hotspot-interaction.js.map +1 -0
- package/dist/interactions/hottext-interaction.d.ts +3 -0
- package/dist/interactions/hottext-interaction.d.ts.map +1 -0
- package/dist/interactions/hottext-interaction.js +66 -0
- package/dist/interactions/hottext-interaction.js.map +1 -0
- package/dist/interactions/inline-choice-interaction.d.ts +4 -0
- package/dist/interactions/inline-choice-interaction.d.ts.map +1 -0
- package/dist/interactions/inline-choice-interaction.js +31 -0
- package/dist/interactions/inline-choice-interaction.js.map +1 -0
- package/dist/interactions/inline-controls.d.ts +6 -0
- package/dist/interactions/inline-controls.d.ts.map +1 -0
- package/dist/interactions/inline-controls.js +15 -0
- package/dist/interactions/inline-controls.js.map +1 -0
- package/dist/interactions/interaction-diagnostics.d.ts +7 -0
- package/dist/interactions/interaction-diagnostics.d.ts.map +1 -0
- package/dist/interactions/interaction-diagnostics.js +137 -0
- package/dist/interactions/interaction-diagnostics.js.map +1 -0
- package/dist/interactions/interaction-dispatch.d.ts +2 -0
- package/dist/interactions/interaction-dispatch.d.ts.map +1 -0
- package/dist/interactions/interaction-dispatch.js +2 -0
- package/dist/interactions/interaction-dispatch.js.map +1 -0
- package/dist/interactions/interaction-label.d.ts +4 -0
- package/dist/interactions/interaction-label.d.ts.map +1 -0
- package/dist/interactions/interaction-label.js +8 -0
- package/dist/interactions/interaction-label.js.map +1 -0
- package/dist/interactions/interaction-registry.d.ts +24 -0
- package/dist/interactions/interaction-registry.d.ts.map +1 -0
- package/dist/interactions/interaction-registry.js +138 -0
- package/dist/interactions/interaction-registry.js.map +1 -0
- package/dist/interactions/match-interaction.d.ts +4 -0
- package/dist/interactions/match-interaction.d.ts.map +1 -0
- package/dist/interactions/match-interaction.js +188 -0
- package/dist/interactions/match-interaction.js.map +1 -0
- package/dist/interactions/object-asset.d.ts +8 -0
- package/dist/interactions/object-asset.d.ts.map +1 -0
- package/dist/interactions/object-asset.js +182 -0
- package/dist/interactions/object-asset.js.map +1 -0
- package/dist/interactions/pair-interaction.d.ts +4 -0
- package/dist/interactions/pair-interaction.d.ts.map +1 -0
- package/dist/interactions/pair-interaction.js +125 -0
- package/dist/interactions/pair-interaction.js.map +1 -0
- package/dist/interactions/point-value.d.ts +16 -0
- package/dist/interactions/point-value.d.ts.map +1 -0
- package/dist/interactions/point-value.js +37 -0
- package/dist/interactions/point-value.js.map +1 -0
- package/dist/interactions/portable-custom-interaction.d.ts +16 -0
- package/dist/interactions/portable-custom-interaction.d.ts.map +1 -0
- package/dist/interactions/portable-custom-interaction.js +97 -0
- package/dist/interactions/portable-custom-interaction.js.map +1 -0
- package/dist/interactions/position-object-interaction.d.ts +4 -0
- package/dist/interactions/position-object-interaction.d.ts.map +1 -0
- package/dist/interactions/position-object-interaction.js +177 -0
- package/dist/interactions/position-object-interaction.js.map +1 -0
- package/dist/interactions/routing.d.ts +5 -0
- package/dist/interactions/routing.d.ts.map +1 -0
- package/dist/interactions/routing.js +24 -0
- package/dist/interactions/routing.js.map +1 -0
- package/dist/interactions/select-point-interaction.d.ts +4 -0
- package/dist/interactions/select-point-interaction.d.ts.map +1 -0
- package/dist/interactions/select-point-interaction.js +166 -0
- package/dist/interactions/select-point-interaction.js.map +1 -0
- package/dist/interactions/shared.d.ts +12 -0
- package/dist/interactions/shared.d.ts.map +1 -0
- package/dist/interactions/shared.js +65 -0
- package/dist/interactions/shared.js.map +1 -0
- package/dist/interactions/text-interaction.d.ts +6 -0
- package/dist/interactions/text-interaction.d.ts.map +1 -0
- package/dist/interactions/text-interaction.js +110 -0
- package/dist/interactions/text-interaction.js.map +1 -0
- package/dist/interactions/unsupported-interaction.d.ts +4 -0
- package/dist/interactions/unsupported-interaction.d.ts.map +1 -0
- package/dist/interactions/unsupported-interaction.js +23 -0
- package/dist/interactions/unsupported-interaction.js.map +1 -0
- package/dist/interactions/upload-interaction.d.ts +4 -0
- package/dist/interactions/upload-interaction.d.ts.map +1 -0
- package/dist/interactions/upload-interaction.js +10 -0
- package/dist/interactions/upload-interaction.js.map +1 -0
- package/dist/player/attempt-availability.d.ts +6 -0
- package/dist/player/attempt-availability.d.ts.map +1 -0
- package/dist/player/attempt-availability.js +27 -0
- package/dist/player/attempt-availability.js.map +1 -0
- package/dist/player/content-state.d.ts +19 -0
- package/dist/player/content-state.d.ts.map +1 -0
- package/dist/player/content-state.js +39 -0
- package/dist/player/content-state.js.map +1 -0
- package/dist/player/dynamic-body.d.ts +7 -0
- package/dist/player/dynamic-body.d.ts.map +1 -0
- package/dist/player/dynamic-body.js +28 -0
- package/dist/player/dynamic-body.js.map +1 -0
- package/dist/player/feedback-panel.d.ts +3 -0
- package/dist/player/feedback-panel.d.ts.map +1 -0
- package/dist/player/feedback-panel.js +14 -0
- package/dist/player/feedback-panel.js.map +1 -0
- package/dist/player/fetch-xml.d.ts +2 -0
- package/dist/player/fetch-xml.d.ts.map +1 -0
- package/dist/player/fetch-xml.js +10 -0
- package/dist/player/fetch-xml.js.map +1 -0
- package/dist/player/interaction-render.d.ts +14 -0
- package/dist/player/interaction-render.d.ts.map +1 -0
- package/dist/player/interaction-render.js +51 -0
- package/dist/player/interaction-render.js.map +1 -0
- package/dist/player/render-shell.d.ts +8 -0
- package/dist/player/render-shell.d.ts.map +1 -0
- package/dist/player/render-shell.js +37 -0
- package/dist/player/render-shell.js.map +1 -0
- package/dist/player/resolve-assets.d.ts +3 -0
- package/dist/player/resolve-assets.d.ts.map +1 -0
- package/dist/player/resolve-assets.js +12 -0
- package/dist/player/resolve-assets.js.map +1 -0
- package/dist/player/validation-messages.d.ts +17 -0
- package/dist/player/validation-messages.d.ts.map +1 -0
- package/dist/player/validation-messages.js +33 -0
- package/dist/player/validation-messages.js.map +1 -0
- package/dist/player-adapter.d.ts +62 -0
- package/dist/player-adapter.d.ts.map +1 -0
- package/dist/player-adapter.js +119 -0
- package/dist/player-adapter.js.map +1 -0
- package/dist/player-dev.d.ts +4 -0
- package/dist/player-dev.d.ts.map +1 -0
- package/dist/player-dev.js +14 -0
- package/dist/player-dev.js.map +1 -0
- package/dist/player-element.d.ts +14 -1
- package/dist/player-element.d.ts.map +1 -1
- package/dist/player-element.js +57 -5
- package/dist/player-element.js.map +1 -1
- package/dist/player-locale.d.ts +8 -3
- package/dist/player-locale.d.ts.map +1 -1
- package/dist/player-locale.js +16 -175
- package/dist/player-locale.js.map +1 -1
- package/dist/player-message-catalog-default.d.ts +4 -0
- package/dist/player-message-catalog-default.d.ts.map +1 -0
- package/dist/player-message-catalog-default.js +118 -0
- package/dist/player-message-catalog-default.js.map +1 -0
- package/dist/player-message-catalog-validate.d.ts +31 -0
- package/dist/player-message-catalog-validate.d.ts.map +1 -0
- package/dist/player-message-catalog-validate.js +327 -0
- package/dist/player-message-catalog-validate.js.map +1 -0
- package/dist/player-message-catalog.d.ts +18 -0
- package/dist/player-message-catalog.d.ts.map +1 -0
- package/dist/player-message-catalog.js +40 -0
- package/dist/player-message-catalog.js.map +1 -0
- package/dist/player-message-keys.d.ts +6 -0
- package/dist/player-message-keys.d.ts.map +1 -0
- package/dist/player-message-keys.js +7 -0
- package/dist/player-message-keys.js.map +1 -0
- package/dist/player-message-manifest.d.ts +272 -0
- package/dist/player-message-manifest.d.ts.map +1 -0
- package/dist/player-message-manifest.js +83 -0
- package/dist/player-message-manifest.js.map +1 -0
- package/dist/player-message-overrides.d.ts +3 -0
- package/dist/player-message-overrides.d.ts.map +1 -0
- package/dist/player-message-overrides.js +28 -0
- package/dist/player-message-overrides.js.map +1 -0
- package/dist/player-message-resolver.d.ts +31 -0
- package/dist/player-message-resolver.d.ts.map +1 -0
- package/dist/player-message-resolver.js +110 -0
- package/dist/player-message-resolver.js.map +1 -0
- package/dist/player-messages.d.ts +0 -38
- package/dist/player-messages.d.ts.map +1 -1
- package/dist/player-types.d.ts +12 -2
- package/dist/player-types.d.ts.map +1 -1
- package/dist/reorder/a11y.d.ts +7 -0
- package/dist/reorder/a11y.d.ts.map +1 -0
- package/dist/reorder/a11y.js +34 -0
- package/dist/reorder/a11y.js.map +1 -0
- package/dist/reorder/graphic-order-interaction.d.ts +4 -0
- package/dist/reorder/graphic-order-interaction.d.ts.map +1 -0
- package/dist/reorder/graphic-order-interaction.js +205 -0
- package/dist/reorder/graphic-order-interaction.js.map +1 -0
- package/dist/reorder/list-controls.d.ts +22 -0
- package/dist/reorder/list-controls.d.ts.map +1 -0
- package/dist/reorder/list-controls.js +75 -0
- package/dist/reorder/list-controls.js.map +1 -0
- package/dist/reorder/order-interaction.d.ts +4 -0
- package/dist/reorder/order-interaction.d.ts.map +1 -0
- package/dist/reorder/order-interaction.js +54 -0
- package/dist/reorder/order-interaction.js.map +1 -0
- package/dist/styles/base-styles.d.ts +2 -0
- package/dist/styles/base-styles.d.ts.map +1 -0
- package/dist/styles/base-styles.js +133 -0
- package/dist/styles/base-styles.js.map +1 -0
- package/dist/styles/choice-hottext-styles.d.ts +2 -0
- package/dist/styles/choice-hottext-styles.d.ts.map +1 -0
- package/dist/styles/choice-hottext-styles.js +76 -0
- package/dist/styles/choice-hottext-styles.js.map +1 -0
- package/dist/styles/control-styles.d.ts +2 -0
- package/dist/styles/control-styles.d.ts.map +1 -0
- package/dist/styles/control-styles.js +114 -0
- package/dist/styles/control-styles.js.map +1 -0
- package/dist/styles/drawing-styles.d.ts +2 -0
- package/dist/styles/drawing-styles.d.ts.map +1 -0
- package/dist/styles/drawing-styles.js +30 -0
- package/dist/styles/drawing-styles.js.map +1 -0
- package/dist/styles/gap-match-styles.d.ts +2 -0
- package/dist/styles/gap-match-styles.d.ts.map +1 -0
- package/dist/styles/gap-match-styles.js +33 -0
- package/dist/styles/gap-match-styles.js.map +1 -0
- package/dist/styles/graphic-styles.d.ts +2 -0
- package/dist/styles/graphic-styles.d.ts.map +1 -0
- package/dist/styles/graphic-styles.js +289 -0
- package/dist/styles/graphic-styles.js.map +1 -0
- package/dist/styles/match-pair-styles.d.ts +2 -0
- package/dist/styles/match-pair-styles.d.ts.map +1 -0
- package/dist/styles/match-pair-styles.js +62 -0
- package/dist/styles/match-pair-styles.js.map +1 -0
- package/dist/styles/text-slider-styles.d.ts +2 -0
- package/dist/styles/text-slider-styles.d.ts.map +1 -0
- package/dist/styles/text-slider-styles.js +35 -0
- package/dist/styles/text-slider-styles.js.map +1 -0
- package/package.json +8 -8
- package/src/controls/remove-button.ts +8 -5
- package/src/index.ts +61 -5
- package/src/interactions/choice-interaction.ts +6 -2
- package/src/interactions/drawing-interaction.ts +14 -9
- package/src/interactions/end-attempt-interaction.ts +3 -3
- package/src/interactions/gap-match-interaction.ts +32 -13
- package/src/interactions/graphic-associate-interaction.ts +15 -10
- package/src/interactions/hotspot-interaction.ts +10 -6
- package/src/interactions/inline-choice-interaction.ts +4 -4
- package/src/interactions/interaction-registry.ts +12 -12
- package/src/interactions/match-interaction.ts +9 -6
- package/src/interactions/pair-interaction.ts +22 -14
- package/src/interactions/position-object-interaction.ts +22 -13
- package/src/interactions/select-point-interaction.ts +25 -13
- package/src/interactions/shared.ts +21 -4
- package/src/interactions/text-interaction.ts +14 -4
- package/src/interactions/upload-interaction.ts +6 -3
- package/src/player/interaction-render.ts +4 -4
- package/src/player-adapter.ts +253 -0
- package/src/player-dev.ts +14 -0
- package/src/player-element.ts +78 -8
- package/src/player-locale.ts +28 -199
- package/src/player-message-catalog-default.ts +119 -0
- package/src/player-message-catalog-validate.ts +425 -0
- package/src/player-message-catalog.ts +72 -0
- package/src/player-message-keys.ts +12 -0
- package/src/player-message-manifest.ts +103 -0
- package/src/player-message-overrides.ts +38 -0
- package/src/player-message-resolver.ts +205 -0
- package/src/player-messages.ts +0 -30
- package/src/player-types.ts +15 -4
- package/src/reorder/a11y.ts +22 -7
- package/src/reorder/graphic-order-interaction.ts +23 -16
- package/src/reorder/list-controls.ts +8 -6
- package/src/reorder/order-interaction.ts +7 -5
- package/src/styles/base-styles.ts +20 -5
- package/src/styles/graphic-styles.ts +0 -6
package/src/player-element.ts
CHANGED
|
@@ -26,7 +26,12 @@ import {
|
|
|
26
26
|
collectEmbeddedInteractionDiagnostics,
|
|
27
27
|
collectInteractionRenderDiagnostics,
|
|
28
28
|
} from "./interactions/interaction-diagnostics.js";
|
|
29
|
+
import type { PlayerMessageCatalog } from "./player-message-catalog.js";
|
|
29
30
|
import { defaultPlayerLocale, normalizedLocale, resolvePlayerMessages } from "./player-locale.js";
|
|
31
|
+
import type {
|
|
32
|
+
PlayerMessageResolver,
|
|
33
|
+
QtiPlayerMessageOverrides,
|
|
34
|
+
} from "./player-message-resolver.js";
|
|
30
35
|
import { syncAttemptAvailability } from "./player/attempt-availability.js";
|
|
31
36
|
import {
|
|
32
37
|
currentTemplateValue,
|
|
@@ -48,7 +53,6 @@ import type {
|
|
|
48
53
|
QtiAssessmentItemPlayerEventDetailMap,
|
|
49
54
|
QtiAssessmentItemPlayerEventName,
|
|
50
55
|
QtiPlayerLoadOptions,
|
|
51
|
-
QtiPlayerMessageOverrides,
|
|
52
56
|
QtiPlayerResolveAsset,
|
|
53
57
|
QtiPlayerSessionControl,
|
|
54
58
|
QtiScoreAttemptOptions,
|
|
@@ -80,11 +84,14 @@ export class QtiAssessmentItemPlayer extends HTMLElementBase {
|
|
|
80
84
|
private validationMessages: QtiDiagnostic[] = [];
|
|
81
85
|
private authoringDiagnostics: QtiDiagnostic[] = [];
|
|
82
86
|
private languageOfInterfaceOverride: string | undefined;
|
|
87
|
+
private messageCatalogOverride: PlayerMessageCatalog | undefined;
|
|
83
88
|
private messageOverrides: QtiPlayerMessageOverrides = {};
|
|
89
|
+
private resolvedMessagesCache: PlayerMessageResolver | undefined;
|
|
84
90
|
private sessionControl: Required<QtiPlayerSessionControl> = {
|
|
85
91
|
validateResponses: true,
|
|
86
92
|
showFeedback: true,
|
|
87
93
|
};
|
|
94
|
+
private loadGeneration = 0;
|
|
88
95
|
|
|
89
96
|
get languageOfInterface(): string {
|
|
90
97
|
return (
|
|
@@ -97,6 +104,7 @@ export class QtiAssessmentItemPlayer extends HTMLElementBase {
|
|
|
97
104
|
|
|
98
105
|
set languageOfInterface(value: string | undefined) {
|
|
99
106
|
this.languageOfInterfaceOverride = normalizedLocale(value);
|
|
107
|
+
this.invalidatePlayerMessages();
|
|
100
108
|
this.rerenderIfLoaded();
|
|
101
109
|
}
|
|
102
110
|
|
|
@@ -114,6 +122,17 @@ export class QtiAssessmentItemPlayer extends HTMLElementBase {
|
|
|
114
122
|
|
|
115
123
|
set messages(value: QtiPlayerMessageOverrides | undefined) {
|
|
116
124
|
this.messageOverrides = value ?? {};
|
|
125
|
+
this.invalidatePlayerMessages();
|
|
126
|
+
this.rerenderIfLoaded();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
get messageCatalog(): PlayerMessageCatalog | undefined {
|
|
130
|
+
return this.messageCatalogOverride;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
set messageCatalog(value: PlayerMessageCatalog | undefined) {
|
|
134
|
+
this.messageCatalogOverride = value;
|
|
135
|
+
this.invalidatePlayerMessages();
|
|
117
136
|
this.rerenderIfLoaded();
|
|
118
137
|
}
|
|
119
138
|
|
|
@@ -121,15 +140,59 @@ export class QtiAssessmentItemPlayer extends HTMLElementBase {
|
|
|
121
140
|
if ((name !== "language-of-interface" && name !== "locale") || oldValue === newValue) {
|
|
122
141
|
return;
|
|
123
142
|
}
|
|
143
|
+
this.invalidatePlayerMessages();
|
|
124
144
|
this.rerenderIfLoaded();
|
|
125
145
|
}
|
|
126
146
|
|
|
147
|
+
private invalidatePlayerMessages(): void {
|
|
148
|
+
this.resolvedMessagesCache = undefined;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** Clears the loaded item. Does not emit player events; declarative hosts control this via `xml`. */
|
|
152
|
+
clearItem(): void {
|
|
153
|
+
this.loadGeneration += 1;
|
|
154
|
+
delete this.documentModel;
|
|
155
|
+
delete this.session;
|
|
156
|
+
this.validationMessages = [];
|
|
157
|
+
this.authoringDiagnostics = [];
|
|
158
|
+
this.replaceChildren();
|
|
159
|
+
}
|
|
160
|
+
|
|
127
161
|
async loadXml(xml: string, options: QtiPlayerLoadOptions = {}): Promise<void> {
|
|
162
|
+
const generation = this.beginLoad();
|
|
163
|
+
await this.applyLoadedXml(generation, xml, options);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
async loadUrl(url: string, options: QtiPlayerLoadOptions = {}): Promise<void> {
|
|
167
|
+
const generation = this.beginLoad();
|
|
168
|
+
const fetchXml = options.fetchXml ?? defaultFetchXml;
|
|
169
|
+
const xml = await fetchXml(url);
|
|
170
|
+
if (!this.isCurrentLoad(generation)) return;
|
|
171
|
+
await this.applyLoadedXml(generation, xml, options);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
private beginLoad(): number {
|
|
175
|
+
this.loadGeneration += 1;
|
|
176
|
+
return this.loadGeneration;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
private isCurrentLoad(generation: number): boolean {
|
|
180
|
+
return generation === this.loadGeneration;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
private async applyLoadedXml(
|
|
184
|
+
generation: number,
|
|
185
|
+
xml: string,
|
|
186
|
+
options: QtiPlayerLoadOptions,
|
|
187
|
+
): Promise<void> {
|
|
188
|
+
if (!this.isCurrentLoad(generation)) return;
|
|
189
|
+
|
|
128
190
|
this.sessionControl = {
|
|
129
191
|
validateResponses: options.sessionControl?.validateResponses ?? true,
|
|
130
192
|
showFeedback: options.sessionControl?.showFeedback ?? true,
|
|
131
193
|
};
|
|
132
194
|
this.resolveAsset = options.resolveAsset;
|
|
195
|
+
|
|
133
196
|
const result = parseQtiXml(xml);
|
|
134
197
|
const playerDiagnostics = result.document
|
|
135
198
|
? [
|
|
@@ -137,6 +200,8 @@ export class QtiAssessmentItemPlayer extends HTMLElementBase {
|
|
|
137
200
|
...collectEmbeddedInteractionDiagnostics(result.document.item),
|
|
138
201
|
]
|
|
139
202
|
: [];
|
|
203
|
+
if (!this.isCurrentLoad(generation)) return;
|
|
204
|
+
|
|
140
205
|
this.dispatchEvent(
|
|
141
206
|
new CustomEvent("qti-diagnostics", {
|
|
142
207
|
detail: { diagnostics: [...result.diagnostics, ...playerDiagnostics] },
|
|
@@ -146,10 +211,13 @@ export class QtiAssessmentItemPlayer extends HTMLElementBase {
|
|
|
146
211
|
playerDiagnostics.filter((diagnostic) => diagnostic.severity === "error"),
|
|
147
212
|
);
|
|
148
213
|
if (!result.document) {
|
|
214
|
+
if (!this.isCurrentLoad(generation)) return;
|
|
149
215
|
this.replaceChildren(errorView("Unable to parse QTI item."));
|
|
150
216
|
return;
|
|
151
217
|
}
|
|
152
218
|
|
|
219
|
+
if (!this.isCurrentLoad(generation)) return;
|
|
220
|
+
|
|
153
221
|
this.documentModel = result.document;
|
|
154
222
|
this.session = createItemSession(result.document, options.state);
|
|
155
223
|
this.validationMessages = cloneDiagnostics(
|
|
@@ -163,11 +231,6 @@ export class QtiAssessmentItemPlayer extends HTMLElementBase {
|
|
|
163
231
|
this.emitStateChange();
|
|
164
232
|
}
|
|
165
233
|
|
|
166
|
-
async loadUrl(url: string, options: QtiPlayerLoadOptions = {}): Promise<void> {
|
|
167
|
-
const fetchXml = options.fetchXml ?? defaultFetchXml;
|
|
168
|
-
await this.loadXml(await fetchXml(url), options);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
234
|
scoreAttempt(options: QtiScoreAttemptOptions = {}): QtiScoreResult | undefined {
|
|
172
235
|
const session = this.session;
|
|
173
236
|
if (!session) return undefined;
|
|
@@ -288,8 +351,15 @@ export class QtiAssessmentItemPlayer extends HTMLElementBase {
|
|
|
288
351
|
this.dispatchEvent(new CustomEvent<QtiAssessmentItemPlayerEventDetailMap[T]>(type, { detail }));
|
|
289
352
|
}
|
|
290
353
|
|
|
291
|
-
private playerMessages() {
|
|
292
|
-
|
|
354
|
+
private playerMessages(): PlayerMessageResolver {
|
|
355
|
+
if (!this.resolvedMessagesCache) {
|
|
356
|
+
this.resolvedMessagesCache = resolvePlayerMessages(
|
|
357
|
+
this.languageOfInterface,
|
|
358
|
+
this.messageOverrides,
|
|
359
|
+
this.messageCatalogOverride,
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
return this.resolvedMessagesCache;
|
|
293
363
|
}
|
|
294
364
|
|
|
295
365
|
private rerenderIfLoaded(): void {
|
package/src/player-locale.ts
CHANGED
|
@@ -1,206 +1,35 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
associationPairLabel: ({ source, target }) => `${source} to ${target}`,
|
|
21
|
-
hotspotSelectedChooseAnother: ({ label }) => `${label} selected. Choose another hotspot.`,
|
|
22
|
-
moveChoice: ({ label, direction }) => `Move ${label} ${direction}`,
|
|
23
|
-
movePoint: ({ direction }) => `Move point ${direction}`,
|
|
24
|
-
moveObject: ({ direction }) => `Move object ${direction}`,
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const playerMessages = {
|
|
28
|
-
defaultEnglish: defaultEnglishPlayerMessages,
|
|
29
|
-
spanish: {
|
|
30
|
-
remove: () => "Quitar",
|
|
31
|
-
removePair: ({ label }) => `Quitar ${label}`,
|
|
32
|
-
clearDrawing: () => "Borrar dibujo",
|
|
33
|
-
clearPoints: () => "Borrar puntos",
|
|
34
|
-
endAttempt: () => "Finalizar intento",
|
|
35
|
-
uploadResponse: () => "Subir respuesta",
|
|
36
|
-
movableObject: () => "Objeto movible",
|
|
37
|
-
placeObject: () => "Colocar",
|
|
38
|
-
inlineChoicePrompt: () => "Elija...",
|
|
39
|
-
noPointSelected: () => "Ningun punto seleccionado",
|
|
40
|
-
noRegionSelected: () => "Ninguna region seleccionada",
|
|
41
|
-
noAssociationsMade: () => "Ninguna asociacion realizada",
|
|
42
|
-
associationsMade: ({ count }) =>
|
|
43
|
-
`${count} ${count === 1 ? "asociacion realizada" : "asociaciones realizadas"}.`,
|
|
44
|
-
associationPairLabel: ({ source, target }) => `${source} con ${target}`,
|
|
45
|
-
hotspotSelectedChooseAnother: ({ label }) => `${label} seleccionado. Elija otro punto activo.`,
|
|
46
|
-
moveChoice: ({ label, direction }) => `Mover ${label} ${spanishDirection(direction)}`,
|
|
47
|
-
movePoint: ({ direction }) => `Mover punto ${spanishDirection(direction)}`,
|
|
48
|
-
moveObject: ({ direction }) => `Mover objeto ${spanishDirection(direction)}`,
|
|
49
|
-
},
|
|
50
|
-
swedish: {
|
|
51
|
-
remove: () => "Ta bort",
|
|
52
|
-
removePair: ({ label }) => `Ta bort ${label}`,
|
|
53
|
-
clearDrawing: () => "Rensa ritning",
|
|
54
|
-
clearPoints: () => "Rensa punkter",
|
|
55
|
-
endAttempt: () => "Avsluta forsok",
|
|
56
|
-
uploadResponse: () => "Ladda upp svar",
|
|
57
|
-
movableObject: () => "Flyttbart objekt",
|
|
58
|
-
placeObject: () => "Placera",
|
|
59
|
-
inlineChoicePrompt: () => "Valj...",
|
|
60
|
-
noPointSelected: () => "Ingen punkt vald",
|
|
61
|
-
noRegionSelected: () => "Ingen region vald",
|
|
62
|
-
noAssociationsMade: () => "Inga associationer gjorda",
|
|
63
|
-
associationsMade: ({ count }) =>
|
|
64
|
-
`${count} ${count === 1 ? "association gjord" : "associationer gjorda"}.`,
|
|
65
|
-
associationPairLabel: ({ source, target }) => `${source} med ${target}`,
|
|
66
|
-
hotspotSelectedChooseAnother: ({ label }) => `${label} valt. Valj en annan hotspot.`,
|
|
67
|
-
moveChoice: ({ label, direction }) => `Flytta ${label} ${swedishDirection(direction)}`,
|
|
68
|
-
movePoint: ({ direction }) => `Flytta punkt ${swedishDirection(direction)}`,
|
|
69
|
-
moveObject: ({ direction }) => `Flytta objekt ${swedishDirection(direction)}`,
|
|
70
|
-
},
|
|
71
|
-
german: {
|
|
72
|
-
remove: () => "Entfernen",
|
|
73
|
-
removePair: ({ label }) => `${label} entfernen`,
|
|
74
|
-
clearDrawing: () => "Zeichnung loeschen",
|
|
75
|
-
clearPoints: () => "Punkte loeschen",
|
|
76
|
-
endAttempt: () => "Versuch beenden",
|
|
77
|
-
uploadResponse: () => "Antwort hochladen",
|
|
78
|
-
movableObject: () => "Bewegliches Objekt",
|
|
79
|
-
placeObject: () => "Platzieren",
|
|
80
|
-
inlineChoicePrompt: () => "Waehlen...",
|
|
81
|
-
noPointSelected: () => "Kein Punkt ausgewaehlt",
|
|
82
|
-
noRegionSelected: () => "Keine Region ausgewaehlt",
|
|
83
|
-
noAssociationsMade: () => "Keine Zuordnungen erstellt",
|
|
84
|
-
associationsMade: ({ count }) =>
|
|
85
|
-
`${count} ${count === 1 ? "Zuordnung erstellt" : "Zuordnungen erstellt"}.`,
|
|
86
|
-
associationPairLabel: ({ source, target }) => `${source} mit ${target}`,
|
|
87
|
-
hotspotSelectedChooseAnother: ({ label }) =>
|
|
88
|
-
`${label} ausgewaehlt. Waehlen Sie einen weiteren Hotspot.`,
|
|
89
|
-
moveChoice: ({ label, direction }) => `${label} ${germanDirection(direction)} bewegen`,
|
|
90
|
-
movePoint: ({ direction }) => `Punkt ${germanDirection(direction)} bewegen`,
|
|
91
|
-
moveObject: ({ direction }) => `Objekt ${germanDirection(direction)} bewegen`,
|
|
92
|
-
},
|
|
93
|
-
portuguese: {
|
|
94
|
-
remove: () => "Remover",
|
|
95
|
-
removePair: ({ label }) => `Remover ${label}`,
|
|
96
|
-
clearDrawing: () => "Limpar desenho",
|
|
97
|
-
clearPoints: () => "Limpar pontos",
|
|
98
|
-
endAttempt: () => "Finalizar tentativa",
|
|
99
|
-
uploadResponse: () => "Enviar resposta",
|
|
100
|
-
movableObject: () => "Objeto movel",
|
|
101
|
-
placeObject: () => "Posicionar",
|
|
102
|
-
inlineChoicePrompt: () => "Escolha...",
|
|
103
|
-
noPointSelected: () => "Nenhum ponto selecionado",
|
|
104
|
-
noRegionSelected: () => "Nenhuma regiao selecionada",
|
|
105
|
-
noAssociationsMade: () => "Nenhuma associacao feita",
|
|
106
|
-
associationsMade: ({ count }) =>
|
|
107
|
-
`${count} ${count === 1 ? "associacao feita" : "associacoes feitas"}.`,
|
|
108
|
-
associationPairLabel: ({ source, target }) => `${source} com ${target}`,
|
|
109
|
-
hotspotSelectedChooseAnother: ({ label }) => `${label} selecionado. Escolha outro ponto ativo.`,
|
|
110
|
-
moveChoice: ({ label, direction }) => `Mover ${label} ${portugueseDirection(direction)}`,
|
|
111
|
-
movePoint: ({ direction }) => `Mover ponto ${portugueseDirection(direction)}`,
|
|
112
|
-
moveObject: ({ direction }) => `Mover objeto ${portugueseDirection(direction)}`,
|
|
113
|
-
},
|
|
114
|
-
french: {
|
|
115
|
-
remove: () => "Supprimer",
|
|
116
|
-
removePair: ({ label }) => `Supprimer ${label}`,
|
|
117
|
-
clearDrawing: () => "Effacer le dessin",
|
|
118
|
-
clearPoints: () => "Effacer les points",
|
|
119
|
-
endAttempt: () => "Terminer la tentative",
|
|
120
|
-
uploadResponse: () => "Televerser la reponse",
|
|
121
|
-
movableObject: () => "Objet mobile",
|
|
122
|
-
placeObject: () => "Placer",
|
|
123
|
-
inlineChoicePrompt: () => "Choisir...",
|
|
124
|
-
noPointSelected: () => "Aucun point selectionne",
|
|
125
|
-
noRegionSelected: () => "Aucune region selectionnee",
|
|
126
|
-
noAssociationsMade: () => "Aucune association effectuee",
|
|
127
|
-
associationsMade: ({ count }) =>
|
|
128
|
-
`${count} ${count === 1 ? "association effectuee" : "associations effectuees"}.`,
|
|
129
|
-
associationPairLabel: ({ source, target }) => `${source} avec ${target}`,
|
|
130
|
-
hotspotSelectedChooseAnother: ({ label }) =>
|
|
131
|
-
`${label} selectionne. Choisissez un autre point actif.`,
|
|
132
|
-
moveChoice: ({ label, direction }) => `Deplacer ${label} vers ${frenchDirection(direction)}`,
|
|
133
|
-
movePoint: ({ direction }) => `Deplacer le point vers ${frenchDirection(direction)}`,
|
|
134
|
-
moveObject: ({ direction }) => `Deplacer l'objet vers ${frenchDirection(direction)}`,
|
|
135
|
-
},
|
|
136
|
-
} satisfies Record<string, QtiPlayerMessageCatalog>;
|
|
137
|
-
|
|
138
|
-
const builtInPlayerMessageCatalogs: ReadonlyMap<string, QtiPlayerMessageCatalog> = new Map([
|
|
139
|
-
["en", playerMessages.defaultEnglish],
|
|
140
|
-
["es", playerMessages.spanish],
|
|
141
|
-
["es-es", playerMessages.spanish],
|
|
142
|
-
["es-mx", playerMessages.spanish],
|
|
143
|
-
["sv", playerMessages.swedish],
|
|
144
|
-
["sv-se", playerMessages.swedish],
|
|
145
|
-
["de", playerMessages.german],
|
|
146
|
-
["de-de", playerMessages.german],
|
|
147
|
-
["pt", playerMessages.portuguese],
|
|
148
|
-
["pt-br", playerMessages.portuguese],
|
|
149
|
-
["pt-pt", playerMessages.portuguese],
|
|
150
|
-
["fr", playerMessages.french],
|
|
151
|
-
["fr-ca", playerMessages.french],
|
|
152
|
-
["fr-fr", playerMessages.french],
|
|
153
|
-
]);
|
|
154
|
-
|
|
1
|
+
import type { PlayerMessageCatalog } from "./player-message-catalog.js";
|
|
2
|
+
import { applyPlayerMessageOverrides } from "./player-message-overrides.js";
|
|
3
|
+
import {
|
|
4
|
+
createPlayerMessageResolver,
|
|
5
|
+
defaultPlayerMessageResolver,
|
|
6
|
+
type PlayerMessageResolver,
|
|
7
|
+
} from "./player-message-resolver.js";
|
|
8
|
+
import { warnPlayerMessageOnce } from "./player-dev.js";
|
|
9
|
+
import type { QtiPlayerMessageOverrides } from "./player-message-resolver.js";
|
|
10
|
+
|
|
11
|
+
function isEnglishLocale(locale: string): boolean {
|
|
12
|
+
const normalized = normalizedLocale(locale) ?? locale;
|
|
13
|
+
return normalized.toLowerCase().startsWith("en");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Resolves player chrome messages: catalog (or English defaults) merged with overrides.
|
|
18
|
+
* `locale` does not select built-in catalogs; use `catalog` via `player.messageCatalog`.
|
|
19
|
+
*/
|
|
155
20
|
export function resolvePlayerMessages(
|
|
156
21
|
locale: string,
|
|
157
22
|
overrides: QtiPlayerMessageOverrides,
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function swedishDirection(direction: "up" | "down" | "left" | "right"): string {
|
|
168
|
-
return { up: "upp", down: "ned", left: "vanster", right: "hoger" }[direction];
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
function germanDirection(direction: "up" | "down" | "left" | "right"): string {
|
|
172
|
-
return { up: "nach oben", down: "nach unten", left: "nach links", right: "nach rechts" }[
|
|
173
|
-
direction
|
|
174
|
-
];
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
function portugueseDirection(direction: "up" | "down" | "left" | "right"): string {
|
|
178
|
-
return { up: "para cima", down: "para baixo", left: "para a esquerda", right: "para a direita" }[
|
|
179
|
-
direction
|
|
180
|
-
];
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
function frenchDirection(direction: "up" | "down" | "left" | "right"): string {
|
|
184
|
-
return { up: "le haut", down: "le bas", left: "la gauche", right: "la droite" }[direction];
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
function builtInPlayerMessageCatalog(locale: string): QtiPlayerMessageCatalog | undefined {
|
|
188
|
-
for (const candidate of localeFallbacks(locale)) {
|
|
189
|
-
const catalog = builtInPlayerMessageCatalogs.get(candidate);
|
|
190
|
-
if (catalog) return catalog;
|
|
191
|
-
}
|
|
192
|
-
return undefined;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
function localeFallbacks(locale: string): string[] {
|
|
196
|
-
const normalized = normalizedLocale(locale)?.toLowerCase();
|
|
197
|
-
if (!normalized) return ["en"];
|
|
198
|
-
const parts = normalized.split("-");
|
|
199
|
-
const fallbacks: string[] = [];
|
|
200
|
-
for (let length = parts.length; length > 0; length -= 1) {
|
|
201
|
-
fallbacks.push(parts.slice(0, length).join("-"));
|
|
23
|
+
catalog?: PlayerMessageCatalog,
|
|
24
|
+
): PlayerMessageResolver {
|
|
25
|
+
if (!catalog && !isEnglishLocale(locale) && Object.keys(overrides).length === 0) {
|
|
26
|
+
warnPlayerMessageOnce(
|
|
27
|
+
`locale-without-catalog:${locale}`,
|
|
28
|
+
`language-of-interface is "${locale}" but no player.messageCatalog was set; chrome stays English. Load a locale file and assign player.messageCatalog.`,
|
|
29
|
+
);
|
|
202
30
|
}
|
|
203
|
-
|
|
31
|
+
const base = catalog ? createPlayerMessageResolver(catalog) : defaultPlayerMessageResolver;
|
|
32
|
+
return applyPlayerMessageOverrides(base, overrides);
|
|
204
33
|
}
|
|
205
34
|
|
|
206
35
|
export function normalizedLocale(value: string | undefined | null): string | undefined {
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { PlayerMessageCatalog } from "./player-message-catalog.js";
|
|
2
|
+
|
|
3
|
+
/** English player chrome catalog (JSON-serializable). Hosts copy this shape for locale files. */
|
|
4
|
+
export const defaultPlayerMessageCatalog: PlayerMessageCatalog = {
|
|
5
|
+
locale: "en",
|
|
6
|
+
directions: {
|
|
7
|
+
up: "up",
|
|
8
|
+
down: "down",
|
|
9
|
+
left: "left",
|
|
10
|
+
right: "right",
|
|
11
|
+
},
|
|
12
|
+
interactionTypes: {
|
|
13
|
+
associate: "Associate",
|
|
14
|
+
choice: "Choice",
|
|
15
|
+
drawing: "Drawing",
|
|
16
|
+
endAttempt: "End attempt",
|
|
17
|
+
extendedText: "Extended text",
|
|
18
|
+
gapMatch: "Gap match",
|
|
19
|
+
graphicAssociate: "Graphic associate",
|
|
20
|
+
graphicGapMatch: "Graphic gap match",
|
|
21
|
+
graphicOrder: "Graphic order",
|
|
22
|
+
hottext: "Hot text",
|
|
23
|
+
hotspot: "Hotspot",
|
|
24
|
+
inlineChoice: "Inline choice",
|
|
25
|
+
match: "Match",
|
|
26
|
+
media: "Media",
|
|
27
|
+
order: "Order",
|
|
28
|
+
pair: "Pair",
|
|
29
|
+
portableCustom: "Portable custom",
|
|
30
|
+
positionObject: "Position object",
|
|
31
|
+
selectPoint: "Select point",
|
|
32
|
+
slider: "Slider",
|
|
33
|
+
textEntry: "Text entry",
|
|
34
|
+
upload: "Upload",
|
|
35
|
+
},
|
|
36
|
+
strings: {
|
|
37
|
+
remove: "Remove",
|
|
38
|
+
removePair: "Remove {label}",
|
|
39
|
+
clearDrawing: "Clear drawing",
|
|
40
|
+
clearPoints: "Clear points",
|
|
41
|
+
endAttempt: "End attempt",
|
|
42
|
+
uploadResponse: "Upload response",
|
|
43
|
+
movableObject: "Movable object",
|
|
44
|
+
placeObject: "Place",
|
|
45
|
+
inlineChoicePrompt: "Choose...",
|
|
46
|
+
extendedTextCounter: "{characters} {characterUnit}, {words} {wordUnit}",
|
|
47
|
+
"characterUnit.one": "character",
|
|
48
|
+
"characterUnit.other": "characters",
|
|
49
|
+
"wordUnit.one": "word",
|
|
50
|
+
"wordUnit.other": "words",
|
|
51
|
+
hotspotSelectionSummary: "Selected {selection}",
|
|
52
|
+
noPointSelected: "No point selected",
|
|
53
|
+
noRegionSelected: "No region selected",
|
|
54
|
+
noAssociationsMade: "No associations made",
|
|
55
|
+
"associationsMade.one": "{count} association made.",
|
|
56
|
+
"associationsMade.other": "{count} associations made.",
|
|
57
|
+
associationPairLabel: "{source} to {target}",
|
|
58
|
+
hotspotSelectedChooseAnother: "{label} selected. Choose another hotspot.",
|
|
59
|
+
moveChoice: "Move {label} {direction}",
|
|
60
|
+
movePoint: "Move point {direction}",
|
|
61
|
+
moveObject: "Move object {direction}",
|
|
62
|
+
matchSourcesBank: "Match sources",
|
|
63
|
+
matchTargetsBank: "Match targets",
|
|
64
|
+
matchSelectedPairsList: "Match selected pairs",
|
|
65
|
+
interactionSourcesBank: "{typeName} sources",
|
|
66
|
+
interactionTargetsBank: "{typeName} targets",
|
|
67
|
+
interactionSelectedPairsList: "{typeName} selected pairs",
|
|
68
|
+
associateFirstConceptRegion: "First concept",
|
|
69
|
+
associatePairWithRegion: "Pair with",
|
|
70
|
+
matchPromptRegion: "Prompt",
|
|
71
|
+
matchMatchRegion: "Match",
|
|
72
|
+
genericSourceRegion: "Source",
|
|
73
|
+
genericTargetRegion: "Target",
|
|
74
|
+
interactionHotspots: "{typeName} hotspots",
|
|
75
|
+
interactionImageAlt: "{typeName} image",
|
|
76
|
+
interactionCurrentOrderList: "{typeName} current order",
|
|
77
|
+
interactionSelectedOrderList: "{typeName} selected order",
|
|
78
|
+
interactionChoicesBank: "{typeName} choices",
|
|
79
|
+
interactionGapTargets: "{typeName} targets",
|
|
80
|
+
interactionTargetImage: "{typeName} target image",
|
|
81
|
+
interactionOptionsList: "{typeName} options",
|
|
82
|
+
interactionCoordinateResponse: "{typeName} coordinate response",
|
|
83
|
+
interactionCoordinateArea: "{typeName} coordinate area",
|
|
84
|
+
interactionCoordinateAreaSelected: "{typeName} coordinate area, selected {coordinates}",
|
|
85
|
+
interactionPlacementResponse: "{typeName} object placement response",
|
|
86
|
+
interactionPlacementStage: "{typeName} placement stage",
|
|
87
|
+
interactionPlacementStageEmpty: "{typeName} placement stage, object not placed",
|
|
88
|
+
interactionPlacementStageAt: "{typeName} placement stage, object at {coordinates}",
|
|
89
|
+
interactionDrawingResponse: "{typeName} response",
|
|
90
|
+
drawingSurface: "Drawing response surface",
|
|
91
|
+
drawingSurfaceEmpty: "Drawing response surface, no strokes",
|
|
92
|
+
"drawingSurfaceStrokeCount.one": "Drawing response surface, {count} stroke",
|
|
93
|
+
"drawingSurfaceStrokeCount.other": "Drawing response surface, {count} strokes",
|
|
94
|
+
drawingStatusEmpty: "No drawing strokes.",
|
|
95
|
+
"drawingStatusStrokeCount.one": "{count} drawing stroke.",
|
|
96
|
+
"drawingStatusStrokeCount.other": "{count} drawing strokes.",
|
|
97
|
+
gapLabel: "Gap {index}",
|
|
98
|
+
graphicGapTargetLabel: "Target {index}",
|
|
99
|
+
gapEmptyState: "{label}, empty",
|
|
100
|
+
gapAssignedState: "{label}, assigned {assigned}",
|
|
101
|
+
"gapLabelsPlacedCount.one": "{count} label placed.",
|
|
102
|
+
"gapLabelsPlacedCount.other": "{count} labels placed.",
|
|
103
|
+
gapNoLabelsPlaced: "No labels placed.",
|
|
104
|
+
orderedItemAtPosition: "{label}, position {position} of {total}",
|
|
105
|
+
orderedItemMovedOneStep: "{label} moved {direction}.",
|
|
106
|
+
orderedItemMovedToPosition: "{label} moved to position {position} of {total}.",
|
|
107
|
+
"graphicOrderRegionsSelected.one": "{count} region ordered.",
|
|
108
|
+
"graphicOrderRegionsSelected.other": "{count} regions ordered.",
|
|
109
|
+
graphicOrderNoRegionsSelected: "No regions ordered.",
|
|
110
|
+
objectNotPlaced: "Object not placed",
|
|
111
|
+
objectPositionedAt: "Object positioned at {coordinates}",
|
|
112
|
+
selectedPointAt: "Selected point {coordinates}",
|
|
113
|
+
"selectedPointsSummary.one": "{count} selected point: {coordinates}",
|
|
114
|
+
"selectedPointsSummary.other": "{count} selected points: {coordinates}",
|
|
115
|
+
extendedTextResponseLabel: "Extended text response",
|
|
116
|
+
textResponseLabel: "Text response",
|
|
117
|
+
sliderResponseLabel: "Slider response",
|
|
118
|
+
},
|
|
119
|
+
};
|