@saykit/carbon
API reference for the Carbon integration
import { createWithSay, SayPlugin } from '@saykit/carbon';SayPlugin
A Carbon Plugin that registers a shared Catalogue globally and applies the interaction- and guild-level extensions.
import { Client } from '@buape/carbon';
import { SayPlugin } from '@saykit/carbon';
const client = new Client({/* ... */}, {/* ... */}, [new SayPlugin(catalogue)]);Constructor
Prop
Type
SayPlugin does three things on construction:
- Stores the
Cataloguein a global slot keyed by an internal symbol. - Applies the
BaseInteraction.prototype.sayextension. - Applies the
Guild.prototype.sayextension.
The plugin has no other lifecycle methods, once you've constructed it and passed it to the Client, you can forget about it.
createWithSay(catalogue)
Binds a withSay to a catalogue, normally once beside the catalogue itself, so commands do not have to take the catalogue themselves.
export const withSay = createWithSay(catalogue);withSay(BaseClass)
A higher-order class that decorates a Carbon class with SayKit support. The exact behaviour depends on what you pass in.
For BaseCommand subclasses
When the base class extends BaseCommand (Command, CommandWithSubcommands, …), the resulting constructor accepts a mapping function:
class PingCommand extends withSay(Command) {
constructor() {
super((say) => ({
name: say`ping`,
description: say`Ping the bot!`,
}));
}
}The mapping function runs once per locale, receiving that locale's view. SayKit then combines those results into Carbon's per-locale command metadata so Discord can render the command in each user's locale.
Localisable keys:
namedescriptionlabeltitleplaceholdercontentoptions(with their ownname/description/placeholder)componentssubcommandssubcommandGroups
For BaseComponent and Modal subclasses
For components (Button, StringSelect, …) and modals, withSay produces a constructor that takes the translated props directly, no per-locale mapping, since Discord doesn't localise component metadata per-user the way it does commands:
class RollAgainButton extends withSay(Button) {
customId = 'roll-again';
constructor(say: View) {
super({ label: say`Roll Again` });
}
}Caching
A bound withSay() caches its output class per base class, calling withSay(Command) twice returns the same generated class, so instanceof and identity checks still work.
Extensions
When SayPlugin is registered, these extensions are applied to Carbon's prototypes:
BaseInteraction.prototype.say
interface BaseInteraction<T> {
get say(): View;
}Returns the view for the interaction's locale. Views are memoised on the catalogue, so repeated access costs nothing and no cloning is involved.
Guild.prototype.say
interface Guild {
get say(): View;
}Returns the view for the guild's preferred_locale, memoised on the catalogue the same way.
Type imports
The package also re-exports type augmentations for completeness:
import type {} from '@saykit/carbon'; // augments @buape/carbon typesYou don't need this for normal use, it's automatic when you import any value from the package.
Next
- Integration guide, full walkthrough
- API: saykit, catalogues and views