npm
Source
Description
Plugin for@wolfstar/http-framework that adds an internationalization layer powered by i18next and @wolfstar/i18next-backend.
It merges two upstream implementations:
@wolfstar/http-framework-i18n(now removed) — the HTTP-interaction helpers (getSupportedLanguageT,applyLocalizedBuilder, localized builders).@sapphire/plugin-i18next— the plugin architecture (container.i18n,InternationalizationHandler, customfetchLanguage, formatters, HMR).
discord-api-types structures instead of discord.js class instances.
Installation
>=22.22.0.
Usage
Import the register entrypoint before creating the client:Activating with modules
On framework 6.1 and later, list the ./module entry in modules in stars.config instead of importing register.
It needs the optional @wolfstar/kit peer dependency, at ^0.2.0 || ^0.3.0.
i18n key of stars.config. The [specifier, options] tuple of modules
still works. Its options are merged over the i18n key, so they win.
The optional @wolfstar/schema peer dependency types the i18n key in defineConfig.
TypeScript only loads that type once the module is imported, so import @wolfstar/plugin-i18next/module in stars.config.ts.
Module options must be JSON-serialisable. Set fetchLanguage and functions in hmr.options through ClientOptions.i18n, which is shallowly merged over the module options. Because the merge is shallow, an hmr object set there replaces the module’s whole hmr object, so include enabled: true in it.
Without the stars CLI, pass the ./plugin definePlugin factory to the
plugins client option:
./plugin factory, and register. Combining them installs the plugin’s hooks twice.
Languages directory
.json file is a namespace (commands/ping).
Typed keys
Keys are typed through i18next’s ownCustomTypeOptions augmentation. Generate it from the locale
files with
@wolfstar/i18next-type-generator,
listed as an optional peer dependency — nothing at runtime depends on it, only the generated types
consumers opt into:
CustomTypeOptions.resources. If defaultNS is set to anything other than
i18next’s own 'translation' default — this plugin’s defaultLanguageDirectory layout usually
implies 'default' — declare it separately, or every helper’s default namespace stops satisfying
i18next’s Namespace type:
Consumption
getSupported*T helpers are synchronous and only read the locales carried by the interaction. Use
the asynchronous fetch* helpers when the language comes from somewhere else — they go through
container.i18n.fetchLanguage:
Targets
Every helper accepts any of four raw payloads, told apart structurally — the framework never hasdiscord.js class instances to check with instanceof:
APIInteraction, APIMessage, APIChannel and APIGuild all satisfy the matching target, so
payloads can be passed straight through:
defaultName for them. Use the asynchronous fetch* helpers instead: the hook receives the
target’s guildId, channelId and userId, which is enough to look the language up.
Localizing command builders
<root>Name and <root>Description; passing two keys uses them
verbatim.
[!IMPORTANT] Builder localization reads the loaded resources, so it may only run after thepreLoadhook has initialized the handler. The plugin already guarantees this ordering for pieces loaded byClient#load.
Hot module replacement
container.i18n.reloadResources() runs on every
addition, change or deletion — including new locale directories and new namespace files, which are
registered on i18next and become usable without a restart.
ignoreInitial defaults to true so the files already on disk do not each trigger a reload on
startup; pass hmr.options to override it or any other chokidar option. The watcher is exposed as
I18nextPlugin.watcher, so it can be closed on shutdown:
Options
Migrating from @wolfstar/http-framework-i18n
@wolfstar/http-framework-i18n has been removed and is no longer maintained. This plugin
replaces it. The upstream changes are documented in
wolfstar-project/stars-components#30; the short version:
getSupportedLanguageName, getSupportedUserLanguageName, getSupportedLanguageT,
getSupportedUserLanguageT (which now also take the key and its options directly, like resolveKey
did), supportedLanguages, isSupportedDiscordLocale, getLocalizedData,
applyNameLocalizedBuilder, applyDescriptionLocalizedBuilder, applyLocalizedBuilder and
createSelectMenuChoiceName keep the same names and signatures — only the module specifier changes.
T, FT, resolveKey and resolveUserKey were removed upstream in
wolfstar-project/stars-components#30 and are gone here
too — see Migrating off T / FT / resolve* below.
Other differences: @wolfstar/http-framework@^3.1.0 is now a peer dependency, i18next moves from ^22 to ^25, and
the locales directory defaults to <root>/languages instead of an explicit path passed to load() — the layout itself
is unchanged.
Migrating off T / FT / resolve*
The branded-key helpers were replaced by i18next’s native TypeScript support, so keys are plain
strings typed by the CustomTypeOptions augmentation
@wolfstar/i18next-type-generator emits.
TFunction#lng (along with lngs, ns and keyPrefix) is still declared, so code reading the
language off a bound function keeps working — i18next assigns them on every function getFixedT
returns but does not type them.
LocalePrefixKey is no longer hardcoded to commands/<file>:<key>: it is now
`${string}${LocaleSeparator}${string}`, with LocaleSeparator read from i18next’s
TypeOptions["nsSeparator"].
Credits
Adapted from@wolfstar/http-framework-i18n and @sapphire/plugin-i18next (MIT).