Rehberler//18 dk okuma

i18n En İyi Uygulamaları 2026: Eksiksiz Rehber

Eray Gündoğmuş
Paylaş
İçindekiler

Uluslararasılaştırma (i18n) büyük bir dönüşüm geçirdi. Bir zamanlar sadece stringleri t() çağrılarıyla sarmaktan ibaret olan bu süreç, artık yapay zeka destekli çeviri iş akışlarını, statik analiz pipeline'larını ve gelişmiş dağıtım mekanizmalarını kapsıyor. Bu rehber, 2026'da her geliştirme ekibinin uygulaması gereken 10 temel i18n en iyi uygulamasını kod örnekleri ve uygulanabilir adımlarla ele alıyor.

İster yeni bir projeyi uluslararasılaştırıyor olun ister mevcut çok dilli bir uygulamayı iyileştiriyor olun, bu uygulamalar ölçeklenebilir bir yerelleştirme iş akışı oluşturmanıza yardımcı olacaktır.


1. Yapay Zeka Destekli Çeviri İş Akışlarını Benimseyin

Manuel çeviri artık eskisi gibi bir darboğaz değil. Yapay zeka çevirisi, çeviri işinin %80-90'ını üstlenebilecek düzeyde olgunlaştı; insan gözden geçiriciler ise nüanslara, marka sesine ve uç durumlara odaklanıyor.

MTPE İş Akışı (Makine Çevirisi Sonrası Düzenleme)

2026'da endüstri standardı yaklaşım MTPE'dir:

  1. Yapay zeka, kaynak stringlerden ilk çevirileri üretir
  2. İnsan gözden geçiriciler kalite ve marka tutarlılığı için düzenleme yapar
  3. Çeviri belleği, onaylanan çevirileri yeniden kullanılmak üzere kaydeder
  4. Yapay zeka, düzeltmelerden zamanla öğrenir

Uygulama

// i18n.config.ts — Configure AI translation with Better i18n
export default defineConfig({
  project: "my-org/my-app",
  sourceLanguage: "en",
  targetLanguages: ["es", "fr", "de", "ja", "ko", "zh"],
  ai: {
    enabled: true,
    // Custom instructions improve AI output quality
    instructions: `
      - Use informal "tu" form for Spanish
      - Keep technical terms in English for Japanese
      - Match the playful, developer-friendly tone of our brand
    `,
    // Auto-translate new keys on push
    autoTranslate: true,
    // Require human review before publishing
    requireReview: true,
  },
});

Önemli Çıkarımlar

  • Kültürel nüansları yönetmek için dil bazında yapay zeka talimatları oluşturun
  • Kullanıcıya yönelik içerikler için her zaman insan gözden geçirmesi zorunlu kılın
  • Onaylı stringlerin tekrar çevrilmesini önlemek için çeviri belleği kullanın
  • Kaliteyi ölçmek için yapay zeka çeviri kabul oranını takip edin

2. i18n İçin Statik Analiz Uygulayın

i18n sorunlarını derleme zamanında yakalamak, üretimde yakalamaktan çok daha az maliyetlidir. Statik analiz araçları, kod birleştirilmeden önce sabit kodlanmış stringleri, eksik çevirileri, kullanılmayan anahtarları ve ICU sözdizimi hatalarını tespit edebilir.

Statik Analizin Yakaladığı Yaygın Sorunlar

  • Sabit kodlanmış stringler — UI bileşenlerinde çeviri anahtarı yerine doğrudan metin kullanımı
  • Eksik çeviriler — Hedef dillerde yeni anahtarlar için çeviri bulunmaması
  • Kullanılmayan anahtarlar — Paket boyutunu şişiren gereksiz anahtarlar
  • ICU sözdizimi hataları — Çoğullama veya değişken yerleştirmede hatalar
  • Tutarsız anahtar adlandırma — Kurallara uymayan isimlendirmeler

Uygulama

// eslint.config.ts — Add i18n linting rules
import i18nPlugin from "eslint-plugin-i18n-json";

export default [
  {
    plugins: { "i18n-json": i18nPlugin },
    rules: {
      // Detect hardcoded strings in JSX
      "i18n-json/no-hardcoded-strings": "error",
      // Ensure all keys have translations
      "i18n-json/valid-message-syntax": "error",
      // Check ICU MessageFormat syntax
      "i18n-json/valid-icu-syntax": "error",
    },
  },
];
# CLI-based static analysis with Better i18n
bunx @better-i18n/cli lint

# Output:
# src/components/Header.tsx:15 — Hardcoded string "Welcome back"
# src/pages/pricing.tsx:42 — Missing key "pricing.enterprise.cta" in: es, fr, de
# locales/en.json — Unused keys: 12 (run `cli prune` to remove)

Önemli Çıkarımlar

  • Anlık geri bildirim için ESLint yapılandırmanıza i18n linting kuralları ekleyin
  • Sorunlu PR'ları engellemek için CI'da i18n statik analizi çalıştırın
  • Çeviri dosyalarınızı yalın tutmak için anahtar budama (pruning) kullanın
  • ICU MessageFormat sözdizimini çevirmenlere ulaşmadan önce doğrulayın

3. i18n'i CI/CD Pipeline'ınıza Entegre Edin

Yerelleştirme, dağıtım pipeline'ınızda birinci sınıf bir vatandaş olmalıdır. CI/CD entegrasyonu, çeviri kapsamının zorunlu kılınmasını, yeni anahtarların senkronize edilmesini ve çeviri kalitesinin otomatik olarak doğrulanmasını sağlar.

i18n CI/CD Pipeline'ı

# .github/workflows/i18n.yml
name: i18n Pipeline
on:
  pull_request:
    paths:
      - "src/**"
      - "locales/**"

jobs:
  i18n-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Check translation coverage
        run: bunx @better-i18n/cli coverage --min 95
        # Fails if any language drops below 95% coverage

      - name: Lint i18n keys
        run: bunx @better-i18n/cli lint --strict
        # Checks for hardcoded strings, unused keys, syntax errors

      - name: Sync new keys
        run: bunx @better-i18n/cli push --dry-run
        # Shows what keys would be synced (no side effects)

      - name: Validate translations
        run: bunx @better-i18n/cli validate
        # Checks ICU syntax, placeholder consistency, length limits

Dağıtım Kapıları

Şu CI kapılarını uygulamayı değerlendirin:

KapıEşikBaşarısızlık Durumunda
Çeviri kapsamıDil başına %95Birleştirmeyi engelle
ICU sözdizimi doğrulama%100 geçerliBirleştirmeyi engelle
Anahtar adlandırma kuralı%100 uyumluUyarı
Kullanılmayan anahtar sayısı< 50 anahtarUyarı
Eksik yer tutucular0 uyumsuzlukBirleştirmeyi engelle

Önemli Çıkarımlar

  • UI koduna dokunan her PR'da kapsam kontrolü çalıştırın
  • Çeviri kapsamı eşiğin altına düştüğünde birleştirmeleri engelleyin
  • CI'dan çeviri platformunuza yeni anahtarları otomatik senkronize edin
  • Üretimde çalışma zamanı hatalarını önlemek için ICU sözdizimini doğrulayın

4. Anahtar Adlandırma Kuralı Belirleyin

Tutarlı anahtar adlandırma, sürdürülebilir çevirilerin temelidir. İyi bir adlandırma kuralı, anahtarları kendi kendini açıklar hale getirir, çakışmaları azaltır ve çevirmen bağlamını iyileştirir.

Önerilen Kural: Namespace.Bölüm.Eleman.Özellik

{
  "auth.login.title": "Sign in to your account",
  "auth.login.email.label": "Email address",
  "auth.login.email.placeholder": "you@example.com",
  "auth.login.email.error.required": "Email is required",
  "auth.login.email.error.invalid": "Please enter a valid email",
  "auth.login.submit": "Sign in",
  "auth.login.forgot_password": "Forgot your password?",

  "dashboard.header.greeting": "Welcome back, {name}",
  "dashboard.projects.empty.title": "No projects yet",
  "dashboard.projects.empty.description": "Create your first project to get started",
  "dashboard.projects.empty.cta": "Create project",

  "common.actions.save": "Save",
  "common.actions.cancel": "Cancel",
  "common.actions.delete": "Delete",
  "common.actions.confirm": "Are you sure?",
  "common.errors.generic": "Something went wrong. Please try again.",
  "common.errors.network": "Network error. Check your connection."
}

Adlandırma Kuralları

  1. Hiyerarşi için nokta notasyonu kullanın: namespace.bölüm.eleman
  2. Çok kelimeli segmentler için snake_case kullanın: forgot_password, forgotPassword değil
  3. Özellik/sayfa namespace'i ile başlayın: auth, dashboard, settings
  4. Paylaşılan stringler için common.* kullanın: sayfalar arası kullanılan butonlar, hatalar, etiketler
  5. Yararlı olduğunda eleman türü ile sonlandırın: .label, .placeholder, .error, .cta
  6. Anahtarları 60 karakterin altında tutun — çeviri araçlarında okunabilirlik için
  7. Kaynak metni asla anahtar olarak kullanmayın: greeting kullanın, welcome_back_name değil

Kaçınılması Gereken Anti-Paternler

{
  "Welcome back": "Welcome back",
  "btn1": "Save",
  "page_title": "Dashboard",
  "err_msg": "Something went wrong",
  "auth_login_email_address_input_field_label_text": "Email"
}

Sorunlar: kaynak metin anahtar olarak kullanılmış (metin değiştiğinde bozulur), anlaşılmaz kısaltmalar, namespace hiyerarşisi yok, aşırı uzun anahtarlar.

Önemli Çıkarımlar

  • Herhangi bir anahtar yazmadan önce adlandırma kuralını belirleyin
  • Kuralı linting ile zorunlu kılın (Uygulama #2'ye bakın)
  • Anahtarları bileşen dosyasına göre değil, özelliğe göre gruplandırın
  • Yeniden kullanılabilir stringler için common.* namespace'i kullanın

5. Çoğullamayı ICU MessageFormat ile Doğru Şekilde Yönetin

Çoğullama, en yaygın i18n hata kaynaklarından biridir. İngilizce'nin basit tekil/çoğul kuralları vardır, ancak Arapça (6 çoğul form), Lehçe (3 form) veya Japonca (çoğul ayrımı yok) gibi diller dikkatli bir yaklaşım gerektirir.

ICU MessageFormat Sözdizimi

{
  "inbox.message_count": "{count, plural, =0 {No messages} one {# message} other {# messages}}",

  "cart.item_count": "{count, plural, =0 {Your cart is empty} one {# item in cart} other {# items in cart}}",

  "project.member_count": "{count, plural, =0 {No members} one {# member} other {# members}}"
}

Karmaşık Çoğullama (Cinsiyet + Çoğul)

{
  "activity.comment": "{gender, select, female {{count, plural, one {She left # comment} other {She left # comments}}} male {{count, plural, one {He left # comment} other {He left # comments}}} other {{count, plural, one {They left # comment} other {They left # comments}}}}"
}

React'te Kullanım

import { useTranslations } from "@better-i18n/use-intl";

function InboxHeader({ messageCount }: { messageCount: number }) {
  const t = useTranslations("inbox");

  return (
    <h2>{t("message_count", { count: messageCount })}</h2>
  );
  // count=0 -> "No messages"
  // count=1 -> "1 message"
  // count=5 -> "5 messages"
}

Dile Özgü Çoğul Kategoriler (CLDR)

DilKategorilerÖrnek
İngilizceone, other1 item, 2 items
Fransızcaone, many, other1 article, 1000000 d'articles, 2 articles
Arapçazero, one, two, few, many, other0, 1, 2, 3-10, 11-99, 100+
JaponcaotherTüm sayılar aynı formu kullanır
Lehçeone, few, many, other1, 2-4, 5-21, 22+
Rusçaone, few, many, other1, 2-4, 5-20, 21

Önemli Çıkarımlar

  • Çoğullama için her zaman ICU MessageFormat kullanın — stringleri asla birleştirmeyin
  • Her hedef dil için gerekli tüm çoğul kategorileri tanımlayın
  • Çoğullamayı uç durumlarla test edin: 0, 1, 2, 5, 11, 21, 100, 1000000
  • Manuel çoğul form oluşturmayı önlemek için ICU sözdizimini anlayan yapay zeka çeviri araçları kullanın

6. RTL (Sağdan Sola) Dilleri Düzgün Destekleyin

Arapça, İbranice ve Farsça gibi RTL dilleri desteklemek, sadece metin yönünü çevirmekten fazlasını gerektirir. Düzen, ikonlar, animasyonlar ve hatta sayı biçimlendirmesi de dikkate alınmalıdır.

CSS Mantıksal Özellikler

En önemli RTL uygulaması, fiziksel özellikler yerine CSS mantıksal özelliklerini kullanmaktır:

/* Physical properties (breaks RTL) */
.card {
  margin-left: 16px;
  padding-right: 24px;
  text-align: left;
  border-left: 2px solid blue;
}

/* Logical properties (works in both LTR and RTL) */
.card {
  margin-inline-start: 16px;
  padding-inline-end: 24px;
  text-align: start;
  border-inline-start: 2px solid blue;
}

Mantıksal Özellik Eşlemesi

Fiziksel (LTR)MantıksalRTL Karşılığı
margin-leftmargin-inline-startmargin-right
margin-rightmargin-inline-endmargin-left
padding-leftpadding-inline-startpadding-right
text-align: lefttext-align: starttext-align: right
float: leftfloat: inline-startfloat: right
left: 0inset-inline-start: 0right: 0

Tailwind CSS v4 RTL Desteği

function NavigationArrow({ direction }: { direction: "back" | "forward" }) {
  return (
    <button className="flex items-center gap-2">
      {/* Tailwind v4 logical utilities */}
      <ChevronIcon className="rtl:rotate-180" />
      <span className="ms-2">{/* margin-inline-start */}</span>
    </button>
  );
}

Belge Yönünü Ayarlama

// In your root layout
function RootLayout({ locale }: { locale: string }) {
  const direction = ["ar", "he", "fa", "ur"].includes(locale) ? "rtl" : "ltr";

  return (
    <html lang={locale} dir={direction}>
      <body>{/* content */}</body>
    </html>
  );
}

Önemli Çıkarımlar

  • Yalnızca CSS mantıksal özelliklerini kullanın — kod incelemesinde fiziksel left/right kullanımını yasaklayın
  • Locale'e göre HTML root elemanınıza dir özniteliği ekleyin
  • RTL için yönlü ikonları (oklar, chevron'lar) çevirin
  • Gerçek RTL içerikle test edin, sadece İngilizce metne dir="rtl" ekleyerek değil

7. Tarih, Sayı ve Para Birimlerini Intl API'leri ile Biçimlendirin

Tarihleri, sayıları veya para birimlerini asla manuel olarak biçimlendirmeyin. Tarayıcının Intl API'si; sayı gruplama, ondalık ayırıcılar, tarih sıralama ve para birimi konumlandırma dahil olmak üzere locale'e özgü biçimlendirmeyi doğru şekilde yönetir.

Tarih Biçimlendirme

// Use Intl.DateTimeFormat — never hardcode date patterns
function formatDate(date: Date, locale: string): string {
  return new Intl.DateTimeFormat(locale, {
    year: "numeric",
    month: "long",
    day: "numeric",
  }).format(date);
}

formatDate(new Date("2026-03-15"), "en-US");  // "March 15, 2026"
formatDate(new Date("2026-03-15"), "de-DE");  // "15. Marz 2026"
formatDate(new Date("2026-03-15"), "ja-JP");  // "2026年3月15日"

Göreceli Zaman Biçimlendirme

function formatRelativeTime(date: Date, locale: string): string {
  const rtf = new Intl.RelativeTimeFormat(locale, { numeric: "auto" });
  const diffMs = date.getTime() - Date.now();
  const diffDays = Math.round(diffMs / (1000 * 60 * 60 * 24));

  if (Math.abs(diffDays) < 1) return rtf.format(0, "day"); // "today"
  if (Math.abs(diffDays) < 7) return rtf.format(diffDays, "day");
  if (Math.abs(diffDays) < 30) return rtf.format(Math.round(diffDays / 7), "week");
  return rtf.format(Math.round(diffDays / 30), "month");
}

formatRelativeTime(yesterday, "en");  // "yesterday"
formatRelativeTime(yesterday, "de");  // "gestern"
formatRelativeTime(yesterday, "ja");  // "昨日"

Sayı ve Para Birimi Biçimlendirme

// Numbers
new Intl.NumberFormat("en-US").format(1234567.89);  // "1,234,567.89"
new Intl.NumberFormat("de-DE").format(1234567.89);  // "1.234.567,89"
new Intl.NumberFormat("ja-JP").format(1234567.89);  // "1,234,567.89"

// Currency
new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "USD",
}).format(29.99);  // "$29.99"

new Intl.NumberFormat("de-DE", {
  style: "currency",
  currency: "EUR",
}).format(29.99);  // "29,99 EUR"

new Intl.NumberFormat("ja-JP", {
  style: "currency",
  currency: "JPY",
}).format(3000);  // "3,000 JPY"

// Compact notation for large numbers
new Intl.NumberFormat("en", { notation: "compact" }).format(1500000);  // "1.5M"
new Intl.NumberFormat("de", { notation: "compact" }).format(1500000);  // "1,5 Mio."
new Intl.NumberFormat("ja", { notation: "compact" }).format(1500000);  // "150万"

Önemli Çıkarımlar

  • Her zaman Intl.DateTimeFormat, Intl.NumberFormat ve Intl.RelativeTimeFormat kullanın
  • MM/DD/YYYY gibi tarih formatlarını asla sabit kodlamayın — bu ABD'ye özgüdür
  • Bölgeye özgü biçimlendirme için tam locale kodunu iletin (örn. de-DE, sadece de değil)
  • Dashboard metrikleri ve istatistikleri için compact notasyon kullanın

8. Çevirileri Sistematik Olarak Test Edin

Çeviri testi genellikle ihmal edilir ve bu durum üretimde utanç verici sorunlara yol açar — kesilmiş metinler, bozulmuş düzenler, ham anahtarların kullanıcılara gösterilmesi.

Çeviri Test Piramidi

        /  Görsel   \         — Ekran görüntüsü regresyon testleri
       /  (5-10)    \        — Dil başına temel kullanıcı akışları
      /---------------\
     / Entegrasyon     \    — Tüm locale'lerle bileşen render'ı
    /   (50-100)        \   — Düzen taşması tespiti
   /---------------------\
  /     Birim Testleri    \ — ICU sözdizimi doğrulama
 /      (200-500)          \— Anahtar kapsam kontrolleri
/---------------------------\— Yer tutucu tutarlılığı

Birim Testleri: Anahtar Kapsamı ve Sözdizimi

import { describe, it, expect } from "vitest";
import en from "../locales/en.json";
import es from "../locales/es.json";
import de from "../locales/de.json";

const sourceKeys = Object.keys(flattenKeys(en));
const targetLocales = { es, de };

describe("Translation coverage", () => {
  for (const [locale, translations] of Object.entries(targetLocales)) {
    it(`${locale} has all keys from source`, () => {
      const targetKeys = Object.keys(flattenKeys(translations));
      const missingKeys = sourceKeys.filter((k) => !targetKeys.includes(k));

      expect(missingKeys).toEqual([]);
    });
  }
});

describe("ICU syntax validation", () => {
  it("all translations have valid ICU MessageFormat", () => {
    for (const [key, value] of Object.entries(flattenKeys(en))) {
      expect(() => new IntlMessageFormat(value, "en")).not.toThrow();
    }
  });
});

Entegrasyon Testleri: Düzen ve Taşma

import { render, screen } from "@testing-library/react";
import { IntlProvider } from "@better-i18n/use-intl";

const LOCALES_TO_TEST = ["en", "de", "ja", "ar"];

describe.each(LOCALES_TO_TEST)("Button layout in %s", (locale) => {
  it("navigation buttons do not overflow container", async () => {
    const messages = await loadMessages(locale);

    const { container } = render(
      <IntlProvider locale={locale} messages={messages}>
        <Navigation />
      </IntlProvider>
    );

    const nav = container.querySelector("nav");
    expect(nav!.scrollWidth).toBeLessThanOrEqual(nav!.clientWidth);
  });
});

Erken Tespit İçin Sözde Yerelleştirme (Pseudo-Localization)

Sözde yerelleştirme, gerçek çevirilere ihtiyaç duymadan çeviri zorluklarını simüle etmek için kaynak stringleri dönüştürür:

// Pseudo-locale transforms
function pseudoLocalize(text: string): string {
  // Accent characters to simulate diacritics
  const accents: Record<string, string> = {
    a: "a", e: "e", i: "i", o: "o", u: "u",
    A: "A", E: "E", I: "I", O: "O", U: "U",
  };

  // Add 40% length expansion (German/Finnish are ~30-40% longer)
  const expanded = text.replace(/[aeiouAEIOU]/g, (c) => accents[c] || c);
  const padding = "~".repeat(Math.ceil(text.length * 0.4));

  return `[${expanded}${padding}]`;
}

// "Save changes" -> "[Save changes~~~~~~~~]"
// Immediately reveals: truncation, overflow, hardcoded strings

Önemli Çıkarımlar

  • ICU sözdizimini birim test seviyesinde test edin — hataları dağıtımdan önce yakalayın
  • Düzen sorunlarını erken yakalamak için geliştirme sırasında sözde yerelleştirme kullanın
  • En az Almanca (uzun kelimeler), Japonca (CJK karakterler) ve Arapça (RTL) ile test edin
  • Desteklenen tüm locale'ler için kritik sayfalarda görsel regresyon testleri çalıştırın

9. Çeviri Paketleri İçin Tembel Yükleme (Lazy Loading) Uygulayın

Tüm locale'ler için tüm çevirileri önceden yüklemek performansı öldürür. Tembel yükleme, kullanıcıların yalnızca aktif locale'leri için çeviri paketini indirmesini sağlar ve olası dil değişiklikleri için isteğe bağlı ön yükleme sunar.

Rota Bazlı Tembel Yükleme

// Load translations per route + locale
// Only load the namespaces needed for the current page

import { createRoute } from "@tanstack/react-router";

export const dashboardRoute = createRoute({
  path: "/dashboard",
  loader: async ({ params }) => {
    const locale = params.locale || "en";

    // Load only dashboard namespace translations
    const messages = await import(`../locales/${locale}/dashboard.json`);

    return { messages: messages.default, locale };
  },
  component: DashboardPage,
});

Namespace Bazlı Bölümleme

// locales/en/common.json — loaded on every page (~2KB)
{
  "common.nav.home": "Home",
  "common.nav.dashboard": "Dashboard",
  "common.actions.save": "Save"
}

// locales/en/dashboard.json — loaded only on dashboard (~5KB)
{
  "dashboard.title": "Dashboard",
  "dashboard.stats.users": "Active users"
}

// locales/en/settings.json — loaded only on settings (~3KB)
{
  "settings.title": "Settings",
  "settings.profile.name": "Display name"
}

Better i18n ile CDN Tabanlı Yükleme

// Better i18n loads translations from edge CDN
// with automatic locale-based splitting

import { createBetterI18n } from "@better-i18n/core";

const i18n = createBetterI18n({
  project: "my-org/my-app",
  // Only fetches the active locale
  // Caches with TTL for instant subsequent loads
  // Supports namespace-level granularity
  cdn: {
    enabled: true,
    ttl: 300, // 5 minutes cache
  },
});

// First load: fetches from CDN (~50ms from edge)
// Subsequent loads: served from memory cache (~0ms)
const messages = await i18n.getMessages("en", ["common", "dashboard"]);

Ön Yükleme Stratejisi

// Preload likely locale switches based on user behavior
function useLocalePreloader(currentLocale: string) {
  useEffect(() => {
    // Preload browser's preferred language if different
    const browserLocale = navigator.language.split("-")[0];
    if (browserLocale !== currentLocale) {
      i18n.preload(browserLocale, ["common"]);
    }

    // Preload on hover over language switcher
    const switcher = document.querySelector("[data-locale-switcher]");
    switcher?.addEventListener("mouseenter", () => {
      const targetLocale = switcher.getAttribute("data-target-locale");
      if (targetLocale) {
        i18n.preload(targetLocale, ["common"]);
      }
    });
  }, [currentLocale]);
}

Paket Boyutu Etkisi

Stratejiİlk YüklemeDil Değişikliği
Tüm locale'ler paketlenmiş~150KB (10 locale)Anında
Locale bazlı tembel yükleme~15KB (1 locale)~50ms (CDN)
Namespace bazlı tembel yükleme~5KB (1 namespace)~30ms (CDN)
Ön yüklemeli CDN~5KB (1 namespace)Anında (ön yüklenmiş)

Önemli Çıkarımlar

  • Tüm locale çevirilerini asla tek bir pakette birleştirmeyin
  • Çevirileri rotalarla uyumlu namespace'lere göre bölün
  • Üretimde CDN dağıtımı kullanın (edge-cached, küresel olarak ~50ms)
  • Kullanıcının tarayıcı locale'ini ve olası geçiş hedeflerini ön yükleyin

10. Kademeli Yayınlama Planı Yapın

Tüm dilleri aynı anda yayınlamak risklidir. Kademeli yayınlama, tam dağıtımdan önce çeviri kalitesini doğrulamanızı, locale'e özgü hataları yakalamanızı ve kullanıcı geri bildirimi toplamanızı sağlar.

Aşamalı Yayınlama Stratejisi

Aşama 1: Ana Pazarlar (1-2. Hafta)

  • En yüksek öncelikli 2-3 dili yayınlayın
  • Ana dil konuşanlarıyla tam QA geçişi
  • Hata oranlarını ve kullanıcı geri bildirimlerini izleyin
  • Düzen veya biçimlendirme sorunlarını düzeltin

Aşama 2: Büyüme Pazarları (3-4. Hafta)

  • 3-5 ek dil ekleyin
  • İnsan gözden geçirmesiyle yapay zeka çevirisi kullanın
  • Dönüşüm etkisi için çevrilmiş ve İngilizce arasında A/B testi yapın
  • Locale'e özgü metrikleri takip edin

Aşama 3: Uzun Kuyruk (5+ Hafta)

  • Kalan dilleri ekleyin
  • Periyodik gözden geçirme ile yalnızca yapay zeka çevirisi
  • Niş diller için topluluk katkısı
  • Otomatik kalite izleme

Feature Flag Entegrasyonu

// Use feature flags to control locale availability
const LOCALE_ROLLOUT = {
  en: { enabled: true, percentage: 100 },
  es: { enabled: true, percentage: 100 },
  fr: { enabled: true, percentage: 100 },
  de: { enabled: true, percentage: 50 },  // 50% rollout
  ja: { enabled: true, percentage: 25 },  // 25% rollout
  ko: { enabled: false, percentage: 0 },  // Not yet launched
} as const;

function getAvailableLocale(
  requestedLocale: string,
  userId: string
): string {
  const config = LOCALE_ROLLOUT[requestedLocale as keyof typeof LOCALE_ROLLOUT];

  if (!config?.enabled) return "en";

  // Consistent user bucketing for gradual rollout
  const bucket = hashUserId(userId) % 100;
  if (bucket >= config.percentage) return "en";

  return requestedLocale;
}

Kalite İzleme Panosu

Yayınlama sonrasında locale başına şu metrikleri takip edin:

MetrikNe ÖlçerUyarı Eşiği
Çeviri kapsamıÇevrilen anahtarların yüzdesi< %95
Hemen çıkma oranı farkıİngilizce bazline göre hemen çıkma oranı> %10 daha yüksek
Dönüşüm oranı farkıİngilizce'ye göre kayıt/satın alma oranı> %15 daha düşük
Hata oranıLocale'e özgü kodda JS hataları> İngilizce oranının 2 katı
Destek talepleriLocale ile ilgili talepler> Haftada 5
Kullanıcı geri bildirimiLocale başına yıldız puanı< 3.5 yıldız

Önemli Çıkarımlar

  • Tüm dilleri asla aynı anda yayınlamayın — aşamalı olarak yayınlayın
  • Kademeli yüzde bazlı yayınlama için feature flag'ler kullanın
  • Locale'e özgü metrikleri İngilizce bazline göre izleyin
  • Çeviri kapsamı ve hata oranları için otomatik kalite uyarıları kurun

Hepsini Bir Araya Getirmek: i18n Olgunluk Modeli

Bu 10 uygulama birbirinin üzerine inşa edilir. İşte etki ve efor bazında önerilen benimseme sırası:

Seviye 1: Temel (1. Hafta)

  • Anahtar adlandırma kuralını belirleyin (#4)
  • Çoğullama için ICU MessageFormat kurun (#5)
  • Tarih/sayı biçimlendirmesi için Intl API'lerini kullanın (#7)

Seviye 2: Kalite (2-3. Hafta)

  • i18n sorunlarını yakalamak için statik analiz ekleyin (#2)
  • Temel çeviri testlerini uygulayın (#8)
  • CSS mantıksal özelliklerle RTL desteği ekleyin (#6)

Seviye 3: Otomasyon (4-5. Hafta)

  • i18n kontrollerini CI/CD'ye entegre edin (#3)
  • Yapay zeka destekli çeviri iş akışını kurun (#1)
  • Çeviri paketleri için tembel yükleme uygulayın (#9)

Seviye 4: Ölçekleme (6+ Hafta)

  • Kademeli yayınlamayı planlayın ve uygulayın (#10)
  • Locale'e özgü metrikleri izleyin
  • Yapay zeka çeviri kalitesini sürekli iyileştirin

Sonuç

2026'da uluslararasılaştırma artık sadece stringleri dışa aktarmaktan ibaret değil. Yapay zeka destekli iş akışlarını, otomatik kalite pipeline'larını, performans optimizasyonunu ve veri odaklı yayınlama stratejilerini kapsayan bir mühendislik disiplinidir.

i18n'i bir sonradan düşünce olarak değil, birinci sınıf bir mühendislik meselesi olarak ele alan ekipler, küresel pazarlara daha hızlı, daha yüksek kalitede ve daha düşük maliyetle ulaşır.

Temelden başlayın (adlandırma kuralları, ICU MessageFormat, Intl API'leri), otomasyon katmanını oluşturun (statik analiz, CI/CD, yapay zeka çevirisi) ve güvenle ölçeklendirin (tembel yükleme, kademeli yayınlama, izleme).

Dünyanın dört bir yanındaki kullanıcılarınız size teşekkür edecek.


Bu uygulamaları hayata geçirme konusunda sorularınız mı var? Blogumuzdaki framework'e özel rehberlere göz atın veya bu en iyi uygulamaları pratikte görmek için Better i18n ile hemen başlayın.

Comments

Loading comments...