Internationalization (i18n
)
Plugin internationalization bisa membuat bot kamu berbicara dalam berbagai macam bahasa.
i18n vs Fluent
Jangan bingung membedakan plugin ini dengan plugin fluent.
Plugin ini merupakan versi upgrade dari plugin fluent. Ia dapat digunakan baik di Deno maupun Node.js.
Penjelasan Internationalization
Di bagian ini kita akan membahas apa itu internationalization, kenapa ia diperlukan, apa saja kendalanya, apa hubungannya dengan localization, serta kenapa kamu perlu sebuah plugin untuk melakukan semua itu. Jika kamu sudah memahami itu semua, langsung gulir ke bawah menuju bagian Memulai.
Pertama-tama, internationalization merupakan kata yang sangat panjang. Karena alasan tersebut, orang-orang lebih memilih menulis huruf pertama (i) dan huruf terakhirnya (n) saja. Mereka kemudian menghitung huruf yang tersisa (nternationalizatio, 18 huruf) lalu meletakkan digit angka tersebut di antara huruf i dan n, sehingga jadilah i18n. Tolong jangan tanya kami apa alasannya. Setidaknya sekarang kamu paham bahwa i18n adalah sebuah singkatan aneh dari kata internationalization.
Hal yang sama juga berlaku untuk localization, yang disingkat menjadi l10n.
Apa itu Localization?
Localization maksudnya adalah membuat sebuah bot yang dapat berbicara dengan berbagai macam bahasa. Bot tersebut didesain sedemikian rupa sehingga bahasa yang ditampilkan serupa dengan bahasa yang digunakan oleh user.
Selain bahasa, ada banyak hal lainnya yang bisa di-localize. Selain itu, kamu juga bisa menyesuaikan perbedaan kultural atau format-format lainnya, misalnya format waktu dan tanggal. Berikut hal-hal yang ditampilkan secara berbeda di berbagai tempat:
- Tanggal
- Waktu
- Angka
- Satuan
- Kata jamak
- Jenis Kelamin
- Tanda hubung
- Huruf Kapital
- Posisi Teks
- Simbol dan ikon
- Pengurutan
… dan lain sebagainya.
Semua hal di atas menentukan jenis locale yang digunakan oleh suatu user. Locale seringkali disimbolkan dengan kode dua huruf, misalnya en
untuk Inggris, id
untuk Indonesia, de
untuk Jerman, dan sebagainya. Jika kamu ingin mengetahui kode locale lainnya, coba lihat daftar berikut.
Apa itu Internationalization?
Singkatnya, internationalization artinya menulis kode yang bisa disesuaikan dengan locale yang digunakan oleh suatu user. Dengan kata lain, internationalization-lah yang menentukan apakah localization akan digunakan atau tidak (lihat di atas). Artinya, meskipun bot kamu bekerja dengan cara yang sama untuk semua orang, namun tampilan pesan yang dikirim akan berbeda dari user ke user. Dengan begitu, bot kamu mampu berbicara menggunakan bahasa yang berbeda.
Kamu telah melakukan Internationalization jika teks yang dikirim oleh bot tidak ditulis secara langsung di coding-an kamu (hard-coded). Sebaliknya, teks-teks tersebut dibaca dari sebuah file secara dinamis. Kamu telah melakukan Internationalization jika format waktu dan tanggal tidak ditulis secara langsung di coding-an kamu. Sebaliknya, gunakan sebuah library untuk menampilkan nilai-nilai tersebut sesuai dengan formatnya masing-masing. Kesimpulannya, jangan menulis sesuatu yang nilainya bisa berubah-ubah (misalnya negara asal atau bahasa yang digunakan user) langsung di coding-an kamu.
Kenapa Kamu Perlu Plugin Ini?
Plugin ini akan memudahkan kamu ketika melakukan internationalization. Ia ditenagai oleh Fluent—sebuah sistem localization yang dibuat oleh Mozilla. Sistem tersebut memiliki syntax yang canggih serta elegan yang dapat kamu gunakan untuk menulis terjemahan agar terlihat lebih natural dan efisien.
Kamu bisa menambahkan hal-hal yang akan mengalami perubahan berdasarkan locale user ke beberapa file teks yang diletakkan secara berdampingan dengan coding-an kamu. Kemudian, kamu dapat menggunakan plugin ini untuk memuat localization tersebut. Plugin akan secara otomatis menentukan locale yang sedang digunakan oleh user, lalu memberikan pilihan bahasa yang sesuai ke bot kamu.
Kita akan memanggil file-file teks tadi dengan sebutan file terjemahan. Semua konten yang ada di file terjemahan wajib mengikuti aturan syntax Fluent.
Memulai
Di bagian ini, kita akan membahas mengenai pengaturan struktur proyek dan tempat peletakkan file terjemahan. Jika kamu sudah memahaminya, langsung lompat ke sini untuk mengetahui cara menginstal dan menggunakan plugin ini.
Ada beberapa cara untuk menambahkan bahasa lain ke bot kamu. Cara termudah adalah dengan membuat sebuah folder yang berisi file terjemahan Fluent kamu. Biasanya, folder tersebut dinamakan locales
. File-file terjemahan harus memiliki ekstension .ftl
(fluent).
Berikut contoh struktur proyek yang bisa kita gunakan:
.
├── bot.ts
└── locales/
├── de.ftl
├── en.ftl
├── id.ftl
└── ru.ftl
Jika kamu belum begitu paham dengan syntax milik Fluent, kamu bisa membaca panduan yang mereka sediakan: https://
Berikut contoh file terjemahan untuk bahasa Inggris dengan nama locales
:
start = Hi, how can I /help you?
help =
Send me some text, and I can make it bold for you.
You can change my language using the /language command.
2
3
4
Untuk bahasa Indonesia kita namakan dengan locales
, isinya akan terlihat seperti ini:
start = Halo, ada yang bisa aku bantu? /help
help =
Kirimi aku sebuah teks, lalu aku akan mengubah teks tersebut menjadi tebal.
Kamu bisa mengubah tampilan bahasa menggunakan perintah /language.
2
3
4
Sekarang kamu bisa menggunakan terjemahannya menggunakan plugin ini di bot kamu. Ia akan tersedia melalui ctx
:
bot.command("start", async (ctx) => {
await ctx.reply(ctx.t("start"));
});
bot.command("help", async (ctx) => {
await ctx.reply(ctx.t("help"));
});
2
3
4
5
6
7
Setiap kali kamu memanggil ctx
, locale dari context object ctx
tersebut akan digunakan untuk mencari terjemahan yang sesuai. Locale negotiator bertugas mencari terjemahan yang sesuai. Untuk penggunaan normal, ia hanya mengembalikan ctx
.
Hasilnya, user dengan locale yang berbeda-beda bisa membaca pesan tersebut menggunakan bahasa mereka masing-masing.
Penggunaan
Plugin ini memperoleh locale seorang user dari berbagai macam faktor. Salah satunya melalui ctx
, yang disediakan oleh aplikasi milik user.
Selain itu, ada hal-hal lain yang bisa digunakan untuk menentukan locale user. Contohnya, kamu bisa menyimpan locale user di session kamu. Oleh karena itu, plugin ini bisa digunakan dengan dua cara: Dengan Session dan Tanpa Session.
Tanpa Session
Cara ini lebih mudah digunakan karena tidak perlu mengatur session untuk plugin. Kekurangannya adalah kamu tidak bisa menyimpan bahasa yang dipilih oleh user.
Seperti yang telah disebutkan di atas, locale yang digunakan oleh user akan ditentukan berdasarkan ctx
, yang diperoleh dari aplikasi Telegram user. Tetapi, jika kamu tidak memiliki terjemahan untuk bahasa tersebut, bahasa bawaanlah yang akan digunakan. Ada kalanya bot tidak dapat mendeteksi bahasa yang digunakan oleh user, jika itu terjadi, bot akan menggunakan bahasa bawaannya juga.
ctx
hanya akan terlihat jika user pernah memulai percakapan pribadi dengan bot kamu.
import { Bot, Context } from "grammy";
import { I18n, I18nFlavor } from "@grammyjs/i18n";
// Extend Context dengan Context Flavor I18n
// agar fitur TypeScript dan auto-complete dapat digunakan.
type MyContext = Context & I18nFlavor;
// Buat sebuah bot seperti biasanya.
// Jangan lupa untuk meng-extend context-nya.
const bot = new Bot<MyContext>("");
// Buat sebuah instance `I18n`.
// Lanjutkan membaca untuk mengetahui bagaimana cara mengatur instance ini.
const i18n = new I18n<MyContext>({
defaultLocale: "en", // Lihat di bawah untuk informasi lebih lanjut.
directory: "locales", // Muat semua file terjemahan dari locales/.
});
// Terakhir, register instance i18n ke bot-nya
// agar pesan bisa langsung diterjemahkan!
bot.use(i18n);
// Semua sudah siap.
// Kamu bisa mengakses terjemahan dengan `t` atau `translate`.
bot.command("start", async (ctx) => {
await ctx.reply(ctx.t("start-msg"));
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const { Bot } = require("grammy");
const { I18n } = require("@grammyjs/i18n");
// Buat sebuah bot seperti biasanya.
const bot = new Bot("");
// Buat sebuah instance `I18n`.
// Lanjutkan membaca untuk mengetahui bagaimana cara mengatur instance ini.
const i18n = new I18n({
defaultLocale: "en", // Lihat di bawah untuk informasi lebih lanjut.
directory: "locales", // Muat semua file terjemahan dari locales/.
});
// Terakhir, register instance i18n ke bot-nya
// agar pesan bisa langsung diterjemahkan!
bot.use(i18n);
// Semua sudah siap.
// Kamu bisa mengakses terjemahan dengan `t` atau `translate`.
bot.command("start", async (ctx) => {
await ctx.reply(ctx.t("start-msg"));
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { Bot, Context } from "https://deno.land/x/grammy@v1.27.0/mod.ts";
import { I18n, I18nFlavor } from "https://deno.land/x/grammy_i18n@v1.0.2/mod.ts";
// Extend Context dengan Context Flavor I18n
// agar fitur TypeScript dan auto-complete dapat digunakan.
type MyContext = Context & I18nFlavor;
// Buat sebuah bot seperti biasanya.
// Jangan lupa untuk meng-extend context-nya.
const bot = new Bot<MyContext>("");
// Buat sebuah instance `I18n`.
// Lanjutkan membaca untuk mengetahui bagaimana cara mengatur instance ini.
const i18n = new I18n<MyContext>({
defaultLocale: "en", // Lihat di bawah untuk informasi lebih lanjut.
// Muat semua file terjemahan dari locales/. (Tidak bekerja di Deno Deploy)
directory: "locales",
});
// Untuk Deno Deploy, pakai cara berikut untuk memuat file terjemahan.
// await i18n.loadLocalesDir("locales");
// Terakhir, register instance i18n ke bot-nya
// agar pesan bisa langsung diterjemahkan!
bot.use(i18n);
// Semua sudah siap.
// Kamu bisa mengakses terjemahan dengan `t` atau `translate`.
bot.command("start", async (ctx) => {
await ctx.reply(ctx.t("start-msg"));
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
ctx
mengembalikan pesan terjemahan untuk key tertentu. Plugin ini secara otomatis memilih bahasa yang sesuai untuk user, sehingga kamu tidak perlu memikirkannya lagi.
Selamat! Bot kamu sekarang bisa berbicara dalam berbagai macam bahasa! 🌏🎉
Dengan Session
Mari kita asumsikan bot kamu memiliki sebuah perintah /language
. Di grammY kita bisa menyimpan data user untuk setiap chat dengan menggunakan session. Agar instance internationalization tahu bahwa session sedang diaktifkan, maka kamu perlu menyetel use
menjadi true
di opsi I18n
.
Berikut contoh sederhana penggunaan perintah /language
:
import { Bot, Context, session, SessionFlavor } from "grammy";
import { I18n, I18nFlavor } from "@grammyjs/i18n";
interface SessionData {
__language_code?: string;
}
type MyContext = Context & SessionFlavor<SessionData> & I18nFlavor;
const bot = new Bot<MyContext>("");
const i18n = new I18n<MyContext>({
defaultLocale: "en",
useSession: true, // Menentukan data bahasa user disimpan di session atau tidak
directory: "locales", // Muat locale dari direktori `locales`.
});
// Jangan lupa untuk me-register middleware `session` sebelum
// me-register middleware instace i18n.
bot.use(
session({
initial: () => {
return {};
},
}),
);
// Register middleware i18n
bot.use(i18n);
bot.command("start", async (ctx) => {
await ctx.reply(ctx.t("greeting"));
});
bot.command("language", async (ctx) => {
if (ctx.match === "") {
return await ctx.reply(ctx.t("language.specify-a-locale"));
}
// `i18n.locales` berisi semua locale yang telah di-register
if (!i18n.locales.includes(ctx.match)) {
return await ctx.reply(ctx.t("language.invalid-locale"));
}
// `ctx.i18n.getLocale` mengembalikan locale yang sedang digunakan.
if (await ctx.i18n.getLocale() === ctx.match) {
return await ctx.reply(ctx.t("language.already-set"));
}
await ctx.i18n.setLocale(ctx.match);
await ctx.reply(ctx.t("language.language-set"));
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
const { Bot, session } = require("grammy");
const { I18n } = require("@grammyjs/i18n");
const bot = new Bot("");
const i18n = new I18n({
defaultLocale: "en",
useSession: true, // Menentukan data bahasa user disimpan di session atau tidak
directory: "locales", // Muat locale dari direktori `locales`.
});
// Jangan lupa untuk me-register middleware `session` sebelum
// me-register middleware instace i18n
bot.use(
session({
initial: () => {
return {};
},
}),
);
// Register middleware i18n
bot.use(i18n);
bot.command("start", async (ctx) => {
await ctx.reply(ctx.t("greeting"));
});
bot.command("language", async (ctx) => {
if (ctx.match === "") {
return await ctx.reply(ctx.t("language.specify-a-locale"));
}
// `i18n.locales` berisi semua locale yang telah di-register
if (!i18n.locales.includes(ctx.match)) {
return await ctx.reply(ctx.t("language.invalid-locale"));
}
// `ctx.i18n.getLocale` mengembalikan locale yang sedang digunakan.
if ((await ctx.i18n.getLocale()) === ctx.match) {
return await ctx.reply(ctx.t("language.already-set"));
}
await ctx.i18n.setLocale(ctx.match);
await ctx.reply(ctx.t("language.language-set"));
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import {
Bot,
Context,
session,
SessionFlavor,
} from "https://deno.land/x/grammy@v1.27.0/mod.ts";
import { I18n, I18nFlavor } from "https://deno.land/x/grammy_i18n@v1.0.2/mod.ts";
interface SessionData {
__language_code?: string;
}
type MyContext = Context & SessionFlavor<SessionData> & I18nFlavor;
const bot = new Bot<MyContext>("");
const i18n = new I18n<MyContext>({
defaultLocale: "en",
useSession: true, // Menentukan data bahasa user disimpan di session atau tidak
// TIDAK BEKERJA di Deno Deploy
directory: "locales",
});
// Untuk Deno Deploy, pakai cara berikut untuk memuat file terjemahan.
// await i18n.loadLocalesDir("locales");
// Jangan lupa untuk me-register middleware `session` sebelum
// me-register middleware instace i18n
bot.use(
session({
initial: () => {
return {};
},
}),
);
// Register middleware i18n
bot.use(i18n);
bot.command("start", async (ctx) => {
await ctx.reply(ctx.t("greeting"));
});
bot.command("language", async (ctx) => {
if (ctx.match === "") {
return await ctx.reply(ctx.t("language.specify-a-locale"));
}
// `i18n.locales` berisi semua locale yang telah di-register
if (!i18n.locales.includes(ctx.match)) {
return await ctx.reply(ctx.t("language.invalid-locale"));
}
// `ctx.i18n.getLocale` mengembalikan locale yang sedang digunakan.
if ((await ctx.i18n.getLocale()) === ctx.match) {
return await ctx.reply(ctx.t("language.already-set"));
}
await ctx.i18n.setLocale(ctx.match);
await ctx.reply(ctx.t("language.language-set"));
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
Ketika session diaktifkan, property _
di session akan digunakan alih-alih ctx
(yang disediakan oleh aplikasi Telegram) selama proses pemilihan bahasa berlangsung. Saat bot kamu mengirim pesan, locale tersebut akan dipilih dari ctx
.
Ada sebuah method set
yang bisa kamu gunakan untuk mengatur bahasa yang diinginkan. Pengaturan tersebut akan disimpan di session kamu.
await ctx.i18n.setLocale("id");
Cara di atas serupa dengan mengatur session secara manual, lalu me-renegotiate locale tersebut:
ctx.session.__language_code = "id";
await ctx.i18n.renegotiateLocale();
2
Me-renegotiate Locale
Ketika kamu menggunakan session atau hal lainnya—selain dari ctx
—untuk memilih locale khusus untuk suatu user, ada beberapa situasi dimana kamu berkeinginan untuk mengganti bahasanya ketika menangani sebuah update. Coba lihat kembali contoh yang menggunakan session di atas.
Ketika kamu cuma melakukan
ctx.session.__language_code = "id";
locale yang sedang digunakan tidak akan diperbarui di instance I18n
. Alih-alih, ia memperbarui session-nya saja. Akibatnya, perubahan tersebut hanya akan diterapkan untuk update selanjutnya.
Jika kamu ingin perubahan diterapkan saat itu juga, kamu perlu memperbarui perubahan tersebut tepat setelah mengatur bahasa user. Untuk melakukannya, gunakan method renegotiate
.
ctx.session.__language_code = "id";
await ctx.i18n.renegotiateLocale();
2
Setelah itu, setiap kali kita menggunakan method t
, bot akan membalas dengan terjemahan bahasa Indonesia untuk pesan tersebut (yang telah ditentukan di locales
).
Perlu diingat juga, ketika menggunakan session built-in, kamu bisa mendapatkan hasil yang serupa dengan menggunakan method set
.
Mengatur Locale Tanpa Menggunakan Session
Jika suatu saat kamu perlu menentukan locale untuk suatu user, tetapi kamu tidak sedang menggunakan session, maka kamu bisa melakukannya dengan menggunakan method use
.
await ctx.i18n.useLocale("id");
Ia akan menggunakan locale yang telah ditentukan untuk terjemahan selanjutnya. Efeknya hanya akan berlaku untuk update yang sedang berlangsung, dan tidak permanen. Kamu bisa menggunakan method ini untuk mengubah terjemahan ketika sedang menangani update (misal, ketika user mengubah bahasa).
Locale Negotiation Khusus
Kamu bisa menggunakan opsi locale
untuk menentukan sebuah locale negotiator khusus. Opsi ini akan berguna jika kamu hendak menggunakan locale berdasarkan sumber dari luar (misalnya database) atau mengatur secara manual locale yang akan digunakan.
Berikut langkah-langkah bawaan yang dilakukan oleh plugin ketika memilih sebuah locale:
Jika session diaktifkan, baca
_
dari session tersebut. Jika locale yang dikembalikan valid, gunakan locale tersebut. Jika tidak mengembalikan apa-apa atau locale tidak terdaftar, lanjutkan ke langkah nomor 2._language _code Baca
ctx
. Jika locale yang dikembalikan valid, gunakan locale tersebut. Jika tidak mengembalikan apa-apa atau locale tidak terdaftar, lanjutkan ke langkah nomor 3..from .language _code Perlu diingat,
ctx
hanya akan tersedia jika user pernah menggunakan bot tersebut. Artinya, jika bot melihat user di sebuah grup atau di tempat lain, tetapi user belum pernah menggunakan bot tersebut, bot tidak dapat melihat.from .language _code ctx
-nya..from .language _code Gunakan konfigurasi bahasa bawaan di
I18n
. Jika locale yang dikembalikan valid, gunakan locale tersebut. Jika tidak mengembalikan apa-apa atau locale tidak terdaftar, lanjutkan ke langkah nomor 4.Gunakan bahasa Inggris (
en
). Plugin akan menggunakan bahasa Inggris sebagai fallback utamanya. Meski begitu, kami menyarankan untuk memiliki sebuah terjemahan walaupun itu bukan syarat utama. Jika locale Inggris tidak tersedia, lanjutkan ke langkah nomor 5.Jika semua langkah di atas gagal, gunakan
{key}
alih-alih terjemahan. Kami sangat merekomendasikan untuk menetapkan sebuah locale yang tersedia di terjemahan kamu sebagaidefault
di opsiLocale I18n
.
Locale Negotiation
Locale negotiation biasanya hanya terjadi sekali selama pemrosesan update Telegram berlangsung. Meski begitu, kamu bisa memanggil kembali negotiator dan menentukan locale yang baru dengan menjalankan ctx
. Ini akan berguna jika locale mengalami perubahan selama proses update berlangsung.
Berikut sebuah contoh penerapan locale
dimana kita menggunakan locale
dari sebuah session alih-alih menggunakan _
. Untuk penggunaan seperti ini, kamu tidak perlu mengubah opsi use
di I18n
menjadi true
.
const i18n = new I18n<MyContext>({
localeNegotiator: (ctx) =>
ctx.session.locale ?? ctx.from?.language_code ?? "en",
});
2
3
4
const i18n = new I18n({
localeNegotiator: (ctx) =>
ctx.session.locale ?? ctx.from?.language_code ?? "en",
});
2
3
4
Jika locale negotiator yang kita buat mengembalikan sebuah locale yang tidak valid, ia akan melakukan fallback dan memilih sebuah locale berdasarkan urutan yang telah dijelaskan di atas.
Me-render Pesan Terjemahan
Mari kita lihat pesan yang sedang di-render berikut.
bot.command("start", async (ctx) => {
// Panggil "translate" atau "t" helper untuk me-render
// pesan berdasarkan ID dan parameter tambahan lainnya:
await ctx.reply(ctx.t("welcome"));
});
2
3
4
5
Sekarang kamu bisa /start
bot-nya. Pesan tersebut kurang lebih akan di-render menjadi seperti ini:
Halo!
Placeables
Terkadang, kamu ingin menaruh sebuah nilai seperti angka dan nama di dalam string-nya. Kamu bisa melakukannya dengan menggunakan placeables.
bot.command("cart", async (ctx) => {
// Kamu bisa menambahkan placeables sebagai object kedua.
await ctx.reply(ctx.t("cart-msg", { items: 10 }));
});
2
3
4
Kita bisa menyebut object { items:
sebagai translation context dari sebuah string cart
.
Jalankan perintah /cart
:
Kamu saat ini memiliki 10 item di keranjang kamu.
Coba ganti nilai variable items
untuk melihat perubahan pada pesan yang telah di-render! Jangan lupa untuk membaca dokumentasi Fluent, khususnya materi placeables.
Global Placeables
Memiliki beberapa placeables di semua terjemahan akan sangat membantu pekerjaan kita. Contohnya, jika kamu hendak mencantumkan nama user di banyak tempat, akan sangat melelahkan untuk menulis translation context { name:
di berbagai tempat.
Global placeables datang menyelamatkan! Coba lihat contoh berikut:
const i18n = new I18n<MyContext>({
defaultLocale: "en",
directory: "locales",
// Tentukan placeables yang tersedia secara global:
globalTranslationContext(ctx) {
return { name: ctx.from?.first_name ?? "" };
},
});
bot.use(i18n);
bot.command("start", async (ctx) => {
// `name` bisa digunakan tanpa perlu menulisnya lagi!
await ctx.reply(ctx.t("welcome"));
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Potensi Masalah Pemformatan
Umumnya, Fluent menggunakan penanda Unicode Isolation untuk proses interpolasi.
Penanda tersebut dapat menghasilkan masalah pemformatan jika kamu menggunakan placeables di dalam suatu tag atau entity (contohnya, placeables akan di-render menjadi text biasa, alih-alih menjadi link atau cashtag seperti yang kita inginkan).
Untuk mengatasinya, matikan opsi use
melalui cara ini:
const i18n = new I18n({
fluentBundleOptions: { useIsolating: false },
});
2
3
Menambahkan Terjemahan
Kita bisa memuat terjemahan dengan tiga cara.
Memuat Locale Menggunakan Opsi directory
Cara termudah untuk menambahkan terjemahan ke instance I18n
adalah dengan mengumpulkan semua file terjemahan ke dalam sebuah direktori lalu masukkan nama direktori tersebut di opsi directory
,
const i18n = new I18n({
directory: "locales",
});
2
3
Memuat Locale dari Sebuah Direktori
Cara ini serupa dengan mengatur opsi directory
. Cukup kumpulkan semua file terjemahan ke dalam sebuah folder lalu muat dengan cara seperti ini:
const i18n = new I18n();
await i18n.loadLocalesDir("locales"); // versi async
i18n.loadLocalesDirSync("locales-2"); // versi sync
2
3
4
Perlu diperhatikan bahwa beberapa lingkungan kerja tertentu mengharuskan kamu untuk menggunakan
async
. Contohnya, Deno Deploy tidak mendukung pengoperasian file menggunakan cara synchronous.
Memuat Satu Locale Saja
Kita juga bisa menambahkan satu terjemahan saja ke instance I18n
. Kamu bisa melakukannya baik dengan menentukan path file ke terjemahan menggunakan
const i18n = new I18n();
await i18n.loadLocale("en", { filePath: "locales/en.ftl" }); // versi async
i18n.loadLocaleSync("id", { filePath: "locales/id.ftl" }); // versi sync
2
3
4
maupun memuat konten terjemahan secara langsung sebagai sebuah string
const i18n = new I18n();
// versi async
await i18n.loadLocale("en", {
source: `greeting = Hello { $name }!
language-set = Language has been set to English!`,
});
// versi sync
i18n.loadLocaleSync("id", {
source: `greeting = Halo { $name }!
language-set = Bahasa telah diganti menjadi bahasa Indonesia!`,
});
2
3
4
5
6
7
8
9
10
11
12
13
Menyimak Teks yang Telah Di-localize
Kita telah berhasil mengirim pesan yang sudah di-localize ke user. Sekarang, mari kita belajar cara menyimak pesan yang dikirim oleh user. Di grammY, kita biasanya menggunakan handler bot
untuk menyimak pesan yang datang. Namun, karena kita berbicara mengenai internationalization, maka di bagian ini kita akan mempelajari bagaimana menyimak pesan yang datang dalam bentuk localize.
Fitur ini akan bermanfaat jika bot kamu memiliki keyboard custom berisi teks yang sudah di-localize.
Berikut contoh sederhana untuk menyimak pesan yang dikirim menggunakan custom keyboard yang sudah di-localize. Alih-alih menggunakan handler bot
, kita akan menggunakan bot
yang dikombinasikan dengan middleware hears
.
import { hears } from "@grammyjs/i18n";
bot.filter(hears("back-to-menu-btn"), async (ctx) => {
await ctx.reply(ctx.t("main-menu-msg"));
});
2
3
4
5
const { hears } = require("@grammyjs/i18n");
bot.filter(hears("back-to-menu-btn"), async (ctx) => {
await ctx.reply(ctx.t("main-menu-msg"));
});
2
3
4
5
import { hears } from "https://deno.land/x/grammy_i18n@v1.0.2/mod.ts";
bot.filter(hears("back-to-menu-btn"), async (ctx) => {
await ctx.reply(ctx.t("main-menu-msg"));
});
2
3
4
5
Function helper hears
dapat membuat bot kamu mampu menyimak pesan yang ditulis menggunakan locale suatu user.
Langkah Berikutnya
- Baca semua dokumentasi Fluent, khususnya di bagian syntax guide.
- Lihat contoh
-contoh lainnya untuk Deno dan Node.js.
Ringkasan Plugin
- Nama:
i18n
- Sumber
- Referensi API