EMZETT.
Giriş yap

next-intl

Kısaca: Next.js projelerinde çok dilli destek (i18n) için bir kütüphane — sabit kodlanmış arayüz metinlerini merkezî çeviri dosyaları üzerinden çevirir.

Biraz daha ayrıntılı: Metinler dil başına JSON dosyalarında bulunur (örneğin messages/de.json, messages/en.json) ve kodda sabit kodlanmak yerine useTranslations/getTranslations (t("key")) ile anahtara göre alınır. Önemli: next-intl yalnızca bu arayüz metinlerini çevirir, veri tabanı içeriğini (örneğin kendi yazdığın blog yazılarını) değil — bunun için ayrı bir özellik gerekir.

Bizim bağlamımız: Emzett’te Almanca/İngilizce için URL öneki olmadan (/de/, /en/) devreye alındı — dil bunun yerine bir çerezde yaşar. Hepsi bir anda değil, sayfa sayfa (alt bilgi, üst bilgi, mağaza, biletler, …) kademeli olarak geçirildi.

Ayrıntılı

Çeviri dosyalarının yapısı

Çeviri dosyaları iç içe JSON nesneleridir, böylece ilişkili metinler birlikte gruplanmış kalır:

{
  "Cart": {
    "title": "Cart",
    "empty": "Your cart is empty.",
    "itemCount": "{count, plural, one {# item} other {# items}}"
  }
}

Bu gruplamanın (her arayüz alanı için bir ad alanı, örneğin Cart, Checkout, Footer) salt düzenin ötesinde pratik bir yararı vardır: useTranslations("Cart") bu ad alanıyla sınırlı bir çeviri işlevi döndürür, böylece kodun geri kalanında daha kısa anahtarlar (t("Cart.title") yerine t("title")) yeterlidir ve alanlar arasında ad çakışmaları dışlanır.

ICU mesaj sözdizimi

itemCount, next-intl’in önemli bir yeteneğini gösterir: çoğul biçimler için ICU mesaj sözdizimi — kodda count === 1 ? "item" : "items" mantığını kendin yazmak yerine (Almanca/İngilizceden daha karmaşık çoğul kuralları olan dillerde çabuk yanlış gider), kütüphane bunu dil başına otomatik ve doğru biçimde halleder. Bazı dillerin (örneğin Lehçe, Rusça) ikiden fazla çoğul biçimi vardır (“bir” için bir, “birkaç” için bir, “çok” için bir) — ICU sözdizimi bunu ek kategorilerle (few, many) eşler; uygulama kodunda dile özgü bir durum ayrımına hiç gerek kalmaz. Koşullu metinler de bu yolla ifade edilebilir; örneğin dilbilgisel cinsiyet select sözdizimiyle ({gender, select, male {he} female {she} other {it}}).

Sunucu ve istemci tarafı kullanım

Sunucu Bileşenlerinde getTranslations() (asenkron), İstemci Bileşenlerinde useTranslations() (bir hook, senkron, çünkü çeviriler zaten sunucu tarafından teslim edilmiştir) kullanılır. İkisi de aynı JSON dosyalarına erişir, ancak arkasındaki mekanizma farklıdır: sunucu tarafında mesajlar doğrudan dosya sisteminden okunur; istemci tarafında bir NextIntlClientProvider ile sağlanır (ilgili çevirileri prop olarak istemciye iletir) — tarayıcıya gönderilen JavaScript paketini küçük tutmak için yalnızca İstemci Bileşenlerinin gerçekten ihtiyaç duyduğu mesajlar iletilmelidir.

Çerez tabanlı ve URL tabanlı yönlendirme

Çerez tabanlı yaklaşıma (Emzett’in kullandığı) alternatif, URL tabanlı yönlendirme olurdu (/de/shop, /en/shop) — buradaki avantaj: arama motorları her dil sürümünü ayrı dizinleyebilir ve paylaşılan URL’ler dile özgü olarak nettir (hreflang etiketleriyle uluslararası SEO için önemli); dezavantaj: daha fazla yönlendirme karmaşıklığı (her rota fiilen iki kez bulunur) ve yanlış paylaşılmış bağlantıları izleyen kullanıcılar otomatik olarak tercih ettikleri dile düşmek yerine yanlış dilde bitebilir. Çerez yaklaşımı uygulaması daha basittir ve dil önekisiz “temiz” URL’leri korur, ancak aynı URL’nin çereze bağlı olarak farklı içerik gösterebilmesi dezavantajına sahiptir — bu, saf SEO açısından en iyi değildir, ama öncelikle tek bir dil bölgesine yönelik bir proje için genellikle pratik bir sorun değildir.

Ayrıca bak: Next.js App Router, i18n