Skip to content

Internasionalisasi (I18n) ​

Workflow I18n

Lokalkan reply bot dengan deteksi locale, dictionary, dan helper di handler.

Deteksi locale

Baca metadata bahasa Telegram dan fallback ke locale default.

Helper terjemahan

Gunakan `ctx.i18n` dari handler setelah middleware dipasang.

Variabel template

Sisipkan nilai ke string terjemahan.

Helper bawaan I18n menyimpan dictionary di memori dan menyuntikkan ctx.i18n.t() ke handler.

Memulai Cepat ​

ts
import { Bot, I18n } from 'vibegram';

const bot = new Bot(process.env.BOT_TOKEN!);
const i18n = new I18n('id');

i18n.loadLocale('en', {
    welcome: 'Welcome {name}!',
    help: 'Available commands: /start, /help',
});

i18n.loadLocale('id', {
    welcome: 'Selamat datang {name}!',
    help: 'Perintah tersedia: /start, /help',
});

bot.use(i18n.middleware());

Menggunakan Terjemahan ​

ts
bot.command('start', async ctx => {
    const text = ctx.i18n!.t('welcome', {
        name: ctx.from?.first_name ?? 'Teman',
    });

    await ctx.reply(text);
});

bot.command('help', ctx => ctx.reply(ctx.i18n!.t('help')));

Jika key tidak ditemukan, t() mengembalikan key itu sendiri.

Variabel Template ​

Gunakan placeholder {variable}:

ts
i18n.loadLocale('id', {
    order_confirmed: 'Pesanan #{id} dikonfirmasi. Total: Rp{amount}.',
});

ctx.i18n!.t('order_confirmed', { id: '1234', amount: '99.000' });
// "Pesanan #1234 dikonfirmasi. Total: Rp99.000."

Placeholder adalah substitusi string sederhana. Escape nilainya sendiri sebelum menaruhnya di pesan HTML atau Markdown berformat.

Cara Kerja Deteksi Bahasa ​

Middleware membaca ctx.from?.language_code, mengambil dua karakter pertama, dan fallback ke locale default dari new I18n(defaultLang).

text
Bahasa Telegram en-US -> locale "en"
Bahasa Telegram id    -> locale "id"
Locale tidak ada      -> locale default

Muat dari File JSON ​

ts
import { readFileSync } from 'node:fs';

function loadLocaleFile(lang: string) {
    return JSON.parse(readFileSync(`./locales/${lang}.json`, 'utf8'));
}

i18n.loadLocale('en', loadLocaleFile('en'));
i18n.loadLocale('id', loadLocaleFile('id'));

Contoh locales/id.json:

json
{
    "welcome": "Selamat datang {name}!",
    "choose_menu": "Silakan pilih menu:",
    "generic_error": "Terjadi kesalahan. Coba lagi nanti."
}

Override Bahasa Manual ​

Simpan pilihan bahasa user di session dan override ctx.i18n setelah middleware i18n bawaan berjalan.

ts
bot.use(session({ initial: () => ({ lang: undefined as string | undefined }) }));
bot.use(i18n.middleware());

bot.use(async (ctx, next) => {
    const lang = ctx.session?.lang;
    if (lang) {
        ctx.i18n = {
            locale: lang,
            t: (key, placeholders) => i18n.t(lang, key, placeholders),
        };
    }

    await next();
});

bot.action(/^lang_(\w+)$/, async ctx => {
    const lang = ctx.match?.[1];
    if (!lang) return;

    ctx.session.lang = lang;
    await ctx.answerCbQuery('Bahasa diperbarui');
    await ctx.reply(i18n.t(lang, 'welcome', { name: ctx.from?.first_name ?? 'Teman' }));
});

Released under the ISC License.