如何在 2026 年打造 AI 驅動的 i18n 現代化 Web App

結合 Lingui 與 AI 翻譯打造多語系 Web App 的完整指南。利用 Next.js、Claude 和 T3 Turbo 技術堆疊,實現自動化支援 17 種語言。

如何在 2026 年打造 AI 驅動的 i18n 現代化 Web App
Feng LiuFeng Liu
2026年1月24日

標題:聽我說,我們真的得聊聊 2026 年的 i18n

內容:

聽著,我們得談談 2026 年的 i18n(國際化)。

大多數的教學還是會告訴你要手動翻譯字串、聘請翻譯人員,或是使用一些蹩腳的 Google Translate API。但問題是:你現在可是生活在 Claude Sonnet 4.5 的時代。為什麼你還在用 2019 年的方式做翻譯?

我要展示給你看,我們如何構建一個能流利說 17 種語言的正式環境 Web App,而且使用的是一個真正合理的兩段式 i18n 架構:

  1. Lingui:負責提取(extraction)、編譯(compilation)和執行階段(runtime)的魔法。
  2. 自定義 i18n 套件:由 LLM 驅動,負責自動化、具備語境意識(context-aware)的翻譯。

我們的技術堆疊(Stack)?Create T3 Turbo 搭配 Next.js、tRPC、Drizzle、Postgres、Tailwind 以及 AI SDK。如果你在 2026 年還沒用這套,那我們得好好聊聊了。

開始動手吧。


傳統 i18n 的問題

傳統的 i18n 工作流程通常長這樣:

# 提取字串
$ lingui extract

# ??? 想辦法弄到翻譯 ???
# (聘請翻譯、使用可疑的服務、崩潰大哭)

# 編譯
$ lingui compile

中間那個步驟?簡直是場惡夢。你通常面臨三種選擇:

  • 花大錢請人工翻譯(又慢又貴)
  • 使用基本的翻譯 API(缺乏語境,讀起來像機器人)
  • 手動翻譯(無法規模化)

我們有更好的做法。


兩段式架構

這是我們的設置:

┌─────────────────────────────────────────────┐
│  Next.js App (Lingui Integration)           │
│  ├─ 使用 macros 提取字串                     │
│  ├─ 程式碼中的 Trans/t 元件                  │
│  └─ 使用編譯後的 catalogs 進行執行階段 i18n    │
└─────────────────────────────────────────────┘
              ↓ 生成 .po 檔案
┌─────────────────────────────────────────────┐
│  @acme/i18n Package (LLM Translation)       │
│  ├─ 讀取 .po 檔案                            │
│  ├─ 使用 Claude/GPT-5 進行批次翻譯            │
│  ├─ 具備語境意識、針對產品優化                 │
│  └─ 寫入翻譯後的 .po 檔案                     │
└─────────────────────────────────────────────┘
              ↓ 編譯為 TypeScript
┌─────────────────────────────────────────────┐
│  Compiled Message Catalogs                  │
│  └─ 快速、型別安全的執行階段翻譯               │
└─────────────────────────────────────────────┘

第一部分 (Lingui) 處理開發者體驗 (DX)。 第二部分 (自定義 i18n 套件) 處理翻譯的魔法。

讓我們深入探討每一個部分。


Technical flow diagram: web UI → AI translation cloud → database, three tiers connected by arrows

第一部分:在 Next.js 中設置 Lingui

安裝

在你的 T3 Turbo monorepo 中:

# 在 apps/nextjs 目錄下
pnpm add @lingui/core @lingui/react @lingui/macro
pnpm add -D @lingui/cli @lingui/swc-plugin

Lingui 設定

建立 apps/nextjs/lingui.config.ts

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;

開箱即用支援 17 種語言。 為什麼不呢?

Next.js 整合

更新 next.config.js 以使用 Lingui 的 SWC plugin:

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

module.exports = {
  experimental: {
    swcPlugins: [
      [
        "@lingui/swc-plugin",
        {
          // 這能讓你的構建速度更快
        },
      ],
    ],
  },
  // ... 其他設定
};

伺服器端設置 (Server-Side Setup)

建立 src/utils/i18n/appRouterI18n.ts

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>>();

// 為所有語系預先建立 i18n 實例
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")!;
}

為什麼這樣做? Server Components 沒有 React Context。這能讓你在伺服器端進行翻譯。

客戶端 Provider (Client-Side Provider)

建立 src/providers/LinguiClientProvider.tsx

"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>;
}

layout.tsx 中包裹你的 App:

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>
  );
}

在程式碼中使用翻譯

在 Server Components 中:

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 Components 中:

"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>

      {/* 帶有變數的情況 */}
      <p>{t`${credits} credits remaining`}</p>
    </div>
  );
}

Macro 語法是關鍵。 Lingui 會在構建時(build time)提取這些字串。


第二部分:AI 驅動的翻譯套件

這裡開始變得有趣了。

套件結構

建立 packages/i18n/

packages/i18n/
├── package.json
├── src/
│   ├── translateWithLLM.ts      # 核心 LLM 翻譯邏輯
│   ├── enhanceTranslations.ts   # 批次處理器
│   └── utils.ts                 # 輔助工具

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 翻譯引擎

這是我們的獨門秘方 —— 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, // 數值越低 = 越穩定
  });

  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",
    // ... 等等
  };
  return names[locale] ?? locale;
}

為什麼這行得通:

  • 語境意識 (Context-aware):LLM 知道 acme 是什麼。
  • 結構化輸出:Zod schema 確保 JSON 格式有效。
  • 低溫度 (Low temperature):翻譯結果一致且穩定。
  • 保留格式:HTML 和變數都能保持原樣。

批次翻譯處理器

建立 enhanceTranslations.ts

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

const BATCH_SIZE = 30; // 一次翻譯 30 個字串
const DELAY_MS = 1000; // 速率限制

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"));

  // 找出未翻譯的項目
  const untranslated = po.items.filter(
    (item) => item.msgid && (!item.msgstr || item.msgstr[0] === "")
  );

  if (untranslated.length === 0) {
    console.log(`✓ ${locale}: 所有字串已翻譯`);
    return;
  }

  console.log(`正在為 ${locale} 翻譯 ${untranslated.length} 個字串...`);

  // 批次處理
  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 檔案
      translations.forEach((translation, index) => {
        const item = batch[index];
        if (item) {
          item.msgstr = [translation.msgstr];
        }
      });

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

      // 儲存進度
      fs.writeFileSync(poPath, po.toString());

      // 速率限制
      if (i + BATCH_SIZE < untranslated.length) {
        await new Promise((resolve) => setTimeout(resolve, DELAY_MS));
      }
    } catch (error) {
      console.error(`  翻譯批次時發生錯誤: ${error}`);
      // 繼續下一個批次
    }
  }

  console.log(`✓ ${locale}: 翻譯完成!`);
}

批次處理可以避免觸發 token 限制並節省成本。

翻譯腳本

建立 apps/nextjs/script/i18n.ts

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() {
  // 步驟 1: 從程式碼中提取字串
  console.log("📝 正在提取字串...");
  await execAsync("pnpm run lingui:extract --clean");

  // 步驟 2: 自動翻譯缺失的字串
  console.log("\n🤖 正在使用 AI 進行翻譯...");
  const catalogPath = "./src/locales";

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

  // 步驟 3: 編譯為 TypeScript
  console.log("\n⚡ 正在編譯 catalogs...");
  await execAsync("npx lingui compile --typescript");

  console.log("\n✅ 完成!所有翻譯已更新。");
}

main().catch(console.error);

加入到 package.json

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

執行你的 i18n 流程

# 一個指令搞定所有事
$ pnpm run i18n

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

🤖 正在使用 AI 進行翻譯...
正在為 zh_CN 翻譯 123 個字串...
  30/123 已翻譯
  60/123 已翻譯
  90/123 已翻譯
  123/123 已翻譯
✓ zh_CN: 翻譯完成!

⚡ 正在編譯 catalogs...
✅ 完成!所有翻譯已更新。

就這樣。 在程式碼中加入新字串,執行 pnpm i18n,砰 —— 自動翻譯成 17 種語言。


Before/after split screen: left shows stressed developer with translation papers and $1000 bill

語言切換 (Locale Switching)

別忘了使用者體驗的部分。這是一個語言切換器:

"use client";

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

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

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 的實作:

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

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

export function useLocaleSwitcher() {
  const switchLocale = (locale: string) => {
    setUserLocale(locale);
    window.location.reload(); // 強制重新整理以套用語言
  };

  return { switchLocale };
}

將偏好設定儲存在 cookie 中:

// 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 年
  });
}

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

進階:型別安全的翻譯

想要型別安全 (Type Safety) 嗎?Lingui 幫你搞定:

// 不要這樣寫:
t`Hello ${name}`

// 使用 msg descriptor:
import { msg } from "@lingui/core/macro";

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

你的 IDE 會自動補全翻譯鍵值 (translation keys)。太完美了。


效能考量

1. 在構建時編譯 (Compile at Build Time)

Lingui 會將翻譯編譯成最小化的 JSON。沒有執行階段的解析開銷。

// 編譯後的輸出 (minified):
export const messages = JSON.parse('{"ICt8/V":["视频"],"..."}');

2. 預先載入 Server Catalogs

在啟動時載入所有 catalogs(見上方的 appRouterI18n.ts)。不需要在每次請求時進行檔案 I/O。

3. 客戶端 Bundle 大小

只傳送當前活躍的語系給客戶端:

<LinguiClientProvider
  locale={locale}
  messages={allMessages[locale]} // 只傳送一個語系
>

4. LLM 成本優化

  • 批次翻譯:每次 API 呼叫處理 30 個字串
  • 快取翻譯:不重複翻譯未變更的字串
  • 使用較便宜的模型:對於非關鍵語言使用 GPT-4o-mini

我們的成本?800+ 個字串 × 16 種語言,大約 2-3 美元。跟人工翻譯比起來簡直是零頭。


完整技術堆疊整合

讓我們看看這如何與 T3 Turbo 的其他部分協作:

tRPC 與 i18n

// 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 }) => {
      // 錯誤訊息也可以翻譯!
      if (!ctx.session?.user) {
        throw new TRPCError({
          code: "UNAUTHORIZED",
          message: ctx.i18n._(msg`You must be logged in`),
        });
      }

      // ... 訂閱邏輯
    }),
});

透過 context 傳遞 i18n 實例:

// 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

儲存使用者的語言偏好:

// 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"),
  // ... 其他欄位
});

AI SDK 整合

即時翻譯 AI 的回應:

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 };
}

我們學到的最佳實踐

1. 永遠使用 Macros

// ❌ 壞習慣:執行階段翻譯 (不會被提取)
const text = t("Hello world");

// ✅ 好習慣:Macro (會在構建時被提取)
const text = t`Hello world`;

2. 語境就是一切

為翻譯人員(或 AI)添加註解:

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

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

Lingui 會將這些提取為翻譯註解。

3. 正確處理複數

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

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

不同語言有不同的複數規則。Lingui 會處理這些。

4. 日期/數字格式化

使用 Intl API:

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 支援

對於阿拉伯語,處理文字方向:

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 config:

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

使用方向性 class:

<div className="ms-4"> {/* margin-start, 同時適用於 LTR/RTL */}

部署檢查清單

在你發布之前:

  • 執行 pnpm i18n 確保所有翻譯都是最新的
  • 在正式環境模式下測試每個語系
  • 驗證 locale cookie 的持久性
  • 檢查阿拉伯語的 RTL 版面配置
  • 測試語言切換器的 UX
  • 為 SEO 加入 hreflang 標籤
  • 如果需要,設定基於語系的路由 (locale-based routing)
  • 監控 LLM 翻譯成本

結果

實施這套系統後:

  • 開箱即用支援 17 種語言
  • ~850 個字串 自動翻譯
  • 總成本 2-3 美元 完成全站翻譯
  • 2 分鐘更新週期 當加入新字串時
  • 零手動翻譯工作
  • 具備語境意識的高品質翻譯

對比一下:

  • 人工翻譯:每個字 0.10-0.30 美元 = 1,000 美元以上
  • 傳統服務:依然昂貴,依然緩慢
  • 手動工作:無法規模化

為什麼這在 2026 年很重要

聽著,網路是全球性的。如果你在 2026 年只發布英文版,你就拋棄了世界上 90% 的用戶。

但傳統的 i18n 實在太痛苦了。這個方法讓它變得微不足道

  1. 用 Trans/t macros 寫程式碼(花 2 秒鐘)
  2. 執行 pnpm i18n(自動化)
  3. 發布給全世界(然後獲利)

Lingui 的開發者體驗 + LLM 驅動的翻譯 的結合徹底改變了遊戲規則。你將獲得:

  • 型別安全的翻譯
  • 零執行階段開銷
  • 自動提取
  • 具備語境意識的 AI 翻譯
  • 每個語言只需幾分錢
  • 無限擴展

更進一步

想更上一層樓嗎?試試這些:

動態內容翻譯

將翻譯儲存在資料庫中:

// 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"),
  // ... 等等
});

儲存時自動翻譯:

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

export const blogRouter = createTRPCRouter({
  create: protectedProcedure
    .input(z.object({ title: z.string() }))
    .mutation(async ({ input }) => {
      // 翻譯成所有語言
      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),
      });
    }),
});

使用者提供的翻譯

讓使用者提交更好的翻譯:

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);

      // 通知維護者
      await sendEmail({
        to: "i18n@acme.com",
        subject: `New translation suggestion for ${input.locale}`,
        body: `"${input.msgid}" → "${input.suggestion}"`,
      });
    }),
});

A/B 測試翻譯

測試哪種翻譯的轉換率更高:

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

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

程式碼

所有這些都是來自真實 App 的正式環境程式碼。完整的實作在我們的 monorepo 中:

t3-acme-app/
├── apps/nextjs/
│   ├── lingui.config.ts
│   ├── src/
│   │   ├── locales/           # 編譯後的 catalogs
│   │   ├── utils/i18n/        # i18n 工具
│   │   └── providers/         # LinguiClientProvider
│   └── script/i18n.ts         # 翻譯腳本
└── packages/i18n/
    └── src/
        ├── translateWithLLM.ts
        ├── enhanceTranslations.ts
        └── utils.ts

最後的想法

在 2026 年構建多語言 AI App 已經不再困難。工具都準備好了:

  • Lingui 負責提取和執行階段
  • Claude/GPT 負責具備語境意識的翻譯
  • T3 Turbo 提供最佳的開發者體驗

別再花幾千美元做翻譯了。別再把你的 App 限制在只有英文了。

做全球化產品。快速發布。善用 AI。

這就是我們在 2026 年的做法。


有問題?發現錯誤?在 Twitter 上找我,或是查看 Lingui 文件AI SDK 文件

現在,去發布那個多語言 App 吧。世界正在等著你。

摘要: 本文介紹了如何在 2026 年利用 Claude/GPT 等 LLM 技術與 Lingui 框架,構建一套自動化、低成本且高品質的 Web App 多語言(i18n)系統。作者劉峰分享了基於 T3 Turbo Stack 的實戰架構,展示如何透過 AI 解決傳統翻譯流程昂貴且緩慢的痛點,實現 17 種語言的快速部署與自動更新。

分享

Feng Liu

Feng Liu

shenjian8628@gmail.com

如何在 2026 年打造 AI 驅動的 i18n 現代化 Web App | 劉峰