İç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:
- Yapay zeka, kaynak stringlerden ilk çevirileri üretir
- İnsan gözden geçiriciler kalite ve marka tutarlılığı için düzenleme yapar
- Çeviri belleği, onaylanan çevirileri yeniden kullanılmak üzere kaydeder
- 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şik | Başarısızlık Durumunda |
|---|---|---|
| Çeviri kapsamı | Dil başına %95 | Birleştirmeyi engelle |
| ICU sözdizimi doğrulama | %100 geçerli | Birleştirmeyi engelle |
| Anahtar adlandırma kuralı | %100 uyumlu | Uyarı |
| Kullanılmayan anahtar sayısı | < 50 anahtar | Uyarı |
| Eksik yer tutucular | 0 uyumsuzluk | Birleş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ı
- Hiyerarşi için nokta notasyonu kullanın:
namespace.bölüm.eleman - Çok kelimeli segmentler için snake_case kullanın:
forgot_password,forgotPassworddeğil - Özellik/sayfa namespace'i ile başlayın:
auth,dashboard,settings - Paylaşılan stringler için
common.*kullanın: sayfalar arası kullanılan butonlar, hatalar, etiketler - Yararlı olduğunda eleman türü ile sonlandırın:
.label,.placeholder,.error,.cta - Anahtarları 60 karakterin altında tutun — çeviri araçlarında okunabilirlik için
- Kaynak metni asla anahtar olarak kullanmayın:
greetingkullanın,welcome_back_namedeğ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)
| Dil | Kategoriler | Örnek |
|---|---|---|
| İngilizce | one, other | 1 item, 2 items |
| Fransızca | one, many, other | 1 article, 1000000 d'articles, 2 articles |
| Arapça | zero, one, two, few, many, other | 0, 1, 2, 3-10, 11-99, 100+ |
| Japonca | other | Tüm sayılar aynı formu kullanır |
| Lehçe | one, few, many, other | 1, 2-4, 5-21, 22+ |
| Rusça | one, few, many, other | 1, 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ıksal | RTL Karşılığı |
|---|---|---|
margin-left | margin-inline-start | margin-right |
margin-right | margin-inline-end | margin-left |
padding-left | padding-inline-start | padding-right |
text-align: left | text-align: start | text-align: right |
float: left | float: inline-start | float: right |
left: 0 | inset-inline-start: 0 | right: 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/rightkullanı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.NumberFormatveIntl.RelativeTimeFormatkullanın MM/DD/YYYYgibi 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, sadecededeğ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ükleme | Dil 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:
| Metrik | Ne Ölçer | Uyarı 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 talepleri | Locale ile ilgili talepler | > Haftada 5 |
| Kullanıcı geri bildirimi | Locale 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
IntlAPI'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.