ヘルプセンター

Lingui.jsローカリゼーション:POファイル、React i18n、および自動化

Lingui.jsは、JavaScriptおよびReactアプリケーション向けの軽量かつ強力な国際化(i18n)フレームワークです。翻訳カタログには業界標準のPO(Portable Object)ファイルを使用し、強力なコンパイル時マクロによって優れた開発者体験を提供し、2 kB未満の最適化されたバンドルを生成します。本ガイドでは、プロジェクトのセットアップからPOファイルのワークフロー、複数形、そしてl10n.devによる翻訳の自動化までを網羅しています。

なぜi18nにLingui.jsを選ぶのか?

Lingui.jsは、開発者体験、パフォーマンス、そしてプロフェッショナルな翻訳ワークフローの組み合わせにおいて、JavaScriptのi18nライブラリの中でも際立っています。

  • クリーンで読みやすい: JSXマクロを使用して自然に翻訳を記述できます。ライブラリは内部でそれらをICU MessageFormatにコンパイルします。
  • ユニバーサル: @lingui/coreはあらゆるJavaScriptプロジェクトで動作し、@lingui/reactはReact Server Components(RSC)サポートを含むReact固有のコンポーネントを追加します。
  • フルリッチテキストサポート: 翻訳可能なメッセージ内にReactコンポーネントをシームレスに使用できます。リンク、太字テキスト、アイコン、およびあらゆるJSXが完全にサポートされています。
  • POファイル形式: 事実上すべての翻訳ツール、TMS、プロの翻訳者ワークフローでサポートされている業界標準のPO形式を使用します。
  • 軽量で最適化: コアライブラリはGzip圧縮で2 kB未満、Reactコンポーネントはわずか1.3 kBの追加です。不要なデータはコンパイル時に削除されます。
  • AI翻訳に対応: Linguiのメッセージ説明とコンテキストコメントは、AI翻訳者が正確で文脈を理解した翻訳を行うために必要な情報を提供します。

インストール

Linguiのコアパッケージと開発ツールをインストールします。ランタイムパッケージ(@lingui/coreおよび@lingui/react)は本番環境で必要ですが、CLI、Viteプラグイン、Babelマクロは開発環境専用です。

npm install @lingui/core @lingui/react
npm install --save-dev @lingui/cli @lingui/vite-plugin @lingui/babel-plugin-lingui-macro

設定

Linguiには、Lingui設定(ロケールとカタログパスを定義)とビルドツール設定(コンパイル時マクロを有効にするため)の2つの設定ファイルが必要です。

Linguiの設定

プロジェクトのルートにlingui.config.jsファイルを作成します。ここで、ソースロケール、ターゲットロケール、POカタログの保存場所、およびカタログ形式を定義します。PO形式がデフォルトであり、推奨される選択肢です。

// lingui.config.js
import { defineConfig } from "@lingui/cli";
import { formatter } from "@lingui/format-po";

export default defineConfig({
  sourceLocale: "en",
  locales: ["en", "fr", "de", "ja", "es", "zh-CN"],
  catalogs: [
    {
      path: "<rootDir>/src/locales/{locale}/messages",
      include: ["src"],
    },
  ],
  format: formatter({ lineNumbers: false }),
});

Viteの設定

Viteを使用している場合は、BabelマクロとともにLinguiプラグインをReactプラグインと併せて追加します。これにより、コンパイル時のメッセージ変換とオンザフライでのカタログコンパイルが可能になります。

// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { lingui } from "@lingui/vite-plugin";

export default defineConfig({
  plugins: [
    react({
      babel: {
        plugins: ["@lingui/babel-plugin-lingui-macro"],
      },
    }),
    lingui(),
  ],
});

POファイル形式

PO(Portable Object)は、GNU gettextシステムに由来する業界標準の翻訳ファイル形式です。Linguiがデフォルトのカタログ形式としてPOを使用しているのは、世界中の翻訳ツール、TMSプラットフォーム、プロの翻訳者に広くサポートされているためです。

  • 読みやすさ: 大規模な翻訳ファイルであっても、明確なmsgid/msgstrペアにより人間が読みやすい状態を維持します。
  • 翻訳者用コメント: #. コメントをサポートしており、コンテキストの説明を翻訳者に直接伝えることができます。
  • ソース参照: 各メッセージには、コードベース内のどこで使用されているかを正確に示す #: ファイル:行 のコメントが含まれます。
  • コンテキストサポート: msgctxtを使用して、異なるコンテキストで異なる意味を持つ同一の文字列を区別できます。
  • ユニバーサルツールサポート: 事実上すべての翻訳管理システム(TMS)、CATツール、ローカリゼーションプラットフォームと互換性があります。

抽出されたPOファイル(ソースメッセージ)

#: src/components/WelcomeBanner.js:6
msgid "Welcome to our platform"
msgstr ""

#: src/components/WelcomeBanner.js:8
msgid "Hello {userName}, check out your <0>dashboard</0> to get started."
msgstr ""

#: src/components/CartSummary.js:5
msgid "{itemCount, plural, =0 {Your cart is empty} one {You have # item in your cart} other {You have # items in your cart}}"
msgstr ""

翻訳されたPOファイル(フランス語)

翻訳後、各msgstrにはローカライズされたバージョンが入力されます。Linguiは、すべての翻訳においてICU MessageFormat構文、Reactコンポーネントのインデックス付きタグ、およびプレースホルダー変数を保持します。

#: src/components/WelcomeBanner.js:6
msgid "Welcome to our platform"
msgstr "Bienvenue sur notre plateforme"

#: src/components/WelcomeBanner.js:8
msgid "Hello {userName}, check out your <0>dashboard</0> to get started."
msgstr "Bonjour {userName}, consultez votre <0>tableau de bord</0> pour commencer."

#: src/components/CartSummary.js:5
msgid "{itemCount, plural, =0 {Your cart is empty} one {You have # item in your cart} other {You have # items in your cart}}"
msgstr "{itemCount, plural, =0 {Votre panier est vide} one {Vous avez # article dans votre panier} other {Vous avez # articles dans votre panier}}"

プロジェクト構造

POカタログをlocalesディレクトリ内に、ロケールごとに1つのサブフォルダーを作成して整理します。Lingui CLIは、抽出中にこれらのファイルを自動的に作成および更新します。コンパイルされたJSモジュールはビルド時に生成されるため、手動で編集すべきではありません。

src/
├── locales/
│   ├── en/
│   │   └── messages.po       ← Source (English)
│   ├── fr/
│   │   └── messages.po       ← French
│   ├── de/
│   │   └── messages.po       ← German
│   ├── ja/
│   │   └── messages.po       ← Japanese
│   ├── es/
│   │   └── messages.po       ← Spanish
│   └── zh-CN/
│       └── messages.po       ← Chinese Simplified
├── components/
├── i18n.ts
├── App.tsx
└── ...

Reactコンポーネントの翻訳

Linguiは、メッセージをマークするために2つの主要なアプローチを提供します。コンポーネントコンテンツ用のJSXマクロと、命令的な文字列用のuseLinguiフックです。どちらも最適化された出力を生成するコンパイル時マクロです。

Transマクロ

JSXコンテンツをTransマクロでラップして翻訳可能にします。変数、HTML要素、Reactコンポーネントが完全にサポートされており、マクロはそれらを自動的にインデックス付きタグを持つICU MessageFormatに変換します。

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

function WelcomeBanner({ userName }) {
  return (
    <div>
      <h1>
        <Trans>Welcome to our platform</Trans>
      </h1>
      <p>
        <Trans>
          Hello {userName}, check out your <a href="/dashboard">dashboard</a> to
          get started.
        </Trans>
      </p>
    </div>
  );
}

useLinguiフック

JSX外の文字列(アラートメッセージ、ariaラベル、属性値、または命令的なコード)には、タグ付きテンプレートリテラルを使用するuseLinguiマクロフックを使用します。

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

function NotificationButton() {
  const { t } = useLingui();

  const showAlert = () => {
    alert(t`Your changes have been saved.`);
  };

  return (
    <button onClick={showAlert} aria-label={t`Save changes`}>
      <Trans>Save</Trans>
    </button>
  );
}

メッセージIDと説明

Linguiは、メッセージ識別に対して2つのアプローチをサポートしています。自動生成ID(ソースメッセージの内容から派生)と明示的ID(開発者が定義したキー)です。どちらのアプローチもPOファイルで機能します。

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

// Auto-generated ID (from message content)
<Trans>Welcome to our platform</Trans>

// Explicit ID (developer-defined key)
<Trans id="nav.welcome">Welcome to our platform</Trans>

翻訳者とAIのためのコンテキストの追加

マクロのcommentプロパティを使用して説明を追加します。このコメントは翻訳者へのメモとしてPOファイルに抽出され、メッセージがどこでどのように表示されるかについての重要なコンテキストを提供します。

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

<Trans comment="Shown on the homepage hero section above the fold">
  Start building with confidence
</Trans>
メッセージの説明は、AIを活用した翻訳において特に価値があります。これらは、AIが短いUI文字列を曖昧さなく理解するために必要なコンテキストを提供し、一般的な翻訳を正確で文脈を理解した翻訳へと変えます。

複数形

Linguiは複数形にICU MessageFormatを使用しており、すべてのCLDR複数形カテゴリをサポートしています。Pluralマクロを使用すると、JSX内で直接簡単に異なる複数形を扱うことができます。

  • value、one、other、およびオプションの正確な形式(_0、_2など)を持つPluralコンポーネントを使用します。
  • # プレースホルダーは、複数形の値に自動的に置き換えられます。
  • l10n.devは、アラビア語(6形式)、ロシア語、ポーランド語などの複雑な言語を含む、すべてのターゲット言語に必要なすべての複数形を、手動介入なしで生成します。
import { Plural } from "@lingui/react/macro";

function CartSummary({ itemCount }) {
  return (
    <p>
      <Plural
        value={itemCount}
        _0="Your cart is empty"
        one="You have # item in your cart"
        other="You have # items in your cart"
      />
    </p>
  );
}

ランタイム初期化

メッセージの抽出とコンパイルが完了したら、i18nインスタンスをセットアップし、アプリをI18nProviderでラップします。

i18nモジュールのセットアップ

コンパイルされたメッセージカタログを動的に読み込むi18nモジュールを作成します。Lingui ViteプラグインはPOファイルの直接インポートを可能にし、開発中にオンザフライでコンパイルされます。

// src/i18n.ts
import { i18n } from "@lingui/core";

export async function loadCatalog(locale: string) {
  const { messages } = await import(`./locales/${locale}/messages.po`);
  i18n.load(locale, messages);
  i18n.activate(locale);
}

// Initialize with default locale
loadCatalog("en");

export default i18n;

I18nProviderのセットアップ

アプリ全体をI18nProviderでラップし、Reactコンテキストを介してすべてのコンポーネントで翻訳を利用できるようにします。

// src/App.tsx
import { I18nProvider } from "@lingui/react";
import { i18n } from "./i18n";

function App() {
  return (
    <I18nProvider i18n={i18n}>
      <YourAppContent />
    </I18nProvider>
  );
}

ランタイムでの言語切り替え

言語の切り替えは簡単です。新しいカタログを読み込み、ロケールをアクティブにすると、Reactは自動的にすべての翻訳済みコンテンツを再レンダリングします。以下は完全な言語スイッチャーコンポーネントの例です。

import { useState } from "react";
import { loadCatalog } from "./i18n";
import { Trans } from "@lingui/react/macro";

const LANGUAGES = {
  en: "English",
  fr: "Français",
  de: "Deutsch",
  ja: "日本語",
  es: "Español",
};

function LanguageSwitcher() {
  const [currentLocale, setCurrentLocale] = useState("en");

  const handleChange = async (locale: string) => {
    await loadCatalog(locale);
    setCurrentLocale(locale);
  };

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

抽出とコンパイルのワークフロー

LinguiのCLIは、翻訳ワークフローの核となる2つの主要なコマンドを提供します。extractはソースコードからメッセージをPOカタログに抽出し、compileはPOファイルを本番用の最適化されたJavaScriptモジュールに変換します。

# Extract messages from source code into PO catalogs
npx lingui extract

# Translate your PO files (manually, with a TMS, or with AI)

# Compile PO catalogs into optimized JS modules for production
npx lingui compile
  1. 抽出:ソースファイルをスキャンし、翻訳可能なすべてのメッセージを含むPOカタログを作成または更新します。
  2. 翻訳:POファイルのmsgstrフィールドを、手動、TMS、またはAIを活用した翻訳で埋めます。
  3. コンパイル:POカタログをランタイムで読み込まれる軽量なJSモジュールに変換します。翻訳されたメッセージのみが含まれます。

l10n.devでの完全なPOサポート

l10n.devはPOファイルのネイティブサポートを提供しており、Lingui.jsプロジェクトの完璧なパートナーです。ソースPOカタログをアップロードして、正確に翻訳されたファイルを受け取ります。

  • ネイティブPO形式: POファイルを直接アップロードします。l10n.devはmsgidエントリを読み取り、翻訳し、正しいmsgstr値を持つ適切にフォーマットされたPOファイルを書き戻します。
  • ICU MessageFormat対応: プレースホルダー({name})、インデックス付きタグ(<0>)、複数形、およびselect式は、すべての翻訳を通じて正しく保持されます。
  • 文脈を理解したAI翻訳: 翻訳者用コメント(#.)とメッセージコンテキスト(msgctxt)は、より正確で文脈を理解した翻訳を生成するためにAIによって使用されます。
  • 複数形の生成: すべてのターゲット言語に必要なすべてのCLDR複数形が生成されます。複雑な複数形ルールを持つ言語(アラビア語、ロシア語、ポーランド語)は自動的に処理されます。
  • バッチおよび増分更新: カタログ全体を一度に翻訳するか、--updateフラグを使用して新規および変更されたメッセージのみを翻訳し、既存の翻訳を保持します。

npmによる翻訳の自動化

ai-l10n npmパッケージを使用して、コマンドラインから、またはCI/CDパイプラインの一部としてLingui POカタログを翻訳します。一度インストールすれば、単一のコマンドで任意の数の言語に翻訳できます。

# Install the CLI
npm install ai-l10n

# Translate your source PO file to multiple languages
npx ai-l10n translate src/locales/en/messages.po \
  --languages fr,de,ja,zh-CN,es,ko

ビルドプロセスへの統合

ai-l10nをLinguiビルドプロセスに直接組み込み、翻訳が常に最新の状態になるようにします。抽出、翻訳、コンパイルを単一のワークフローにまとめます。

package.jsonスクリプト経由

抽出、翻訳、コンパイルをスクリプトとして追加し、それらを連結します。i18nスクリプトはパイプライン全体を実行します。出荷前に翻訳が常に最新であることを保証するために、prebuildで使用してください。

{
  "scripts": {
    "extract": "lingui extract",
    "compile": "lingui compile",
    "translate": "ai-l10n translate src/locales/en/messages.po --languages fr,de,ja,zh-CN,es,ko --update",
    "i18n": "npm run extract && npm run translate && npm run compile",
    "prebuild": "npm run i18n",
    "build": "vite build",
    "dev": "vite"
  }
}

Makefile経由

チームがMakeを使用している場合は、抽出、翻訳、コンパイルを適切な依存関係を持つ個別のターゲットとして宣言します。

LANGUAGES = fr,de,ja,zh-CN,es,ko

extract:
	npx lingui extract

translate:
	npx ai-l10n translate src/locales/en/messages.po --languages $(LANGUAGES) --update

compile:
	npx lingui compile

i18n: extract translate compile

dev: i18n
	npx vite

build: i18n
	npx vite build

CI/CD統合、増分更新、複数ファイルにわたるバッチ翻訳、およびGitHub Actionsワークフローの例については、ローカリゼーション自動化ガイド

VS Code拡張機能

l10n.devのVS Code拡張機能は、POファイルの翻訳をエディタに直接もたらします。VS Codeを離れることなくLinguiカタログを翻訳できます。

VS Codeでの仕組み:

  1. エディタでソースPOファイル(例:src/locales/en/messages.po)を開きます。
  2. エディタ内で右クリックし、「Translate...」を選択します(POファイルでも動作します)。
  3. 1つ以上のターゲット言語(例:フランス語、日本語、ドイツ語)を選択します。
  4. 拡張機能は、対応するロケールフォルダーに翻訳されたPOファイルを作成し、コンパイル可能な状態にします。

LinguiでReactアプリのローカライズを開始する

世界中のユーザーにリーチする準備はできましたか?Lingui POファイルをl10n.devワークスペースで直接翻訳するか、npm CLIで自動化するか、VS Code内で翻訳しましょう。