Next.js統合
@lingo.dev/compilerは、WebpackとTurbopackの両方をサポートする非同期設定ラッパーを通じてNext.js App Routerと統合されます。
セットアップ
1. パッケージのインストール
pnpm install @lingo.dev/compiler
2. Next.jsの設定
next.config.tsを更新して、非同期withLingo()ラッパーを使用します:
import type { NextConfig } from "next";
import { withLingo } from "@lingo.dev/compiler/next";
const nextConfig: NextConfig = {
// Your existing Next.js config
};
export default async function (): Promise<NextConfig> {
return await withLingo(nextConfig, {
sourceRoot: "./app",
sourceLocale: "en",
targetLocales: ["es", "de", "fr"],
models: "lingo.dev",
dev: {
usePseudotranslator: true,
},
});
}
なぜ非同期なのか? ラッパーはプラグインを遅延ロードし、設定を動的に解決します。これによりビルドを高速に保ち、条件付きプラグインロードを可能にします。
3. プロバイダーの追加
ルートレイアウトでLingoProviderを使用してアプリをラップします:
// app/layout.tsx
import { LingoProvider } from "@lingo.dev/compiler/react";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<LingoProvider>
<html>
<body>{children}</body>
</html>
</LingoProvider>
);
}
重要: LingoProviderは<html>の内側に配置し、すべてのコンテンツをラップします。サーバーコンポーネントとクライアントコンポーネントの両方で動作します。
Reactサーバーコンポーネント
コンパイラはReactサーバーコンポーネント(RSC)を完全にサポートしています。サーバーコンポーネントはビルド時に翻訳され、翻訳はサーバー出力に埋め込まれます。
// app/page.tsx (Server Component)
export default function Page() {
return (
<div>
<h1>Welcome to our app</h1>
<p>This is a server component—translated at build time</p>
</div>
);
}
サーバーコンポーネント内の翻訳されたテキストに対して、クライアント側のJavaScriptは追加されません。
クライアントコンポーネント
クライアントコンポーネントの場合は、"use client"ディレクティブを使用します:
"use client";
import { useLingoContext } from "@lingo.dev/compiler/react";
export function LanguageSwitcher() {
const { locale, setLocale } = useLingoContext();
return (
<select value={locale} onChange={(e) => setLocale(e.target.value)}>
<option value="en">English</option>
<option value="es">Español</option>
<option value="de">Deutsch</option>
</select>
);
}
クライアントコンポーネントは最適化された翻訳バンドルを受け取ります。そのコンポーネントで使用される翻訳のみが含まれます。
ロケール検出
デフォルトでは、ロケールはCookie(locale)に保存されます。コンパイラは自動的にロケール検出と永続化を処理します。
カスタムサーバーロケール検出
カスタムロジック(データベース、ヘッダー、サブドメイン)の場合は、.lingo/locale-resolver.server.tsを作成します:
// .lingo/locale-resolver.server.ts
import { headers } from "next/headers";
export async function getServerLocale(): Promise<string> {
const headersList = await headers();
const acceptLanguage = headersList.get("accept-language");
// Parse accept-language header
const locale = acceptLanguage?.split(",")[0]?.split("-")[0] || "en";
return locale;
}
この関数は、すべてのリクエストに対してサーバー上で呼び出されます。ロケールコード(例:"en"、"es")を返す必要があります。
カスタムクライアントロケール永続化
カスタムクライアント側ロジック(localStorage、URLパラメータ)の場合、.lingo/locale-resolver.client.tsを作成します:
// .lingo/locale-resolver.client.ts
export function getClientLocale(): string {
// Check URL parameter first
const params = new URLSearchParams(window.location.search);
const urlLocale = params.get("lang");
if (urlLocale) return urlLocale;
// Fall back to localStorage
return localStorage.getItem("locale") || "en";
}
export function persistLocale(locale: string): void {
localStorage.setItem("locale", locale);
// Optionally update URL
const url = new URL(window.location.href);
url.searchParams.set("lang", locale);
window.history.replaceState({}, "", url.toString());
}
詳細については、カスタムロケールリゾルバーを参照してください。
ロケールルーティング用ミドルウェア
ロケールベースのルーティング(/en/about、/es/about)が必要な場合は、Next.jsミドルウェアを実装します:
// middleware.ts
import { NextRequest, NextResponse } from "next/server";
const locales = ["en", "es", "de", "fr"];
const defaultLocale = "en";
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
// Check if pathname already has a locale
const pathnameHasLocale = locales.some(
(locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`
);
if (pathnameHasLocale) return;
// Get locale from cookie or accept-language header
const localeCookie = request.cookies.get("locale")?.value;
const acceptLanguage = request.headers.get("accept-language");
const locale =
localeCookie ||
acceptLanguage?.split(",")[0]?.split("-")[0] ||
defaultLocale;
// Redirect to localized pathname
request.nextUrl.pathname = `/${locale}${pathname}`;
return NextResponse.redirect(request.nextUrl);
}
export const config = {
matcher: ["/((?!api|_next|_vercel|.*\\..*).*)"],
};
ルートを更新して[locale]動的セグメントを使用します:
app/
[locale]/
page.tsx
about/
page.tsx
layout.tsx
ビルド設定
開発ビルド
{
dev: {
usePseudotranslator: true, // Fast fake translations
}
}
npm run devを実行して、即座に疑似翻訳を使用した開発サーバーを起動します。
本番ビルド
{
buildMode: "cache-only", // Use pre-generated translations
}
npm run buildを実行して本番用にビルドします。APIキーは不要です。翻訳は.lingo/metadata.jsonから取得されます。
**ベストプラクティス:**本番用にビルドする前に、CIで実際の翻訳を生成してください。推奨されるワークフローについては、ビルドモードを参照してください。
Turbopackサポート
コンパイラーはWebpackとTurbopack(Next.js 15以降)の両方で動作します。
開発環境でTurbopackを使用するには:
next dev --turbo
コンパイラーは適切なバンドラーを自動的に検出して設定します。
TypeScript
コンパイラは完全に型付けされています。@lingo.dev/compilerから型をインポートしてください:
import type { LingoConfig } from "@lingo.dev/compiler";
const config: LingoConfig = {
sourceRoot: "./app",
sourceLocale: "en",
targetLocales: ["es", "de"],
models: "lingo.dev",
};
よくある問題
「モジュール'@lingo.dev/compiler/react'が見つかりません」
パッケージがインストールされていることを確認してください: pnpm install @lingo.dev/compiler
LingoProviderを追加後、HMRが動作しない
LingoProviderがルートレイアウトに正しく配置されており、ネストされたレイアウトやページに配置されていないことを確認してください。
本番ビルドで翻訳が表示されない
buildMode: "cache-only"を使用していること、および.lingo/metadata.jsonにすべてのロケールの翻訳が含まれていることを確認してください。
「ロケールXの翻訳が見つかりません」
開発サーバーをusePseudotranslator: falseで実行して実際の翻訳を生成するか、CIビルドを実行して.lingo/metadata.jsonに翻訳を追加してください。
次のステップ
- 設定リファレンス — すべての設定オプション
- カスタムロケールリゾルバー — ロケール検出のカスタマイズ
- 手動オーバーライド — 特定の翻訳のオーバーライド
- ベストプラクティス — 推奨されるパターンとワークフロー