Локализация
@necord/localization
is a lightweight localization module for Necord. It allows you to easily localize your bot's
commands and messages. The module provides a simple API for managing locales and translations, as well as a powerful localization adapter
system.
Установка
- npm
- Yarn
- pnpm
npm i @necord/localization necord discord.js
yarn add @necord/localization necord discord.js
pnpm add @necord/localization necord discord.js
Использование
Once the installation process is complete, we can import the NecordLocalizationModule
with your NecordModule
into the root AppModule
:
import { NecordModule } from 'necord';
import { Module } from '@nestjs/common';
import { NecordLocalizationModule, DefaultLocalizationAdapter, UserResolver } from '@necord/localization';
import { AppService } from './app.service';
@Module({
imports: [
NecordModule.forRoot({
token: process.env.DISCORD_TOKEN,
intents: [
IntentsBitField.Flags.Guilds,
IntentsBitField.Flags.DirectMessages,
IntentsBitField.Flags.GuildMembers,
IntentsBitField.Flags.GuildMessages,
IntentsBitField.Flags.MessageContent
],
prefix: '!',
development: [process.env.DISCORD_TEST_GUILD]
}),
NecordLocalizationModule.forRoot({
resolvers: UserResolver,
// Also you can provide class for support injection by @Inject
adapter: new DefaultLocalizationAdapter({
fallbackLocale: 'en-US',
locales: {
'en-US': {
'commands.ping.name': 'ping',
'commands.ping.description': 'Pong!'
},
ru: {
'commands.ping.name': 'пинг',
'commands.ping.description': 'Понг!'
}
}
})
})
],
providers: [AppService]
})
export class AppModule {
}
Adapters
The DefaultLocalizationAdapter
is a simple adapter that allows you to provide a map of locales and translations.
Also you can use the NestedLocalizationAdapter
that allows you to organize translation keys into objects
import { NecordModule } from 'necord';
import { Module } from '@nestjs/common';
import { NecordLocalizationModule, NestedLocalizationAdapter, UserResolver } from '@necord/localization';
import { AppService } from './app.service';
@Module({
imports: [
NecordModule.forRoot({
token: process.env.DISCORD_TOKEN,
intents: [
IntentsBitField.Flags.Guilds,
IntentsBitField.Flags.DirectMessages,
IntentsBitField.Flags.GuildMembers,
IntentsBitField.Flags.GuildMessages,
IntentsBitField.Flags.MessageContent
],
prefix: '!',
development: [process.env.DISCORD_TEST_GUILD]
}),
NecordLocalizationModule.forRoot({
resolvers: UserResolver,
adapter: new NestedLocalizationAdapter({
fallbackLocale: 'en-US',
locales: {
'en-US': {
'commands': {
'ping': {
'name': 'ping',
'description': 'Pong!'
}
}
},
ru: {
'commands': {
'ping': {
'name': 'пинг',
'description': 'Понг!'
}
}
}
}
})
})
],
providers: [AppService]
})
export class AppModule {
}
DefaultLocalizationAdapter
and NestedLocalizationAdapter
can translate your localization strings and placeholders (e.g {{username}}
)
Custom Adapters
Also, you can create your own localization adapter. Just implement the BaseLocalizationAdapter
interface:
import { BaseLocalizationAdapter } from '@necord/localization';
interface CustomLocalizationOptions {
fallbackLocale: string;
locales: Record<string, Record<string, string>>;
}
export class CustomLocalizationAdapter extends BaseLocalizationAdapter<CustomLocalizationOptions> {
public getTranslation(key: string, locale: string, ...args: any[]): string {
return `${key} by ${locale}`;
}
}
Resolvers
Resolvers are used to get the locale for translation. By default, Necord provides two resolvers: UserResolver
and GuildResolver
.
Resolver | Description |
---|---|
UserResolver | Gets the locale from the user's locale property (interaction.locale ) |
GuildResolver | Gets the locale from the guild's locale property (interaction.guildLocale ) |
Custom Resolvers
Also, you can create your own Resolver. Just implement the LocaleResolver
interface:
import { CommandContext, LocaleResolver } from '@necord/localization';
import { ExecutionContext, Injectable } from '@nestjs/common';
import { NecordExecutionContext } from 'necord';
@Injectable()
export class GuildResolver implements LocaleResolver {
resolve(context: ExecutionContext): string | string[] | undefined {
const necordContext = NecordExecutionContext.create(context);
const [interaction] = necordContext.getContext<CommandContext>();
return interaction.guildLocale;
}
}
Localization
We can inject the LOCALIZATION_ADAPTER
into our service and use it to localize our commands and messages:
import { Injectable, Inject, OnModuleInit } from '@nestjs/common';
import { DefaultLocalizationAdapter, localizationMapByKey, LOCALIZATION_ADAPTER } from '@necord/localization';
import { Context, SlashCommand, SlashCommandContext } from 'necord';
@Injectable()
export class AppService implements OnModuleInit {
public constructor(
@Inject(LOCALIZATION_ADAPTER)
private readonly localizationAdapter: DefaultLocalizationAdapter
) {
}
@SlashCommand({
name: 'ping',
description: 'Pong!',
nameLocalizations: localizationMapByKey('commands.ping.name'),
descriptionLocalizations: localizationMapByKey('commands.ping.name')
})
public ping(@Context() [interaction]: SlashCommandContext) {
const message = this.localizationAdapter.getTranslation(
'commands.ping.description',
interaction.locale
);
return interaction.reply(message);
}
}
Or you can use @CurrentTranslate
decorator to get the current translation from context:
import { Injectable, Inject, OnModuleInit } from '@nestjs/common';
import { DefaultLocalizationAdapter, CurrentTranslate, localizationMapByKey, TranslationFn } from '@necord/localization';
import { Context, SlashCommand, SlashCommandContext } from 'necord';
@Injectable()
export class AppService implements OnModuleInit {
@SlashCommand({
name: 'ping',
description: 'Pong!',
nameLocalizations: localizationMapByKey('commands.ping.name'),
descriptionLocalizations: localizationMapByKey('commands.ping.name')
})
public ping(
@Context() [interaction]: SlashCommandContext,
@CurrentTranslate() t: TranslationFn
) {
const message = t('commands.ping.description');
return interaction.reply(message);
}
}
Function localizationMapByKey
are used to localize the command name and description. You pass the translation key or localization map as
an argument to the function.
Setting up localized commands
You can set what locales the command will be localized
@SlashCommand({
name: 'ping',
description: 'Pong!',
nameLocalizations: localizationMapByKey('commands.ping.name', ['en', 'ru']),
descriptionLocalizations: localizationMapByKey('commands.ping.name', ['en', 'ru'])
})
Or just pass a localization object with the location id and translation key to the nameLocalization
and descriptionLocalizations
properties
@SlashCommand({
name: 'ping',
description: 'Pong!',
nameLocalizations: {
en: 'command.ping.name',
ru: 'command.ping.name'
},
descriptionLocalizations: {
en: 'command.ping.description',
ru: 'command.ping.description'
}
})
Congratulations! You have successfully created your first localized command with Necord!
You can view a working example here.