Skip to main content

Локализация

Это легковесный модуль локализации для 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': 'Понг!'
}
}
}
}
})
})

info

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 в наш сервис и использовать его для локализации наших команд и сообщений:

src/app.gateway.ts
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 из адаптера локализации:

src/app.gateway.ts
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);
}
}
info

Функция 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!