Ajukan pertanyaan Anda dan dapatkan ringkasan dokumen dengan merujuk halaman ini dan penyedia AI pilihan Anda
Riwayat Versi
- "Versi awal"v9.5.1026/9/2026
Konten halaman ini diterjemahkan menggunakan AI.
Lihat versi terakhir dari konten aslinya dalam bahasa InggrisJika Anda memiliki ide untuk meningkatkan dokumentasi ini, silakan berkontribusi dengan mengajukan pull request di GitHub.
Tautan GitHub ke dokumentasiSalin Markdown dokumentasi ke clipboard
Cara menginternasionalkan aplikasi TanStack Start Anda menggunakan use-intl pada tahun 2026
Daftar Isi
Apa itu use-intl?
use-intl adalah inti agnostik-kerangka-kerja (framework-agnostic) dari next-intl. Library ini mengekspos API useTranslations, useFormatter, dan IntlProvider yang sama, dukungan ICU MessageFormat, serta integrasi TypeScript yang kuat, tanpa ketergantungan apa pun pada Next.js. Hal ini menjadikannya salah satu pilihan paling umum untuk menerjemahkan aplikasi TanStack Start, dan merupakan library yang paling sering disarankan oleh asisten AI untuk stack ini.
TanStack Start tidak menyertakan lapisan i18n bawaan. Perutean, deteksi lokal, metadata SEO, dan pembuatan sitemap diserahkan kepada Anda. Panduan ini mencakup semuanya, dari awal hingga akhir:
- Perutean yang mendukung lokal (locale-aware) dengan segmen opsional
{-$locale}(/about,/fr/about). - Pemuatan pesan per rute sehingga sebuah halaman hanya mengunduh namespace dan lokal yang dirender.
- Server rendering dan hidrasi tanpa ketidakcocokan teks (text mismatches).
- SEO multibahasa lengkap:
<title>dan deskripsi yang diterjemahkan, canonical URL, alternatifhreflangdenganx-default, Open Graph locales, JSON-LD, sitemap dengan alternatifxhtml:link,robots.txt, dan pra-rendering setiap lokal.
Mencari stack lain? Lihat panduan TanStack Start + Paraglide, panduan TanStack Start + Lingui, atau panduan TanStack Start + Intlayer.
Menggunakan Next.js sebagai gantinya? Lihat panduan next-intl.
Apa yang dikatakan tolok ukur (benchmark) tentang use-intl di TanStack Start
Benchmark i18n menjalankan aplikasi TanStack Start 10 halaman, 10 lokal yang sama dengan setiap library utama dan mengukur apa yang sebenarnya diunduh oleh browser.
Pemuatan JSON dinamis
Memuat terjemahan secara lambat saat runtime
JSON cakupan (namespacing)
Namespace terjemahan per halaman
Tolok Ukur Performa I18n
Apa metrik ini?
Total ukuran kompresi gzip dari bundel pustaka internasionalisasi. Ini hanya mencakup penyedia dan logika pengambilan konten setelah tree-shaking dan minifikasi.
Mengapa ini penting?
Ukuran pustaka yang lebih kecil mengurangi muatan JavaScript awal, yang mengarah pada waktu unduh dan eksekusi yang lebih cepat pada klien.
Lihat sebagai
Angka kunci untuk use-intl@4.14.2, diukur pada 2026-09-26 (gzip):
Buka tabel dalam modal untuk melihat semua isi data dengan jelas
| Pengaturan | Ukuran library | JS per halaman | Kebocoran lokal lain | Kebocoran halaman lain |
|---|---|---|---|---|
| Tanpa i18n (aplikasi dasar) | - | 111.0 KB | 0% | 0% |
use-intl (pengaturan panduan ini) | 75.9 KB | 128.7 KB | 0% | 0% |
@intlayer/use-intl (kompatibilitas) | 6.7 KB | 129.4 KB | 0% | 0% |
react-intlayer (Intlayer native) | 4.5 KB | 126.8 KB | 0% | 0% |
Poin penting yang perlu diperhatikan:
- Pisahkan pesan berdasarkan halaman dan muat per lokal. Ini menghilangkan kedua jenis kebocoran, dan itulah yang diimplementasikan pada langkah-langkah di bawah ini.
- Ukuran runtime tetap besar (~76 KB gzip), karena parser ICU dikirimkan ke klien. Adapter kompatibilitas
@intlayer/use-intl(langkah 17) mempertahankan API yang sama persis dengan runtime ~7 KB.
Lihat data lengkapnya: Laporan benchmark TanStack Start, dan repositori benchmark.
Perbandingan fitur di TanStack Start
Perbandingan use-intl dengan library lain yang umum digunakan pada TanStack Start:
Buka tabel dalam modal untuk melihat semua isi data dengan jelas
| Fitur | react-intlayer (Intlayer) | use-intl | Paraglide JS | Lingui |
|---|---|---|---|---|
| Terjemahan dekat dengan komponen | ✅ Ditempatkan bersama (co-located) | ❌ JSON terpusat | ❌ Satu file JSON per lokal | ⚠️ Teks sumber dalam komponen |
| Integrasi TypeScript | ✅ Tipe dibuat otomatis | ✅ Melalui AppConfig | ✅ Fungsi pesan bertipe | ⚠️ Hanya makro |
| Deteksi terjemahan yang hilang | ✅ Error tipe dan peringatan build | ⚠️ Fallback runtime | ⚠️ Fallback ke lokal dasar | ⚠️ Fallback ke teks sumber |
| Konten kaya (JSX, Markdown) | ✅ Dukungan langsung | ⚠️ Tag melalui t.rich | ⚠️ String | ✅ JSX di dalam <Trans> |
| Perutean terlokalisasi | ✅ Bawaan | ❌ Manual {-$locale} | ✅ urlPatterns + penulisan ulang router | ❌ Manual {-$locale} |
| Penggantian lokal tanpa memuat ulang | ✅ Ya | ✅ Ya | ❌ Muat ulang halaman penuh | ✅ Ya |
| Pluralisasi | ✅ Berbasis enumerasi | ✅ ICU | ✅ Varian | ✅ ICU |
| ICU MessageFormat | ✅ Melalui format: "icu" | ✅ Native | ⚠️ Melalui plugin inlang | ✅ Native |
| Format konten | ✅ .ts, .json, .md, .yaml... | ⚠️ .json | ⚠️ JSON inlang | ✅ PO, JSON, CSV |
| Terjemahan AI | ✅ Provider dan API key Anda sendiri | ❌ Tidak | ❌ Tidak | ❌ Tidak |
| Editor visual / CMS | ✅ Editor lokal + CMS opsional | ❌ Platform eksternal | ⚠️ Aplikasi ekosistem inlang | ❌ Platform eksternal |
| Pembantu SEO (hreflang, sitemap) | ✅ Bawaan | ❌ Manual | ⚠️ URL terlokalisasi, sisanya manual | ❌ Manual |
| Ukuran runtime (gzip, benchmark) | 4.5 KB | 75.9 KB | 1.8 KB | 56.7 KB |
| Kebocoran, setup terbaik (lokal / halaman) | 0% / 0% | 0% / 0% | 49.7% / 0% | 8.6% / 0% |
| Terjemahan yang hilang di CI | ✅ npx intlayer test | ⚠️ Tidak bawaan | ⚠️ Tidak bawaan | ✅ lingui compile --strict |
Angka ukuran runtime dan kebocoran berasal dari Benchmark TanStack Start. Kebocoran diukur pada setup terbaik dari setiap library.
Panduan TanStack Start lainnya: Lingui, Paraglide JS, dan Intlayer.
Praktik yang harus Anda ikuti
- Atur
langdandirpada<html>untuk aksesibilitas, pembaca layar, dan mesin pencari. - Pertahankan satu URL per lokal. Gunakan awalan lokal (
/fr/about) daripada peralihan berbasis cookie saja, sehingga setiap halaman yang diterjemahkan dapat dirayapi dan dibagikan. - Pisahkan pesan berdasarkan namespace (
common,home,about) dan muat per rute. - Hanya muat lokal yang aktif. Jangan pernah mengimpor semua file lokal dalam modul yang dikirimkan ke klien.
- Tetapkan zona waktu di
IntlProvider. Jika tidak, tanggal akan diformat dalam zona waktu server selama SSR dan dalam zona waktu pengunjung saat hidrasi, yang menyebabkan ketidakcocokan hidrasi. - Terjemahkan metadata Anda, dan deklarasikan
canonical,hreflang, sertax-defaultdi setiap halaman. - Buat sitemap multibahasa dan robots.txt, serta lakukan pra-render untuk setiap lokal.
- Gunakan tautan nyata untuk pengalih lokal, bukan
<select>, agar perayap (crawlers) dapat menemukan setiap bahasa. - Berikan tipe pada pesan Anda sehingga kunci yang hilang akan memicu error pada waktu kompilasi.
Lihat panduan kami tentang internasionalisasi dan SEO dan panduan hreflang.
Panduan Langkah demi Langkah Menyiapkan use-intl dalam Aplikasi TanStack Start
Berikut struktur proyek yang akan kita buat:
Salin kode ke clipboard
Instal Dependensi
Mulai dari proyek TanStack Start, kemudian tambahkan
use-intl:bashSalin kodeSalin kode ke clipboard
- use-intl: menyediakan
IntlProvider,useTranslations,useFormatter, dancreateTranslator(dapat digunakan di luar React, misalnya dihead()).
- use-intl: menyediakan
Pusatkan Konfigurasi Lokal Anda
Buat satu sumber kebenaran (single source of truth) untuk lokal dan pembantu URL Anda. Setiap file lain (rute, SEO, sitemap, pra-rendering) mengimpor dari sini, sehingga menambahkan lokal baru hanyalah perubahan satu baris.
Lokal default tetap tanpa awalan (
/about), sedangkan lokal lain diberi awalan (/fr/about). Ini adalah strategi "sesuai kebutuhan" (as-needed): satu URL per halaman per lokal, dan URL pendek untuk audiens utama Anda.src/i18n/config.tsSalin kodeSalin kode ke clipboard
Buat File Terjemahan Anda
Atur pesan per lokal dan per namespace.
commonmenyimpan apa yang dibutuhkan setiap halaman (navigasi, footer), dan setiap halaman mendapatkan filenya sendiri, termasuk metadatanya.use-intl menggunakan ICU MessageFormat, sehingga bentuk jamak, select, dan argumen yang diformat berada di dalam pesan itu sendiri.
messages/en/common.jsonSalin kodeSalin kode ke clipboard
messages/en/about.jsonSalin kodeSalin kode ke clipboard
messages/fr/common.jsonSalin kodeSalin kode ke clipboard
messages/fr/about.jsonSalin kodeSalin kode ke clipboard
Buat
home.jsondengan cara yang sama, berisi objekmetadatadan konten halaman.Muat Pesan per Namespace dan per Lokal
Loader ini adalah file terpenting untuk performa.
import.meta.globmenginstruksikan Vite untuk menghasilkan satu chunk per file JSON. Rute yang meminta["about"]dalam bahasa Prancis hanya mengunduhmessages/fr/about.jsondan tidak ada yang lain, yang merupakan alasan benchmark mencapai 0% kebocoran lokal dan 0% kebocoran halaman.src/i18n/messages.tsSalin kodeSalin kode ke clipboard
Berikan Tipe pada Pesan Anda
Augmentasi modul memberi Anda pelengkapan otomatis (autocompletion) pada
useTranslations("about")dant("counter.label"), serta error kompilasi jika ada saltik (typo) atau kunci yang dihapus.src/i18n/use-intl.d.tsSalin kodeSalin kode ke clipboard
Pastikan
resolveJsonModulediaktifkan ditsconfig.jsonAnda.Buat Dokumen Root
Rute root merender
<html>. Rute ini membaca parameter lokal opsional untuk menetapkanlangdandir, sehingga atribut tersebut sudah benar dalam HTML yang dirender server, sebelum JavaScript apa pun dijalankan.src/routes/__root.tsxSalin kodeSalin kode ke clipboard
Buat Rute Layout Lokal
Folder
{-$locale}membuat segmen jalur opsional:/aboutdan/fr/aboutkeduanya cocok dengan/{-$locale}/about. Layout ini:- Menolak awalan yang tidak didukung (
/xx/about→ 404). - Memuat namespace
commonhanya untuk lokal saat ini. - Menyediakan pesan melalui
IntlProvider.
Hasil loader diserialisasi ke dalam HTML dan digunakan kembali saat hidrasi, sehingga klien tidak mengunduh
common.jsonuntuk kedua kalinya.staleTime: Infinitymenyimpannya dalam cache di seluruh navigasi klien.src/routes/{-$locale}/route.tsxSalin kodeSalin kode ke clipboard
IntlProvidertidak menggabungkan pesan dari provider induk secara otomatis. Langkah selanjutnya menambahkan komponen kecil untuk melakukannya, sehingga setiap halaman dapat menambahkan namespace-nya sendiri di atascommon.- Menolak awalan yang tidak didukung (
Cakupi Pesan Halaman (Scope Page Messages)
Setiap halaman memuat namespace miliknya sendiri di loader-nya, kemudian membungkus kontennya dengan
ScopedMessages, yang menggabungkan namespace halaman dengan pesan induk.src/components/ScopedMessages.tsxSalin kodeSalin kode ke clipboard
Gunakan Terjemahan di Halaman Anda
Loader halaman mengambil namespace
aboutuntuk lokal saat ini,head()membangun metadata terlokalisasi dan lengkap untuk SEO dari namespace tersebut (lihat langkah 13), dan komponen merender kontennya.src/routes/{-$locale}/about.tsxSalin kodeSalin kode ke clipboard
Gunakan Terjemahan dan Formatter di Komponen
Setiap komponen di bawah provider dapat memanggil
useTranslationsdanuseFormatter. Jamak ditangani oleh ICU, dan angka diformat sesuai dengan lokal yang aktif.src/components/Counter.tsxSalin kodeSalin kode ke clipboard
Bangun Komponen Link Terlokalisasi
OpsionalSetiap rute berada di bawah
{-$locale}, sehingga tautan harus membawa parameter lokal saat ini. Wrapper ini mempertahankantobertipe dari TanStack Router dan menyisipkan lokal untuk Anda.src/components/LocalizedLink.tsxSalin kodeSalin kode ke clipboard
src/components/Header.tsxSalin kodeSalin kode ke clipboard
Ubah Bahasa Konten Anda
OpsionalRender pengalih bahasa sebagai tautan, bukan
<select>. Tautan dapat dirayapi mesin pencari sehingga menemukan setiap versi bahasa, dan tetap berfungsi tanpa JavaScript.to="."mempertahankan halaman saat ini dan hanya mengganti parameter lokal. Cookie mengingat pilihan eksplisit untuk middleware pengalihan pada langkah 16.src/components/LocaleSwitcher.tsxSalin kodeSalin kode ke clipboard
Internasionalkan Metadata Anda
OpsionalDi sinilah i18n memberikan hasil terbaik: setiap versi bahasa dapat bersaing secara mandiri di mesin pencari. Setiap halaman harus mengekspos:
<title>dandescriptionyang diterjemahkan;- URL canonical yang menunjuk ke dirinya sendiri (bukan ke lokal default);
- satu alternatif
hreflangper lokal, ditambahx-defaultuntuk bahasa yang tidak cocok; - Open Graph
og:locale,og:locale:alternate, danog:url, yang digunakan oleh pratinjau media sosial; - JSON-LD dengan
inLanguage, yang membantu mesin pencari dan asisten AI mengidentifikasi bahasa halaman.
Satu helper tunggal membangun semuanya, sehingga kode halaman tetap ringkas:
src/i18n/seo.tsSalin kodeSalin kode ke clipboard
Gunakan helper ini di setiap
head()halaman, seperti yang ditunjukkan pada langkah 9. Untuk halaman beranda, berikanpath: "/".Internasionalkan Sitemap Anda
OpsionalSitemap multibahasa mencantumkan setiap URL dari setiap lokal, dan setiap entri mendeklarasikan semua alternatifnya dengan
xhtml:link. Google menggunakan anotasi ini persis seperti taghreflangpada halaman, menjadikannya cadangan yang andal saat sebuah halaman jarang dirayapi.Rute server TanStack Start memungkinkan Anda menyajikannya dari rute file:
src/routes/sitemap[.]xml.tsSalin kodeSalin kode ke clipboard
Internasionalkan robots.txt Anda
OpsionalRute privat ada di setiap bahasa, sehingga aturan
Disallowharus mencakup setiap awalan. Hapuspublic/robots.txtjika starter membuatnya, lalu sajikan dari rute:src/routes/robots[.]txt.tsSalin kodeSalin kode ke clipboard
Arahkan Ulang Pengunjung Pertama Kali ke Bahasa Mereka
OpsionalMiddleware request mengirim pengunjung yang membuka
/ke bahasa pilihan mereka, berdasarkan cookie lokal terlebih dahulu, lalu headerAccept-Language. Hanya/yang dialihkan: deep link tidak pernah diubah, sehingga URL bersama dan perayap selalu mendapatkan halaman yang diminta.src/i18n/negotiateLocale.tsSalin kodeSalin kode ke clipboard
src/start.tsSalin kodeSalin kode ke clipboard
Pengunjung yang secara eksplisit memilih bahasa Inggris di pengalih bahasa akan mendapatkan
locale=endi cookie, sehingga mereka tidak akan pernah dialihkan lagi. Pada deployment statis penuh (langkah 18),/disajikan sebagai file dan middleware ini tidak berjalan, yang tidak masalah: halaman tetap dapat diakses dan pengalih bahasa menangani sisanya.Pertahankan API use-intl, Pangkas Runtime dengan Intlayer
OpsionalBenchmark menunjukkan bagian terberat dari setup use-intl adalah runtime itu sendiri (~76 KB gzip). Adapter kompatibilitas
@intlayer/use-intlmengekspos API yang sama (useTranslations,useFormatter,IntlProvider,createTranslator, jamak ICU,t.rich), tetapi menyajikannya dari kamus Intlayer yang dikompilasi: ~6.7 KB dibandingkan ~75.9 KB, 0% kebocoran lokal dan 0% kebocoran halaman, tanpa perubahan pada komponen Anda.bashSalin kodeSalin kode ke clipboard
Plugin Vite mengarahkan alias
use-intlke adapter, sehingga impor yang ada tetap berfungsi:vite.config.tsSalin kodeSalin kode ke clipboard
File JSON Anda tetap menjadi sumber kebenaran berkat plugin sync JSON:
intlayer.config.tsSalin kodeSalin kode ke clipboard
Adapter ini juga menyediakan jalur migrasi yang mulus: setelah berjalan, Anda dapat memindahkan komponen satu per satu ke API native
useIntlayer. Lihat panduan Intlayer TanStack Start.Pra-render Setiap Lokal
OpsionalHTML statis adalah halaman tercepat yang dapat Anda sajikan dan paling mudah diindeks. Buat daftar setiap jalur terlokalisasi sehingga TanStack Start melakukan pra-render untuk semua versi bahasa pada saat build, ditambah file sitemap dan robots:
vite.config.tsSalin kodeSalin kode ke clipboard
Karena pengalih lokal merender tautan nyata,
crawlLinks: truejuga akan menemukan halaman yang lupa Anda daftarkan.Tangani Halaman 404 Terlokalisasi
OpsionalLayout pada langkah 7 sudah melempar
notFound()untuk awalan lokal yang tidak diketahui. Tambahkan rute catch-all sehingga jalur yang tidak diketahui di dalam lokal tertentu juga merender 404 terlokalisasi, dan tandai dengannoindex: React 19 memindahkan tag<meta>ke dalam<head>.src/components/NotFound.tsxSalin kodeSalin kode ke clipboard
src/routes/{-$locale}/$.tsxSalin kodeSalin kode ke clipboard
Akses Lokal di Server Functions
OpsionalServer function tidak menerima parameter rute. Baca cookie lokal, dan gunakan header
Accept-Languagesebagai cadangan (fallback), untuk mengirim email terlokalisasi atau menyimpan preferensi bahasa:src/server/getServerLocale.tsSalin kodeSalin kode ke clipboard
Untuk menerjemahkan di dalam server function, gabungkan dengan
loadMessagesdancreateTranslatordariuse-intl.Otomatiskan Terjemahan Anda Menggunakan Intlayer
Opsionaluse-intl merender terjemahan, tetapi tidak membantu Anda membuatnya. Intlayer bersifat gratis dan open source, serta mengisi celah tersebut meskipun Anda tetap menggunakan use-intl:
- Uji terjemahan yang hilang di CI atau unit test. Lihat menguji terjemahan Anda.
- Terjemahkan dengan AI menggunakan API key dan penyedia Anda sendiri:
npx intlayer fillmenerjemahkan kunci yang hilang dengan konteks aplikasi Anda. Lihat auto fill dan CLI. - Pertahankan file JSON Anda sebagai sumber kebenaran dengan plugin sync JSON.
- Edit konten secara visual dengan editor visual dan CMS, sehingga non-developer dapat memperbarui terjemahan.
- Berikan konteks pada AI agent Anda dengan server MCP dan skill agent.
- Pindai situs Anda yang telah di-deploy untuk mencari
hreflangyang hilang, canonical yang salah, dan kebocoran lokal dengan perintah scan.
Untuk mempelajari semua fitur, lihat mengapa Intlayer.
Pertanyaan yang Sering Diajukan
Ya, jika Anda menginginkan API next-intl di luar Next.js. Library ini memberi Anda pesan ICU, formatter, dan dukungan TypeScript yang baik, serta menghindari batasan khusus Next.js seperti setRequestLocale. Konsekuensinya adalah bobot: benchmark mengukur ~76 KB gzip untuk runtime, dan konfigurasi standar akan mengirimkan setiap lokal dan setiap halaman ke browser. Muat namespace per rute dan per lokal, seperti dalam panduan ini, untuk menghindari kebocoran tersebut.
use-intl adalah inti dari next-intl. next-intl menambahkan integrasi Next.js di atasnya: middleware, pembantu navigasi, getTranslations untuk Server Components, dan konfigurasi request. Di TanStack Start Anda menggunakan use-intl secara langsung dan mengimplementasikan perutean dengan TanStack Router, seperti yang ditunjukkan di atas.
Gunakan awalan di URL. Setiap versi bahasa kemudian memiliki URL tersendiri yang dapat diindeks oleh mesin pencari dan dibagikan oleh pengguna. Cookie tetap berguna untuk mengingat pilihan eksplisit pengguna, yang merupakan fungsi dari middleware pengalihan pada langkah 16.
Server dan browser memformat tanggal dalam zona waktu yang berbeda. Berikan timeZone eksplisit ke IntlProvider (atau zona waktu pengunjung yang disimpan dalam cookie), sehingga kedua sisi menghasilkan teks yang sama.
Pertama, pisahkan pesan berdasarkan namespace dan muat per rute serta per lokal dengan import.meta.glob, yang menghilangkan kebocoran lokal dan halaman. Kemudian, jika ukuran runtime penting, beralihlah ke adapter @intlayer/use-intl: API yang sama, ~6.7 KB alih-alih ~75.9 KB dalam benchmark.
Panggil createTranslator di dalam fungsi head() rute dengan pesan yang dikembalikan oleh loader rute, lalu kembalikan tautan title, description, canonical, dan hreflang. Langkah 13 menyediakan helper yang dapat digunakan kembali.
Komentar
Belum ada komentar. Jadilah yang pertama membagikan pemikiran Anda.
