Mühendislik//13 dk okuma

JSON Çeviri Dosyaları: i18n için Formatlar, Yapı ve En İyi Uygulamalar

Eray Gündoğmuş
Paylaş

JSON Çeviri Dosyaları: i18n için Formatlar, Yapı ve En İyi Uygulamalar

Birden fazla dilde yayınlanan hemen her web uygulaması, çevirileri JSON dosyalarında saklar. Format her yerde kullanılmaktadır; ancak buna ilişkin kurallar tek tip değildir. Farklı framework'ler farklı yapılar bekler: düz anahtar-değer nesnesi, derin iç içe geçmiş namespace ağacı, gömülü ICU sözdizimi içeren mesaj ya da kendi tanımlayıcı yapısına sahip Chrome uzantısı manifest'i. Yanlış formatı erkenden seçmek ya da daha sonra formatlar arasında geçiş yapmak gerçek maliyetler doğurur.

Bu kılavuz, günümüzde kullanılan başlıca JSON çeviri formatlarını, büyük ölçekte çeviri dosyalarının nasıl düzenleneceğini, anahtar adlandırma kurallarını, çoğullama kalıplarını, doğrulama araçlarını ve JSON ile XLIFF ile PO gibi alternatif formatlar arasında nasıl geçiş yapılacağını ele almaktadır.


Özet / Temel Çıkarımlar

  • JSON, web i18n için baskın format olmaya devam etmektedir; çünkü JavaScript'e özgüdür, insan tarafından okunabilir ve sürüm kontrolüyle iyi çalışır — ancak tek bir "JSON i18n formatı" yoktur. Her büyük kütüphane kendi kurallarını tanımlar.
  • En yaygın varyantlar şunlardır: düz anahtar-değer (basit ama büyük ölçekte bakımı zor), iç içe geçmiş/namespace'li (düzenli ama ayrıntılı), i18next (yerleşik çoğul anahtar son eklerine sahip namespace'li), FormatJS/react-intl (değerlerde ICU MessageFormat) ve chrome.i18n (bir message alanı ve isteğe bağlı description içeren tanımlayıcı nesneler).
  • Dosya organizasyonu, format kadar önemlidir: çevirileri namespace veya özellik alanına göre bölmek dosyaları küçük tutar, birleştirme çakışmalarını azaltır ve geç yüklemeyi mümkün kılar.
  • Çoğullama ve değişken enterpolasyon sözdizimi kütüphaneye göre değişir — değerlerinizde ICU MessageFormat kullanmak en taşınabilir ve ifade gücü yüksek seçeneği sunar, ancak uyumlu bir çalışma zamanı gerektirir.
  • CI doğrulaması — eksik anahtarları, hatalı biçimlendirilmiş JSON'u ve çevrilmemiş dizeleri kontrol etmek — bozuk çevirilerin üretime ulaşmasını önlemenin en etkili yoludur.

Çeviriler için Neden JSON?

Formatları karşılaştırmadan önce, JSON'un neden web i18n için varsayılan haline geldiğini ve bu seçimin neden her zaman açık olmadığını anlamak faydalıdır.

İnsan tarafından okunabilir ve diff'e uygun. Bir JSON çeviri dosyası, araç kullanmadan okunabilir. Bir pull request'teki diff, tam olarak hangi dizelerin değiştiğini, hangilerinin eklendiğini ve hangilerinin kaldırıldığını gösterir. Bunu, aynı değişikliğin birden fazla öğede XML özniteliklerine gömüldüğü XLIFF 2.0 ile ya da diff'lerin okunamaz olduğu derlenmiş ikili formatlarla karşılaştırın.

JavaScript'e özgü. JSON.parse(), her JavaScript çalışma zamanında yerleşik olarak bulunur. Kurulacak bir ayrıştırma bağımlılığı, yapılandırılacak bir format adaptörü yoktur. Bir Next.js uygulaması tarayıcı için çevirileri paketlediğinde, düz JSON gönderir — serileştirme ek yükü yok, özel ayrıştırıcı yok.

Programatik olarak oluşturmak ve kullanmak kolaydır. Her dilde bir JSON kütüphanesi vardır. Bir veritabanından, elektronik tablo dışa aktarımından veya çeviri yönetim sistemi API'sinden çeviri dosyaları oluşturmak, doğrudan bir JSON serileştirme görevidir.

Sürüm kontrolüyle iyi çalışır. JSON dosyaları metindir. Değişiklikler farklı anahtarlardaysa temiz birleşirler, okunabilir blame geçmişi üretirler ve standart diff araçlarıyla çalışırlar.

Alternatifler ve Ödünleşimleri

FormatGüçlü YönlerZayıf Yönler
XLIFF 2.0Zengin meta veri, çevirmen notları, durum takibi, endüstri standardıAyrıntılı XML, zayıf diff okunabilirliği, karmaşık araçlar
PO / GettextOlgun ekosistem, msgid/msgstr modeli bağlamı destekler, çoğul formlar yerleşikÖzel ayrıştırıcılar gerektirir, JavaScript'te daha az yaygın
YAMLOkunabilir, çok satırlı dizeleri doğal olarak desteklerGirinti hassasiyeti (hata eğilimli), yerleşik tarayıcı ayrıştırıcısı yok
ARB (Application Resource Bundle)Flutter/Dart'a özgü, anahtar başına meta veri desteklerDart'a özgü ekosistem, sınırlı web araçları
JSONHer yerde kullanılır, yerel JavaScript, harika araçlarYerleşik meta veri yok, çoğul işleme kütüphaneye göre değişir

XLIFF, çeviriler CAT araçlarına sahip profesyonel bir çeviri ajansından geçtiğinde doğru seçimdir. PO, Gettext ekosisteminden yararlanmak isteyen projeler için uygundur (Poedit, GNU gettext yardımcı programları). React, Vue, Angular veya Svelte ile oluşturulan çoğu web uygulaması için JSON pratik varsayılandır.


Yaygın JSON Çeviri Formatları

Düz Anahtar-Değer

En basit JSON çeviri dosyası, her anahtarın bir dize tanımlayıcısı ve her değerin çevrilmiş dize olduğu tek düzeyli bir nesnedir.

{
  "welcome_message": "Platformumuza hoş geldiniz",
  "login_button": "Giriş yap",
  "logout_button": "Çıkış yap",
  "error_not_found": "Sayfa bulunamadı",
  "error_server": "Bir şeyler ters gitti. Lütfen tekrar deneyin."
}

Bu formatın öğrenme eğrisi sıfırdır ve herhangi bir JSON ayrıştırıcısıyla çalışır. Sorun ölçekte ortaya çıkar: büyük bir uygulama için 500 anahtarlı düz bir dosya gezinmek için imkânsız hale gelir. Görsel gruplama yok, bir dizenin nerede kullanıldığına dair gösterge yok ve geç yükleme için çeviri alt kümesi çıkarma yolu yok.

En iyisi: Küçük projeler, prototipler veya 100'den az çeviri anahtarına sahip uygulamalar.

İç İçe Geçmiş / Namespace'li JSON

İç içe geçmiş JSON, anahtarları uygulamanın yapısını yansıtan bir hiyerarşide düzenler.

{
  "auth": {
    "login": {
      "title": "Hesabınıza giriş yapın",
      "email_label": "E-posta adresi",
      "password_label": "Şifre",
      "submit_button": "Giriş yap",
      "forgot_password": "Şifrenizi mi unuttunuz?"
    },
    "logout": {
      "confirm": "Çıkış yapmak istediğinizden emin misiniz?"
    }
  },
  "dashboard": {
    "greeting": "Günaydın, {{name}}",
    "stats": {
      "total_users": "Toplam kullanıcı",
      "active_sessions": "Aktif oturumlar"
    }
  }
}

vue-i18n ve angular/localize gibi kütüphaneler iç içe geçmiş JSON'u doğal olarak destekler. Anahtara nokta notasyonuyla erişilir: t('auth.login.title'). Bu yapı, bileşen hiyerarşileriyle doğal olarak örtüşür ve her dizenin nerede kullanıldığını belirlemeyi kolaylaştırır.

Ödünleşim, derin iç içe geçmiş nesnelerin daha dikkatli anahtar yönetimi gerektirmesi ve uzun erişim yolları üretebilmesidir. Çoğu ekip, pratik maksimum olarak iki veya üç iç içe geçme seviyesinde karar kılar.

i18next Formatı

i18next, JavaScript ekosistemindeki en yaygın kullanılan i18n kütüphanesidir ve iç içe geçmiş JSON'un üzerine inşa edilmiş kendi kurallarına sahiptir. En önemlisi çoğul anahtar son ek sistemidir.

{
  "common": {
    "save": "Kaydet",
    "cancel": "İptal",
    "loading": "Yükleniyor..."
  },
  "items": {
    "count_one": "{{count}} öğe",
    "count_other": "{{count}} öğe",
    "count_zero": "Öğe yok"
  },
  "notifications": {
    "new_one": "{{count}} yeni bildiriminiz var",
    "new_other": "{{count}} yeni bildiriminiz var"
  }
}

i18next, temel anahtara son ek ekleyerek çoğul formları çözer. Son ekler CLDR çoğul kural kategorilerini takip eder: zero, one, two, few, many, other. Türkçe için yalnızca one ve other geçerlidir. Arapça veya Rusça için tam set önemlidir.

i18next ayrıca dosya düzeyinde namespace'lemeyi destekler: her JSON dosyası bir namespace'dir. t('common:save') çağırdığınızda, i18next aktif yerel için common.json'ı yükler. Bu, react-i18next kullanan React uygulamalarında namespace düzeyinde geç yüklemeyi mümkün kılar.

{
  "title": "Hoş geldiniz, {{name}}!",
  "description": "{{date, datetime}} tarihinde katıldınız",
  "price": "{{price, currency}}"
}

{{value, formatType}} sözdizimi, tarihler, sayılar ve para birimi için Intl API ile entegre olan i18next'in biçimlendirme hattını tetikler.

FormatJS / react-intl Formatı

FormatJS (react-intl'i güçlendirir), ICU MessageFormat sözdizimini doğrudan dize değerlerine gömer. Bu, tüm çoğullama ve değişken mantığını anahtar son eklerinde değil mesaj dizesinin içine yerleştirir.

{
  "welcome": "Hoş geldiniz, {name}!",
  "item_count": "{count, plural, =0 {Öğe yok} one {# öğe} other {# öğe}}",
  "last_login": "Son giriş: {date, date, medium}",
  "account_status": "{gender, select, male {O} female {O} other {O}} doğrulanmış bir üyedir.",
  "notification_badge": "{count, plural, =0 {} one {({count})} other {({count})}}"
}

ICU MessageFormat, karmaşık çoğul ve cinsiyet uyumu kuralları için mevcut en ifade gücü yüksek seçenektir. select anahtar sözcüğü koşullu dizeleri işler, plural sayıma dayalı formları işler ve format türleri (date, number, currency) Intl API'ye devreder.

Anahtarlar genellikle düz dizelerdir ve çoğunlukla bileşen yolu veya anlamsal bir tanımlayıcıyla eşleşir. FormatJS, derin iç içe geçmiş yapılar yerine açıklayıcı düz anahtarları tercih eder.

react-intl ile kullanım:

import { useIntl, FormattedMessage } from 'react-intl';

function ItemList({ count }) {
  const intl = useIntl();
  return (
    <p>
      <FormattedMessage id="item_count" values={{ count }} />
    </p>
  );
}

chrome.i18n Formatı

Chrome uzantıları, chrome.i18n API tarafından tanımlanan belirli bir JSON formatı kullanır. Her anahtar, düz bir dize yerine bir tanımlayıcı nesneyle eşleşir.

{
  "extensionName": {
    "message": "Uzantım",
    "description": "Chrome Web Mağazası'nda görüntülenen uzantının adı."
  },
  "welcomeMessage": {
    "message": "Merhaba, $USER$!",
    "description": "Uzantı açıldığında gösterilen karşılama mesajı",
    "placeholders": {
      "user": {
        "content": "$1",
        "example": "Alice"
      }
    }
  },
  "itemCount": {
    "message": "$COUNT$ öğe seçildi",
    "placeholders": {
      "count": {
        "content": "$1",
        "example": "3"
      }
    }
  }
}

description alanı son kullanıcılara gösterilmez — çevirmenler ve Chrome Web Mağazası inceleme süreci için bağlamdır. Yer tutucular, içeriği ve örnek değeri tanımlayan ayrı bir placeholders nesnesiyle $YER_TUTUCU_ADI$ kuralını kullanır.

Bu format Chrome uzantıları için zorunludur. Genel amaçlı web uygulaması i18n için uygun değildir.


Dosya Organizasyon Kalıpları

Yerel Başına Tek Dosya

En basit organizasyon, uygulama için tüm çevirileri içeren yerel başına bir JSON dosyasıdır.

locales/
  en.json
  fr.json
  de.json
  ja.json
  es.json

Bu, küçük uygulamalar için işe yarar ancak ölçekte sorunlar yaratır: dosyalar büyür, ilgisiz özellikler aynı dosyada birleştirme çakışmalarına neden olur ve kullanıcının ziyaret etmediği bölümler için çevirileri geç yükleyemezsiniz.

Namespace Bölme

Orta ve büyük uygulamalar için en yaygın kalıp, çevirileri namespace'e göre bölmektir — her işlevsel alan için yerel başına bir JSON dosyası.

locales/
  en/
    common.json
    auth.json
    dashboard.json
    settings.json
    errors.json
  fr/
    common.json
    auth.json
    dashboard.json
    settings.json
    errors.json
  de/
    common.json
    auth.json
    dashboard.json
    settings.json
    errors.json

Her namespace dosyası küçük ve odaklıdır. common namespace'i, uygulama genelinde kullanılan dizeleri içerir (düğme etiketleri, form alanı etiketleri, genel hata mesajları). Özellik namespace'leri, o özelliğe özgü dizeleri içerir.

i18next ve react-i18next bu kalıbı doğal olarak kullanır: t('auth:login.title'), aktif yerel için auth.json'ı yükler. next-i18next kullanan Next.js uygulamaları bu yapıyı kurala göre izler.

Özellik Tabanlı Bölme

Çok büyük uygulamalar için veya her paketin kendi çevirilerine sahip olduğu monorepo'larda, özellik tabanlı yapı çeviri dosyalarını kullanan kodun yanına yerleştirir.

src/
  features/
    auth/
      locales/
        en.json
        fr.json
      components/
        LoginForm.tsx
        SignupForm.tsx
    dashboard/
      locales/
        en.json
        fr.json
      components/
        DashboardHeader.tsx
    checkout/
      locales/
        en.json
        fr.json

Bu kalıp uyumu en üst düzeye çıkarır: çeviri dosyası, onu kullanan bileşenin yanında yaşar. Derleme sistemi veya i18n yükleyicisi, namespace dosyalarını çalışma zamanında veya derleme zamanında birleştirir. Dezavantaj, belirli bir yerel için tüm çevirileri bulmak üzere kaynak ağacının tamamında gezinmek gerekmesidir; bu da çevirmenler ve çeviri yönetim sistemleri için iş akışını karmaşıklaştırır.

Öneri: Çoğu uygulama için namespace bölmeyi kullanın. Özellik tabanlı bölmeyi yalnızca ekibiniz farklı özelliklere sahip farklı ekiplerden oluşuyorsa ve çeviri dosyalarında çapraz özellik birleştirme çakışmalarını önlemeniz gerekiyorsa kullanın.


Çeviri Dosyası Format Karşılaştırma Tablosu

FormatOkunabilirlikAraç DesteğiMeta Veri DesteğiICU DesteğiDiff Uyumluluğu
JSON (düz)YüksekMükemmelYokHayır (varsayılan olarak)Mükemmel
JSON (iç içe)YüksekMükemmelYokHayır (varsayılan olarak)Mükemmel
JSON (FormatJS)OrtaİyiYokEvet (doğal)İyi
XLIFF 2.0DüşükMükemmel (CAT araçları)Zengin (durum, notlar, alternatif çeviriler)EvetZayıf
PO / GettextOrtaİyi (Poedit, Weblate)Orta (yorumlar, bağlam)KısmiOrta
YAMLYüksekOrtaYokHayırİyi
ARBYüksekİyi (Flutter)Anahtar başına meta veriHayırİyi

XLIFF'in meta veri avantajı, profesyonel çeviri ajanslarıyla çalışırken önemlidir: format çeviri durumunu takip eder (yeni, çevrildi, incelendi, son), alternatif çevirileri destekler ve Phrase, memoQ ve SDL Trados gibi çoğu profesyonel CAT aracının yerel formatıdır. Çeviri iş akışınız ajans devirlerini içeriyorsa, JSON kaynağınızdan XLIFF oluşturmak (ham JSON göndermek yerine) çevirmen verimliliğini artırır ve hataları azaltır.


Anahtar Adlandırma Kuralları

Tutarlı anahtar adlandırma, bakımı kolay bir çeviri dosyası ile hataların ve karışıklığın kaynağı olan bir dosya arasındaki farktır.

Nokta Notasyonu vs. İç İçe Geçme

Noktalar içeren düz anahtarlar ve gerçekten iç içe geçmiş nesneler her ikisi de hiyerarşiyi temsil eder, ancak farklı davranırlar. Noktalı düz anahtar tek bir dizedir — "auth.login.title". İç içe geçmiş nesne, auth içindeki login içindeki title anahtarına sahip gerçek bir nesne yapısıdır. Çoğu kütüphane her ikisini de destekler, ancak aynı dosyada ikisini karıştırmak belirsizliğe yol açar.

Öneri: JSON dosyalarınızda gerçek iç içe geçme ve anahtarlara erişirken yalnızca kodda nokta notasyonu kullanın. Aynı iç içe geçme seviyesindeki anahtar adlarında nokta kullanmayın.

{
  "auth": {
    "login": {
      "title": "Giriş yap"
    }
  }
}

Koda t('auth.login.title') olarak erişilir — kütüphane geçişi işler.

snake_case vs. camelCase

Her ikisi de yaygındır. snake_case, kelimeler görsel olarak birbirine karışmadığından JSON dosyalarında daha okunabilirdir. camelCase, JavaScript kurallarıyla uyumludur ve FormatJS projelerinde yaygındır.

{
  "submit_button": "Gönder",
  "error_message": "Bir hata oluştu"
}
{
  "submitButton": "Gönder",
  "errorMessage": "Bir hata oluştu"
}

Birini seçin ve bir linter ile uygulayın. Bir proje içindeki tutarsızlık her iki seçimden de kötüdür.

Açıklayıcı vs. Kısa

Kısa anahtarlar küçüktür ancak bağlamı hızla kaybeder:

{
  "btn_sub": "Abone ol",
  "btn_cncl": "İptal",
  "err_404": "Sayfa bulunamadı"
}

Açıklayıcı anahtarlar, değeri okumadan amacı iletir:

{
  "newsletter_subscribe_button": "Abone ol",
  "modal_cancel_button": "İptal",
  "error_page_not_found_title": "Sayfa bulunamadı"
}

Öneri: UI bağlamını (bileşen türü veya konumu) ve içerik türünü (düğme, başlık, açıklama, yer tutucu) içeren açıklayıcı anahtarlar kullanın. Bu, bir anahtarın bileşen kodunu okumadan nasıl kullanıldığını anlamayı mümkün kılar.

Hiyerarşik Gruplama

İç içe geçmiş JSON kullanırken, önce UI alanına, sonra bileşen veya eyleme, ardından öğe türüne göre gruplayın:

{
  "checkout": {
    "cart": {
      "title": "Sepetiniz",
      "empty_message": "Sepetiniz boş",
      "item_count_one": "{{count}} öğe",
      "item_count_other": "{{count}} öğe"
    },
    "payment": {
      "title": "Ödeme detayları",
      "card_number_label": "Kart numarası",
      "expiry_label": "Son kullanma tarihi",
      "submit_button": "Şimdi öde"
    }
  }
}

JSON'da Çoğulları ve Değişkenleri Yönetme

ICU MessageFormat (FormatJS, vue-i18n, diğerleri)

ICU MessageFormat, çoğullar ve değişkenler için en ifade gücü yüksek ve taşınabilir sözdizimidir. FormatJS tarafından doğal olarak desteklenir ve vue-i18n ile diğer kütüphanelerde yapılandırılabilir.

{
  "file_count": "{count, plural, =0 {Dosya yok} one {# dosya} other {# dosya}}",
  "upload_progress": "{total} dosyanın {current} tanesi yükleniyor",
  "last_seen": "Son görülme: {time, date, relative}",
  "user_role": "{role, select, admin {Yönetici} editor {Editör} other {Görüntüleyici}}"
}

Çoğul dalındaki # sembolü, biçimlendirilmiş sayıyla değiştirilir. select anahtar sözcüğü, bir sayı yerine bir dize değerine göre dallanır.

i18next Çoğul Son Ek Kuralı

i18next, anahtara son ek ekleyerek çoğulları çözer. Türkçe için:

{
  "message_count_one": "{{count}} mesaj",
  "message_count_other": "{{count}} mesaj",
  "message_count_zero": "Mesaj yok"
}

t('message_count', { count: 5 }) ile çağrıldığında, i18next message_count_other'ı seçer ve count'u enterpolasyon yapar. Daha fazla çoğul forma sahip diller için (Rusça'nın dördü vardır), ek son ek varyantları tanımlanır:

{
  "file_one": "{{count}} файл",
  "file_few": "{{count}} файла",
  "file_many": "{{count}} файлов",
  "file_other": "{{count}} файлов"
}

CLDR çoğul kural kategorileri (zero, one, two, few, many, other), i18next'in kullandığı son eklerle eşleşir.

Değişken Enterpolasyonu

Her kütüphane, değişken enterpolasyonun bir biçimini destekler. Sözdizimi değişir:

{
  "greeting_i18next": "Merhaba, {{name}}!",
  "greeting_icu": "Merhaba, {name}!",
  "greeting_vue": "Merhaba, {name}!",
  "greeting_angular": "Merhaba, {{ name }}!"
}

i18next varsayılan olarak çift süslü parantez kullanır. ICU tek süslü parantez kullanır. Angular'ın $localize'ı, JSON değerindeki bir çalışma zamanı enterpolasyon sözdizimi yerine kodda etiketli şablon literali kullanır.

Aynı projede enterpolasyon sözdizimlerini karıştırmayın. Kütüphanenizle eşleşen sözdizimini seçin ve JSON şema doğrulamanızda uygulayın.


Araçlar ve Doğrulama

Çeviri Dosyaları için JSON Schema

Bir JSON Schema tanımı, CI hattında, editörlerde ve ön commit kancalarında çeviri dosyası yapısını doğrulamanıza olanak tanır. İşte düz anahtar-değer çeviri dosyası için minimal bir şema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "additionalProperties": {
    "type": "string"
  },
  "minProperties": 1
}

İç içe geçmiş dosyalar için şema özyinelemeli hale gelir. Çoğu ekip, yapısal doğrulama için JSON Schema ile anlambilimsel kontroller için özel bir i18n linting aracı kombinasyonu kullanır.

Eksik Anahtarlar için Linting

En yaygın üretim i18n hatası, eksik çeviri anahtarıdır — İngilizce'de mevcut olan ancak yerel dosyada bulunmayan bir anahtar. Bu, anahtar adının kendisine veya boş bir dizeye geri dönüşe neden olur ve bu UI'yi bozar.

i18next-parser, t('key') çağrıları için kaynak kodunuzu tarar ve çeviri dosyaları oluşturur veya doğrular:

npx i18next-parser --config i18next-parser.config.js

eslint-plugin-i18n-json, JSON çeviri dosyalarını doğrudan doğrular:

npm install --save-dev eslint-plugin-i18n-json

Çeviri dosyası doğrulaması için temel bir ESLint yapılandırması:

{
  "plugins": ["i18n-json"],
  "rules": {
    "i18n-json/valid-json": "error",
    "i18n-json/sorted-keys": ["warn", { "order": "asc" }],
    "i18n-json/identical-keys": [
      "error",
      { "filePath": "src/locales/en.json" }
    ]
  }
}

identical-keys kuralı, her yerel dosyanın referans yerel dosyayla (genellikle İngilizce) aynı anahtar kümesini içerip içermediğini kontrol eder. Hem eksik anahtarları hem de mevcut olmaması gereken ekstra anahtarları işaretler.

Tamlık için CI Kontrolleri

Bir yerel dosyası tamamlanmamış olduğunda birleştirmeleri engelleyen bir CI adımı, çeviri borcunun birikmesini önler. Basit bir kabuk betiği kontrolü:

#!/usr/bin/env bash
BASE="src/locales/en.json"
LOCALES=("fr" "de" "ja" "es")

for locale in "${LOCALES[@]}"; do
  FILE="src/locales/${locale}.json"
  BASE_KEYS=$(jq 'keys | length' "$BASE")
  LOCALE_KEYS=$(jq 'keys | length' "$FILE")

  if [ "$BASE_KEYS" != "$LOCALE_KEYS" ]; then
    echo "HATA: ${FILE} ${LOCALE_KEYS} anahtara sahip, beklenen ${BASE_KEYS}"
    exit 1
  fi
done

echo "Tüm yerel dosyalar tamamdır."

İç içe geçmiş dosyalar için jq yolu geçişi gereklidir. Better i18n gibi platformlar JSON'u kendi yerel formatları olarak kullanır ve çevirileri CLI aracılığıyla senkronize eder; bu da tamlık kontrolünün, tamamlanmamış dosyalarda CI düzeyindeki kontrollere olan ihtiyacı azaltarak çeviriler commit edilmeden önce platform tarafında uygulanabileceği anlamına gelir.

Editör Entegrasyonu

"i18n Ally" gibi VS Code uzantıları, satır içi çeviri önizlemeleri, eksik anahtar vurgulama ve doğrudan editörde makine çevirisi önerileri sağlar. Bu, doğrulamayı öne taşır — geliştiriciler eksik çevirileri CI sırasında değil, kod yazarken görür.


Formatlar Arasında Geçiş

JSON'dan XLIFF'e

XLIFF, çevirileri profesyonel bir ajansa gönderirken gereklidir. JSON'dan XLIFF 2.0'a dönüştürme, anahtar-değer çiftlerini <segment> alt öğelerine sahip <unit> öğeleriyle eşleştirmeyi içerir.

i18next-conv aracı çift yönlü dönüşümü işler:

npm install -g i18next-conv

# JSON'dan XLIFF'e
i18next-conv -l en -s locales/en.json -t locales/en.xliff

# XLIFF'ten JSON'a
i18next-conv -l fr -s locales/fr.xliff -t locales/fr.json

FormatJS projeleri için @formatjs/cli XLIFF dışa aktarımı sağlar:

npx formatjs compile-folder --ast src/locales/en.json > compiled/en.json

JSON'dan PO'ya

PO (Portable Object) formatı, Gettext ekosistemi tarafından kullanılır ve Poedit ile Weblate gibi araçlar tarafından desteklenir. i18next-conv aracı PO'yu da destekler:

# JSON'dan PO'ya
i18next-conv -l en -s locales/en.json -t locales/en.po

# PO'dan JSON'a
i18next-conv -l fr -s locales/fr.po -t locales/fr.json

vue-i18n projeleri için @intlify/vue-i18n-loader, JSON'a alternatif olarak .po dosyalarını doğrudan destekler; bu da Vue projenizin Gettext kullanan sunucu tarafı uygulamasıyla çeviri belleğini paylaşması durumunda kullanışlıdır.

Yaygın Dönüştürme Araçları

AraçDönüştürürNotlar
i18next-convJSON ↔ PO, JSON ↔ XLIFF, JSON ↔ CSVi18next formatı için en kapsamlı
@formatjs/cliFormatJS JSON → XLIFF, ayıklanan mesajlar → yerel dosyalarFormatJS/react-intl projeleri için gerekli
gettext-converterPO ↔ JSON (düz)Basit, framework varsayımı yok
xliff-simple-mergeXLIFF birleştirme ve bölmeangular/localize kullanan Angular projeleri için kullanışlı
Çevrimiçi XLIFF editörleriXLIFF ↔ JSON (UI aracılığıyla)Phrase, Lokalise ve Crowdin hepsi içe/dışa aktarma sağlar

Formatlar arasında geçiş yaparken, commit etmeden önce çıktıyı doğrulayın. Otomatik dönüştürme araçları, standart dışı çoğul kurallara sahip diller için bağlam dizelerini zaman zaman kaybeder, yorumları düşürür veya çoğul formları yanlış işler.


SSS

Yeni bir React projesi için hangi JSON formatını kullanmalıyım?

react-i18next kullanıyorsanız (en yaygın seçim), i18next kurallarını izleyen namespace bölünmüş iç içe geçmiş JSON ile başlayın. react-intl veya FormatJS tabanlı bir kurulum kullanıyorsanız, değerlerde ICU MessageFormat sözdizimi olan düz anahtarlar kullanın. Seçtiğiniz kütüphane formatı belirler — önce proje gereksinimlerinize göre kütüphaneyi seçin, ardından belgelenmiş kurallarını izleyin.

JSON anahtarlarım İngilizce dize mi yoksa anlamsal tanımlayıcı mı olmalı?

Anlamsal tanımlayıcılar (auth.login.submit_button gibi) çoğu uygulama için tercih edilir. İngilizce dizeyi anahtar olarak kullanmak (Gettext stili: t('Submit')) küçük projeler için işe yarar ancak ölçekte sorunlar yaratır: aynı namespace'de bağlamı farklı iki farklı "Gönder" düğmeniz olamaz ve İngilizce kopyayı değiştirmek, koddaki tüm anahtar referanslarını güncellemeyi gerektirir.

UI'yi bozmadan çalışma zamanında eksik çevirileri nasıl işlerim?

Her büyük i18n kütüphanesi, bir anahtar eksik olduğunda yapılandırılmış bir varsayılan yerel konuma geri döner. Kütüphanenizi yedek olarak İngilizce yerel dosyasını kullanacak şekilde yapılandırın; bu, eksik Fransızca çevirinin anahtar adı yerine İngilizce dizeyi göstereceği anlamına gelir. Eksik anahtarları geliştirme sırasında günlüğe kaydedin (çoğu kütüphane bir missingKeyHandler geri aramasını destekler), böylece test sırasında görünür olurlar.

JSON çeviri dosyalarında yorum kullanmak güvenli mi?

Standart JSON yorumları desteklemez. Bazı araçlar JSON5 veya JSONC'yi (Yorumlu JSON) bir uzantı olarak destekler, ancak bu standart JSON ayrıştırıcılarıyla uyumluluğu bozar. Dizelere çevirmenler için bağlam açıklaması eklemeniz gerekiyorsa, anahtar düzeyinde ayrı bir description alanı kullanın (chrome.i18n'nin yaptığı gibi) veya ayrı bir meta veri dosyası tutun. Daha basit bir yaklaşım: açıklama gerektiren satır içi yorumlar olmadan bağlamı ileten açıklayıcı anahtar adları kullanın.

JSON dosyalarımda sağdan sola (RTL) dilleri nasıl işlemeliyim?

RTL dilleri (Arapça, İbranice, Farsça) için JSON yapısı, LTR dilleriyle aynıdır — dosya formatı değişmez. RTL desteği, bir çeviri dosyası sorunu değil, CSS ve düzen sorunudur. i18n kütüphaneniz, aktif yerel konumun metin yönünü tespit etmek için bir yol sağlar (genellikle Intl.Locale API veya bir yerel meta veri nesnesi aracılığıyla) ve uygulamanız belgeye veya bileşene dir="rtl" uygular. RTL'ye özgü CSS'i stillerinizde tutun, çeviri değerlerinizde değil.


Sonuç

JSON çeviri dosyaları tek bir evrensel standardı izlemez — onları okuyan kütüphanenin kurallarını izler. Kütüphanenizin hangi formatı beklediğini ve neden bu şekilde tasarlandığını anlamak, "doğru" yaklaşımı aramaktan daha faydalıdır.

Pratik kılavuz şudur: React, Vue veya Node.js uygulaması oluşturuyorsanız ve en büyük araç ve örnek ekosistemine sahip olmak istiyorsanız, i18next kurallarıyla iç içe geçmiş JSON kullanın. Uygulamanızın birçok yerel dilde karmaşık çoğulları, cinsiyet anlaşmasını veya zengin biçimlendirmeyi işlemesi gerekiyorsa ve ifadelerin mümkün olduğunca taşınabilir olmasını istiyorsanız değerlerinizde ICU MessageFormat kullanın. Bilişsel ek yükün organizasyon yapısından daha önemli olduğu küçük projeler veya hızlı prototipler için düz anahtarlar kullanın.

Dosya organizasyonu, anahtar adlandırma ve CI doğrulaması, format seçimi kadar önemlidir. Tutarlı adlandırma ve otomatik tamlık kontrollerine sahip düz bir dosya, araçsız ve uygulamasız dikkatli bir namespace yapısından küçük bir ekibe daha iyi hizmet edecektir.

Çeviri borcu sessizce birikir — burada bir eksik anahtar, orada eski bir dize — yerelleştirilmiş kullanıcılar bozuk UI dizeleriyle karşılaşana kadar. Bu sonuçtan kaçınan ekipler, çeviri dosyalarına diğer kod yapıtlarıyla aynı şekilde davranır: pull request'lerde incelenir, CI'da doğrulanır ve gelecekteki bakımcılar göz önünde bulundurularak düzenlenir.


Referanslar


Son güncelleme: Mart 2026

Comments

Loading comments...