Sorunuzu sorun ve bu sayfaya ve seçtiğiniz AI sağlayıcısına referans vererek belgenin bir özetini alın
Intlayer MCP Sunucusunu favori AI asistanınıza entegre ederek tüm belgeleri doğrudan ChatGPT, DeepSeek, Cursor, VSCode vb. üzerinden alabilirsiniz.
MCP Sunucu belgesini görüntüleBu sayfanın içeriği bir yapay zeka kullanılarak çevrildi.
Orijinal içeriğin İngilizce son sürümünü görüntüleyinBu dokümantasyonu geliştirmek için bir fikriniz varsa, lütfen GitHub'da bir çekme isteği göndererek katkıda bulunmaktan çekinmeyin.
Dokümantasyon için GitHub bağlantısıBelge Markdown'ını panoya kopyala
Intlayer kullanarak Next.js 15 sitenizi next-intl ile çevirin | Uluslararasılaştırma (i18n)
Bu rehber, Next.js 15 (App Router) uygulamasında next-intl en iyi uygulamalarını adım adım anlatır ve sağlam çeviri yönetimi ve otomasyon için Intlayer'ı nasıl entegre edeceğinizi gösterir.
Karşılaştırmayı next-i18next vs next-intl vs Intlayer sayfasında inceleyin.
- Yeni başlayanlar için: çalışan çok dilli bir uygulama elde etmek için adım adım bölümleri takip edin.
- Orta seviye geliştiriciler için: payload optimizasyonu ve sunucu/istemci ayrımına dikkat edin.
- Uzmanlar için: statik üretim, middleware, SEO entegrasyonu ve otomasyon kancalarına dikkat edin.
Ele alacaklarımız:
- Kurulum ve dosya yapısı
- Mesajların yüklenme optimizasyonu
- İstemci ve sunucu bileşen kullanımı
- SEO için metadata, sitemap, robots
- Locale yönlendirmesi için middleware
- Üstüne Intlayer eklemek (CLI ve otomasyon)
next-intl kullanarak uygulamanızı kurun
next-intl bağımlılıklarını yükleyin:
npm install next-intl.├── locales│ ├── en│ │ ├── common.json│ │ └── about.json│ ├── fr│ │ ├── common.json│ │ └── about.json│ └── es│ ├── common.json│ └── about.json└── src ├── i18n.ts ├── middleware.ts ├── app │ └── [locale] │ ├── layout.tsx │ └── about │ └── page.tsx └── components ├── ClientComponentExample.tsx └── ServerComponent.tsxKurulum ve İçerik Yükleme
Yalnızca rotalarınızın ihtiyaç duyduğu namespace'leri yükleyin ve locale'leri erken doğrulayın. Mümkün olduğunda sunucu bileşenlerini senkron tutun ve istemciye yalnızca gerekli mesajları gönderin.
Kodu panoya kopyala
import { getRequestConfig } from "next-intl/server";import { notFound } from "next/navigation";export const locales = ["en", "fr", "es"] as const;export const defaultLocale = "en" as const;async function loadMessages(locale: string) { // Yalnızca layout/ sayfalarınızın ihtiyaç duyduğu namespace'leri yükleyin const [common, about] = await Promise.all([ import(`../locales/${locale}/common.json`).then((m) => m.default), import(`../locales/${locale}/about.json`).then((m) => m.default), ]); return { common, about } as const;}export default getRequestConfig(async ({ locale }) => { if (!locales.includes(locale as any)) notFound(); return { messages: await loadMessages(locale), };});Kodu panoya kopyala
import type { ReactNode } from "react";import { locales } from "@/i18n";import { getLocaleDirection, unstable_setRequestLocale,} from "next-intl/server";export const dynamic = "force-static";export function generateStaticParams() { return locales.map((locale) => ({ locale }));}export default async function LocaleLayout({ children, params,}: { children: ReactNode; params: { locale: string };}) { const { locale } = params; // Bu sunucu renderı (RSC) için aktif istek yerelini ayarla unstable_setRequestLocale(locale); const dir = getLocaleDirection(locale); return ( <html lang={locale} dir={dir}> <body>{children}</body> </html> );}Kodu panoya kopyala
import { getTranslations, getMessages, getFormatter } from "next-intl/server";import { NextIntlClientProvider } from "next-intl";import pick from "lodash/pick";import ServerComponent from "@/components/ServerComponent";import ClientComponentExample from "@/components/ClientComponentExample";export const dynamic = "force-static";export default async function AboutPage({ params,}: { params: { locale: string };}) { const { locale } = params; // Mesajlar sunucu tarafında yüklenir. İstemciye sadece gerekenleri gönderin. const messages = await getMessages(); const clientMessages = pick(messages, ["common", "about"]); // Sadece sunucu tarafı çeviriler/formatlama const tAbout = await getTranslations("about"); const tCounter = await getTranslations("about.counter"); const format = await getFormatter(); const initialFormattedCount = format.number(0); return ( <NextIntlClientProvider locale={locale} messages={clientMessages}> <main> <h1>{tAbout("title")}</h1> <ClientComponentExample /> <ServerComponent formattedCount={initialFormattedCount} label={tCounter("label")} increment={tCounter("increment")} /> </main> </NextIntlClientProvider> );}Bir istemci bileşeninde kullanım
Bir sayaç render eden istemci bileşenine bir örnek alalım.
Çeviriler (şekil yeniden kullanıldı; bunları istediğiniz gibi next-intl mesajlarına yükleyin)
Kodu panoya kopyala
{ "counter": { "label": "Counter", "increment": "Increment" }}Kodu panoya kopyala
{ "counter": { "label": "Sayaç", "increment": "Arttır" }}İstemci bileşeni
Kodu panoya kopyala
"use client";import React, { useState } from "react";import { useTranslations, useFormatter } from "next-intl";const ClientComponentExample = () => { // Doğrudan iç içe nesneye kapsam belirleme const t = useTranslations("about.counter"); const format = useFormatter(); const [count, setCount] = useState(0); return ( <div> <p>{format.number(count)}</p> <button aria-label={t("label")} onClick={() => setCount((count) => count + 1)} > {t("increment")} </button> </div> );};Sayfa istemci mesajına "about" mesajını eklemeyi unutmayın (istemcinizin gerçekten ihtiyaç duyduğu ad alanlarını dahil edin).
Bir sunucu bileşeninde kullanım
Bu UI bileşeni bir sunucu bileşenidir ve bir istemci bileşeni altında render edilebilir (sayfa → istemci → sunucu). Önceden hesaplanmış dizeleri geçirerek senkron tutun.
Kodu panoya kopyala
type ServerComponentProps = { formattedCount: string; label: string; increment: string;};const ServerComponent = ({ formattedCount, label, increment,}: ServerComponentProps) => { return ( <div> <p>{formattedCount}</p> <button aria-label={label}>{increment}</button> </div> );};Notlar:
- formattedCount değerini sunucu tarafında hesaplayın (örneğin, const initialFormattedCount = format.number(0)).
- Sunucu bileşenlerine fonksiyonlar veya serileştirilemeyen nesneler geçirmemeye dikkat edin.
Kodu panoya kopyala
import type { Metadata } from "next";import { locales, defaultLocale } from "@/i18n";import { getTranslations } from "next-intl/server";function localizedPath(locale: string, path: string) { return locale === defaultLocale ? path : "/" + locale + path;}export async function generateMetadata({ params,}: { params: { locale: string };}): Promise<Metadata> { const { locale } = params; const t = await getTranslations({ locale, namespace: "about" }); const url = "/about"; const languages = Object.fromEntries( locales.map((locale) => [locale, localizedPath(locale, url)]) ); return { title: t("title"), description: t("description"), alternates: { canonical: localizedPath(locale, url), languages: { ...languages, "x-default": url }, }, };}// ... Sayfanın geri kalan koduKodu panoya kopyala
import type { MetadataRoute } from "next";import { locales, defaultLocale } from "@/i18n";const origin = "https://example.com";const formatterLocalizedPath = (locale: string, path: string) => locale === defaultLocale ? origin + path : origin + "/" + locale + path;export default function sitemap(): MetadataRoute.Sitemap { const aboutLanguages = Object.fromEntries( locales.map((l) => [l, formatterLocalizedPath(l, "/about")]) ); return [ { url: formatterLocalizedPath(defaultLocale, "/about"), lastModified: new Date(), changeFrequency: "aylık", priority: 0.7, alternates: { languages: aboutLanguages }, }, ];}Kodu panoya kopyala
import type { MetadataRoute } from "next";import { locales, defaultLocale } from "@/i18n";const origin = "https://example.com";const withAllLocales = (path: string) => [ path, ...locales .filter((locale) => locale !== defaultLocale) .map((locale) => "/" + locale + path),];export default function robots(): MetadataRoute.Robots { const disallow = [ ...withAllLocales("/dashboard"), ...withAllLocales("/admin"), ]; return { rules: { userAgent: "*", allow: ["/"], disallow }, host: origin, sitemap: origin + "/sitemap.xml", };}Yerel yönlendirme için Middleware
Yerel algılama ve yönlendirmeyi yönetmek için bir middleware ekleyin:
Kodu panoya kopyala
import createMiddleware from "next-intl/middleware";import { locales, defaultLocale } from "@/i18n";export default createMiddleware({ locales: [...locales], defaultLocale, localeDetection: true,});export const config = { // API, Next dahili ve statik varlıkları atla matcher: ["/((?!api|_next|.*\\..*).*)"],};En iyi uygulamalar
- html lang ve dir ayarlayın: src/app/[locale]/layout.tsx içinde, dir değerini getLocaleDirection(locale) ile hesaplayın ve <html lang={locale} dir={dir}> olarak ayarlayın.
- Mesajları namespace bazında ayırın: JSON dosyalarını locale ve namespace bazında organize edin (örneğin, common.json, about.json).
- İstemci yükünü minimize edin: Sayfalarda, NextIntlClientProvider'a yalnızca gerekli namespace'leri gönderin (örneğin, pick(messages, ['common', 'about'])).
- Statik sayfaları tercih edin: export const dynamic = 'force-static' olarak dışa aktarın ve tüm locales için statik parametreler oluşturun.
- Eşzamanlı sunucu bileşenleri: Önceden hesaplanmış dizeleri (çevirilmiş etiketler, biçimlendirilmiş sayılar) async çağrılar veya serileştirilemeyen fonksiyonlar yerine geçirin.
next-intl üzerine Intlayer'ı uygulayın
Intlayer bağımlılıklarını yükleyin:
npm install intlayer @intlayer/sync-json-plugin -DIntlayer yapılandırma dosyasını oluşturun:
Kodu panoya kopyala
import { type IntlayerConfig, Locales } from "intlayer";import { syncJSON } from "@intlayer/sync-json-plugin";const config: IntlayerConfig = { internationalization: { locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH], defaultLocale: Locales.ENGLISH, }, ai: { apiKey: process.env.OPENAI_API_KEY, }, plugins: [ // Namespace başına klasör yapınızı Intlayer ile senkronize tutun syncJSON({ source: ({ key, locale }) => `./locales/${locale}/${key}.json`, }), ],};export default config;package.json betiklerini ekleyin:
Kodu panoya kopyala
{ "scripts": { "i18n:fill": "intlayer fill", "i18n:test": "intlayer test" }}Notlar:
- intlayer fill: yapılandırdığınız yerel ayarlara göre eksik çevirileri doldurmak için AI sağlayıcınızı kullanır.
- intlayer test: eksik/geçersiz çevirileri kontrol eder (CI'da kullanın).
Argümanları ve sağlayıcıları yapılandırabilirsiniz; bkz. Intlayer CLI.