https://github.com/gramiojs/i18n
This plugin provide good way to add internationalization for your bots!
https://github.com/gramiojs/i18n
fluent i10n i18n internationalization locales telegram telegram-bot telegram-bot-api
Last synced: 8 months ago
JSON representation
This plugin provide good way to add internationalization for your bots!
- Host: GitHub
- URL: https://github.com/gramiojs/i18n
- Owner: gramiojs
- License: mit
- Created: 2024-05-01T17:39:54.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2025-07-12T22:20:44.000Z (12 months ago)
- Last Synced: 2025-09-14T02:49:12.876Z (9 months ago)
- Topics: fluent, i10n, i18n, internationalization, locales, telegram, telegram-bot, telegram-bot-api
- Language: TypeScript
- Homepage: https://gramio.netlify.app/plugins/official/i18n.html
- Size: 178 KB
- Stars: 4
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# @gramio/i18n
[](https://www.npmjs.org/package/@gramio/i18n)
[](https://www.npmjs.org/package/@gramio/i18n)
[](https://jsr.io/@gramio/i18n)
[](https://jsr.io/@gramio/i18n)
`i18n` plugin for [GramIO](https://gramio.dev/).
This plugin provide good way to add internationalization for your bots! It can be used without GramIO, but it will always keep it in mind.
> [!IMPORTANT]
> Since `1.0.0`, we have two ways to write localization: [`I18n-in-TS`](#i18n-in-ts-syntax) and [`Fluent`](#fluent-syntax)
### Installation
For [I18n-in-TS syntax](#i18n-in-ts-syntax)
```bash
npm install @gramio/i18n
```
For [Fluent syntax](#fluent-syntax)
```bash
npm install @gramio/i18n @fluent/bundle
```
## I18n-in-TS syntax
This syntax allows you to write localization without leaving `.ts` files and does not require code-generation for **type-safety**, as well as provides convenient integration with the Format API out of the box!
```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;
// Strict will show error on missing keys
// satisfies ShouldFollowLanguageStrict;
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) => {
// u can take language from database or whatever u want and bind it to context without loosing type-safety
return {
t: i18n.buildT(context.from?.languageCode ?? "en"),
};
})
.on("message", (context) => {
return context.send(
context.t("greeting", context.from?.firstName ?? "World")
);
});
```
### Plurals
```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 яблок.
```
### Get type-safe params for i18n
```ts
// Most great way to get type-safe params for i18n
export type GetI18nArgs> = GetI18nParams<
typeof i18n,
Key
>;
function test(...args: GetI18nArgs<"greeting">) {
return args;
}
type EnLocalization = ExtractLanguages["en"];
type EnLocalizationKeys = keyof ExtractLanguages["en"];
type EnGreetingArgs = ExtractArgsParams;
```
## [Fluent](https://projectfluent.org/) syntax
This plugin provide internationalization for your bots with [Fluent](https://projectfluent.org/) syntax.

You can [setup type-safety](#type-safety) for it.
## Usage
### Create `locales` folder with `en.ftl` file
```fluent
# Simple things are simple.
hello-user = Hello, {$userName}!
# Complex things are possible.
shared-photos =
{$userName} {$photoCount ->
[one] added a new photo
*[other] added {$photoCount} new photos
} to {$userGender ->
[male] his stream
[female] her stream
*[other] their stream
}.
```
> [!IMPORTANT]
> Fluent language support extensions for [VSCode](https://marketplace.visualstudio.com/items?itemName=macabeus.vscode-fluent) and [WebStorm](https://plugins.jetbrains.com/plugin/18416-fluent-language)
### Use plugin
```ts
// 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: "Anna",
userGender: "female",
photoCount: 3,
})
);
})
.onError(console.error)
.onStart(console.log);
bot.start();
```
## Options
| Key | Type | Default | Description |
| -------------- | ------ | --------------------- | ----------------------------------------- |
| defaultLocale? | string | first loaded language | Default locale |
| directory? | string | "locales" | The path to the folder with `*.ftl` files |
##### Or provide an client
```ts
// ...
import { getFluentClient, i18n } from "@gramio/i18n/fluent";
const client = getFluentClient({
defaultLocale: "en",
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: "Anna" }));
});
```
### Methods
#### t
Using this method, you can get the text in your chosen language.
For example:
```ftl
hello-user = Hello, {$userName}!
```
```ts
context.t("hello-user", { userName: "Anna" }); // Hello, Anna!
```
#### i18n.setLocale
You can set user locale by `setLocale` method.
> [!WARNING]
> At the moment, there is no integration with sessions, and therefore, after the message, the language will again become the one that defaultLocale
```ts
bot.command("start", async (context) => {
context.i18n.setLocale("ru"); // if ru not found fallback to defaultLocale
// context.i18n.setLocale("ru", true); if ru not found throw error
return context.send(
context.t("shared-photos", {
userName: "Anna",
userGender: "female",
photoCount: 3,
})
);
});
```
#### i18n.locale
Get current user locale.
```ts
bot.command("lang", async (context) => {
return context.send(context.i18n.locale);
});
```
#### i18n.locales
Get loaded locales
```ts
bot.command("languages", async (context) => {
return context.send(context.i18n.locales.join(", "));
});
```
## Type-safety
You can use this plugin with [fluent2ts](https://github.com/kravetsone/fluent2ts) which code-generates typescript types from your `.ftl` files.
See [usage](https://github.com/kravetsone/fluent2ts?tab=readme-ov-file#usage).
Npm:
```bash [npm]
npx fluent2ts
```
Bun:
```bash [bun]
bunx fluent2ts
```
Yarn:
```bash [yarn]
yarn dlx fluent2ts
```
Pnpm:
```bash [pnpm]
pnpm exec fluent2ts
```
And so we have a generated `locales.types.ts` file in `src` folder that exports the `TypedFluentBundle` interface.
We set this type as a **generic** for the `i18n` plugin. And now we have **type-safety**!
```ts
import type { TypedFluentBundle } from "./locales.types";
import { Bot } from "gramio";
import { i18n } from "@gramio/i18n/fluent";
const bot = new Bot(process.env.BOT_TOKEN as string)
// or i18n(getFluentClient())
.extend(i18n())
.command("start", async (context) => {
return context.send(
context.t("shared-photos", {
userName: "Anna",
userGender: "female",
photoCount: 3,
})
);
})
.onError(console.error)
.onStart(console.log);
bot.start();
```