تكامل Next.js

يتكامل @lingo.dev/compiler مع Next.js App Router من خلال غلاف تكوين غير متزامن يدعم كلاً من Webpack وTurbopack.

الإعداد

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

تتلقى مكونات العميل حزم ترجمة محسّنة. يتم تضمين الترجمات المستخدمة في ذلك المكون فقط.

اكتشاف اللغة

بشكل افتراضي، يتم تخزين اللغة في ملف تعريف ارتباط (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());
}

راجع محللات اللغة المخصصة لمزيد من التفاصيل.

middleware للتوجيه حسب اللغة

إذا كنت تريد التوجيه حسب اللغة (/en/about، /es/about)، قم بتنفيذ middleware في 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",
};

المشاكل الشائعة

"Cannot find module '@lingo.dev/compiler/react'" تأكد من تثبيت الحزمة: pnpm install @lingo.dev/compiler

HMR لا يعمل بعد إضافة LingoProvider تأكد من وضع LingoProvider بشكل صحيح في التخطيط الجذري، وليس في تخطيط متداخل أو صفحة.

الترجمات لا تظهر في بناء الإنتاج تحقق من أنك تستخدم buildMode: "cache-only" وأن .lingo/metadata.json يحتوي على ترجمات لجميع اللغات.

"Missing translations for locale X" شغّل خادم التطوير الخاص بك مع usePseudotranslator: false لإنشاء ترجمات حقيقية، أو قم بتشغيل بناء CI لملء .lingo/metadata.json.

الخطوات التالية