Sorunuzu sorun ve bu sayfaya ve seçtiğiniz AI sağlayıcısına referans vererek belgenin bir özetini alın
Bu sayfanın içeriği bir yapay zeka kullanılarak çevrildi.
Orijinal içeriğin İngilizce son sürümünü görüntüleyinBu dokümantasyonu geliştirmek için bir fikriniz varsa, lütfen GitHub'da bir çekme isteği göndererek katkıda bulunmaktan çekinmeyin.
Dokümantasyon için GitHub bağlantısıBelge Markdown'ını panoya kopyala
ICU Message Format: Sözdizimi ve en çok hata yapılan noktalar
ICU MessageFormat, bir çevirinin kendi dallanma mantığını (çoğullar, cinsiyete bağlı biçimler, sayı ve tarih biçimlendirmesi) içermesini sağlayan bir metin sözdizimidir. Temel mantığı, dilbilgisinin if (count === 1) yazan geliştiriciye değil, çevirmene ait olması gerektiğidir. Bu makalede sözdizimi, basit yaklaşımların yetersiz kaldığı dile özgü kurallar ve JavaScript ekosisteminin bu süreci nasıl ele aldığı açıklanmaktadır.
İçindekiler
Somut olarak problem
İşte neredeyse her geliştiricinin ilk yazdığı kod:
Kodu panoya kopyala
Bu mantık İngilizcede çalışır ancak diğer neredeyse tüm dillerde bozulur:
- Rusça ve Lehçe iki değil, üç veya dört biçime ihtiyaç duyar.
- Türkçe ve Japonca tek bir biçim kullanır ve araya eklenen boşluk gereksiz veya hatalı olabilir.
- Arapça altı çoğul biçimi gerektirir ve sayının kendisi de yerel rakam sistemiyle işlenmelidir.
- Fransızca bazı noktalama işaretlerinden önce bölünemez boşluk (non-breaking space) koyar, bu da
+ " "ile birleştirildiğinde kaybolur.
Daha derin sorun ise cümlenin parçalara bölünmüş olmasıdır. Çevirmen, bağlamdan yoksun item ve items kelimelerini görür ve cümlenin sözdizimini değiştirme olanağını kaybeder. ICU MessageFormat, tüm cümleyi tek bir çevrilebilir dizede tutarak ve çevirmene dallanma operatörleri sağlayarak bu sorunu çözer.
Basit Argümanlar
En küçük birim, tekli süslü parantezler içindeki bir yer tutucudur:
Kodu panoya kopyala
Biçimlendirme sırasında { name: "Alice" } değerini ilettiğinizde Hello, Alice! çıktısını alırsınız. Süslü parantezler tek özel karakterlerdir; ekrana gerçek bir süslü parantez yazdırmak için tek tırnak içine alırsınız: '{'.
Tüm "enterpolasyon" (değer yerleştirme) özelliği bundan ibarettir. ICU'daki diğer tüm özellikler bunun üzerine inşa edilmiştir.
Çoğul (plural)
plural, sayısal bir değere göre bir dal seçer:
Kodu panoya kopyala
Bilinmesi gereken üç temel nokta:
#simgesi,countdeğerinin yerel ayarlara uygun olarak biçimlendirilmiş haliyle değiştirilir. Örneğin1234,en-USiçin1,234vetr-TRiçin1.234haline gelir.otherzorunludur. Eksik olduğunda tüm ICU uygulamaları hata fırlatır veya doğrulamada başarısız olur. Hiçbir kategori eşleşmediğinde yedek dal olarak kullanılır.=0,=1, … tam değerlerle eşleşir ve CLDR kategorilerinden önce denetlenir. Bunlarıoneyerine değil, özel durumlar ("Hiç mesaj yok") için kullanın.
Kodu panoya kopyala
offset (kaydırma)
offset:n, kategori seçiminden ve # değişiminden önce sayıdan n çıkarır. "Alice ve diğer 3 kişi bunu beğendi" gibi kalıplar için tasarlanmıştır:
Kodu panoya kopyala
count: 4 olduğunda, # 3 değerini üretir. offset oldukça yararlıdır ancak çalışma zamanlarında destek düzeyi değişiklik gösterebilir, bu yüzden projenizde doğrulamayı ihmal etmeyin.
Çoğul kategorileri dile bağımlıdır
En sık hata yapılan nokta burasıdır. zero, one, two, few, many, other kategori adları, her dil için doldurulan evrensel kutular değildir. Her yerel ayar, CLDR çoğul kuralları tarafından tanımlanan bir alt kümeyi kullanır ve bu kurallar matematiksel sezgiye değil dilbilgisine dayanır.
Tüm veri içeriğini net bir şekilde görmek için tabloyu modalde açın
| Dil | Kod | Kullanılan Kategoriler | Adet |
|---|---|---|---|
| Türkçe | tr | one, other | 2 |
| Japonca | ja | other | 1 |
| Çince | zh | other | 1 |
| İngilizce | en | one, other | 2 |
| Almanca | de | one, other | 2 |
| Fransızca | fr | one, many, other | 3 |
| Çekçe | cs | one, few, many, other | 4 |
| Lehçe | pl | one, few, many, other | 4 |
| Rusça | ru | one, few, many, other | 4 |
| Arapça | ar | zero, one, two, few, many, other | 6 |
| Galce | cy | zero, one, two, few, many, other | 6 |
Şaşırtıcı iki önemli sonuç:
onemutlaka "1" anlamına gelmez. Rusçadaone, 11 ile bitenler hariç 1, 21, 31, 101 gibi 1 ile biten tüm sayıları kapsar. Fransızcada ise0daonekategorisine girer.- İngilizce kaynak metne kategori eklemek hiçbir şeyi çözmez. İngilizce mesaj sadece
oneveotherdallarına ihtiyaç duyar; Lehçe çeviri ise dört dala ihtiyaç duyar ve bu yapı Lehçe metnin içinde bulunmalıdır. Tüm dillere aynı anahtar yapısını dayatan formatlar burada sorun yaratır.
Herhangi bir paket yüklemeden çalışma zamanınızın nasıl davrandığını test edebilirsiniz:
Kodu panoya kopyala
Intl.PluralRules, modern tarayıcılarda ve Node'da CLDR verilerini yerleşik olarak sağlar. CLDR desteği sunan kütüphaneler arka planda çoğunlukla bu API'yi çağırır.
select ve selectordinal
select, rastgele bir dizeye (cinsiyet, kullanıcı rolü, durum veya abonelik planı) göre dallanma yapar.
Kodu panoya kopyala
Anahtarlar birebir eşleştirilir ve other burada da zorunludur. Dillerin dilbilgisi farklı enum değerlerinden etkilendiği için, cümle yapısı bir enum değerine bağlı olduğunda select doğru araçtır.
selectordinal, plural ile aynı yapıya sahiptir ancak asıl sayılardan farklı bir tablo kullanan sıra sayıları (1., 2. vb.) kurallarını temel alır:
Kodu panoya kopyala
İngilizce, asıl sayılarda yalnızca iki kategori kullanmasına rağmen sıra sayılarında dört kategori (1st, 2nd, 3rd, 4th) kullanır. Bu asimetri nedeniyle iki operatör birbirinden ayrılmıştır.
Sayı, tarih ve saat argümanları
ICU, yerleştirdiği değerleri doğrudan biçimlendirebilir:
Kodu panoya kopyala
Modern biçimlendirme yöntemi, ICU 60 ile tanıtılan ve :: önekiyle belirtilen skeleton (iskelet) yapısıdır. İskeletler geleneksel biçim adlarına göre çok daha kapsamlıdır:
Kodu panoya kopyala
Ekosistemde iskelet desteği farklılık gösterir. FormatJS bunları tam olarak desteklerken, bazı diğer çalışma zamanları yalnızca geleneksel number, currency veya date, long biçimlerini kabul eder. Canlıya almadan önce ortamınızın desteğini kontrol edin.
İç içe yerleştirme ve okunabilirlik
ICU birleştirilebilir bir yapıya sahiptir. Bir çoğul dalı bir select içerebilir, bu select de başka bir çoğul içerebilir:
Kodu panoya kopyala
Bu, klasik bir ICU örneğidir ve aynı zamanda aşırı iç içe yerleştirmeye karşı en güçlü kanıttır. İki seviyeden sonra çevirmenler parantez hataları yapmaya başlar ve TMS editörleri yetersiz kalır. En fazla iki seviye iç içe yerleştirme yapın; üçüncü bir seviye gerekiyorsa cümleyi iki ayrı mesaja bölün.
JavaScript kütüphanelerinin ICU desteği
Tüm veri içeriğini net bir şekilde görmek için tabloyu modalde açın
| Kütüphane | ICU Desteği | Pratikte yazdığınız kod |
|---|---|---|
| react-intl (FormatJS) | Yerel, tam | İskeletler ve zengin metin etiketleri dahil ICU dizeleri |
| next-intl | Yerel | FormatJS'in intl-messageformat paketi üzerinden ICU dizeleri |
| i18next | Eklenti gerektirir | key_one / key_other son ekleri ve {{name}}; i18next-icu ile ICU |
| vue-i18n | Kısmi / kendine özgü | {name} enterpolasyonu ve boru karakteriyle ayrılmış çoğul dalları |
Angular ($localize) | Alt küme | Şablonlar içinde ICU plural / select, XLIFF dosyasına çıkarılır |
Tabloya dair önemli notlar:
- i18next'in varsayılan sözdizimi ICU değildir, ancak bu bir dezavantaj olmak zorunda değildir. Son ekli anahtarlar (
item_one,item_few)Intl.PluralRuleskategorileriyle eşleşir ve düz JSON dosyalarında çevirmenlerin düzenlemesi genellikle daha kolaydır. Ancakselectve iç içe dallanmalar standart yapıda yer almadığındani18next-icueklemeniz ya da mantığı kod içinde kurmanız gerekir. - vue-i18n'in çoğulları varsayılan olarak CLDR kategorileri yerine dil başına tanımlı bir kural fonksiyonu kullanır. Bu pratik olsa da çoğul kuralı veride değil uygulama yapılandırmasında tutulur.
- FormatJS referans uygulamadır. JavaScript bağlamında "ICU MessageFormat" denildiğinde genellikle FormatJS'in desteklediği standart kastedilir.
- Tam ICU desteği paket boyutu maliyeti getirir. Parser ve iskelet yönetimi yaklaşık 10 KB sıkıştırılmış JavaScript ekler. Bkz. ICU neden JavaScript için uygun değil.
Intlayer bu durumu nasıl çözer?
Intlayer metin tabanlı bir DSL kullanmaz. Dallanma operatörleri, içerik bildirim dosyasında bulunan tip güvenli fonksiyonlardır. Bu sayede yapı her zaman doğrulanabilir ve her yerel ayar yalnızca kendi dilbilgisinin ihtiyaç duyduğu kategorileri tanımlar:
Kodu panoya kopyala
Kodu panoya kopyala
ICU kavramlarıyla eşleşme son derece doğaldır:
Tüm veri içeriğini net bir şekilde görmek için tabloyu modalde açın
| ICU Yapısı | Intlayer Karşılığı |
|---|---|
{name} | insert("Hello {{name}}") veya otomatik algılama |
{count, plural, …} | plural({ one, few, many, other }) |
{value, select, …} | select({ draft, published, fallback }) |
select içindeki cinsiyet dalı | gender({ male, female, fallback }) |
select içindeki boolean dalı | cond({ true, false }) |
| Sayısal aralıklar (CLDR dışı) | enu({ "0": …, ">5": …, fallback: … }) |
{n, number, ::currency/EUR} | useCurrency()(1234.5, { currency: "EUR" }) |
plural, kategori seçimini doğrudan Intl.PluralRules API'sine devreder, böylece yukarıdaki CLDR tablosu eksiksiz çalışır. Biçimlendirme ayrı tutulur: Sayılar, tarihler, para birimleri ve listeler mesaj metnine gömülmek yerine biçimlendirici kancaları (formatter hooks) üzerinden yönetilir.
Bilinmesi gereken kısıtlamalar:
- Intlayer bir derleme adımı gerektirir; derleyici bildirimleri derleme aşamasında çıkarır. Çalışma zamanında salt JSON yüklemek istiyorsanız bu farklı bir yaklaşımdır.
pluraldalları içinde henüz doğrudan birt()yerleştirilemez;pluralifadesinit()içine sarmanız gerekir.- Ekosistem i18next'e göre daha yenidir, bu nedenle hazır TMS entegrasyonu sayısı henüz gelişme aşamasındadır.
Mevcut projenizde hazır ICU metinleri bulunuyorsa, react-intl uyumluluk bağdaştırıcısı bunları doğrudan ayrıştırır: plural, select, selectordinal, # ve geleneksel number / date / time argümanları. İskeletler ve offset: bu çözümleyici tarafından henüz desteklenmemektedir. i18next bağdaştırıcısı ise son ek biçimini (key_one, key_male) Intl.PluralRules ile eşleştirir.
Yaygın hatalar
- Çoğul mantığını JS koduna gömmek.
count === 1 ? a : bifadesi, yukarıdaki tablodaki 10 dilden 8'inde yanlış sonuç üretir. Üçlü operatör koda yazıldıktan sonra hiçbir çevirmen bunu düzeltemez. - Çevrilmiş parçaları uç uca birleştirmek. Kelime sırası, tamlamalar ve noktalama boşlukları yerel ayarlara göre değişir. Cümleyi her zaman tek bir bütün olarak koruyun.
otherdalını unutmak. Bu bir seçenek değil, şartnamenin zorunlu kıldığı bir kuraldır. Çoğu ayrıştırıcı hata verir, vermeyenler ise hiçbir şey görüntülemez.- Kategorilerin her dilde aynı olduğunu varsaymak. İngilizce kaynak metinde
oneveotherolması, Lehçe çeviride de iki dal olacağı anlamına gelmez. Her yerel ayarın kendi dallarını tanımlamasına izin verin. Bkz: Yerel ayar bazında içerik bildirimi. oneyerine=1kullanmak.=1yalnızca tam olarak 1 sayısıyla eşleşir. Rusçada 21 sayısıonekategorisini gerektirir ve=1kuralı bu sayı için asla çalışmaz.#işaretini çoğul dalının dışına koymak. Yalnızcapluralveyaselectordinaliçinde özel bir anlam taşır. Başka bir yerde normal diyez karakteri olarak işlenir.#işaretinin zaten biçimlendirilmiş olduğunu unutmak. Sayının ham haline ihtiyacınız varsa argümanı adıyla yerleştirin.
Daha fazlası
Yorumlar
Henüz yorum yok. Düşüncelerinizi paylaşan ilk kişi olun.
