Next.js / i18n үндэс

i18n үндэс

i18n (internationalization) гэдэг нь аппыг олон хэлэнд дэмжих чадвар юм. Монгол хөгжүүлэгчийн хувьд энэ ойлголт маш практик — та Монгол болон Англи хэлтэй апп хийхийг хүсвэл яг энэ аргыг хэрэглэнэ. Next.js App Router нь middleware болон dynamic segment ашиглан i18n-г тохируулах боломж олгодог.

Locale бүтэц тохируулах

Хамгийн энгийн арга бол URL-д locale оруулах явдал юм — /mn/courses, /en/courses гэх мэт. Үүнийг [locale] dynamic segment болон middleware-ээр хийнэ:

код
app/
├── [locale]/
│   ├── layout.tsx
│   ├── page.tsx
│   └── courses/
│       └── page.tsx
├── middleware.ts
└── lib/
    └── i18n.ts

Эхлээд locale-уудаа тодорхойлно:

typescript
// lib/i18n.ts
export const locales = ["mn", "en"] as const;
export type Locale = (typeof locales)[number];
export const defaultLocale: Locale = "mn";

export function isValidLocale(value: string): value is Locale {
  return (locales as readonly string[]).includes(value);
}

Middleware ашиглан чиглүүлэх

Middleware нь хэрэглэгчийг зөв locale руу автоматаар чиглүүлдэг:

typescript
// middleware.ts
import { NextRequest, NextResponse } from "next/server";
import { defaultLocale, isValidLocale, locales } from "@/lib/i18n";

export function middleware(request: NextRequest): NextResponse {
  const pathname = request.nextUrl.pathname;

  // locale аль хэдийн байгаа эсэхийг шалгана
  const pathnameHasLocale = locales.some(
    (locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`,
  );

  if (pathnameHasLocale) return NextResponse.next();

  // Browser-н хэл унших
  const acceptLanguage = request.headers.get("accept-language") ?? "";
  const preferredLocale = acceptLanguage.startsWith("mn")
    ? "mn"
    : defaultLocale;

  const redirectUrl = new URL(`/${preferredLocale}${pathname}`, request.url);
  return NextResponse.redirect(redirectUrl);
}

export const config = {
  matcher: ["/((?!api|_next|public|favicon.ico).*)"],
};

Орчуулгын файл үүсгэх

Хэлний текстийг JSON файлд хадгална:

json
// locales/mn.json
{
  "nav": {
    "courses": "Сургалтууд",
    "projects": "Төслүүд",
    "profile": "Профайл"
  },
  "home": {
    "title": "Кодлохыг монголоор сур",
    "subtitle": "Дэлхийн хамгийн шилдэг технологийг эх хэлээрээ эзэмш."
  },
  "course": {
    "free": "Үнэгүй",
    "pro": "Pro",
    "start": "Эхлэх",
    "continue": "Үргэлжлүүлэх"
  }
}
json
// locales/en.json
{
  "nav": {
    "courses": "Courses",
    "projects": "Projects",
    "profile": "Profile"
  },
  "home": {
    "title": "Learn to code in Mongolian",
    "subtitle": "Master world-class technology in your native language."
  },
  "course": {
    "free": "Free",
    "pro": "Pro",
    "start": "Start",
    "continue": "Continue"
  }
}

Layout болон Page дотор locale ашиглах

tsx
// app/[locale]/layout.tsx
import { Locale, isValidLocale, defaultLocale } from "@/lib/i18n";
import { notFound } from "next/navigation";

interface LocaleLayoutProps {
  children: React.ReactNode;
  params: Promise<{ locale: string }>;
}

export default async function LocaleLayout({
  children,
  params,
}: LocaleLayoutProps) {
  const { locale } = await params;

  if (!isValidLocale(locale)) notFound();

  return (
    <html lang={locale}>
      <body>{children}</body>
    </html>
  );
}
tsx
// app/[locale]/page.tsx
import mn from "@/locales/mn.json";
import en from "@/locales/en.json";
import { Locale } from "@/lib/i18n";

const translations = { mn, en };

interface HomePageProps {
  params: Promise<{ locale: Locale }>;
}

export default async function HomePage({ params }: HomePageProps) {
  const { locale } = await params;
  const t = translations[locale];

  return (
    <main>
      <h1>{t.home.title}</h1>
      <p>{t.home.subtitle}</p>
    </main>
  );
}

generateStaticParams ашиглах

Build хийх үед бүх locale-н хуудсыг урьдчилан үүсгэхийн тулд generateStaticParams хэрэглэнэ:

tsx
// app/[locale]/page.tsx
import { locales } from "@/lib/i18n";

export function generateStaticParams() {
  return locales.map((locale) => ({ locale }));
}

| Зүйл | Тайлбар | | ---------------------- | ------------------------------------ | | [locale] segment | URL-д хэл оруулах | | middleware.ts | Автоматаар locale руу чиглүүлэх | | JSON файл | Орчуулгын текст хадгалах | | generateStaticParams | Build үед бүх locale pre-render хийх |

Энэ бол хамгийн хялбар i18n хэрэгжүүлэлт — нэмэлт library суулгахгүйгээр Next.js-н built-in чадамжаар олон хэл дэмждэг апп хийж болно.

Дараагийн хичээлд:

Next.js аппыг хэрхэн тест хийхийг сурна. Unit test, component test, integration test бичих аргуудыг практикаар дадлагажина.