Criação:2026-04-02Última atualização:2026-04-02

    Domínios personalizados

    O Intlayer suporta roteamento de locale baseado em domínio, permitindo que você sirva locales específicos a partir de hostnames dedicados. Por exemplo, os visitantes chineses podem ser direcionados para intlayer.zh em vez de intlayer.org/zh.

    Como funciona

    O mapa domains em routing associa cada locale a um hostname. O Intlayer usa esse mapa em dois lugares:

    1. Geração de URL (getLocalizedUrl): quando o locale de destino vive em um domínio diferente da página atual, uma URL absoluta é retornada (ex: https://intlayer.zh/about). Quando ambos os domínios coincidem, uma URL relativa é retornada (ex: /fr/about).
    2. Proxy do servidor (Next.js & Vite): as solicitações recebidas são redirecionadas ou rescritas com base no domínio em que chegam.

    Domínios exclusivos vs. compartilhados

    A distinção principal é a exclusividade:

    • Domínio exclusivo - apenas um locale mapeia para esse hostname (ex: zh → intlayer.zh). O próprio domínio identifica o locale, portanto, nenhum prefixo de locale é adicionado ao caminho. https://intlayer.zh/about serve conteúdo em chinês.
    • Domínio compartilhado - vários locales mapeiam para o mesmo hostname (ex: tanto en quanto fr mapeiam para intlayer.org). O roteamento padrão baseado em prefixo se aplica. intlayer.org/fr/about serve conteúdo em francês.

    Configuração

    import { Locales, type IntlayerConfig } from "intlayer";
    
    const config: IntlayerConfig = {
      internationalization: {
        locales: [
          Locales.ENGLISH,
          Locales.FRENCH,
          Locales.SPANISH,
          Locales.CHINESE,
        ],
        defaultLocale: Locales.ENGLISH,
      },
      routing: {
        mode: "prefix-no-default",
        domains: {
          // Domínio compartilhado - en e fr usam roteamento de prefixo em intlayer.org
          en: "intlayer.org",
          // Domínio exclusivo - zh tem seu próprio hostname, nenhum prefixo /zh/ é necessário
          zh: "intlayer.zh",
        },
      },
    };
    
    export default config;

    Locales que não estão listados em domains continuam a usar o roteamento de prefixo padrão sem qualquer substituição de domínio.

    Geração de URL

    getLocalizedUrl produz automaticamente o tipo de URL correto com base no contexto da chamada.

    Locale no mesmo domínio (URL relativa)

    // Página atual: intlayer.org/about
    getLocalizedUrl("/about", "fr", { currentDomain: "intlayer.org" });
    // → "/fr/about"
    
    getLocalizedUrl("/about", "en", { currentDomain: "intlayer.org" });
    // → "/about"  (locale padrão, sem prefixo)

    Locale em um domínio diferente (URL absoluta)

    // Página atual: intlayer.org/about
    getLocalizedUrl("/about", "zh", { currentDomain: "intlayer.org" });
    // → "https://intlayer.zh/about"  (domínio exclusivo, sem prefixo /zh/)

    Servindo a partir do domínio do próprio locale

    // Página atual: intlayer.zh/about
    getLocalizedUrl("/about", "zh", { currentDomain: "intlayer.zh" });
    // → "/about"  (já está no domínio correto - URL relativa)
    
    getLocalizedUrl("/about", "fr", { currentDomain: "intlayer.zh" });
    // → "https://intlayer.org/fr/about"  (link entre domínios de volta para intlayer.org)

    Detecção automática do domínio atual

    currentDomain é opcional. Quando omitido, getLocalizedUrl o resolve nesta ordem:

    1. O hostname de uma URL de entrada absoluta (ex: https://intlayer.org/aboutintlayer.org).
    2. window.location.hostname em ambientes de navegador.
    3. Se nenhum estiver disponível (SSR sem opção explícita), uma URL relativa é retornada para locales do mesmo domínio e nenhuma URL absoluta é produzida - este é o fallback seguro.
    // Navegador - window.location.hostname === 'intlayer.org'
    getLocalizedUrl("/about", "zh");
    // → "https://intlayer.zh/about"  (detectado automaticamente a partir de window)
    
    // A partir de uma URL absoluta - domínio detectado automaticamente
    getLocalizedUrl("https://intlayer.org/about", "zh");
    // → "https://intlayer.zh/about"

    getMultilingualUrls com domínios

    getMultilingualUrls chama getLocalizedUrl para cada locale, por o que produz uma mistura de URLs relativas e absolutas dependendo do domínio do chamador:

    // currentDomain: 'intlayer.org'
    getMultilingualUrls("/about", { currentDomain: "intlayer.org" });
    // {
    //   en: "/about",
    //   fr: "/fr/about",
    //   es: "/es/about",
    //   zh: "https://intlayer.zh/about",
    // }

    Essas URLs absolutas estão prontas para usar em tags <link rel="alternate" hreflang="..."> para SEO.

    Comportamento do Proxy

    Next.js

    O middleware intlayerProxy lida com o roteamento de domínio automaticamente. Adicione-o ao seu middleware.ts:

    export { intlayerProxy as default } from "next-intlayer/proxy";
    
    export const config = {
      matcher: "/((?!api|static|assets|robots|sitemap|.*\\..*|_next).*)",
    };

    Redirecionamento - a solicitação chega no domínio errado para um determinado prefixo de locale:

    GET intlayer.org/zh/about
    → 301 https://intlayer.zh/about

    Reescrita - a solicitação chega no domínio exclusivo do locale sem um prefixo:

    GET intlayer.zh/about
    → reescrita para /zh/about  (apenas roteamento interno do Next.js, a URL permanece limpa)

    Vite

    O plugin Vite intlayerProxy aplica a mesma lógica durante o desenvolvimento:

    import { defineConfig } from "vite";
    import { intlayerProxy } from "vite-intlayer";
    
    export default defineConfig({
      plugins: [intlayerProxy()],
    });
    Nota: no desenvolvimento local você está normalmente no localhost, então redirecionamentos entre domínios apontarão para os domínios reais em vez de outra porta local. Use uma substituição no arquivo hosts (ex: 127.0.0.1 intlayer.zh) or um proxy reverso se precisar testar o roteamento multidomínio localmente.

    Seletor de locale (Locale Switcher)

    O hook useLocale do next-intlayer lida com a navegação consciente do domínio automaticamente. Quando um usuário muda para um locale em um domínio diferente, o hook realiza uma navegação de página completa (window.location.href) em vez de um push do roteador no lado do cliente, porque o roteador do Next.js não pode cruzar origens.

    "use client";
    
    import { useLocale } from "next-intlayer";
    
    export const LocaleSwitcher = () => {
      const { availableLocales, locale, setLocale } = useLocale();
    
      return (
        <ul>
          {availableLocales.map((localeEl) => (
            <li key={localeEl}>
              <button
                onClick={() => setLocale(localeEl)}
                aria-current={localeEl === locale ? "true" : undefined}
              >
                {l.toUpperCase()}
              </button>
            </li>
          ))}
        </ul>
      );
    };

    Nenhuma configuração extra é necessária - useLocale detecta window.location.hostname internamente e decide entre router.replace (mesmo domínio) e window.location.href (cross-domain).

    O roteamento baseado em domínio é comumente usado junto com hreflang para informar aos mecanismos de pesquisa qual URL indexar para cada idioma. Use getMultilingualUrls para gerar o conjunto completo de URLs alternativas:

    import { getMultilingualUrls } from "intlayer";
    import type { Metadata } from "next";
    
    export const generateMetadata = (): Metadata => {
      const alternates = getMultilingualUrls("/", {
        currentDomain: process.env.NEXT_PUBLIC_DOMAIN, // ex: "intlayer.org"
      });
    
      return {
        alternates: {
          languages: alternates,
        },
      };
    };

    Isso produz:

    <link rel="alternate" hreflang="en" href="https://intlayer.org/" />
    <link rel="alternate" hreflang="fr" href="https://intlayer.org/fr/" />
    <link rel="alternate" hreflang="es" href="https://intlayer.org/es/" />
    <link rel="alternate" hreflang="zh" href="https://intlayer.zh/" />

    Utilitários principais

    Utilitário Descrição
    getLocalizedUrl(url, locale, { currentDomain }) Retorna uma URL relativa ou absoluta dependendo se o locale de destino está no domínio atual ou não.
    getMultilingualUrls(url, { currentDomain }) Retorna um mapa de URLs localizadas por locale, misturando relativas e absolutas conforme necessário.
    getPrefix(locale, { domains }) Retorna um prefixo vazio para locales de domínio exclusivo, caso contrário, o prefixo normal.