Next.js
مسیریاب app
برنامه تان را بسیازید
مسیریابی Routing
بین المللی سازی

بین المللی سازی

Next.js به شما این امکان را می‌دهد تا مسیریابی و رندر کردن محتوا را برای پشتیبانی از چندین زبان پیکربندی کنید. سازگاری سایت شما با مناطق مختلف شامل محتوای ترجمه شده (بومی‌سازی) و مسیرهای بین‌المللی می‌شود.

اصطلاحات

  • محلی (Locale): شناسه‌ای برای مجموعه‌ای از ترجیحات زبان و قالب‌بندی. این معمولاً شامل زبان ترجیحی کاربر و احتمالاً منطقه جغرافیایی آنها می‌شود.
    • en-US: انگلیسی به لهجه ایالات متحده
    • nl-NL: هلندی به لهجه هلند
    • nl: هلندی، بدون منطقه خاص

بررسی اجمالی مسیریابی

توصیه می‌شود از ترجیحات زبانی کاربر در مرورگر برای انتخاب محلی که باید استفاده شود، استفاده کنید. تغییر زبان ترجیحی شما هدر Accept-Language ورودی را در برنامه شما تغییر می‌دهد.

برای مثال، با استفاده از کتابخانه‌های زیر، می‌توانید یک درخواست Request ورودی را بررسی کنید تا مشخص کنید کدام منطقه را بر اساس Headers، مناطق پشتیبانی‌شده و منطقه پیش‌فرض انتخاب کنید.

middleware.js
import { match } from '@formatjs/intl-localematcher'
import Negotiator from 'negotiator'
 
let headers = { 'accept-language': 'en-US,en;q=0.5' }
let languages = new Negotiator({ headers }).languages()
let locales = ['en-US', 'nl-NL', 'nl']
let defaultLocale = 'en-US'
 
match(languages, locales, defaultLocale) // -> 'en-US'

مسیریابی را می‌توان با استفاده از زیرمسیر (مانند /fr/products) یا دامنه (مانند my-site.fr/products) بین‌المللی‌سازی کرد. با این اطلاعات، می‌توانید کاربر را بر اساس منطقه‌ی او درون میان افزار تغییر مسیر دهید.

middleware.js
import { NextResponse } from "next/server";
 
let locales = ['en-US', 'nl-NL', 'nl']
 
// Get the preferred locale, similar to the above or using a library
function getLocale(request) { ... }
 
export function middleware(request) {
  // Check if there is any supported locale in the pathname
  const { pathname } = request.nextUrl
  const pathnameHasLocale = locales.some(
    (locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`
  )
 
  if (pathnameHasLocale) return
 
  // Redirect if there is no locale
  const locale = getLocale(request)
  request.nextUrl.pathname = `/${locale}${pathname}`
  // e.g. incoming request is /products
  // The new URL is now /en-US/products
  return NextResponse.redirect(request.nextUrl)
}
 
export const config = {
  matcher: [
    // Skip all internal paths (_next)
    '/((?!_next).*)',
    // Optional: only run on root (/) URL
    // '/'
  ],
}

در نهایت، مطمئن شوید که همه فایل‌های خاص درون پوشه app/ زیرمجموعه app/[lang] قرار گرفته‌اند. این کار به مسیریاب Next.js اجازه می‌دهد تا به صورت داینامیک از مناطق مختلف در مسیر پشتیبانی کند و پارامتر lang را به تمام چیدمان‌ها و صفحات ارسال کند. برای نمونه:

app/[lang]/page.js
// You now have access to the current locale
// e.g. /en-US/products -> `lang` is "en-US"
export default async function Page({ params: { lang } }) {
  return ...
}

چیدمان ریشه (root layout) نیز می‌تواند درون پوشه جدید قرار داده شود (به عنوان مثال: app/[lang]/layout.js).

بومی‌سازی (Localization)

تغییر محتوای نمایش داده شده بر اساس منطقه‌ی ترجیحی کاربر، یا بومی‌سازی، مختص Next.js نیست. الگوهای شرح داده شده در زیر برای هر برنامه وب دیگری نیز به همین صورت عمل می‌کنند.

فرض کنید می‌خواهیم از محتوای انگلیسی و هلندی در برنامه خود پشتیبانی کنیم. ما ممکن است دو «فرهنگ لغت» متفاوت را نگهداری کنیم که اشیاءای هستند که نگاشت‌هایی از یک کلید به یک رشته محلی‌سازی شده به ما می‌دهند. برای نمونه:

dictionaries/en.json
{
	"products": {
		"cart": "Add to Cart"
	}
}
dictionaries/nl.json
{
	"products": {
		"cart": "Toevoegen aan Winkelwagen"
	}
}

سپس می‌توانیم تابعی به نام getDictionary برای بارگیری ترجمه‌های منطقه‌ی درخواستی ایجاد کنیم:

app/[lang]/dictionaries.js
import 'server-only'
 
const dictionaries = {
	en: () => import('./dictionaries/en.json').then((module) => module.default),
	nl: () => import('./dictionaries/nl.json').then((module) => module.default),
}
 
export const getDictionary = async (locale) => dictionaries[locale]()

با توجه به زبان انتخاب‌شده فعلی، می‌توانیم فرهنگ لغت را درون یک چیدمان یا صفحه فراخوانی کنیم.

app/[lang]/page.js
import { getDictionary } from './dictionaries'
 
export default async function Page({ params: { lang } }) {
	const dict = await getDictionary(lang) // en
	return <button>{dict.products.cart}</button> // Add to Cart
}

از آنجایی که همه چیدمان‌ها و صفحات در پوشه‌ی app/ به طور پیش‌فرض Server Components هستند، نیازی نیست نگران تأثیر اندازه‌ی فایل‌های ترجمه روی اندازه‌ی بسته‌ی JavaScript سمت کاربر باشیم. این کد فقط روی سرور اجرا می‌شود و تنها HTML حاصل‌شده برای مرورگر ارسال خواهد شد.

تولید ایستا Static Generation

برای تولید مسیرهای ایستا برای مجموعه‌ای از مناطق، می‌توانیم از generateStaticParams با هر صفحه یا چیدمانی استفاده کنیم. این می‌تواند به صورت کلی، مثلا در چیدمان اصلی، باشد:

app/[lang]/layout.js
export async function generateStaticParams() {
	return [{ lang: 'en-US' }, { lang: 'de' }]
}
 
export default function Root({ children, params }) {
	return (
		<html lang={params.lang}>
			<body>{children}</body>
		</html>
	)
}

منابع