2026'da i18n ve AI Destekli Modern Web Uygulaması Nasıl Geliştirilir?

Lingui ve AI çevirileriyle çok dilli web uygulamaları geliştirme rehberi. Next.js, Claude ve T3 Turbo kullanarak 17 dili otomatik olarak destekleyin.

2026'da i18n ve AI Destekli Modern Web Uygulaması Nasıl Geliştirilir?
Feng LiuFeng Liu
24 Ocak 2026

Bakın, 2026'da i18n (uluslararasılaştırma) hakkında konuşmamız lazım.

Çoğu eğitim size metinleri manuel olarak çevirmenizi, tercüman tutmanızı veya dandik Google Translate API'larını kullanmanızı söyleyecektir. Ama olay şu: Siz Claude Sonnet 4.5 çağında yaşıyorsunuz. Neden hala 2019'daymışız gibi çeviri yapıyorsunuz?

Size, gerçekten mantıklı olan iki parçalı bir i18n mimarisi kullanarak, 17 dili akıcı bir şekilde konuşan production seviyesinde bir web uygulamasını nasıl geliştirdiğimizi göstereceğim:

  1. Lingui: Çıkarma (extraction), derleme ve runtime sihri için.
  2. Özel bir i18n paketi: Otomatik, bağlam duyarlı (context-aware) çeviriler için LLM'lerden güç alan bir paket.

Teknoloji yığınımız (stack) mı? Next.js, tRPC, Drizzle, Postgres, Tailwind ve AI SDK ile Create T3 Turbo. Eğer 2026'da bunu kullanmıyorsanız, oturup farklı bir konuşma yapmamız lazım.

Hadi inşa edelim.


Geleneksel i18n İle İlgili Sorun

Geleneksel i18n iş akışları şuna benzer:

# Metinleri çıkar (extract)
$ lingui extract

# ??? Bir şekilde çevirileri al ???
# (tercüman tut, şüpheli servisler kullan, ağla)

# Derle (compile)
$ lingui compile

O ortadaki adım var ya? Tam bir kabus. Ya:

  • İnsan çevirmenlere $$$ ödüyorsunuz (yavaş, pahalı)
  • Temel çeviri API'ları kullanıyorsunuz (bağlamdan habersiz, robotik duyuluyor)
  • Manuel çeviriyorsunuz (ölçeklenemez)

Biz daha iyisini yapıyoruz.


İki Parçalı Mimari

İşte bizim kurulumumuz:

┌─────────────────────────────────────────────┐
│  Next.js Uygulaması (Lingui Entegrasyonu)  │
│  ├─ Makrolarla metinleri çıkarma            │
│  ├─ Kodunuzda Trans/t bileşenleri           │
│  └─ Derlenmiş kataloglarla runtime i18n     │
└─────────────────────────────────────────────┘
              ↓ .po dosyaları üretir
┌─────────────────────────────────────────────┐
│  @acme/i18n Paketi (LLM Çevirisi)         │
│  ├─ .po dosyalarını okur                    │
│  ├─ Claude/GPT-5 ile toplu çeviri yapar     │
│  ├─ Bağlam duyarlı, ürüne özel              │
│  └─ Çevrilmiş .po dosyalarını yazar         │
└─────────────────────────────────────────────┘
              ↓ TypeScript'e derlenir
┌─────────────────────────────────────────────┐
│  Derlenmiş Mesaj Katalogları                │
│  └─ Hızlı, tip güvenli runtime çevirileri   │
└─────────────────────────────────────────────┘

1. Parça (Lingui) geliştirici deneyimini (DX) halleder. 2. Parça (Özel i18n Paketi) çeviri sihrini halleder.

Hadi her birine derinlemesine bakalım.


Teknik akış şeması: web arayüzü → AI çeviri bulutu → veritabanı, oklarla birbirine bağlı üç katman

Bölüm 1: Next.js İçinde Lingui Kurulumu

Kurulum

T3 Turbo monorepo'nuzda:

# apps/nextjs içinde
pnpm add @lingui/core @lingui/react @lingui/macro
pnpm add -D @lingui/cli @lingui/swc-plugin

Lingui Konfigürasyonu

apps/nextjs/lingui.config.ts dosyasını oluşturun:

import type { LinguiConfig } from "@lingui/conf";

const config: LinguiConfig = {
  locales: [
    "en", "zh_CN", "zh_TW", "ja", "ko",
    "de", "fr", "es", "pt", "ar", "it",
    "ru", "tr", "th", "id", "vi", "hi"
  ],
  sourceLocale: "en",
  fallbackLocales: {
    default: "en"
  },
  catalogs: [
    {
      path: "<rootDir>/src/locales/{locale}/messages",
      include: ["src"],
    },
  ],
};

export default config;

Kutudan çıktığı gibi 17 dil. Neden olmasın ki?

Next.js Entegrasyonu

Lingui'nin SWC eklentisini kullanmak için next.config.js dosyasını güncelleyin:

const linguiConfig = require("./lingui.config");

module.exports = {
  experimental: {
    swcPlugins: [
      [
        "@lingui/swc-plugin",
        {
          // Bu, buildlerinizi hızlandırır
        },
      ],
    ],
  },
  // ... konfigürasyonunuzun geri kalanı
};

Sunucu Tarafı (Server-Side) Kurulumu

src/utils/i18n/appRouterI18n.ts dosyasını oluşturun:

import { setupI18n } from "@lingui/core";
import { allMessages } from "./initLingui";

const locales = ["en", "zh_CN", "zh_TW", /* ... */] as const;

const instances = new Map<string, ReturnType<typeof setupI18n>>();

// Tüm diller için i18n örneklerini önceden oluşturun
locales.forEach((locale) => {
  const i18n = setupI18n({
    locale,
    messages: { [locale]: allMessages[locale] },
  });
  instances.set(locale, i18n);
});

export function getI18nInstance(locale: string) {
  return instances.get(locale) ?? instances.get("en")!;
}

Neden? Server Component'lerin React Context'i yoktur. Bu size sunucu tarafı çevirileri sağlar.

İstemci Tarafı (Client-Side) Provider

src/providers/LinguiClientProvider.tsx dosyasını oluşturun:

"use client";

import { I18nProvider } from "@lingui/react";
import { setupI18n } from "@lingui/core";
import { useEffect, useState } from "react";

export function LinguiClientProvider({
  children,
  locale,
  messages
}: {
  children: React.ReactNode;
  locale: string;
  messages: any;
}) {
  const [i18n] = useState(() =>
    setupI18n({
      locale,
      messages: { [locale]: messages },
    })
  );

  useEffect(() => {
    i18n.load(locale, messages);
    i18n.activate(locale);
  }, [locale, messages, i18n]);

  return <I18nProvider i18n={i18n}>{children}</I18nProvider>;
}

Uygulamanızı layout.tsx içinde sarmalayın:

import { LinguiClientProvider } from "@/providers/LinguiClientProvider";
import { getLocale } from "@/utils/i18n/localeDetection";
import { allMessages } from "@/utils/i18n/initLingui";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  const locale = getLocale();

  return (
    <html lang={locale}>
      <body>
        <LinguiClientProvider locale={locale} messages={allMessages[locale]}>
          {children}
        </LinguiClientProvider>
      </body>
    </html>
  );
}

Kodunuzda Çevirileri Kullanmak

Server Component'lerde:

import { msg } from "@lingui/core/macro";
import { getI18nInstance } from "@/utils/i18n/appRouterI18n";

export async function generateMetadata({ params }) {
  const locale = getLocale();
  const i18n = getI18nInstance(locale);

  return {
    title: i18n._(msg`Pricing Plans | acme`),
    description: i18n._(msg`Choose the perfect plan for you`),
  };
}

Client Component'lerde:

"use client";

import { Trans, useLingui } from "@lingui/react/macro";

export function PricingCard() {
  const { t } = useLingui();

  return (
    <div>
      <h1><Trans>Pricing Plans</Trans></h1>
      <p>{t`Ultimate entertainment experience`}</p>

      {/* Değişkenlerle */}
      <p>{t`${credits} credits remaining`}</p>
    </div>
  );
}

Makro sözdizimi ANAHTAR noktadır. Lingui bunları build zamanında (build time) ayıklar.


Bölüm 2: AI Destekli Çeviri Paketi

İşin en civcivli kısmı burası.

Paket Yapısı

packages/i18n/ oluşturun:

packages/i18n/
├── package.json
├── src/
│   ├── translateWithLLM.ts      # Çekirdek LLM çevirisi
│   ├── enhanceTranslations.ts   # Toplu işlemci
│   └── utils.ts                  # Yardımcılar

package.json

{
  "name": "@acme/i18n",
  "version": "0.1.0",
  "dependencies": {
    "@acme/ai": "workspace:*",
    "openai": "^4.77.3",
    "pofile": "^1.1.4",
    "zod": "^3.23.8"
  }
}

LLM Çeviri Motoru

İşte gizli sosumuz - translateWithLLM.ts:

import { openai } from "@ai-sdk/openai";
import { generateText } from "ai";
import { z } from "zod";

const translationSchema = z.object({
  translations: z.array(
    z.object({
      msgid: z.string(),
      msgstr: z.string(),
    })
  ),
});

export async function translateWithLLM(
  messages: Array<{ msgid: string; msgstr: string }>,
  targetLocale: string,
  options?: { model?: string }
) {
  const prompt = `You are a professional translator for acme, an AI-powered creative platform.

Translate the following strings from English to ${getLanguageName(targetLocale)}.

CONTEXT:
- acme is a platform for AI chat, image generation, and creative content
- Keep brand names unchanged (acme, Claude, etc.)
- Preserve HTML tags, variables like {count}, and placeholders
- Adapt culturally where appropriate
- Maintain tone: friendly, creative, engaging

STRINGS TO TRANSLATE:
${JSON.stringify(messages, null, 2)}

Return a JSON object with this structure:
{
  "translations": [
    { "msgid": "original", "msgstr": "translation" },
    ...
  ]
}`;

  const result = await generateText({
    model: openai(options?.model ?? "gpt-4o"),
    prompt,
    temperature: 0.3, // Düşük = daha tutarlı
  });

  const parsed = translationSchema.parse(JSON.parse(result.text));
  return parsed.translations;
}

function getLanguageName(locale: string): string {
  const names: Record<string, string> = {
    zh_CN: "Simplified Chinese",
    zh_TW: "Traditional Chinese",
    ja: "Japanese",
    ko: "Korean",
    de: "German",
    fr: "French",
    es: "Spanish",
    pt: "Portuguese",
    ar: "Arabic",
    // ... vb
  };
  return names[locale] ?? locale;
}

Bu neden çalışıyor:

  • Bağlam duyarlı (Context-aware): LLM, acme'nin ne olduğunu biliyor.
  • Yapılandırılmış çıktı: Zod şeması geçerli JSON olmasını garanti eder.
  • Düşük sıcaklık (temperature): Tutarlı çeviriler.
  • Formatı korur: HTML ve değişkenler bozulmadan kalır.

Toplu Çeviri İşlemcisi

enhanceTranslations.ts dosyasını oluşturun:

import fs from "fs";
import path from "path";
import pofile from "pofile";
import { translateWithLLM } from "./translateWithLLM";

const BATCH_SIZE = 30; // Her seferinde 30 metin çevir
const DELAY_MS = 1000; // Hız sınırlaması (Rate limiting)

export async function enhanceTranslations(
  locale: string,
  catalogPath: string
) {
  const poPath = path.join(catalogPath, locale, "messages.po");
  const po = pofile.parse(fs.readFileSync(poPath, "utf-8"));

  // Çevrilmemiş öğeleri bul
  const untranslated = po.items.filter(
    (item) => item.msgid && (!item.msgstr || item.msgstr[0] === "")
  );

  if (untranslated.length === 0) {
    console.log(`✓ ${locale}: All strings translated`);
    return;
  }

  console.log(`Translating ${untranslated.length} strings for ${locale}...`);

  // Gruplar (batch) halinde işle
  for (let i = 0; i < untranslated.length; i += BATCH_SIZE) {
    const batch = untranslated.slice(i, i + BATCH_SIZE);
    const messages = batch.map((item) => ({
      msgid: item.msgid,
      msgstr: item.msgstr?.[0] ?? "",
    }));

    try {
      const translations = await translateWithLLM(messages, locale);

      // PO dosyasını güncelle
      translations.forEach((translation, index) => {
        const item = batch[index];
        if (item) {
          item.msgstr = [translation.msgstr];
        }
      });

      console.log(`  ${i + batch.length}/${untranslated.length} translated`);

      // İlerlemeyi kaydet
      fs.writeFileSync(poPath, po.toString());

      // Hız sınırlaması
      if (i + BATCH_SIZE < untranslated.length) {
        await new Promise((resolve) => setTimeout(resolve, DELAY_MS));
      }
    } catch (error) {
      console.error(`  Error translating batch: ${error}`);
      // Sonraki grupla devam et
    }
  }

  console.log(`✓ ${locale}: Translation complete!`);
}

Toplu işleme (Batch processing) token limitlerini önler ve maliyetten tasarruf sağlar.

Çeviri Script'i

apps/nextjs/script/i18n.ts dosyasını oluşturun:

import { enhanceTranslations } from "@acme/i18n";
import { exec } from "child_process";
import { promisify } from "util";

const execAsync = promisify(exec);

const LOCALES = [
  "zh_CN", "zh_TW", "ja", "ko", "de",
  "fr", "es", "pt", "ar", "it", "ru"
];

async function main() {
  // Adım 1: Koddan metinleri çıkar
  console.log("📝 Extracting strings...");
  await execAsync("pnpm run lingui:extract --clean");

  // Adım 2: Eksik metinleri otomatik çevir
  console.log("\n🤖 Translating with AI...");
  const catalogPath = "./src/locales";

  for (const locale of LOCALES) {
    await enhanceTranslations(locale, catalogPath);
  }

  // Adım 3: TypeScript'e derle
  console.log("\n⚡ Compiling catalogs...");
  await execAsync("npx lingui compile --typescript");

  console.log("\n✅ Done! All translations updated.");
}

main().catch(console.error);

package.json dosyasına ekleyin:

{
  "scripts": {
    "i18n": "tsx script/i18n.ts",
    "lingui:extract": "lingui extract",
    "lingui:compile": "lingui compile --typescript"
  }
}

i18n Pipeline'ınızı Çalıştırma

# Hepsine hükmedecek tek bir komut
$ pnpm run i18n

📝 Extracting strings...
Catalog statistics for src/locales/{locale}/messages:
┌──────────┬─────────────┬─────────┐
│ Language │ Total count │ Missing │
├──────────┼─────────────┼─────────┤
│ en       │         847 │       0 │
│ zh_CN    │         847 │     123 │
│ ja       │         847 │      89 │
└──────────┴─────────────┴─────────┘

🤖 Translating with AI...
Translating 123 strings for zh_CN...
  30/123 translated
  60/123 translated
  90/123 translated
  123/123 translated
✓ zh_CN: Translation complete!

⚡ Compiling catalogs...
✅ Done! All translations updated.

İşte bu kadar. Kodunuza yeni bir metin ekleyin, pnpm i18n çalıştırın, bum - 17 dile çevrildi.


Öncesi/sonrası bölünmüş ekran: solda çeviri kağıtları ve 1000 dolarlık faturayla stresli geliştirici

Dil Değiştirme (Locale Switching)

UX kısmını unutmayın. İşte bir dil değiştirici:

"use client";

import { useLocaleSwitcher } from "@/hooks/useLocaleSwitcher";
import { useLocale } from "@/hooks/useLocale";

const LOCALES = {
  en: "English",
  zh_CN: "简体中文",
  zh_TW: "繁體中文",
  ja: "日本語",
  ko: "한국어",
  // ... vb
};

export function LocaleSelector() {
  const currentLocale = useLocale();
  const { switchLocale } = useLocaleSwitcher();

  return (
    <select
      value={currentLocale}
      onChange={(e) => switchLocale(e.target.value)}
    >
      {Object.entries(LOCALES).map(([code, name]) => (
        <option key={code} value={code}>
          {name}
        </option>
      ))}
    </select>
  );
}

Hook implementasyonu:

// hooks/useLocaleSwitcher.tsx
"use client";

import { setUserLocale } from "@/utils/i18n/localeDetection";

export function useLocaleSwitcher() {
  const switchLocale = (locale: string) => {
    setUserLocale(locale);
    window.location.reload(); // Dili uygulamak için zorla yenile
  };

  return { switchLocale };
}

Tercihi bir çerezde (cookie) saklayın:

// utils/i18n/localeDetection.ts
import { cookies } from "next/headers";

export function setUserLocale(locale: string) {
  cookies().set("NEXT_LOCALE", locale, {
    maxAge: 365 * 24 * 60 * 60, // 1 yıl
  });
}

export function getLocale(): string {
  const cookieStore = cookies();
  return cookieStore.get("NEXT_LOCALE")?.value ?? "en";
}

İleri Seviye: Tip Güvenli (Type-Safe) Çeviriler

Tip güvenliği mi istiyorsunuz? Lingui arkanızda:

// Bunun yerine:
t`Hello ${name}`

// msg tanımlayıcısını kullanın:
import { msg } from "@lingui/core/macro";

const greeting = msg`Hello ${name}`;
const translated = i18n._(greeting);

IDE'niz çeviri anahtarlarını otomatik tamamlayacak. Muazzam.


Performans Değerlendirmeleri

1. Build Zamanında Derleme

Lingui çevirileri küçültülmüş (minified) JSON'a derler. Runtime'da ayrıştırma (parsing) yükü yoktur.

// Derlenmiş çıktı (minified):
export const messages = JSON.parse('{"ICt8/V":["视频"],"..."}');

2. Sunucu Kataloglarını Önceden Yükleme

Başlangıçta tüm katalogları bir kez yükleyin (yukarıdaki appRouterI18n.ts'e bakın). Her istekte dosya I/O işlemi olmaz.

3. İstemci Bundle Boyutu

İstemciye sadece aktif dili gönderin:

<LinguiClientProvider
  locale={locale}
  messages={allMessages[locale]} // Sadece tek bir dil
>

4. LLM Maliyet Optimizasyonu

  • Toplu çeviriler: API çağrısı başına 30 metin
  • Çevirileri önbelleğe alma: Değişmeyen metinleri tekrar çevirmeyin
  • Daha ucuz modeller kullanma: Kritik olmayan diller için GPT-4o-mini

Bizim maliyetimiz? 800+ metin × 16 dil için ~$2-3. İnsan çevirmenlere kıyasla çerez parası.


Tam Teknoloji Yığını Entegrasyonu

Bunun T3 Turbo'nun geri kalanıyla nasıl çalıştığına bakalım:

i18n ile tRPC

// server/api/routers/user.ts
import { createTRPCRouter, publicProcedure } from "../trpc";
import { msg } from "@lingui/core/macro";

export const userRouter = createTRPCRouter({
  subscribe: publicProcedure
    .mutation(async ({ ctx }) => {
      // Hatalar da çevrilebilir!
      if (!ctx.session?.user) {
        throw new TRPCError({
          code: "UNAUTHORIZED",
          message: ctx.i18n._(msg`You must be logged in`),
        });
      }

      // ... abonelik mantığı
    }),
});

i18n örneğini context üzerinden geçirin:

// server/api/trpc.ts
import { getI18nInstance } from "@/utils/i18n/appRouterI18n";

export const createTRPCContext = async (opts: CreateNextContextOptions) => {
  const locale = getLocale();
  const i18n = getI18nInstance(locale);

  return {
    session: await getServerAuthSession(),
    i18n,
    locale,
  };
};

Drizzle ile Veritabanı

Kullanıcı dil tercihini saklayın:

// packages/db/schema/user.ts
import { pgTable, text, varchar } from "drizzle-orm/pg-core";

export const users = pgTable("user", {
  id: varchar("id", { length: 255 }).primaryKey(),
  locale: varchar("locale", { length: 10 }).default("en"),
  // ... diğer alanlar
});

AI SDK Entegrasyonu

AI yanıtlarını anında çevirin:

import { openai } from "@ai-sdk/openai";
import { generateText } from "ai";
import { useLingui } from "@lingui/react/macro";

export function useAIChat() {
  const { i18n } = useLingui();

  const chat = async (prompt: string) => {
    const systemPrompt = i18n._(msg`You are a helpful AI assistant for acme.`);

    return generateText({
      model: openai("gpt-4"),
      messages: [
        { role: "system", content: systemPrompt },
        { role: "user", content: prompt },
      ],
    });
  };

  return { chat };
}

Öğrendiğimiz En İyi Uygulamalar (Best Practices)

1. Her Zaman Makro Kullanın

// ❌ Kötü: Runtime çevirisi (çıkarılmaz/extract edilmez)
const text = t("Hello world");

// ✅ İyi: Makro (build zamanında çıkarılır)
const text = t`Hello world`;

2. Bağlam Her Şeydir

Çevirmenler (veya AI) için yorumlar ekleyin:

// i18n: This appears in the pricing table header
<Trans>Monthly</Trans>

// i18n: Button to submit payment form
<button>{t`Subscribe Now`}</button>

Lingui bunları çevirmen notları olarak ayıklar.

3. Çoğulları Düzgün Yönetin

import { Plural } from "@lingui/react/macro";

<Plural
  value={count}
  one="# credit remaining"
  other="# credits remaining"
/>

Farklı dillerin farklı çoğul kuralları vardır. Lingui bunu halleder.

4. Tarih/Sayı Formatlama

Intl API'larını kullanın:

const date = new Intl.DateTimeFormat(locale, {
  dateStyle: "long",
}).format(new Date());

const price = new Intl.NumberFormat(locale, {
  style: "currency",
  currency: "USD",
}).format(29.99);

5. RTL Desteği

Arapça için yönü (direction) yönetin:

export default function RootLayout({ children }) {
  const locale = getLocale();
  const direction = locale === "ar" ? "rtl" : "ltr";

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

Tailwind konfigürasyonuna ekleyin:

module.exports = {
  plugins: [
    require('tailwindcss-rtl'),
  ],
};

Yönsel sınıfları kullanın:

<div className="ms-4"> {/* margin-start, hem LTR hem RTL için çalışır */}

Deployment Kontrol Listesi

Ship etmeden önce:

  • Tüm çevirilerin güncel olduğundan emin olmak için pnpm i18n çalıştırın
  • Production modunda her dili test edin
  • Dil çerezinin (cookie) kalıcılığını doğrulayın
  • Arapça için RTL düzenini kontrol edin
  • Dil değiştirici UX'ini test edin
  • SEO için hreflang etiketlerini ekleyin
  • Gerekirse dile dayalı yönlendirmeyi (routing) ayarlayın
  • LLM çeviri maliyetlerini izleyin

Sonuçlar

Bu sistemi uyguladıktan sonra:

  • 17 dil desteği kutudan çıktığı gibi
  • ~850 metin otomatik olarak çevrildi
  • Tam çeviri için $2-3 toplam maliyet
  • Yeni metinler eklendiğinde 2 dakikalık güncelleme döngüsü
  • Sıfır manuel çeviri işi
  • Bağlam duyarlı, yüksek kaliteli çeviriler

Şununla karşılaştırın:

  • İnsan çevirmenler: Kelime başına $0.10-0.30 = $1,000+
  • Geleneksel servisler: Hala pahalı, hala yavaş
  • Manuel iş: Ölçeklenemez

Bu Neden 2026'da Önemli?

Bakın, web global bir yer. Eğer 2026'da sadece İngilizce ship ediyorsanız, dünyanın %90'ını geride bırakıyorsunuz demektir.

Ama geleneksel i18n tam bir çile. Bu yaklaşım işi çocuk oyuncağına çeviriyor:

  1. Trans/t makrolarıyla kod yazın (2 saniye sürer)
  2. pnpm i18n çalıştırın (otomatik)
  3. Dünyaya ship edin (kazanç)

Lingui'nin geliştirici deneyimi + LLM destekli çevirilerin kombinasyonu oyunun kurallarını değiştiriyor. Şunlara sahip oluyorsunuz:

  • Tip güvenli çeviriler
  • Sıfır runtime yükü
  • Otomatik çıkarma (extraction)
  • Bağlam duyarlı AI çevirileri
  • Dil başına kuruş maliyet
  • Sonsuz ölçeklenebilirlik

Daha İleri Gitmek

Seviye atlamak mı istiyorsunuz? Şunları deneyin:

Dinamik İçerik Çevirisi

Çevirileri veritabanınızda saklayın:

// packages/db/schema/content.ts
export const blogPosts = pgTable("blog_post", {
  id: varchar("id", { length: 255 }).primaryKey(),
  titleEn: text("title_en"),
  titleZhCn: text("title_zh_cn"),
  titleJa: text("title_ja"),
  // ... vb
});

Kaydederken otomatik çevirin:

import { translateWithLLM } from "@acme/i18n";

export const blogRouter = createTRPCRouter({
  create: protectedProcedure
    .input(z.object({ title: z.string() }))
    .mutation(async ({ input }) => {
      // Tüm dillere çevir
      const translations = await Promise.all(
        LOCALES.map(async (locale) => {
          const result = await translateWithLLM(
            [{ msgid: input.title, msgstr: "" }],
            locale
          );
          return [locale, result[0].msgstr];
        })
      );

      await db.insert(blogPosts).values({
        id: generateId(),
        titleEn: input.title,
        ...Object.fromEntries(translations),
      });
    }),
});

Kullanıcı Tarafından Sağlanan Çeviriler

Kullanıcıların daha iyi çeviriler önermesine izin verin:

export const i18nRouter = createTRPCRouter({
  suggestTranslation: publicProcedure
    .input(z.object({
      msgid: z.string(),
      locale: z.string(),
      suggestion: z.string(),
    }))
    .mutation(async ({ input }) => {
      await db.insert(translationSuggestions).values(input);

      // Bakım yapanları (maintainers) bilgilendir
      await sendEmail({
        to: "i18n@acme.com",
        subject: `New translation suggestion for ${input.locale}`,
        body: `"${input.msgid}" → "${input.suggestion}"`,
      });
    }),
});

Çevirileri A/B Testi Yapmak

Hangi çevirilerin daha iyi dönüşüm sağladığını test edin:

const variant = await abTest.getVariant("pricing-cta", locale);

const ctaText = variant === "A"
  ? t`Start Your Free Trial`
  : t`Try acme Free`;

Kod

Bunların hepsi gerçek bir uygulamadan alınan production kodlarıdır. Tam implementasyon monorepo'muzda:

t3-acme-app/
├── apps/nextjs/
│   ├── lingui.config.ts
│   ├── src/
│   │   ├── locales/           # Derlenmiş kataloglar
│   │   ├── utils/i18n/        # i18n araçları
│   │   └── providers/         # LinguiClientProvider
│   └── script/i18n.ts         # Çeviri script'i
└── packages/i18n/
    └── src/
        ├── translateWithLLM.ts
        ├── enhanceTranslations.ts
        └── utils.ts

Son Düşünceler

2026'da çok dilli bir AI uygulaması geliştirmek artık zor değil. Araçlar burada:

  • Çıkarma ve runtime için Lingui
  • Bağlam duyarlı çeviri için Claude/GPT
  • Piyasadaki en iyi DX için T3 Turbo

Çeviriler için binlerce dolar ödemeyi bırakın. Uygulamanızı İngilizce ile sınırlamayı bırakın.

Global inşa edin. Hızlı ship edin. AI kullanın.

2026'da işleri böyle hallediyoruz.


Sorular? Sorunlar? Beni Twitter'da bulun veya Lingui dokümanlarına ve AI SDK dokümanlarına göz atın.

Şimdi gidin ve o çok dilli uygulamayı ship edin. Dünya sizi bekliyor.

Bunu paylaş

Feng Liu

Feng Liu

shenjian8628@gmail.com

2026'da i18n ve AI Destekli Modern Web Uygulaması Nasıl Geliştirilir? | Feng Liu