Ana SayfaPlaygroundShowcaseUygulamaDokümanBlog
    • Englishİngilizce
      EN
    • русскийRusça
      RU
    • 日本語Japonca
      JA
    • françaisFransızca
      FR
    • 한국어Korece
      KO
    • 中文Çince
      ZH
    • españolİspanyolca
      ES
    • DeutschAlmanca
      DE
    • العربيةArapça
      AR
    • italianoİtalyanca
      IT
    • British Englishİngiliz İngilizcesi
      EN-GB
    • portuguêsPortekizce
      PT
    • हिन्दीHintçe
      HI
    • TürkçeTürkçe
      TR
    • polskiLehçe
      PL
    • IndonesiaEndonezce
      ID
    • Tiếng ViệtVietnamca
      VI
    • українськаUkraynaca
      UK
    /
    Çerçeveye göre belgeleri filtrele
    Alt+←
    Neden Intlayer?
    Başla
    Kavram
    • Intlayer Nasıl Çalışır
    • Yapılandırma
    • TestFillBuildWatchExtractLoginPushPullConfigurationListVersionEditorLiveDebugDoc ReviewDoc TranslateSDK
    • Görsel Editör
    • CMS
    • CI/CD Entegrasyonu
    • ÇeviriÇoğulNumaralandırmaKoşulCinsiyetEklemeDosyaİç İçe GeçmeMarkdownHTMLFonksiyon Getirme
    • Yerel Dosya
    • Derleyici
    • Otomatik Doldurma
    • Test
    • Paket Optimizasyonu
    Ortam
    • Next.js 14 ve Uygulama Yönlendirici
      Next.js 15
      Next.js locale’siz URL
      Next.js ve Sayfa Yönlendirici
      Derleyici
    • Tanstack Start Solid
    • Astro ve React
      Astro ve Svelte
      Astro ve Vue
      Astro ve Solid
      Astro ve Preact
      Astro ve Lit
      Astro ve Vanilla JS
    • React Router v7
      React Router v7 (fs-routes)
      Compiler
    • Nuxt ve Vue
    • Vite ve Solid
    • SvelteKit
    • Vite ve Preact
    • Vite ve Vanilla JS
    • Vite ve Lit
    • Angular 19 (Webpack)
      Analog
    • React CRA
    • React Native ve Expo
    • Express.js
      NestJS
      Fastify
      Hono
      Adonis
    • Lynx ve React
    Plugins
    • JSON
    • gettext (.po)
    VS Code Uzantısı
    Aracı
    • MCP Sunucusu
    • Aracı becerileri
    Sürümler
    • v8
    • v7
    • v6
    Karşılaştırma
    • Next.js
    • TanStack
    • Vue
    • Solid
    • Svelte
    Blog
    Bir soru sor
    1. Documentation
    2. Next intl
    Oluşturma:2025-10-05Son güncelleme:2025-10-05
    GitHub'da uygulama şablonunu görüntüle

    Bu sayfada kullanılabilir bir uygulama şablonu var.

    Bu dokümanı favori AI asistanınıza referans verin
    ChatGPT
    Claude
    DeepSeek
    Google AI mode
    Gemini
    Perplexity
    Mistral
    Grok

    Sorunuzu sorun ve bu sayfaya ve seçtiğiniz AI sağlayıcısına referans vererek belgenin bir özetini alın

    Bu sayfanın içeriği bir yapay zeka kullanılarak çevrildi.

    Orijinal içeriğin İngilizce son sürümünü görüntüleyin
    Bu dokümanı düzenle

    Bu 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ı
    Kopyala

    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:

    bash
    Kodu kopyala

    Kodu panoya kopyala

    npm install next-intl
    bash
    Kodu kopyala

    Kodu panoya kopyala

    .├── 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.tsx

    Kurulum 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.

    src/i18n.ts
    Kodu kopyala

    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)) notFound();  return {    messages: await loadMessages(locale),  };});
    src/app/[locale]/layout.tsx
    Kodu kopyala

    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>  );}
    src/app/[locale]/about/page.tsx
    Kodu kopyala

    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)

    locales/en/about.json
    Kodu kopyala

    Kodu panoya kopyala

    {  "counter": {    "label": "Counter",    "increment": "Increment"  }}
    locales/fr/about.json
    Kodu kopyala

    Kodu panoya kopyala

    {  "counter": {    "label": "Sayaç",    "increment": "Arttır"  }}

    İstemci bileşeni

    src/components/ClientComponentExample.tsx
    Kodu kopyala

    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.

    src/components/ServerComponent.tsx
    Kodu kopyala

    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.
    src/app/[locale]/about/layout.tsx
    Kodu kopyala

    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 kodu
    src/app/sitemap.ts
    Kodu kopyala

    Kodu 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 },    },  ];}
    src/app/robots.ts
    Kodu kopyala

    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:

    src/middleware.ts
    Kodu kopyala

    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:

    bash
    Kodu kopyala

    Kodu panoya kopyala

    npm install intlayer @intlayer/sync-json-plugin --save-dev

    Intlayer yapılandırma dosyasını oluşturun:

    intlayer.config.ts
    Kodu kopyala

    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({      format: "icu",      source: ({ key, locale }) => `./locales/${locale}/${key}.json`,    }),  ],};export default config;

    package.json betiklerini ekleyin:

    package.json
    Kodu kopyala

    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.

    Neden Intlayer?
    Alt+→

    Bu sayfada

      Tartışmalar anonimdir ve yaygın sorunları ele almak için düzenli olarak incelenir. Özellik fikirleri, belgeleme hakkında geri bildirimler veya Intlayer ile ilgili herhangi bir şeyi paylaşmaktan çekinmeyin, bu girdileri yol haritamızı şekillendirmek ve ürünü geliştirmek için kullanıyoruz.

      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.tsx
      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)) notFound();  return {    messages: await loadMessages(locale),  };});
      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>  );}
      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>  );}
      {  "counter": {    "label": "Counter",    "increment": "Increment"  }}
      {  "counter": {    "label": "Sayaç",    "increment": "Arttır"  }}
      "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>  );};
      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>  );};
      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 kodu
      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 },    },  ];}
      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",  };}
      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|.*\\..*).*)"],};
      npm install intlayer @intlayer/sync-json-plugin --save-dev
      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({      format: "icu",      source: ({ key, locale }) => `./locales/${locale}/${key}.json`,    }),  ],};export default config;
      {  "scripts": {    "i18n:fill": "intlayer fill",    "i18n:test": "intlayer test"  }}