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
    /
    Alt+←
    Uluslararasılaştırma (i18n) nedir?
    SEO ve i18n
    Rehber
    • next-i18next ile i18n
    • next-intl ile i18n
    Çözümünüzde Intlayer kullanın
    • next-i18next otomatikleştir
    • react-i18next otomatikleştir
    • next-intl otomatikleştir
    • react-intl otomatikleştir
    • vue-i18n otomatikleştir
    Karşılaştırmalar
    • next-i18next vs next-intl vs Intlayer
    • react-i18next vs react-intl vs Intlayer
    Dokümantasyon
    1. Blog
    2. Blog seo i18n nextjs
    Creation:2025-09-28Last update:2025-09-28
    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
    Edit this doc

    If you have an idea for improving this documentation, please feel free to contribute by submitting a pull request on GitHub.

    GitHub link to the documentation
    Copy

    Copy doc Markdown to clipboard

    Next.js'te SEO ve i18n: Çeviri yapmak yeterli değil

    Geliştiriciler uluslararasılaştırma (i18n) düşündüklerinde, ilk refleks genellikle: içeriği çevirmek olur. Ancak insanlar genellikle uluslararasılaştırmanın asıl amacının web sitenizi dünyaya daha görünür kılmak olduğunu unutur. Eğer çok dilli Next.js uygulamanız, arama motorlarına farklı dil versiyonlarınızı nasıl tarayacaklarını ve anlayacaklarını söylemiyorsa, çabanızın çoğu fark edilmeden kalabilir.

    Bu blogda, neden i18n'in bir SEO süper gücü olduğunu ve next-intl, next-i18next ve Intlayer ile Next.js'te bunu nasıl doğru şekilde uygulayacağımızı keşfedeceğiz.


    Neden SEO ve i18n

    Dil eklemek sadece kullanıcı deneyimi (UX) ile ilgili değildir. Aynı zamanda organik görünürlük için güçlü bir kaldıraçtır. İşte nedenleri:

    1. Daha iyi keşfedilebilirlik: Arama motorları yerelleştirilmiş versiyonları indeksler ve kullanıcıların kendi ana dillerinde arama yaptıklarında onları sıralar.
    2. Yinelenen içerikten kaçınma: Doğru canonical ve alternatif etiketler, tarayıcılara hangi sayfanın hangi dil versiyonuna ait olduğunu bildirir.
    3. Daha iyi kullanıcı deneyimi: Ziyaretçiler sitenizin doğru versiyonuna hemen ulaşır.
    4. Rekabet avantajı: Çok az site çok dilli SEO'yu iyi uygular, bu da sizin öne çıkmanızı sağlar.

    Next.js'te Çok Dilli SEO için En İyi Uygulamalar

    Her çok dilli uygulamanın uygulaması gereken kontrol listesi:

    • <head> içinde hreflang meta etiketlerini ayarlayın
      Google'ın her dil için hangi versiyonların mevcut olduğunu anlamasına yardımcı olur.

    • Tüm çevrilmiş sayfaları sitemap.xml içinde listeleyin
      Tarayıcıların alternatifleri kolayca bulabilmesi için xhtml şemasını kullanın.

    • Özel/yerelleştirilmiş rotaları robots.txt içinde hariç tutun
      Örneğin /dashboard, /fr/dashboard, /es/dashboard gibi sayfaların indekslenmesine izin vermeyin.

    • Yerelleştirilmiş bağlantılar kullanın
      Örnek: Varsayılan /about yerine <a href="/fr/about">À propos</a> kullanın.

    Bunlar basit adımlar, ancak atlanmaları görünürlüğünüzü kaybetmenize neden olabilir.


    Uygulama Örnekleri

    Geliştiriciler genellikle sayfalarını farklı yereller arasında doğru şekilde referanslamayı unutur, bu yüzden bunun farklı kütüphanelerle pratikte nasıl çalıştığına bakalım.

    next-intl

    src/app/[locale]/about/layout.tsx
    Kodu kopyala

    Kodu panoya kopyala

    import type { Metadata } from "next";import { locales, defaultLocale } from "@/i18n";import { getTranslations, unstable_setRequestLocale } 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((l) => [l, localizedPath(l, 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((l) => l !== defaultLocale).map((l) => `/${l}${path}`),];export default function robots(): MetadataRoute.Robots {const disallow = [  ...withAllLocales("/dashboard"),  ...withAllLocales("/admin"),];return {  rules: { userAgent: "*", allow: ["/"], disallow },  host: origin,  sitemap: `${origin}/sitemap.xml`,};}

    next-i18next

    i18n.config.ts
    Kodu kopyala

    Kodu panoya kopyala

    export const locales = ["en", "fr"] as const;export type Locale = (typeof locales)[number];export const defaultLocale: Locale = "en";/** Varsayılan yerel değilse, yolu yerelleştirilmiş yerel ile önekler */export function localizedPath(locale: string, path: string) {return locale === defaultLocale ? path : `/${locale}${path}`;}/** Mutlak URL yardımcı fonksiyonu */const ORIGIN = "https://example.com";export function abs(locale: string, path: string) {return `${ORIGIN}${localizedPath(locale, path)}`;}
    src/app/[locale]/about/layout.tsx
    Kodu kopyala

    Kodu panoya kopyala

    import type { Metadata } from "next";import { locales, defaultLocale, localizedPath } from "@/i18n.config";export async function generateMetadata({params,}: {params: { locale: string };}): Promise<Metadata> {const { locale } = params;// Doğru JSON dosyasını dinamik olarak içe aktarconst messages = (await import(`@/../public/locales/${locale}/about.json`))  .default;const languages = Object.fromEntries(  locales.map((l) => [l, localizedPath(l, "/about")]));return {  title: messages.title,  description: messages.description,  alternates: {    canonical: localizedPath(locale, "/about"),    languages: { ...languages, "x-default": "/about" },  },};}export default async function AboutPage() {return <h1>Hakkında</h1>;}
    src/app/sitemap.ts
    Kodu kopyala

    Kodu panoya kopyala

    import type { MetadataRoute } from "next";import { locales, defaultLocale, abs } from "@/i18n.config";export default function sitemap(): MetadataRoute.Sitemap {const languages = Object.fromEntries(  locales.map((l) => [l, abs(l, "/about")]));return [  {    url: abs(defaultLocale, "/about"),    lastModified: new Date(),    changeFrequency: "monthly",    priority: 0.7,    alternates: { languages },  },];}
    src/app/robots.ts
    Kodu kopyala

    Kodu panoya kopyala

    import type { MetadataRoute } from "next";import { locales, defaultLocale, localizedPath } from "@/i18n.config";const ORIGIN = "https://example.com";const expandAllLocales = (path: string) => [localizedPath(defaultLocale, path),...locales  .filter((l) => l !== defaultLocale)  .map((l) => localizedPath(l, path)),];export default function robots(): MetadataRoute.Robots {const disallow = [  ...expandAllLocales("/dashboard"),  ...expandAllLocales("/admin"),];return {  rules: { userAgent: "*", allow: ["/"], disallow },  host: ORIGIN,  sitemap: `${ORIGIN}/sitemap.xml`,};}

    Intlayer

    src/app/[locale]/about/layout.tsx
    Kodu kopyala

    Kodu panoya kopyala

    import { getIntlayer, getMultilingualUrls } from "intlayer";import type { Metadata } from "next";import type { LocalPromiseParams } from "next-intlayer";export const generateMetadata = async ({params,}: LocalPromiseParams): Promise<Metadata> => {const { locale } = await params;const metadata = getIntlayer("page-metadata", locale);/** * Her yerel için tüm URL'leri içeren bir nesne oluşturur. * * Örnek: * ```ts *  getMultilingualUrls('/about'); * *  // Döner *  // { *  //   en: '/about', *  //   fr: '/fr/about', *  //   es: '/es/about', *  // } * ``` */const multilingualUrls = getMultilingualUrls("/about");return {  ...metadata,  alternates: {    canonical: multilingualUrls[locale as keyof typeof multilingualUrls],    languages: { ...multilingualUrls, "x-default": "/about" },  },};};// ... Sayfanın geri kalan kodu
    src/app/sitemap.ts
    Kodu kopyala

    Kodu panoya kopyala

    import { getMultilingualUrls } from "intlayer";import type { MetadataRoute } from "next";const sitemap = (): MetadataRoute.Sitemap => [{  url: "https://example.com/about",  alternates: {    languages: { ...getMultilingualUrls("https://example.com/about") },  },},];
    src/app/robots.ts
    Kodu kopyala

    Kodu panoya kopyala

    import { getMultilingualUrls } from "intlayer";import type { MetadataRoute } from "next";// Tüm çok dilli URL'leri verilen URL listesinden alırconst getAllMultilingualUrls = (urls: string[]) =>urls.flatMap((url) => Object.values(getMultilingualUrls(url)) as string[]);// Robots.txt kurallarını tanımlarconst robots = (): MetadataRoute.Robots => ({rules: {  userAgent: "*",  allow: ["/"],  disallow: getAllMultilingualUrls(["/dashboard"]), // "/dashboard" sayfasına erişimi engeller},host: "https://example.com",sitemap: `https://example.com/sitemap.xml`,});export default robots;
    Intlayer, site haritanız için çok dilli URL'ler oluşturmak üzere getMultilingualUrls fonksiyonunu sağlar.

    Sonuç

    Next.js'te i18n'i doğru yapmak sadece metni çevirmekle ilgili değildir, aynı zamanda arama motorlarının ve kullanıcıların içeriğinizin hangi sürümünü sunacağını tam olarak bilmelerini sağlamaktır. Hreflang, site haritaları ve robots kurallarını ayarlamak, çevirileri gerçek SEO değerine dönüştüren şeydir.

    next-intl ve next-i18next size bunu bağlamak için sağlam yollar sunarken, genellikle yereller arasında tutarlılığı sağlamak için çok fazla manuel kurulum gerektirirler.

    İşte burada Intlayer gerçekten parlıyor:

    getMultilingualUrls gibi yerleşik yardımcılarla birlikte gelir, bu da hreflang, site haritası ve robots entegrasyonunu neredeyse zahmetsiz hale getirir.

    Meta veriler JSON dosyaları veya özel yardımcı araçlar arasında dağılmak yerine merkezi olarak tutulur.

    Next.js için baştan sona tasarlanmıştır, böylece yapılandırmayı hata ayıklamakla daha az, projeyi teslim etmekle daha çok zaman harcarsınız.

    Amacınız sadece çeviri yapmak değil, çok dilli SEO'yu sorunsuz bir şekilde ölçeklendirmekse, Intlayer size en temiz ve en geleceğe dönük kurulumu sunar.

    Uluslararasılaştırma (i18n) nedir?
    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.

      import type { Metadata } from "next";import { locales, defaultLocale } from "@/i18n";import { getTranslations, unstable_setRequestLocale } 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((l) => [l, localizedPath(l, 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((l) => l !== defaultLocale).map((l) => `/${l}${path}`),];export default function robots(): MetadataRoute.Robots {const disallow = [  ...withAllLocales("/dashboard"),  ...withAllLocales("/admin"),];return {  rules: { userAgent: "*", allow: ["/"], disallow },  host: origin,  sitemap: `${origin}/sitemap.xml`,};}
      export const locales = ["en", "fr"] as const;export type Locale = (typeof locales)[number];export const defaultLocale: Locale = "en";/** Varsayılan yerel değilse, yolu yerelleştirilmiş yerel ile önekler */export function localizedPath(locale: string, path: string) {return locale === defaultLocale ? path : `/${locale}${path}`;}/** Mutlak URL yardımcı fonksiyonu */const ORIGIN = "https://example.com";export function abs(locale: string, path: string) {return `${ORIGIN}${localizedPath(locale, path)}`;}
      import type { Metadata } from "next";import { locales, defaultLocale, localizedPath } from "@/i18n.config";export async function generateMetadata({params,}: {params: { locale: string };}): Promise<Metadata> {const { locale } = params;// Doğru JSON dosyasını dinamik olarak içe aktarconst messages = (await import(`@/../public/locales/${locale}/about.json`))  .default;const languages = Object.fromEntries(  locales.map((l) => [l, localizedPath(l, "/about")]));return {  title: messages.title,  description: messages.description,  alternates: {    canonical: localizedPath(locale, "/about"),    languages: { ...languages, "x-default": "/about" },  },};}export default async function AboutPage() {return <h1>Hakkında</h1>;}
      import type { MetadataRoute } from "next";import { locales, defaultLocale, abs } from "@/i18n.config";export default function sitemap(): MetadataRoute.Sitemap {const languages = Object.fromEntries(  locales.map((l) => [l, abs(l, "/about")]));return [  {    url: abs(defaultLocale, "/about"),    lastModified: new Date(),    changeFrequency: "monthly",    priority: 0.7,    alternates: { languages },  },];}
      import type { MetadataRoute } from "next";import { locales, defaultLocale, localizedPath } from "@/i18n.config";const ORIGIN = "https://example.com";const expandAllLocales = (path: string) => [localizedPath(defaultLocale, path),...locales  .filter((l) => l !== defaultLocale)  .map((l) => localizedPath(l, path)),];export default function robots(): MetadataRoute.Robots {const disallow = [  ...expandAllLocales("/dashboard"),  ...expandAllLocales("/admin"),];return {  rules: { userAgent: "*", allow: ["/"], disallow },  host: ORIGIN,  sitemap: `${ORIGIN}/sitemap.xml`,};}
      import { getIntlayer, getMultilingualUrls } from "intlayer";import type { Metadata } from "next";import type { LocalPromiseParams } from "next-intlayer";export const generateMetadata = async ({params,}: LocalPromiseParams): Promise<Metadata> => {const { locale } = await params;const metadata = getIntlayer("page-metadata", locale);/** * Her yerel için tüm URL'leri içeren bir nesne oluşturur. * * Örnek: * ```ts *  getMultilingualUrls('/about'); * *  // Döner *  // { *  //   en: '/about', *  //   fr: '/fr/about', *  //   es: '/es/about', *  // } * ``` */const multilingualUrls = getMultilingualUrls("/about");return {  ...metadata,  alternates: {    canonical: multilingualUrls[locale as keyof typeof multilingualUrls],    languages: { ...multilingualUrls, "x-default": "/about" },  },};};// ... Sayfanın geri kalan kodu
      import { getMultilingualUrls } from "intlayer";import type { MetadataRoute } from "next";const sitemap = (): MetadataRoute.Sitemap => [{  url: "https://example.com/about",  alternates: {    languages: { ...getMultilingualUrls("https://example.com/about") },  },},];
      import { getMultilingualUrls } from "intlayer";import type { MetadataRoute } from "next";// Tüm çok dilli URL'leri verilen URL listesinden alırconst getAllMultilingualUrls = (urls: string[]) =>urls.flatMap((url) => Object.values(getMultilingualUrls(url)) as string[]);// Robots.txt kurallarını tanımlarconst robots = (): MetadataRoute.Robots => ({rules: {  userAgent: "*",  allow: ["/"],  disallow: getAllMultilingualUrls(["/dashboard"]), // "/dashboard" sayfasına erişimi engeller},host: "https://example.com",sitemap: `https://example.com/sitemap.xml`,});export default robots;