Cara termudah untuk menerjemahkan aplikasi Next.js Anda (dengan pengaturan halaman) .
Jika Anda menggunakan next-i18next (direktori halaman) dalam produksi dan ingin mengeluarkan kekuatan super, Anda dapat melihat postingan blog ini.
Jika Anda menggunakan Next.js 13/14 dengan direktori aplikasi, tidak perlu next-i18next, Anda bisa langsung menggunakan i18next dan react-i18next, seperti yang dijelaskan dalam postingan blog ini.
Meskipun Next.js menyediakan perutean internasional secara langsung, Next.js tidak menangani pengelolaan konten terjemahan apa pun, atau fungsi terjemahan sebenarnya. Yang dilakukan Next.js hanyalah menjaga lokal dan URL Anda tetap sinkron.
Untuk melengkapi hal ini, next-i18next
menyediakan fungsionalitas yang tersisa – pengelolaan konten terjemahan, dan komponen/hook untuk menerjemahkan komponen React Anda – sekaligus mendukung penuh SSG/SSR, beberapa namespace, pemisahan kode, dll.
Meskipun next-i18next
menggunakan i18next dan react-i18next, pengguna next-i18next
hanya perlu menyertakan konten terjemahan mereka sebagai file JSON dan tidak perlu mengkhawatirkan banyak hal lainnya.
Demo langsung tersedia di sini. Aplikasi demo ini adalah contoh sederhana - tidak lebih, tidak kurang.
Mudah diatur, mudah digunakan: pengaturan hanya memerlukan beberapa langkah, dan konfigurasinya sederhana.
Tidak ada persyaratan lain: next-i18next
menyederhanakan internasionalisasi untuk aplikasi Next.js Anda tanpa ketergantungan tambahan.
Siap produksi: next-i18next
mendukung penerusan terjemahan dan opsi konfigurasi ke dalam halaman sebagai props dengan dukungan SSG/SSR.
File next-i18next.config.js
Anda akan menyediakan konfigurasi untuk next-i18next
. Setelah konfigurasi, appWithTranslation
memungkinkan kita untuk menggunakan fungsi t
(translate) di komponen kita melalui hook.
Kemudian kami menambahkan serverSideTranslation
ke getStaticProps atau getServerSideProps (tergantung kasus Anda) di komponen tingkat halaman kami.
Sekarang aplikasi Next.js kami dapat diterjemahkan sepenuhnya!
yarn add next-i18next react-i18next i18next
Anda juga harus react
dan menginstal next
.
Secara default, next-i18next
mengharapkan terjemahan Anda diatur seperti ini:
.
└── public
└── locales
├── en
| └── common.json
└── de
└── common.json
Struktur ini juga dapat dilihat pada contoh sederhana.
Jika Anda ingin menyusun terjemahan/ruang nama dengan cara khusus, Anda harus meneruskan nilai localePath
dan localeStructure
yang dimodifikasi ke dalam konfigurasi inisialisasi.
Pertama, buat file next-i18next.config.js
di root proyek Anda. Sintaks untuk objek i18n
bersarang berasal langsung dari Next.js.
Ini memberi tahu next-i18next
apa defaultLocale
Anda dan lokal lainnya, sehingga dapat memuat terjemahan terlebih dahulu di server:
next-i18next.config.js
/** @type {import('next-i18next').UserConfig} */
module . exports = {
i18n : {
defaultLocale : 'en' ,
locales : [ 'en' , 'de' ] ,
} ,
}
Sekarang, buat atau modifikasi file next.config.js
Anda, dengan meneruskan objek i18n
ke file next.config.js
Anda, untuk mengaktifkan perutean URL yang dilokalkan:
next.config.js
const { i18n } = require ( './next-i18next.config' )
module . exports = {
i18n ,
}
Ada tiga fungsi yang diekspor next-i18next
, yang perlu Anda gunakan untuk menerjemahkan proyek Anda:
Ini adalah HOC yang membungkus _app
Anda:
import { appWithTranslation } from 'next-i18next'
const MyApp = ( { Component , pageProps } ) => (
< Component { ... pageProps } / >
)
export default appWithTranslation ( MyApp )
appWithTranslation
HOC terutama bertanggung jawab untuk menambahkan I18nextProvider
.
Ini adalah fungsi async yang perlu Anda sertakan pada komponen tingkat halaman, melalui getStaticProps
atau getServerSideProps
(tergantung pada kasus penggunaan Anda):
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
export async function getStaticProps ( { locale } ) {
return {
props : {
... ( await serverSideTranslations ( locale , [
'common' ,
'footer' ,
] ) ) ,
// Will be passed to the page component as props
} ,
}
}
Perhatikan bahwa serverSideTranslations
harus diimpor dari next-i18next/serverSideTranslations
– ini adalah modul terpisah yang berisi kode khusus NodeJs.
Perlu diketahui juga bahwa serverSideTranslations
tidak kompatibel dengan getInitialProps
, karena hanya dapat dijalankan di lingkungan server, sedangkan getInitialProps
dipanggil di sisi klien saat bernavigasi antar halaman.
HOC serverSideTranslations
terutama bertanggung jawab untuk meneruskan terjemahan dan opsi konfigurasi ke dalam halaman, sebagai alat peraga – Anda perlu menambahkannya ke halaman mana pun yang memiliki terjemahan.
Ini adalah pengait yang sebenarnya akan Anda gunakan untuk melakukan penerjemahan itu sendiri. Kait useTranslation
berasal dari react-i18next
, tetapi perlu diimpor langsung dari next-i18next
.
JANGAN gunakan ekspor useTranslation
dari react-i18next
, tetapi HANYA gunakan yang dari next-i18next
!
import { useTranslation } from 'next-i18next'
export const Footer = ( ) => {
const { t } = useTranslation ( 'footer' )
return (
< footer >
< p > { t ( 'description' ) } < / p >
< / footer >
)
}
Secara default, next-i18next
akan mengirimkan semua namespace Anda ke klien pada setiap permintaan awal. Ini bisa menjadi pendekatan yang tepat untuk aplikasi kecil dengan konten lebih sedikit, namun banyak aplikasi akan mendapatkan keuntungan dari pemisahan namespace berdasarkan rute.
Untuk melakukannya, Anda dapat meneruskan array namespace yang diperlukan untuk setiap halaman ke serverSideTranslations
. Anda dapat melihat pendekatan ini di contoh/simple/pages/index.tsx. Melewati array kosong dari namespace yang diperlukan tidak akan mengirimkan namespace.
Catatan: useTranslation
menyediakan namespace ke komponen yang Anda gunakan. Namun, serverSideTranslations
menyediakan total namespace yang tersedia untuk keseluruhan pohon React dan berada di tingkat halaman. Keduanya diperlukan.
Secara default, next-i18next
hanya akan mengirimkan lokal aktif ke klien pada setiap permintaan. Hal ini membantu mengurangi ukuran muatan awal yang dikirim ke klien. Namun dalam beberapa kasus, seseorang mungkin memerlukan terjemahan untuk bahasa lain pada saat runtime juga. Misalnya saat menggunakan getFixedT dari kait useTranslation
.
Untuk mengubah perilaku dan memuat lokal tambahan, cukup masukkan array lokal sebagai argumen terakhir ke serverSideTranslations
.
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
export async function getStaticProps({ locale }) {
return {
props: {
- ...(await serverSideTranslations(locale, ['common', 'footer'])),
+ ...(await serverSideTranslations(locale, ['common', 'footer'], null, ['en', 'no'])),
},
};
}
Hasilnya, terjemahan untuk lokal no
dan en
akan selalu dimuat apa pun bahasanya saat ini.
Catatan: Argumen tambahan harus ditambahkan ke semua halaman yang menggunakan fungsi
getFixedT
.
Secara default, next-i18next
akan menambahkan defaultLocale
sebagai fallback. Untuk mengubahnya, Anda dapat menyetel fallbackLng
. Semua nilai yang didukung oleh i18next
( string
, array
, object
dan function
) juga didukung oleh next-i18next
.
Selain itu, nonExplicitSupportedLngs
dapat disetel ke true
untuk mendukung semua varian bahasa, tanpa perlu menyediakan file JSON untuk masing-masing varian tersebut. Perhatikan bahwa semua varian masih harus disertakan dalam locales
untuk mengaktifkan perutean dalam next.js
.
Catatan:
fallbackLng
dannonExplicitSupportedLngs
dapat digunakan sekaligus. Hanya ada satu pengecualian: Anda tidak dapat menggunakan fungsi untukfallbackLng
ketikanonExplicitSupportedLngs
bernilaitrue
,
module . exports = {
i18n : {
defaultLocale : 'en' ,
locales : [ 'en' , 'fr' , 'de-AT' , 'de-DE' , 'de-CH' ] ,
} ,
fallbackLng : {
default : [ 'en' ] ,
'de-CH' : [ 'fr' ] ,
} ,
nonExplicitSupportedLngs : true ,
// de, fr and en will be loaded as fallback languages for de-CH
}
Ketahuilah bahwa menggunakan fallbackLng
dan nonExplicitSupportedLngs
dapat dengan mudah meningkatkan ukuran awal halaman.
fyi: Menyetel fallbackLng
ke false
TIDAK akan membuat serial bahasa fallback Anda (biasanya defaultLocale
). Ini akan mengurangi ukuran pemuatan halaman awal Anda.
Jika Anda perlu mengubah opsi konfigurasi lanjutan, Anda dapat meneruskannya melalui next-i18next.config.js
. Misalnya:
module . exports = {
i18n : {
defaultLocale : 'en' ,
locales : [ 'en' , 'de' ] ,
} ,
localePath :
typeof window === 'undefined'
? require ( 'path' ) . resolve ( './my-custom/path' )
: '/public/my-custom/path' ,
ns : [ 'common' ] ,
}
Beberapa plugin i18next
(yang dapat Anda masukkan ke config.use
) tidak dapat diserialisasi, karena mengandung fungsi dan primitif JavaScript lainnya.
Anda mungkin mengalami hal ini jika kasus penggunaan Anda lebih maju. Anda akan melihat Next.js menimbulkan kesalahan seperti:
Error: Error serializing `._nextI18Next.userConfig.use[0].process` returned from `getStaticProps` in "/my-page".
Reason: `function` cannot be serialized as JSON. Please only return JSON serializable data types.
Untuk memperbaikinya, Anda harus menyetel config.serializeConfig
ke false
, dan meneruskan konfigurasi Anda secara manual ke appWithTranslation
:
import { appWithTranslation } from 'next-i18next'
import nextI18NextConfig from '../next-i18next.config.js'
const MyApp = ( { Component , pageProps } ) => (
< Component { ... pageProps } / >
)
export default appWithTranslation ( MyApp , nextI18NextConfig )
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import nextI18NextConfig from '../next-i18next.config.js'
export const getStaticProps = async ( { locale } ) => ( {
props : {
... ( await serverSideTranslations (
locale ,
[ 'common' , 'footer' ] ,
nextI18NextConfig
) ) ,
} ,
} )
Saat menggunakan halaman yang dihasilkan sisi server dengan getStaticPaths
dan fallback: true
atau fallback: 'blocking'
, pengaturan default yang ditunjukkan di atas akan menyebabkan aplikasi dilepas dan dipasang kembali pada setiap pemuatan, menyebabkan berbagai konsekuensi buruk seperti memanggil setiap useEffect(() => {...}, [])
kait dua kali dan sedikit penurunan kinerja.
Hal ini disebabkan oleh fakta bahwa, untuk halaman tersebut, Next.js melakukan render pertama dengan serverSideProps
kosong dan kemudian render kedua dengan serverSideProps
yang menyertakan terjemahan next-i18next
. Dengan pengaturan default, instance i18n
awalnya undefined
ketika serverSideProps
empty
, sehingga menyebabkan unmount-remount.
Untuk mengurangi masalah ini, Anda dapat melakukan hal berikut:
import { UserConfig } from 'next-i18next' ;
import nextI18NextConfig from '../next-i18next.config.js'
const emptyInitialI18NextConfig : UserConfig = {
i18n : {
defaultLocale : nextI18NextConfig . i18n . defaultLocale ,
locales : nextI18NextConfig . i18n . locales ,
} ,
} ;
const MyApp = ( { Component , pageProps } ) => (
< Component { ... pageProps } / >
)
export default appWithTranslation ( MyApp , emptyInitialI18NextConfig ) // Makes sure the initial i18n instance is not undefined
Ini akan berfungsi selama Anda memastikan bahwa, dalam status halaman cadangan, kode sisi klien Anda tidak mencoba menampilkan terjemahan apa pun karena jika tidak, Anda akan mendapatkan kesalahan "ketidakcocokan server-klien" dari Next.js (karena ke fakta bahwa server memiliki terjemahan aktual dalam htmlnya sedangkan html klien memiliki kunci terjemahan di tempat yang sama).
Ini normal dan bagus: Anda tidak seharusnya menampilkan kunci terjemahan kepada pengguna Anda!
Sejak v11.0.0 next-i18next juga menyediakan dukungan untuk pemuatan terjemahan di sisi klien.
Dalam beberapa kasus penggunaan, Anda mungkin ingin memuat file terjemahan secara dinamis tanpa harus menggunakan serverSideTranslations
. Hal ini khususnya berguna untuk komponen yang lambat dimuat dan Anda tidak ingin memperlambat halaman.
Informasi lebih lanjut tentang itu dapat ditemukan di sini.
Karena sumber daya dimuat satu kali saat server dimulai, perubahan apa pun yang dilakukan pada file JSON terjemahan Anda yang sedang dikembangkan tidak akan dimuat hingga server dimulai ulang.
Dalam produksi, hal ini cenderung tidak menjadi masalah, namun dalam pengembangan Anda mungkin ingin melihat pembaruan pada file JSON terjemahan Anda tanpa harus memulai ulang server pengembangan Anda setiap kali. Untuk melakukannya, setel opsi konfigurasi reloadOnPrerender
ke true
.
Opsi ini akan memuat ulang terjemahan Anda setiap kali serverSideTranslations
dipanggil (dalam getStaticProps
atau getServerSideProps
). Jika Anda menggunakan serverSideTranslations
di getServerSideProps
, disarankan untuk menonaktifkan reloadOnPrerender
di lingkungan produksi untuk menghindari memuat ulang sumber daya pada setiap panggilan server.
Kunci | Nilai bawaan | Catatan |
---|---|---|
defaultNS | 'common' | |
localePath | './public/locales' | Bisa berupa fungsi, lihat catatan di bawah. (bisa juga nol, jika meneruskan opsi sumber daya secara langsung melalui konfigurasi, seperti di sini) |
localeExtension | 'json' | Diabaikan jika localePath adalah sebuah fungsi. |
localeStructure | '{{lng}}/{{ns}}' | Diabaikan jika localePath adalah sebuah fungsi. |
reloadOnPrerender | false | |
serializeConfig | true | |
use (untuk plugin) | [] | |
onPreInitI18next | undefined | yaitu (i18n) => i18n.on('failedLoading', handleFailedLoading) |
localePath
sebagai fungsi berbentuk (locale: string, namespace: string, missing: boolean) => string
mengembalikan seluruh jalur termasuk nama file dan ekstensi. Jika missing
benar, kembalikan jalur untuk opsi addPath
dari i18next-fs-backend
, jika salah, kembalikan jalur untuk opsi loadPath
. Info lebih lanjut di repo i18next-fs-backend
.
Jika localePath adalah sebuah fungsi, pastikan Anda juga menentukan opsi ns, karena di sisi server kami tidak dapat memuat namespace terlebih dahulu.
Semua opsi i18next dan opsi react-i18next lainnya juga dapat diteruskan.
Anda juga dapat meneruskan resources
secara langsung bersamaan dengan pengaturan localePath
ke null
.
Secara default, i18next menggunakan {{
sebagai awalan dan }}
sebagai akhiran untuk interpolasi. Jika Anda ingin/perlu mengganti pengaturan interpolasi ini, Anda juga harus menentukan pengaturan localeStructure
alternatif yang cocok dengan awalan dan akhiran khusus Anda.
Misalnya, jika Anda ingin menggunakan {
dan }
konfigurasinya akan terlihat seperti ini:
{
i18n : {
defaultLocale : 'en' ,
locales : [ 'en' , 'nl' ] ,
} ,
interpolation : {
prefix : '{' ,
suffix : '}' ,
} ,
localeStructure : '{lng}/{ns}' ,
}
next-i18next.config.js
Jika Anda ingin mengubah jalur konfigurasi default, Anda dapat mengatur variabel lingkungan I18NEXT_DEFAULT_CONFIG_PATH
.
Misalnya, di dalam file .env
Anda dapat mengatur jalur statis:
I18NEXT_DEFAULT_CONFIG_PATH=/path/to/project/apps/my-app/next-i18next.config.js
Atau Anda dapat menggunakan trik untuk jalur dinamis dan mengatur yang berikut ini di dalam next.config.js
:
process . env . I18NEXT_DEFAULT_CONFIG_PATH = ` ${ __dirname } /next-i18next.config.js` ;
// ... Some other imports
const { i18n } = require ( './next-i18next.config' ) ;
// ... Some other code
module . exports = {
i18n ,
...
} ;
Ini berarti file konfigurasi i18n akan berada di direktori yang sama dengan next.config.js
dan tidak masalah di mana direktori kerja Anda saat ini berada. Ini membantu misalnya untuk nx
ketika Anda memiliki monorepo dan memulai aplikasi Anda dari root proyek tetapi aplikasi tersebut ada di apps/{appName}
.
Pemberitahuan Jika konfigurasi next-i18next.config.js
Anda tidak berada di direktori yang sama dengan next.config.js
, Anda harus menyalinnya secara manual (atau dengan skrip khusus).
Jika Anda berencana menambahkan next-i18next ke proyek Anda secara bertahap, kami menyarankan agar Anda meneruskan next-i18next.config
ke appWithTranslation
untuk menghindari masalah apa pun.
yaitu
import nextI18nextConfig from '../../next-i18next.config' ;
//...
export default appWithTranslation ( MyApp , nextI18nextConfig ) ;
Lihat Edisi #2259 untuk informasi lebih lanjut.
Beberapa PaaS tanpa server mungkin tidak dapat menemukan jalur terjemahan Anda dan memerlukan konfigurasi tambahan. Jika Anda memiliki masalah sistem file saat menggunakan serverSideTranslations
, setel config.localePath
untuk menggunakan path.resolve
. Contohnya dapat ditemukan di sini.
Untuk penerapan Docker, perhatikan bahwa jika Anda menggunakan Dockerfile
dari dokumen Next.js jangan lupa untuk menyalin next.config.js
dan next-i18next.config.js
ke dalam image Docker.
COPY --from=builder /app/next.config.js ./next.config.js
COPY --from=builder /app/next-i18next.config.js ./next-i18next.config.js
Jika Anda memilih untuk menggunakan backend i18next yang berbeda dengan backend i18next-fs bawaan, Anda perlu memastikan sumber daya terjemahan dimuat sebelum Anda memanggil fungsi t
. Karena React suspense belum didukung untuk SSR, hal ini dapat diselesaikan dengan 2 cara berbeda:
1) Pramuat namespace:
Atur opsi ns
, seperti pada contoh ini. Melakukan hal ini akan memastikan semua sumber terjemahan dimuat pada inisialisasi.
2) Periksa bendera siap:
Jika Anda tidak bisa atau tidak ingin menyediakan array ns
, panggilan ke fungsi t
akan menyebabkan namespace dimuat dengan cepat. Ini berarti Anda harus menangani status "belum siap" dengan mencentang ready === true
atau props.tReady === true
. Tidak melakukan hal ini akan mengakibatkan terjemahan Anda dirender sebelum dimuat, yang akan menyebabkan "simpan yang hilang" dipanggil meskipun terjemahan sebenarnya sudah ada (belum dimuat). Ini dapat dilakukan dengan kait useTranslation atau withTranslation HOC.
Apakah Anda mencoba membuat ekspor HTML statis dengan menjalankan next export
dan mendapatkan kesalahan ini?
Kesalahan: dukungan i18n tidak kompatibel dengan ekspor berikutnya. Lihat di sini untuk informasi selengkapnya tentang penerapan: https://nextjs.org/docs/deployment
Namun ada cara untuk mengatasinya dengan bantuan pendeteksi bahasa berikutnya. Lihat posting blog ini dan proyek contoh ini.
Anda memiliki beberapa cara untuk menggunakan fungsi t di komponen anak Anda:
t
melalui props ke anak-anakuseTranslation
, seperti dalam contoh ini:berikutnya-i18next/examples/simple/components/Footer.tsx
Baris 6 di e6b5085
withTranslation
Dan secara umum, Anda selalu perlu memastikan serverSideTranslations berisi semua namespace yang Anda perlukan di pohon.
Terima kasih kepada orang-orang hebat ini (kunci emoji):
Rob Capellini | Alexander Kachkaev ? ? | Mathias Wobbe ? | Lukas Feliciano ? ? | Ryan Leung | Nathan Frimel ? | Isaac Hinman ️️️️♿️ ? ? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ? ?️ ? |
Adriano Raiano ️️️️♿️ ? ? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ? ?️ ? | Felix Mosheev ? | Sébastien Vanvelthem ? ? |
Proyek ini mengikuti spesifikasi semua kontributor. Kontribusi apa pun diterima!
lokalisasi sebagai layanan - locize.com
Membutuhkan manajemen terjemahan? Ingin mengedit terjemahan Anda dengan Editor InContext? Gunakan dokumen asli yang disediakan oleh pengelola i18next!
Dengan menggunakan locize Anda secara langsung mendukung masa depan i18next dan next-i18next.