How to get the resolve a key without a target?

šŸ‘‹ Is there a way to access the locale strings using the i18next plugin passing the language instead of delegate it to the fetchLanguage? I'd love to have the nameLocalizations and descriptionLocalizations on my slash commands coming from the i18n json files. That will make it easy to collaborative translation. Something like:
public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand({
name: this.name,
description: this.description,
descriptionLocalizations: {
'en-US': resolKey('en-US', 'ping:description')
'pt-BR': resolKey('pt-BR', 'ping:description')
}
});
}
public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand({
name: this.name,
description: this.description,
descriptionLocalizations: {
'en-US': resolKey('en-US', 'ping:description')
'pt-BR': resolKey('pt-BR', 'ping:description')
}
});
}
Maybe something like resolKey('language', 'ping:success')
Solution:
Use applyLocalizedBuilder šŸ™‚ Exemple: ```ts import { Subcommand } from '@kaname-png/plugin-subcommands-advanced';...
Jump to solution
10 Replies
Solution
Swiizyy
Swiizyyā€¢2y ago
Use applyLocalizedBuilder šŸ™‚ Exemple:
import { Subcommand } from '@kaname-png/plugin-subcommands-advanced';
import { ApplyOptions } from '@sapphire/decorators';
import type { ApplicationCommandRegistry } from '@sapphire/framework';
import { applyLocalizedBuilder } from '@sapphire/plugin-i18next';
import { PermissionFlagsBits } from 'discord.js';

@ApplyOptions<Subcommand.Options>({
name: 'birthday',
description: 'Birthday Command',
})
export class BirthdayCommand extends Subcommand {
public override registerApplicationCommands(registry: ApplicationCommandRegistry) {
registry.registerChatInputCommand((builder) => {
// It is necessary to call this hook and pass the builder context to register the subcommands stored in the subcommand register in the parent command.

// Calling both hooks is only necessary if required, it is not mandatory.
applyLocalizedBuilder(builder, 'commands/birthday:name', 'commands/birthday:description')
.setDefaultMemberPermissions(PermissionFlagsBits.ViewChannel)
.setDMPermission(false);

this.hooks.subcommands(this, builder);
});
}
}
import { Subcommand } from '@kaname-png/plugin-subcommands-advanced';
import { ApplyOptions } from '@sapphire/decorators';
import type { ApplicationCommandRegistry } from '@sapphire/framework';
import { applyLocalizedBuilder } from '@sapphire/plugin-i18next';
import { PermissionFlagsBits } from 'discord.js';

@ApplyOptions<Subcommand.Options>({
name: 'birthday',
description: 'Birthday Command',
})
export class BirthdayCommand extends Subcommand {
public override registerApplicationCommands(registry: ApplicationCommandRegistry) {
registry.registerChatInputCommand((builder) => {
// It is necessary to call this hook and pass the builder context to register the subcommands stored in the subcommand register in the parent command.

// Calling both hooks is only necessary if required, it is not mandatory.
applyLocalizedBuilder(builder, 'commands/birthday:name', 'commands/birthday:description')
.setDefaultMemberPermissions(PermissionFlagsBits.ViewChannel)
.setDMPermission(false);

this.hooks.subcommands(this, builder);
});
}
}
Daniel Passos
Daniel PassosOPā€¢2y ago
WoW! I did not know that exists. Thanks!
Swiizyy
Swiizyyā€¢2y ago
In your case, this would look like this
public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand((builder) => {
applyLocalizedBuilder(builder, 'ping:name', 'ping:description');
});
}
public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand((builder) => {
applyLocalizedBuilder(builder, 'ping:name', 'ping:description');
});
}
Favna
Favnaā€¢2y ago
Quick tip about it btw - mind the max lengths. With ArchId bots Kyra and I have noticed that sometimes they get exceeded by external translators (we use Crowdin). Crowdin however has the capability to let you set length limits for certain strings.
Daniel Passos
Daniel PassosOPā€¢2y ago
Quick question regards the applyLocalizedBuilder where the language coming from? Is this based on user language on guild, guild language? I realized that is not provided by the i18n fetchLanguage, right?
Swiizyy
Swiizyyā€¢2y ago
It goes through fetchLanguage if there is no value it searches if a language is configured on the server if none it returns the default value you have configured.
Daniel Passos
Daniel PassosOPā€¢2y ago
@Swiizyy I don't see it relaying on the fetchLanguage it seems to get the language information from the user discord language preference. If the user change the discord language the slash command name/description set using applyLocalizedBuilder will follow that choice not what I set in the fetchLanguage
Favna
Favnaā€¢2y ago
your file system, src/languages by default. It iterates over all available languages. see the guide for how to use the i18next plugin should be in the getting started info
Daniel Passos
Daniel PassosOPā€¢2y ago
Sorry maybe I was not clean in my question. Let's say I'm configuring my slash command using the applyLocalizedBuilder:
export class PingCommand extends Command {
public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand((builder) => {
applyLocalizedBuilder(builder, 'commands/ping:name', 'commands/ping:description');
});
}
}
export class PingCommand extends Command {
public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand((builder) => {
applyLocalizedBuilder(builder, 'commands/ping:name', 'commands/ping:description');
});
}
}
Let's say I have provide 2 differente languages in the language folder:
src/languages
ā”œā”€ā”€ en-US
ā””ā”€ā”€ pt-BR
src/languages
ā”œā”€ā”€ en-US
ā””ā”€ā”€ pt-BR
And in my fetchLanguage I'm returning a fixed locale:
i18n: {
fetchLanguage: async (context: InternationalizationContext) => {
return 'en-US';
}
}
i18n: {
fetchLanguage: async (context: InternationalizationContext) => {
return 'en-US';
}
}
If the user set the language for pt-BR in the Discord language setting, the Slash command name and description will be in pt-BR instead of en-US. That means the applyLocalizedBuilder does not relay on the fetchLanguage for set the name and description of the Slash Command, but all messages using resolveKey for example resolveKey(interaction, 'commands/ping:reply') will be in en-US because that relays on the fetchLanguage. Is that right?
Favna
Favnaā€¢2y ago
That means the applyLocalizedBuilder does not relay on the fetchLanguage for set the name and description of the Slash Command
no because applyLocalizedBuilder is on the builder. It adds to the data being sent to the Discord API when registering the command. The JSON object has name_localization and description_localization properties which are a key/value map of languages and their values.
but all messages using resolveKey for example resolveKey(interaction, 'commands/ping:reply') will be in en-US because that relays on the fetchLanguage. Is that right
That's right, because that's a runtime check as opposed to a register-time check. Sidenote you mentioned pt-BR and en-US here which are valid but be careful with the language codes. The full list of codes for Discord are in the Discord API docs I think but otherwise they are:
bg, cs, da, de, el, en-GB, en-US, es-ES, fi, fr, hi, hr, hu, id, it, ja, ko, lt, nl, no, pl, pt-BR, ro, ru, sv-SE, th, tr, tr, uk, vi, zh-CN, zh-TW
bg, cs, da, de, el, en-GB, en-US, es-ES, fi, fr, hi, hr, hu, id, it, ja, ko, lt, nl, no, pl, pt-BR, ro, ru, sv-SE, th, tr, tr, uk, vi, zh-CN, zh-TW
Want results from more Discord servers?
Add your server