Локализация
Это легковесный модуль локализации для NestCord. Он позволяет легко локализовать команды и сообщения вашего бота. Модуль предоставляет простой API для управления локалями и переводами, а также мощную систему адаптера локализации.
Использование
После завершения процесса установки мы можем импортировать NestCordPaginationModule
вместе с вашим NestCordModule
в корневой AppModule
:
import { NestCordModule } from '@globalart/nestcord';
import { Module } from '@nestjs/common';
import { NestCordLocalizationModule, DefaultLocalizationAdapter, UserResolver } from '@globalart/nestcord';
import { AppService } from './app.service';
@Module({
imports: [
NestCordModule.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]
}),
NestCordLocalizationModule.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 {
}
Адаптеры
Адаптер DefaultLocalizationAdapter
- это простой адаптер, который позволяет вам предоставить карту локалей и переводов.
Также вы можете использовать NestedLocalizationAdapter
, который позволяет организовать ключи перевода в объекты
import { NestCordLocalizationModule, NestedLocalizationAdapter, UserResolver } from '@globalart/nestcord/localization';
NestCordLocalizationModule.forRoot({
resolvers: UserResolver,
adapter: new NestedLocalizationAdapter({
fallbackLocale: 'en-US',
locales: {
'en-US': {
'commands': {
'ping': {
'name': 'ping',
'description': 'Pong!'
}
}
},
ru: {
'commands': {
'ping': {
'name': 'пинг',
'description': 'Понг!'
}
}
}
}
})
})
DefaultLocalizationAdapter
и NestedLocalizationAdapter
могут переводить строки локализации и заполнители (например, {{username}}
)
Пользовательские адаптеры
Кроме того, вы можете создать свой собственный адаптер локализации. Просто реализуйте интерфейс BaseLocalizationAdapter
:
import { BaseLocalizationAdapter } from '@globalart/nestcord/localization';
interface CustomLocalizationOptions {
fallbackLocale: string;
locales: Record<string, Record<string, string>>;
}
export class CustomLocalizationAdapter extends BaseLocalizationAdapter<CustomLocalizationOptions> {
public getTranslation(key: string, locale: string, ...args: unknown[]): string {
return `${key} by ${locale}`;
}
}
Резолверы
Резольверы используются для получения локали для перевода. По умолчанию NestCord предоставляет два резольвера: UserResolver
и GuildResolver
.
Резолвер | Описание |
---|---|
UserResolver | Получает локаль из свойства локали пользователя (interaction.locale ) |
GuildResolver | Получает локаль из свойства локали гильдии (interaction.guildLocale ) |
Пользовательские резолверы
Кроме того, вы можете создать свой собственный резолвер. Просто реализуйте интерфейс LocaleResolver
:
import { CommandContext, LocaleResolver } from '@globalart/nestcord';
import { ExecutionContext, Injectable } from '@nestjs/common';
import { NestCordExecutionContext } from '@globalart/nestcord';
@Injectable()
export class GuildResolver implements LocaleResolver {
resolve(context: ExecutionContext): string | string[] | undefined {
const nestcordContext = NestCordExecutionContext.create(context);
const [interaction] = nestcordContext.getContext<CommandContext>();
return interaction.guildLocale;
}
}
Локализация
Мы можем внедрить LOCALIZATION_ADAPTER
в наш сервис и использовать его для локализации наших команд и сообщений:
import { Injectable, Inject, OnModuleInit } from '@nestjs/common';
import { DefaultLocalizationAdapter, localizationMapByKey, LOCALIZATION_ADAPTER } from '@globalart/nestcord';
import { Context, SlashCommand, SlashCommandContext } from '@globalart/nestcord';
@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);
}
}
Или вы можете использовать функцию translate
из адаптера локализации:
import { Injectable, Inject, OnModuleInit } from '@nestjs/common';
import { DefaultLocalizationAdapter, localizationMapByKey, LOCALIZATION_ADAPTER } from '@globalart/nestcord';
import { Context, SlashCommand, SlashCommandContext } from '@globalart/nestcord';
@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.translate(
'commands.ping.description',
);
return interaction.reply(message);
}
}
Или вы можете использовать декоратор @CurrentTranslate
, чтобы получить текущий перевод из контекста:
import { Injectable, Inject, OnModuleInit } from '@nestjs/common';
import { DefaultLocalizationAdapter, CurrentTranslate, localizationMapByKey, TranslationFn } from '@globalart/nestcord/localization';
import { Context, SlashCommand, SlashCommandContext } from '@globalart/nestcord';
@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);
}
}
Функция localizationMapByKey
используется для локализации названия и описания команды. Вы передаете ключ перевода или карту локализации в качестве
аргумента функции.
Настройка локализованных команд
Вы можете задать, в каких локалях будет локализована команда
@SlashCommand({
name: 'ping',
description: 'Pong!',
nameLocalizations: localizationMapByKey('commands.ping.name', ['en', 'ru']),
descriptionLocalizations: localizationMapByKey('commands.ping.name', ['en', 'ru'])
})
Или просто передайте объект локализации с идентификатором местоположения и ключом перевода в свойства nameLocalization
и descriptionLocalizations
@SlashCommand({
name: 'ping',
description: 'Pong!',
nameLocalizations: {
en: 'command.ping.name',
ru: 'command.ping.name'
},
descriptionLocalizations: {
en: 'command.ping.description',
ru: 'command.ping.description'
}
})
Обновление локализации без перезапуска приложения
Если вы получаете переводы из внешнего API, например, crowdin, weblate или других сервисов перевода.
Для обновления достаточно вызвать localizationService
import {
Context,
NestCordLocalizationService,
SlashCommand,
SlashCommandContext,
} from '@globalart/nestcord';
export class AppService {
constructor(
private readonly nestCordLocalizationService: NestCordLocalizationService,
) {}
@SlashCommand({
name: 'update_translations',
description: 'Update translations',
})
updateTranslations(@Context() [interaction]: SlashCommandContext) {
// Get data from API
this.nestCordLocalizationService.updateLocales({
// static translates for test or you can put it from API
'en-US': {
'commands.ping.description': 'My new translation',
},
});
return interaction.reply({ content: "Updated successful" });
}
}
Поздравляем! Вы успешно создали свою первую локализованную команду с помощью NestCord!