Skip to content

Плагин i18n

npmJSRJSR Score

Плагин i18n для GramIO.

Этот плагин помогает добавить многоязычность в ваши боты с помощью синтаксиса Fluent.

example

Вы можете настроить типо-безопасность для него.

Плагин i18n для GramIO.

Этот плагин предоставляет удобный способ добавить многоязычность в ваши боты! Его можно использовать без GramIO, но он всегда будет учитывать его особенности.

IMPORTANT

Начиная с версии 1.0.0, у нас есть два способа написания локализации: I18n-in-TS и Fluent

Установка

Для синтаксиса I18n-in-TS

bash
npm install @gramio/i18n
bash
bun add @gramio/i18n
bash
yarn add @gramio/i18n
bash
pnpm add @gramio/i18n

Для синтаксиса Fluent

bash
npm install @gramio/i18n @fluent/bundle
bash
bun add @gramio/i18n @fluent/bundle
bash
yarn add @gramio/i18n @fluent/bundle
bash
pnpm add @gramio/i18n @fluent/bundle

Синтаксис I18n-in-TS

Этот синтаксис позволяет вам писать локализацию, не выходя из файлов .ts, и не требует генерации кода для типо-безопасности, а также обеспечивает удобную интеграцию с Format API из коробки!

ts
import { 
format
,
Bot
} from "gramio";
import {
defineI18n
,
type LanguageMap, type
ShouldFollowLanguage
,
} from "@gramio/i18n"; const
en
= {
greeting
: (
name
: string) =>
format
`Hello, ${
name
}!`,
and
: {
some
: {
nested
: "Hi!!!",
}, }, } satisfies LanguageMap; const
ru
= {
greeting
: (
name
: string) =>
format
`Привет, ${
name
}!`,
and
: {
some
: {
nested
: "Hi!!!",
}, }, } satisfies
ShouldFollowLanguage
<typeof
en
>;
// Strict покажет ошибку при отсутствии ключей // satisfies ShouldFollowLanguageStrict<typeof en>; const
i18n
=
defineI18n
({
primaryLanguage
: "en",
languages
: {
en
,
ru
,
}, });
i18n
.
t
("en", "greeting", "World"); // Hello, World!
i18n
.
t
("en", "and.some.nested"); // Hi!!!
const
bot
= new
Bot
(
process
.
env
.
BOT_TOKEN
as string)
.
derive
("message", (
context
) => {
// вы можете взять язык из базы данных или любого другого источника и привязать его к контексту, не теряя типо-безопасности return {
t
:
i18n
.
buildT
(
context
.
from
?.
languageCode
),
}; }) .
on
("message", (
context
) => {
return
context
.
send
(
context
.
t
("greeting",
context
.
from
?.
firstName
?? "World")
); });

Множественные числа

ts
import { pluralizeEnglish, pluralizeRussian } from "@gramio/i18n";

const count = 5;

console.log(`You have ${count} ${pluralizeEnglish(count, "apple", "apples")}.`); // You have 5 apples.

console.log(
    `У вас ${count} ${pluralizeRussian(count, "яблоко", "яблока", "яблок")}.`
); // У вас 5 яблок.

ExtractLanguages помогает извлечь типы языков из экземпляра i18n.

ts
type EnLocalization = ExtractLanguages<typeof i18n>["en"];
type EnLocalizationKeys = keyof ExtractLanguages<typeof i18n>["en"];

type EnGreetingArgs = ExtractArgsParams<EnLocalization["greeting"]>;

Синтаксис Fluent

Этот плагин помогает добавить многоязычность в ваши боты с помощью синтаксиса Fluent.

example

Вы можете настроить типо-безопасность для него.

Использование

Создайте папку locales с файлом ru.ftl

ftl
# Простые вещи просты.
hello-user = Привет, {$userName}!

# Сложные вещи возможны.
shared-photos =
    {$userName} {$photoCount ->
        [one] добавил новую фотографию
        [few] добавил {$photoCount} новые фотографии
       *[other] добавил {$photoCount} новых фотографий
    } в {$userGender ->
        [male] свою ленту
        [female] свою ленту
       *[other] свою ленту
    }.

IMPORTANT

Есть расширения с поддержкой языка Fluent для VSCode и WebStorm

Использование плагина

ts
// @moduleResolution: NodeNext
// @module: NodeNext
// src/index.ts
import { Bot } from "gramio";
import { i18n } from "@gramio/i18n/fluent";

const bot = new Bot(process.env.BOT_TOKEN as string)
    .extend(i18n())
    .command("start", async (context) => {
        return context.send(
            context.t("shared-photos", {
                userName: "Анна",
                userGender: "female",
                photoCount: 3,
            })
        );
    })
    .onError(console.error)
    .onStart(console.log);

bot.start();

Опции

КлючТипПо умолчаниюОписание
defaultLocale?string"en"Язык по умолчанию
directory?string"locales"Путь к папке с файлами *.ftl
Или предоставьте клиент
ts
import { 
Bot
} from "gramio";
import {
getFluentClient
,
i18n
} from "@gramio/i18n/fluent";
// или getFluentClient<TypedFluentBundle>() const
client
=
getFluentClient
({
defaultLocale
: "ru",
directory
: "locales",
}); const
bot
= new
Bot
(
process
.
env
.
BOT_TOKEN
as string)
.
extend
(
i18n
(
client
))
.
command
("start", async (
context
) => {
return
context
.
send
(
context
.
t
("hello-user", {
userName
: "Анна" }));
});

IMPORTANT

См. Типо-безопасность. Для обеспечения типо-безопасности нужно указать дженерик для getFluentClient.

Методы

t

С помощью этого метода вы можете получить текст на выбранном языке.

Например:

ftl
hello-user = Привет, {$userName}!
ts
context.t("hello-user", { userName: "Анна" }); // Привет, Анна!

setLocale

Вы можете установить язык пользователя методом setLocale.

WARNING

На данный момент нет интеграции с сессиями, поэтому после сообщения язык снова станет таким, какой указан в defaultLocale

ts
bot.command("start", async (context) => {
    context.setLocale("ru");

    return context.send(
        context.t("shared-photos", {
            userName: "Анна",
            userGender: "female",
            photoCount: 3,
        })
    );
});

Типо-безопасность

Вы можете использовать этот плагин с fluent2ts, который генерирует типы TypeScript из ваших файлов .ftl. См. инструкцию по использованию.

Npm:

npm
bash
npx fluent2ts

Bun:

bun
bash
bunx fluent2ts

Yarn:

yarn
bash
yarn dlx fluent2ts

Pnpm:

pnpm
bash
pnpm exec fluent2ts

В результате вы получите сгенерированный файл locales.types.ts в папке src, который экспортирует интерфейс TypedFluentBundle. Устанавливаем этот тип как дженерик для плагина i18n - и вот у нас есть типо-безопасность!

ts
import type { TypedFluentBundle } from "./locales.types.js";
import { 
Bot
} from "gramio";
import {
i18n
} from "@gramio/i18n/fluent";
const
bot
= new
Bot
(
process
.
env
.
BOT_TOKEN
as string)
// или .extend(i18n(createFluentClient<TypedFluentBundle>())) .
extend
(
i18n
<TypedFluentBundle>())
.
command
("start", async (
context
) => {
const
firstMsg
=
context
.
t
("hello-user");
// // // const
secondMsg
=
context
.
t
("shared-photos", {
userName
: "Анна",
userGender
: "female",
photoCount
: 3,
}); // // // // return
context
.
send
(
secondMsg
);
}) .
onError
(
console
.
error
)
.
onStart
(
console
.
log
);
bot
.
start
();