saykit 0.10.0 → 0.11.0
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 +3 -1
- package/dist/index.d.mts +22 -14
- package/dist/index.mjs +5 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
The core runtime for [SayKit](https://saykit.js.org). Exports `createCatalogue`, which holds your locales and where each one's messages come from, `createView`, which binds one locale and formats messages using ICU MessageFormat, and `createStore`, which holds the current view and swaps it when you switch locale.
|
|
8
8
|
|
|
9
|
-
You author messages with the `` say`...` `` tagged template (and `say.plural`, `say.ordinal`, `say.select`)
|
|
9
|
+
You author messages with the `` say`...` `` tagged template (and `say.plural`, `say.ordinal`, `say.select`), and format numbers, dates and times for the locale with `say.number`, `say.date` and `say.time`; a SayKit build-tool plugin rewrites them at build time into small runtime calls.
|
|
10
10
|
|
|
11
11
|
## Install
|
|
12
12
|
|
|
@@ -29,6 +29,8 @@ const say = catalogue.locale('en');
|
|
|
29
29
|
|
|
30
30
|
say`Hello, ${name}!`;
|
|
31
31
|
say.plural(count, { one: '1 item', other: `${count} items` });
|
|
32
|
+
say`Total: ${say.number(total, { style: '::currency/EUR' })}`;
|
|
33
|
+
say.date(new Date(), { style: 'long' });
|
|
32
34
|
```
|
|
33
35
|
|
|
34
36
|
In a browser, where the locale can change, hold a store instead of a view:
|
package/dist/index.d.mts
CHANGED
|
@@ -58,6 +58,18 @@ declare namespace View {
|
|
|
58
58
|
type Messages = {
|
|
59
59
|
[key: string]: string;
|
|
60
60
|
};
|
|
61
|
+
/**
|
|
62
|
+
* What the transform compiles a message down to: the id it was extracted
|
|
63
|
+
* under, or the ICU message itself when there was nothing to extract, with
|
|
64
|
+
* its values behind one underscore each.
|
|
65
|
+
*/
|
|
66
|
+
type Descriptor = ({
|
|
67
|
+
id: string;
|
|
68
|
+
} | {
|
|
69
|
+
message: string;
|
|
70
|
+
}) & {
|
|
71
|
+
[match: string | number]: unknown;
|
|
72
|
+
};
|
|
61
73
|
}
|
|
62
74
|
/**
|
|
63
75
|
* One locale, bound to the messages it formats against.
|
|
@@ -104,16 +116,17 @@ interface View<Locale extends string = string> {
|
|
|
104
116
|
/** The messages this view formats against. */
|
|
105
117
|
readonly messages: Readonly<View.Messages>;
|
|
106
118
|
/**
|
|
107
|
-
* Format the message a descriptor names.
|
|
119
|
+
* Format the message a descriptor names, or the message it carries.
|
|
120
|
+
*
|
|
121
|
+
* A message with nothing to translate, a lone `say.date(x)` with no text
|
|
122
|
+
* around it, is never extracted: the transform writes the ICU into the call
|
|
123
|
+
* instead of an id.
|
|
108
124
|
*
|
|
109
125
|
* @param descriptor Descriptor to format
|
|
110
126
|
* @returns The formatted message
|
|
111
127
|
* @throws If the id has no message
|
|
112
128
|
*/
|
|
113
|
-
call(descriptor:
|
|
114
|
-
id: string;
|
|
115
|
-
[match: string | number]: unknown;
|
|
116
|
-
}): string;
|
|
129
|
+
call(descriptor: View.Descriptor): string;
|
|
117
130
|
/**
|
|
118
131
|
* Define a pluralised message.
|
|
119
132
|
*
|
|
@@ -268,13 +281,6 @@ declare namespace Catalogue {
|
|
|
268
281
|
type Produced = View.Messages | {
|
|
269
282
|
default: View.Messages;
|
|
270
283
|
};
|
|
271
|
-
/**
|
|
272
|
-
* Where each locale's messages come from, keyed by locale.
|
|
273
|
-
*
|
|
274
|
-
* The keys are the catalogue's locales, in the order they are written, and
|
|
275
|
-
* the first of them is the default locale.
|
|
276
|
-
*/
|
|
277
|
-
type Options<Locale extends string> = Record<Locale, Source>;
|
|
278
284
|
}
|
|
279
285
|
/**
|
|
280
286
|
* Everything an application knows how to say: its locales and where their
|
|
@@ -356,10 +362,12 @@ interface Catalogue<Locale extends string = string> {
|
|
|
356
362
|
* const say = catalogue.locale('en');
|
|
357
363
|
* ```
|
|
358
364
|
*
|
|
359
|
-
* @param messages Where each locale's messages come from, keyed by locale
|
|
365
|
+
* @param messages Where each locale's messages come from, keyed by locale. The
|
|
366
|
+
* keys are the catalogue's locales, in the order they are written, and the
|
|
367
|
+
* first of them is the default locale
|
|
360
368
|
* @returns The catalogue
|
|
361
369
|
*/
|
|
362
|
-
declare function createCatalogue<const Locale extends string = string>(messages: Catalogue.
|
|
370
|
+
declare function createCatalogue<const Locale extends string = string>(messages: Record<Locale, Catalogue.Source>): Catalogue<Locale>;
|
|
363
371
|
//#endregion
|
|
364
372
|
//#region src/store.d.ts
|
|
365
373
|
declare namespace Store {
|
package/dist/index.mjs
CHANGED
|
@@ -426,7 +426,7 @@ function compile(locale, source) {
|
|
|
426
426
|
//#endregion
|
|
427
427
|
//#region src/view.ts
|
|
428
428
|
function resolveDescriptorValues(descriptor) {
|
|
429
|
-
return Object.fromEntries(Object.entries(descriptor).filter(([key]) => key !== "id").map(([key, value]) => [key.startsWith("_") ? key.slice(1) : key, value]));
|
|
429
|
+
return Object.fromEntries(Object.entries(descriptor).filter(([key]) => key !== "id" && key !== "message").map(([key, value]) => [key.startsWith("_") ? key.slice(1) : key, value]));
|
|
430
430
|
}
|
|
431
431
|
function macro(name) {
|
|
432
432
|
throw new Error(`'say.${name}' is a macro and must be used with the relevant saykit plugin`);
|
|
@@ -438,10 +438,10 @@ function createView(locale, messages) {
|
|
|
438
438
|
throw new Error("'say' is a macro and must be used with the relevant saykit plugin");
|
|
439
439
|
});
|
|
440
440
|
function call(descriptor) {
|
|
441
|
-
const message = own[
|
|
442
|
-
if (typeof message !== "string") throw new Error(`Message for ${
|
|
443
|
-
let format = formats.get(
|
|
444
|
-
if (!format) formats.set(
|
|
441
|
+
const { id, message = own[id] } = descriptor;
|
|
442
|
+
if (typeof message !== "string") throw new Error(`Message for ${id} is not a string`);
|
|
443
|
+
let format = formats.get(message);
|
|
444
|
+
if (!format) formats.set(message, format = compile(locale, message));
|
|
445
445
|
return String(format.format(resolveDescriptorValues(descriptor)));
|
|
446
446
|
}
|
|
447
447
|
return Object.freeze(Object.defineProperties(say, {
|