@lvl99dotcom/paintcanvas 0.2.0 → 0.3.1
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 +2 -2
- package/dist/lib/classes/PaintCanvas/index.js +2 -1
- package/dist/lib/i18n/index.d.ts +50 -13
- package/dist/lib/i18n/index.js +121 -26
- package/dist/locales/en-GB.js +177 -184
- package/dist/locales/en-US.js +177 -184
- package/dist/locales/fr.js +177 -184
- package/dist/locales/ja.js +177 -184
- package/dist/locales/ko.js +177 -184
- package/dist/locales/zh-Hans.js +177 -184
- package/dist/locales/zh-Hant.js +177 -184
- package/dist/package.js +1 -1
- package/dist/ui/base/index.d.ts +1 -1
- package/dist/ui/base/index.js +1 -1
- package/dist/ui/elements/PaintCanvas/index.js +20 -11
- package/dist/ui/elements/PcBrushConfig/index.d.ts +3 -3
- package/dist/ui/elements/PcBrushConfig/index.js +44 -41
- package/dist/ui/elements/PcBrushMenu/index.js +20 -19
- package/dist/ui/elements/PcBrushTest/index.js +2 -2
- package/dist/ui/elements/PcButton/index.js +1 -0
- package/dist/ui/elements/PcCanvas/index.js +1 -1
- package/dist/ui/elements/PcCanvasMap/index.js +1 -1
- package/dist/ui/elements/PcDialog/index.js +1 -0
- package/dist/ui/elements/PcIconToggle/index.js +1 -0
- package/dist/ui/elements/PcInfoTip/index.js +1 -1
- package/dist/ui/elements/PcInputSettings/index.js +17 -13
- package/dist/ui/elements/PcLayerItem/index.js +34 -34
- package/dist/ui/elements/PcLayersMenu/index.js +1 -1
- package/dist/ui/elements/PcStats/index.js +8 -5
- package/dist/ui/elements/PcThemePicker/index.js +3 -2
- package/dist/ui/elements/PcToast/index.js +2 -1
- package/dist/ui/elements/PcToolSettings/index.js +51 -45
- package/dist/ui/elements/PcToolbar/index.js +19 -19
- package/locales/en-GB.json +177 -184
- package/locales/en-US.json +177 -184
- package/locales/fr.json +177 -184
- package/locales/ja.json +177 -184
- package/locales/ko.json +177 -184
- package/locales/zh-Hans.json +177 -184
- package/locales/zh-Hant.json +177 -184
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -75,7 +75,7 @@ Guides and API pages are in [docs/](docs/), a [Docusaurus](https://docusaurus.io
|
|
|
75
75
|
- [Building your own UI on the engine](docs/docs/engine.md)
|
|
76
76
|
- [Messages and events](docs/docs/messages.md)
|
|
77
77
|
- [Saving and opening drawings](docs/docs/documents.md)
|
|
78
|
-
- [Translations](docs/docs/translations.md)
|
|
78
|
+
- [Translations, and adding your app's own](docs/docs/translations.md)
|
|
79
79
|
- [Icons](docs/docs/icons.md)
|
|
80
80
|
- [Theming](docs/docs/theming.md)
|
|
81
81
|
|
|
@@ -92,7 +92,7 @@ Starts a development server and opens the demo in your browser. It uses the sour
|
|
|
92
92
|
|
|
93
93
|
To try it with a pen or touch on another device (e.g. a tablet) on the same network, run `pnpm dev --host` and open the network address it prints. This makes the server reachable by anyone on that network.
|
|
94
94
|
|
|
95
|
-
The UI text follows your device's languages: on an English (UK) device, edit `locales/en-GB.json` to see text changes.
|
|
95
|
+
The UI text follows your device's languages: on an English (UK) device, edit `locales/en-GB.json` to see text changes. The demo's own text (e.g. the "New drawing" button) is in `demo/locales/`, added the way an app adds its translations.
|
|
96
96
|
|
|
97
97
|
## Development
|
|
98
98
|
|
|
@@ -13,8 +13,9 @@ import Layer, { createOffscreenCanvas } from "../Layer/index.js";
|
|
|
13
13
|
import LayerAutosave from "../LayerAutosave/index.js";
|
|
14
14
|
import { brushPresets, eraserPresets } from "../../brushes/index.js";
|
|
15
15
|
import { BUILT_IN_AUTHOR, UNKNOWN_AUTHOR, authorHandle } from "../../brushes/authors/index.js";
|
|
16
|
-
import
|
|
16
|
+
import "../../presets/index.js";
|
|
17
17
|
import CustomPresets from "../CustomPresets/index.js";
|
|
18
|
+
import { BRUSH_PRESET_FILE_FORMAT } from "../../presets/schema.js";
|
|
18
19
|
import InputSettings from "../InputSettings/index.js";
|
|
19
20
|
import ExternalSheets from "../ExternalSheets/index.js";
|
|
20
21
|
import PatchSender from "../../messages/PatchSender/index.js";
|
package/dist/lib/i18n/index.d.ts
CHANGED
|
@@ -26,6 +26,16 @@ export declare const matchLocale: (requested: readonly string[], available: read
|
|
|
26
26
|
* interpolate("Delete \"{name}\"?", { name: "Sketch" }); // 'Delete "Sketch"?'
|
|
27
27
|
*/
|
|
28
28
|
export declare const interpolate: (text: string, values?: Record<string, string | number>) => string;
|
|
29
|
+
/**
|
|
30
|
+
* A locale's language name, written in that language (so people can find their own), with its first letter in
|
|
31
|
+
* capitals. Gives the tag itself if the browser can't name it.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* languageName("ja"); // "日本語"
|
|
35
|
+
* languageName("fr"); // "Français"
|
|
36
|
+
* languageName("en-GB"); // "English (United Kingdom)"
|
|
37
|
+
*/
|
|
38
|
+
export declare const languageName: (locale: string) => string;
|
|
29
39
|
/** Options for translations */
|
|
30
40
|
export interface TranslationsOptions {
|
|
31
41
|
/** Locales that can be used, and how to load each (default: all the locales that come with PaintCanvas) */
|
|
@@ -40,53 +50,80 @@ export interface TranslationsOptions {
|
|
|
40
50
|
* match for the device, and `setLocale` to any available locale. Locale files load when first used, without reloading
|
|
41
51
|
* the page. Strings missing from a locale come from the fallback locale, then the key itself.
|
|
42
52
|
*
|
|
53
|
+
* Other projects can add their own strings and locales with `addLocales` and `addStrings`. A locale's strings from
|
|
54
|
+
* every set load together and are merged in the order the sets were added (PaintCanvas's first), so a key in a later
|
|
55
|
+
* set replaces the same key in an earlier one. Keys are prefixed by project by convention: `paintCanvas.` for
|
|
56
|
+
* PaintCanvas's, and e.g. `liveCanvas.` for an app's.
|
|
57
|
+
*
|
|
43
58
|
* Dispatches a `change` event when the locale or its strings change, so the UI can show the new text.
|
|
44
59
|
*
|
|
45
60
|
* @example
|
|
46
61
|
* const translations = new Translations({ locales: { "en-US": ..., ja: () => import("./ja.json") } });
|
|
47
62
|
* await translations.useDeviceLocale();
|
|
48
|
-
* translations.t("layers.delete", { name: "Sketch" });
|
|
63
|
+
* translations.t("paintCanvas.layers.delete", { name: "Sketch" });
|
|
49
64
|
*/
|
|
50
65
|
export default class Translations extends EventTarget {
|
|
51
|
-
private readonly loaders;
|
|
52
66
|
private readonly fallback;
|
|
53
|
-
/**
|
|
54
|
-
private readonly
|
|
67
|
+
/** Sets of strings, in the order they were added */
|
|
68
|
+
private readonly sources;
|
|
69
|
+
/** Each locale's strings from every set loaded so far, merged in order */
|
|
70
|
+
private readonly merged;
|
|
55
71
|
private current;
|
|
56
72
|
/** The locale most recently asked for, so a slow load can't override a later choice */
|
|
57
73
|
private requested?;
|
|
58
74
|
constructor(options?: TranslationsOptions);
|
|
59
75
|
/** The locale in use (an IETF BCP 47 tag, e.g. `ja`) */
|
|
60
76
|
get locale(): string;
|
|
61
|
-
/** Locales that can be used */
|
|
77
|
+
/** Locales that can be used: the fallback, and every locale a set of strings can load */
|
|
62
78
|
get locales(): string[];
|
|
63
79
|
/**
|
|
64
80
|
* Switch to the best available locale for the device's languages (`navigator.languages`).
|
|
65
81
|
*/
|
|
66
82
|
useDeviceLocale(languages?: readonly string[]): Promise<void>;
|
|
67
83
|
/**
|
|
68
|
-
* Switch to a locale (the best available match for the tag), loading its strings if needed.
|
|
69
|
-
*
|
|
84
|
+
* Switch to a locale (the best available match for the tag), loading its strings from every set if needed.
|
|
85
|
+
* Dispatches `change` once they're ready. If loading fails, the current locale stays and this rejects.
|
|
70
86
|
*
|
|
71
87
|
* @example
|
|
72
88
|
* await translations.setLocale("zh-TW"); // uses zh-Hant
|
|
73
89
|
*/
|
|
74
90
|
setLocale(tag: string): Promise<void>;
|
|
75
91
|
/**
|
|
76
|
-
* Add
|
|
77
|
-
*
|
|
92
|
+
* Add a set of strings for some locales, loaded when first used, after the sets already added (so its keys replace
|
|
93
|
+
* theirs). Its locales become available. The locale in use and the fallback load straight away, then `change` is
|
|
94
|
+
* dispatched if the set has strings for either.
|
|
78
95
|
*
|
|
79
96
|
* @example
|
|
80
|
-
* translations.
|
|
97
|
+
* await translations.addLocales({
|
|
98
|
+
* "en-US": () => import("./locales/en-US.json"),
|
|
99
|
+
* fr: () => import("./locales/fr.json"),
|
|
100
|
+
* });
|
|
101
|
+
* translations.t("liveCanvas.share");
|
|
102
|
+
*/
|
|
103
|
+
addLocales(loaders: Record<string, LocaleLoader>): Promise<void>;
|
|
104
|
+
/**
|
|
105
|
+
* Add or replace strings for a locale (e.g. the implementer's own wording or extra keys), after the sets already
|
|
106
|
+
* added. Dispatches `change` if it's the locale in use or the fallback.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* translations.addStrings("en-US", { "paintCanvas.tool.brush": "Paintbrush" });
|
|
81
110
|
*/
|
|
82
111
|
addStrings(locale: string, strings: Strings): void;
|
|
112
|
+
/**
|
|
113
|
+
* Load a locale's strings from every set, including sets added while loading, then merge them.
|
|
114
|
+
*/
|
|
115
|
+
private load;
|
|
116
|
+
/**
|
|
117
|
+
* Merge a locale's strings loaded so far from every set, in the order the sets were added.
|
|
118
|
+
*/
|
|
119
|
+
private merge;
|
|
83
120
|
/**
|
|
84
121
|
* Translate a key, putting values into its `{name}` placeholders. With a numeric `count`, the key's plural form for
|
|
85
|
-
* the locale is used when there is one (e.g. `presets.imported.one` and
|
|
86
|
-
* fallback locale, then the key.
|
|
122
|
+
* the locale is used when there is one (e.g. `paintCanvas.presets.imported.one` and
|
|
123
|
+
* `paintCanvas.presets.imported.other`). Falls back to the fallback locale, then the key.
|
|
87
124
|
*
|
|
88
125
|
* @example
|
|
89
|
-
* translations.t("presets.imported", { count: 3 }); // "Imported 3 brush presets"
|
|
126
|
+
* translations.t("paintCanvas.presets.imported", { count: 3 }); // "Imported 3 brush presets"
|
|
90
127
|
*/
|
|
91
128
|
t(key: string, values?: Record<string, string | number>): string;
|
|
92
129
|
}
|
package/dist/lib/i18n/index.js
CHANGED
|
@@ -82,39 +82,102 @@ var matchLocale = (requested, available, fallback = FALLBACK_LOCALE) => {
|
|
|
82
82
|
*/
|
|
83
83
|
var interpolate = (text, values = {}) => text.replace(/\{(\w+)\}/g, (placeholder, name) => Object.hasOwn(values, name) ? String(values[name]) : placeholder);
|
|
84
84
|
/**
|
|
85
|
+
* A locale's language name, written in that language (so people can find their own), with its first letter in
|
|
86
|
+
* capitals. Gives the tag itself if the browser can't name it.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* languageName("ja"); // "日本語"
|
|
90
|
+
* languageName("fr"); // "Français"
|
|
91
|
+
* languageName("en-GB"); // "English (United Kingdom)"
|
|
92
|
+
*/
|
|
93
|
+
var languageName = (locale) => {
|
|
94
|
+
try {
|
|
95
|
+
const name = new Intl.DisplayNames([locale], {
|
|
96
|
+
type: "language",
|
|
97
|
+
languageDisplay: "standard",
|
|
98
|
+
fallback: "none"
|
|
99
|
+
}).of(locale);
|
|
100
|
+
return name ? name.charAt(0).toLocaleUpperCase(locale) + name.slice(1) : locale;
|
|
101
|
+
} catch {
|
|
102
|
+
return locale;
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
/** A locale loader's strings, whether given directly or as a module's default export */
|
|
106
|
+
var unwrap = (module) => "default" in module && typeof module.default === "object" ? module.default : module;
|
|
107
|
+
/**
|
|
108
|
+
* One set of strings for some locales (e.g. PaintCanvas's, or an app's), each loaded once, when first needed.
|
|
109
|
+
*/
|
|
110
|
+
var LocaleSource = class {
|
|
111
|
+
loaders;
|
|
112
|
+
/** Strings of each locale loaded so far */
|
|
113
|
+
strings = /* @__PURE__ */ new Map();
|
|
114
|
+
/** Loads started, so a locale loading for two callers loads once */
|
|
115
|
+
loading = /* @__PURE__ */ new Map();
|
|
116
|
+
constructor(loaders = {}) {
|
|
117
|
+
this.loaders = loaders;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Load a locale's strings, if this has a loader for it and they aren't loaded yet. A failed load rejects, and can be
|
|
121
|
+
* tried again.
|
|
122
|
+
*/
|
|
123
|
+
load(locale) {
|
|
124
|
+
const loader = this.loaders[locale];
|
|
125
|
+
if (!loader || this.strings.has(locale)) return Promise.resolve();
|
|
126
|
+
let loading = this.loading.get(locale);
|
|
127
|
+
if (!loading) {
|
|
128
|
+
loading = loader().then((module) => {
|
|
129
|
+
this.strings.set(locale, unwrap(module));
|
|
130
|
+
}, (error) => {
|
|
131
|
+
this.loading.delete(locale);
|
|
132
|
+
throw error;
|
|
133
|
+
});
|
|
134
|
+
this.loading.set(locale, loading);
|
|
135
|
+
}
|
|
136
|
+
return loading;
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
85
140
|
* The text the UI shows, in the chosen language. Starts in the fallback locale; `useDeviceLocale` switches to the best
|
|
86
141
|
* match for the device, and `setLocale` to any available locale. Locale files load when first used, without reloading
|
|
87
142
|
* the page. Strings missing from a locale come from the fallback locale, then the key itself.
|
|
88
143
|
*
|
|
144
|
+
* Other projects can add their own strings and locales with `addLocales` and `addStrings`. A locale's strings from
|
|
145
|
+
* every set load together and are merged in the order the sets were added (PaintCanvas's first), so a key in a later
|
|
146
|
+
* set replaces the same key in an earlier one. Keys are prefixed by project by convention: `paintCanvas.` for
|
|
147
|
+
* PaintCanvas's, and e.g. `liveCanvas.` for an app's.
|
|
148
|
+
*
|
|
89
149
|
* Dispatches a `change` event when the locale or its strings change, so the UI can show the new text.
|
|
90
150
|
*
|
|
91
151
|
* @example
|
|
92
152
|
* const translations = new Translations({ locales: { "en-US": ..., ja: () => import("./ja.json") } });
|
|
93
153
|
* await translations.useDeviceLocale();
|
|
94
|
-
* translations.t("layers.delete", { name: "Sketch" });
|
|
154
|
+
* translations.t("paintCanvas.layers.delete", { name: "Sketch" });
|
|
95
155
|
*/
|
|
96
156
|
var Translations = class extends EventTarget {
|
|
97
|
-
loaders;
|
|
98
157
|
fallback;
|
|
99
|
-
/**
|
|
100
|
-
|
|
158
|
+
/** Sets of strings, in the order they were added */
|
|
159
|
+
sources;
|
|
160
|
+
/** Each locale's strings from every set loaded so far, merged in order */
|
|
161
|
+
merged = /* @__PURE__ */ new Map();
|
|
101
162
|
current;
|
|
102
163
|
/** The locale most recently asked for, so a slow load can't override a later choice */
|
|
103
164
|
requested;
|
|
104
165
|
constructor(options = {}) {
|
|
105
166
|
super();
|
|
106
|
-
this.loaders = options.locales ?? BUILT_IN_LOCALES;
|
|
107
167
|
this.fallback = options.fallback ?? "en-US";
|
|
108
|
-
|
|
168
|
+
const builtIn = new LocaleSource(options.locales ?? BUILT_IN_LOCALES);
|
|
169
|
+
builtIn.strings.set(this.fallback, options.fallbackStrings ?? en_US_default);
|
|
170
|
+
this.sources = [builtIn];
|
|
171
|
+
this.merge(this.fallback);
|
|
109
172
|
this.current = this.fallback;
|
|
110
173
|
}
|
|
111
174
|
/** The locale in use (an IETF BCP 47 tag, e.g. `ja`) */
|
|
112
175
|
get locale() {
|
|
113
176
|
return this.current;
|
|
114
177
|
}
|
|
115
|
-
/** Locales that can be used */
|
|
178
|
+
/** Locales that can be used: the fallback, and every locale a set of strings can load */
|
|
116
179
|
get locales() {
|
|
117
|
-
return [.../* @__PURE__ */ new Set([this.fallback, ...Object.keys(
|
|
180
|
+
return [.../* @__PURE__ */ new Set([this.fallback, ...this.sources.flatMap((source) => Object.keys(source.loaders))])];
|
|
118
181
|
}
|
|
119
182
|
/**
|
|
120
183
|
* Switch to the best available locale for the device's languages (`navigator.languages`).
|
|
@@ -123,8 +186,8 @@ var Translations = class extends EventTarget {
|
|
|
123
186
|
return this.setLocale(matchLocale(languages, this.locales, this.fallback));
|
|
124
187
|
}
|
|
125
188
|
/**
|
|
126
|
-
* Switch to a locale (the best available match for the tag), loading its strings if needed.
|
|
127
|
-
*
|
|
189
|
+
* Switch to a locale (the best available match for the tag), loading its strings from every set if needed.
|
|
190
|
+
* Dispatches `change` once they're ready. If loading fails, the current locale stays and this rejects.
|
|
128
191
|
*
|
|
129
192
|
* @example
|
|
130
193
|
* await translations.setLocale("zh-TW"); // uses zh-Hant
|
|
@@ -132,35 +195,67 @@ var Translations = class extends EventTarget {
|
|
|
132
195
|
async setLocale(tag) {
|
|
133
196
|
const locale = matchLocale([tag], this.locales, this.fallback);
|
|
134
197
|
this.requested = locale;
|
|
135
|
-
|
|
136
|
-
const module = await this.loaders[locale]();
|
|
137
|
-
this.loaded.set(locale, "default" in module && typeof module.default === "object" ? module.default : module);
|
|
138
|
-
}
|
|
198
|
+
await this.load(locale);
|
|
139
199
|
if (this.requested !== locale) return;
|
|
140
200
|
this.current = locale;
|
|
141
201
|
this.dispatchEvent(new Event("change"));
|
|
142
202
|
}
|
|
143
203
|
/**
|
|
144
|
-
* Add
|
|
145
|
-
*
|
|
204
|
+
* Add a set of strings for some locales, loaded when first used, after the sets already added (so its keys replace
|
|
205
|
+
* theirs). Its locales become available. The locale in use and the fallback load straight away, then `change` is
|
|
206
|
+
* dispatched if the set has strings for either.
|
|
146
207
|
*
|
|
147
208
|
* @example
|
|
148
|
-
* translations.
|
|
209
|
+
* await translations.addLocales({
|
|
210
|
+
* "en-US": () => import("./locales/en-US.json"),
|
|
211
|
+
* fr: () => import("./locales/fr.json"),
|
|
212
|
+
* });
|
|
213
|
+
* translations.t("liveCanvas.share");
|
|
214
|
+
*/
|
|
215
|
+
async addLocales(loaders) {
|
|
216
|
+
this.sources.push(new LocaleSource(loaders));
|
|
217
|
+
const locales = [.../* @__PURE__ */ new Set([this.current, this.fallback])];
|
|
218
|
+
await Promise.all(locales.map((locale) => this.load(locale)));
|
|
219
|
+
if (locales.some((locale) => Object.hasOwn(loaders, locale))) this.dispatchEvent(new Event("change"));
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Add or replace strings for a locale (e.g. the implementer's own wording or extra keys), after the sets already
|
|
223
|
+
* added. Dispatches `change` if it's the locale in use or the fallback.
|
|
224
|
+
*
|
|
225
|
+
* @example
|
|
226
|
+
* translations.addStrings("en-US", { "paintCanvas.tool.brush": "Paintbrush" });
|
|
149
227
|
*/
|
|
150
228
|
addStrings(locale, strings) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
229
|
+
const source = new LocaleSource();
|
|
230
|
+
source.strings.set(locale, strings);
|
|
231
|
+
this.sources.push(source);
|
|
232
|
+
this.merge(locale);
|
|
155
233
|
if (locale === this.current || locale === this.fallback) this.dispatchEvent(new Event("change"));
|
|
156
234
|
}
|
|
157
235
|
/**
|
|
236
|
+
* Load a locale's strings from every set, including sets added while loading, then merge them.
|
|
237
|
+
*/
|
|
238
|
+
async load(locale) {
|
|
239
|
+
let count;
|
|
240
|
+
do {
|
|
241
|
+
count = this.sources.length;
|
|
242
|
+
await Promise.all(this.sources.map((source) => source.load(locale)));
|
|
243
|
+
} while (count !== this.sources.length);
|
|
244
|
+
this.merge(locale);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Merge a locale's strings loaded so far from every set, in the order the sets were added.
|
|
248
|
+
*/
|
|
249
|
+
merge(locale) {
|
|
250
|
+
this.merged.set(locale, Object.assign({}, ...this.sources.map((source) => source.strings.get(locale))));
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
158
253
|
* Translate a key, putting values into its `{name}` placeholders. With a numeric `count`, the key's plural form for
|
|
159
|
-
* the locale is used when there is one (e.g. `presets.imported.one` and
|
|
160
|
-
* fallback locale, then the key.
|
|
254
|
+
* the locale is used when there is one (e.g. `paintCanvas.presets.imported.one` and
|
|
255
|
+
* `paintCanvas.presets.imported.other`). Falls back to the fallback locale, then the key.
|
|
161
256
|
*
|
|
162
257
|
* @example
|
|
163
|
-
* translations.t("presets.imported", { count: 3 }); // "Imported 3 brush presets"
|
|
258
|
+
* translations.t("paintCanvas.presets.imported", { count: 3 }); // "Imported 3 brush presets"
|
|
164
259
|
*/
|
|
165
260
|
t(key, values) {
|
|
166
261
|
const count = values?.count;
|
|
@@ -170,7 +265,7 @@ var Translations = class extends EventTarget {
|
|
|
170
265
|
key
|
|
171
266
|
] : [key];
|
|
172
267
|
for (const locale of [this.current, this.fallback]) {
|
|
173
|
-
const strings = this.
|
|
268
|
+
const strings = this.merged.get(locale);
|
|
174
269
|
const found = keys.find((each) => strings && Object.hasOwn(strings, each));
|
|
175
270
|
if (found) return interpolate(strings[found], values);
|
|
176
271
|
}
|
|
@@ -179,4 +274,4 @@ var Translations = class extends EventTarget {
|
|
|
179
274
|
};
|
|
180
275
|
/** The translations PaintCanvas's UI uses, unless an element is given others */
|
|
181
276
|
var translations = new Translations();
|
|
182
|
-
export { BUILT_IN_LOCALES, FALLBACK_LOCALE, Translations as default, interpolate, matchLocale, translations };
|
|
277
|
+
export { BUILT_IN_LOCALES, FALLBACK_LOCALE, Translations as default, interpolate, languageName, matchLocale, translations };
|