saykit
API reference for the saykit core runtime
The saykit package exports the Say class and a handful of supporting types.
import { Say } from 'saykit';
import type { ReadonlySay } from 'saykit';Say
A container for locales, messages, the active locale, and formatting.
new Say(options)
new Say<Locale, Loader>(options: Say.Options<Locale, Loader>);Prop
Type
Properties
Prop
Type
load(...locales)
Loads message catalogues for the given locales through the configured loader. With no arguments, loads every configured locale.
say.load();
say.load('fr');
say.load('fr', 'ja');Already-loaded locales are skipped. If a loader is required but missing, throws. Returns this synchronously if all loaders are sync, or a promise resolving to this otherwise.
assign(locale, messages) / assign(record)
Directly attach messages without going through a loader.
say.assign('fr', { abc123: 'Bonjour !' });
say.assign({ en: { ... }, fr: { ... } });Returns this.
activate(locale)
Set the active locale. The locale must be loaded or assigned first.
say.activate('fr');Returns this.
match(...guesses)
Pick the best supported locale from one or more guesses. Each argument can be a string or array of strings; all guesses are flattened in order.
say.match('fr-CA', 'en');
say.match(['fr-CA', 'en-US'], 'de');Matching order:
- exact match against
locales - language-prefix match (
fr-CA→fr) - the first configured locale, as a final fallback
Returns the matched locale.
clone()
Returns a new Say with the same locales, messages, and loader. The new instance is independent, activating a locale on it doesn't affect the original.
freeze()
Returns a ReadonlySay view. Frozen instances can still read state and format messages, but cannot load, assign, or activate.
const readonly = say.clone().activate('fr').freeze();call(descriptor)
Format a compiled message descriptor against the active locale's catalogue.
say.call({ id: 'abc123', name: 'Ada' }); // → "Hello, Ada!"The descriptor must have an id. Extra properties are ICU placeholder values.
In normal application code, you don't write this, the build transform emits it from your say`...` macros.
Iteration
Say instances are iterable. They yield [frozenLocaleSay, locale] pairs for every configured locale.
for (const [localised, locale] of say) {
console.log(locale, localised`Hello!`);
}Each localised is a frozen clone with that locale already activated.
Macros
These methods are recognised by the SayKit build-tool plugins and rewritten into say.call(...) invocations. Calling them at runtime without a plugin throws.
say`template`
The tagged-template macro.
say`Hello, ${name}!`;say({ id, context })
Descriptor form, returns a callable that you tag the template against.
say({ id: 'greeting' })`Hello!`;
say({ context: 'direction' })`Right`;say.plural(value, options)
say.plural(count, {
one: 'You have 1 item',
other: 'You have # items',
});say.ordinal(value, options)
say.ordinal(position, {
1: '#st',
2: '#nd',
3: '#rd',
other: '#th',
});say.select(value, options)
say.select(gender, {
male: 'He liked it',
female: 'She liked it',
other: 'They liked it',
});Types
Say.Messages
namespace Say {
type Messages = { [key: string]: string };
}Say.Loader<Locale>
namespace Say {
type Loader<Locale extends string> = (locale: Locale) => Messages | Promise<Messages>;
}Say.Options<Locale, Loader>
Either messages is required (and loader optional), or loader is required (and messages optional).
ReadonlySay<Locale, Loader>
Say with load, assign, and activate typed as never. Returned by say.freeze().
NumeralOptions / SelectOptions
Option-bag types for plural, ordinal, and select. Both require an other key.
Next
- Runtime concepts, how to use these APIs in practice
- API: @saykit/react
- API: @saykit/carbon