@wolfstar/plugin-i18next. For the weekly summary across all packages, see the changelog overview.
2.3.0 (2026-10-20)
New features
- Own
stars.configkey — The module setsmeta.configKey, so you can write its options under the top-leveli18nkey ofstars.configinstead of the[specifier, options]tuple ofmodules. The tuple still works and is merged over the key. The key is typed indefineConfigonce the module is imported instars.config.ts. (#259)
Updates
- New optional peer —
@wolfstar/schema(^0.9.0) is a new optional peer that carries theStarsConfigtype the keys extend.
Migration
@wolfstar/kitpeer raised — The@wolfstar/kitpeer range moves from^0.1.0to^0.2.0, the first version that readsconfigKey. If your project uses@wolfstar/kit0.1, update it.
2.2.0 (2026-10-05)
New features
/moduleand/pluginentrypoints — Adds@wolfstar/plugin-i18next/moduleand@wolfstar/plugin-i18next/plugin. List the module inmodulesinstars.config, or pass thedefinePluginfactory toplugins. Both need@wolfstar/http-framework6.1 (and@wolfstar/kitfor the module)../registeris unchanged and still supports framework v3, v5, and v6. (#188)
2.1.2 (2026-10-04)
Updates
http-framework6 support — The peer range now accepts@wolfstar/http-framework^6.0.0. (#176)
Bug fixes
- Peer range — Accept
@wolfstar/http-frameworkv6 in the peer range (|| ^6.0.0). (#176)
2.1.1
Updates
- Dependencies — Updated all non-major dependencies. (#132)
2.1.0
New features
- Compatibility shims — Export
T,FT,resolveKey,resolveUserKey,TypedT, andTypedFTagain as deprecated compatibility shims with@wolfstar/http-framework-i18n’s names and signatures, so a migration only has to rename the module specifier instead of failing at load time withdoes not provide an export named 'T'. (#116)
Bug fixes
- Dependencies — Updated
i18nextto v26. (#60) - Peer dependency — Accept
@wolfstar/http-frameworkv5 as a peer dependency (^3.1.0 || ^5.0.0), so v5 projects no longer install the plugin with an unmet peer. (#116)
2.0.4
Bug fixes
- TypeScript overload resolution — Fix overload resolution in
getSupportedLanguageT,getSupportedUserLanguageT, andfetchKeywhenkeyis a union type (such as a ternary expression). Previously, these functions used a single generic signature with a union-typed rest parameter. Whenkeywas a union, TypeScript failed to resolve the candidate tuple properly and rejected valid options objects as if they were positionaldefaultValuestrings. Each call shape is now declared as an independent overload, while the original generic signature is retained as a deprecated trailing overload for full backward compatibility. (#86)
2.0.3
Updates
- Dependencies — Updated all non-major dependencies. (#75)
2.0.2
Updates
- Type validation — Validate every published subpath export with
are-the-types-wrong, not just the main entrypoint.createTsdownOptionshardcodedattw.entrypointsto["."], so the./registerexport of each package shipped unchecked. It now accepts anattwEntrypointsoption, and all packages list their real entrypoints. (#70)
2.0.1
Bug fixes
- Typed-key helpers — Fix the typed-key helpers introduced in v2.0.0 under a real
@wolfstar/i18next-type-generatoraugmentation, which was never exercised before. Every fully-qualified<namespace>:<key>string (the shapegetSupportedLanguageT,getSupportedUserLanguageT,container.i18n.format,fetchKey, and the builder helpers all expect) failed to typecheck onceCustomTypeOptions.resourcesdeclared more than one namespace, andcontainer.i18n.format/fetchKeyfailed to typecheck at all. Namespace-prefixed keys are now typed against every namespaceCustomTypeOptions.resourcesdeclares (previously only i18next’s ownDefaultNamespace, which is what left non-default namespaces unreachable) through the newAnyNamespacetype. The genericRetthese functions andInternationalizationHandler#formatcompute their return type through had an invalid default that violated its own constraint as soon as it resolved to something narrower thanstring. It is dropped in favour of letting it resolve from the constraint, matching how i18next’s ownt()overloads are typed.@wolfstar/i18next-type-generatoris now an optional peer dependency. A newtests/typedConsumption.test.ts, checked by a dedicatedtsconfig.consumption.jsonwired into the package’stypecheckscript, runs the public API against types generated from the test fixtures so a regression like this is caught continuously. (#62)
2.0.0
Updates
- Native TypeScript support — Drop the branded-key helpers in favour of i18next’s native TypeScript support, porting wolfstar-project/stars-components#30. Keys are now plain strings typed through the
CustomTypeOptionsaugmentation generated by@wolfstar/i18next-type-generator.resolveKey(target, key, options)becomesgetSupportedLanguageT(target, key, options)(andresolveUserKeyitsgetSupportedUserLanguageTcounterpart), keeping the call shape those helpers had.LocalePrefixKeyis no longer hardcoded tocommands/<file>:<key>. It is now${string}${LocaleSeparator}${string}, with the newLocaleSeparatortype read from i18next’sTypeOptions["nsSeparator"].getSupportedLanguageTandgetSupportedUserLanguageTresolve the key when one is passed, and still return the boundTFunctionwhen it is not. TheTFunctionaugmentation that declareslng,lngs,ns, andkeyPrefixis kept, so code reading the language off a bound function still compiles.InternationalizationHandler#getTtakes an optional namespace and returns aTFunction<Ns>bound to it, so its keys can be written without the<namespace>:prefix. (#57)
Bug fixes
- Dependencies — Updated all non-major dependencies. (#47)
- Dependencies — Updated
chokidarto v5. (#59) - Documentation — Document how to migrate from the deprecated
@wolfstar/http-framework-i18nin the README, including the bootstrap diff and a table mapping every removed export to its replacement. (#56)
Migration
- Remove
T,FT,resolveKey,resolveUserKey,TypedT,TypedFT,Value,Values, andDifference. - Replace
resolveKey(target, key, options)withgetSupportedLanguageT(target, key, options). - Replace
resolveUserKey(target, key, options)withgetSupportedUserLanguageT(target, key, options). - Use
@wolfstar/i18next-type-generatorto generate theCustomTypeOptionsaugmentation.
1.0.0
New features
- New package — Add
@wolfstar/plugin-i18next. An internationalization layer for@wolfstar/http-frameworkpowered byi18nextand@wolfstar/i18next-backend, merging@wolfstar/http-framework-i18n(HTTP-interaction helpers, typedT/FTkeys, builder localization) with the plugin architecture of@sapphire/plugin-i18next(container.i18n,InternationalizationHandler, customfetchLanguage, formatters and HMR). Register it before creating the client withimport "@wolfstar/plugin-i18next/register". (#50) - Target types — Accept guild, channel, and message targets.
TargetwasInteractiononly, so the guild, channel, and message targets@sapphire/plugin-i18nextsupports had no equivalent here.Targetis nowInteraction | MessageTarget | ChannelTarget | GuildTarget, and every helper (getSupportedLanguageName,getSupportedUserLanguageName, their...Tvariants,resolveKey,resolveUserKey,fetchLanguage,fetchT,fetchKey) accepts all four.APIGuild,APIChannel, andAPIMessagesatisfy the matching target structurally, so payloads can be passed straight through. Since the framework receives raw JSON rather thandiscord.jsclass instances, the members are told apart by shape: an interaction haslocale, a message haschannel_id, a channel hastype, and anything left is a guild. A guild resolves its language frompreferred_locale, mirroringGuild#preferredLocalein Sapphire. Channels and messages carry no locale, so the synchronous helpers fall back todefaultNamefor them.InternationalizationContextnow also carriespreferredLocale, and the hook keeps receivingguildId,channelId, anduserIdso an asynchronous lookup can resolve them. Interaction behaviour is unchanged. (#53)
Bug fixes
defaultNameand HMR — HonourdefaultNameand register resources added by HMR.getSupportedLanguageNameandgetSupportedUserLanguageNamereturned a hard-coded'en-US'when none of the interaction’s locales was loaded, soInternationalizationOptions.defaultNamewas never consulted. A bot with onlyes-ESloaded anddefaultName: 'es-ES'madefetchTthrowReferenceError: Invalid language (en-US)on any interaction with an unmatched locale. Both helpers now fall back todefaultNamewhen it is a loaded Discord locale, and only then to'en-US'. The HMR watcher subscribed tochangeandunlinkonly, so adding a locale directory or a namespace file (addDir/add) triggered no reload, andreloadResourcesnever registered anything discovered after init. It now watches additions and deletions of both files and directories, callsi18next.loadLanguages/loadNamespacesfor what appeared since startup, and keepsInternationalizationHandler#languagesand#namespacesin sync. Reloads are serialized, since a single edit can emit several events.hmr.options.ignoreInitialnow defaults totrue, otherwise chokidar replays anaddper existing translation file on startup. The watcher is exposed asI18nextPlugin.watcherso it can be closed on shutdown. (#52)