|
Documentação
Agende uma demoPlataforma
PlataformaMCPCLIAPIWorkflows
Guias
Changelog

Localização

  • Visão geral
  • API de Tradução
  • Localização de apps web
  • Localização de aplicativos mobile
  • iOS com String Catalogs
  • Android com strings.xml
  • Localização de e-mails
  • Conteúdo estático (ex.: .md, .json)
  • Next.js com Markdoc
  • Rails com i18n

Workflows

  • Configuração do engine com MCP
  • Triagem no Jira
  • CI/CD

Localização do App Router do Next.js com Markdoc

A CLI da Lingo.dev traduz arquivos Markdoc e catálogos JSON de strings de UI por meio de um engine de localização configurado. O Markdoc é um formato de autoria baseado em Markdown com tags personalizadas tipadas e integradas ao React — ideal para sites em Next.js App Router que combinam conteúdo extenso com componentes interativos.

Este guia mostra, de ponta a ponta, como localizar um site em Next.js App Router: configurar a CLI, organizar o conteúdo por idioma, renderizar Markdoc em rotas dinâmicas e automatizar as traduções com GitHub Actions.

Repositório de demonstração

Clone ou faça um fork de lingodotdev/markdoc-nextjs-localization-example para acompanhar. O repositório traz um app funcional em Next.js App Router com conteúdo em Markdoc, uma configuração da CLI da Lingo.dev e um workflow do GitHub Actions.

Como funciona a localização com Next.js + Markdoc#

A maioria dos sites em Next.js App Router divide o conteúdo localizado em duas camadas:

CamadaO que fica aquiArquivo de exemplo
Conteúdo extensoPáginas de marketing, documentação, posts de blogsrc/content/[locale]/pages/home.md
Strings de UIRótulos da navbar, CTAs, estados de botõessrc/content/[locale]/ui.json

As rotas ficam em src/app/[lang]/ e leem, no momento da requisição, os arquivos do idioma correspondente. Um middleware define um idioma padrão com base no cabeçalho Accept-Language do navegador e redireciona caminhos sem prefixo, como /, para /en (ou para a melhor correspondência disponível).

O bucket markdoc da CLI processa arquivos Markdoc preservando o frontmatter e as tags personalizadas, enquanto o bucket json cuida do catálogo de strings de UI. Ambos traduzem apenas o delta por meio do seu engine de localização e gravam arquivos por idioma ao lado da origem.

Pré-requisitos#

1

Crie um engine de localização

Cada execução da CLI envia o conteúdo por um engine de localização — a configuração que determina qual modelo de LLM, glossário, voz da marca e instruções serão aplicados. Crie um no dashboard da Lingo.dev e gere uma chave de API.

2

Verifique o Node.js

A CLI exige Node.js 18 ou superior:

bash
node -v
3

Configure seu projeto Next.js

Seu projeto precisa do App Router (src/app/) e de um diretório de conteúdo por idioma. O repositório de demonstração usa src/content/[locale]/ com duas subpastas (pages/ e blog/) mais um arquivo ui.json. Consulte internationalization do Next.js para entender o básico do roteamento.

Organize o conteúdo#

Separe o conteúdo por função. Páginas e posts longos são escritos em Markdoc; strings curtas de UI ficam em JSON para que os componentes possam carregá-las diretamente.

text
src/content/
  en/                  # Source locale
    pages/home.md      # Long-form Markdoc
    blog/hello.md
    ui.json            # UI strings (navbar, CTAs, button states)
  es/                  # Target locales – generated by Lingo.dev
  fr/
  de/

Arquivos Markdoc aceitam frontmatter para metadados por página (título, descrição, data, autor) e tags personalizadas renderizadas como componentes React. Uma página mínima se parece com isto:

markdown
---
title: Author once in Markdoc, ship in every language.
description: An example Next.js App Router app that localizes Markdoc with Lingo.
---

{% inline-callout type="info" %}
This page is authored in Markdoc and translated by Lingo.dev.
{% /inline-callout %}

## Built from three pieces

Markdoc custom tags render as React components – even interactive ones.

Configure a CLI#

Crie um arquivo i18n.json na raiz do projeto. Declare dois buckets — um para o conteúdo em Markdoc e outro para o catálogo de strings de UI:

json
{
  "$schema": "https://lingo.dev/schema/i18n.json",
  "version": "1.15",
  "locale": {
    "source": "en",
    "targets": ["es", "fr", "de"]
  },
  "buckets": {
    "markdoc": {
      "include": [
        "src/content/[locale]/pages/*.md",
        "src/content/[locale]/blog/*.md"
      ]
    },
    "json": {
      "include": ["src/content/[locale]/ui.json"]
    }
  }
}

O placeholder [locale] é resolvido para cada código de idioma configurado. Com source: "en", a CLI lê de src/content/en/ e grava os arquivos traduzidos em src/content/es/, src/content/fr/ e src/content/de/.

Catálogos em arquivo único

Se suas strings de UI estiverem em um único arquivo JSON com vários idiomas, em vez de um arquivo por idioma, use o tipo de bucket json-per-locale. Consulte Static Content Localization para ver a lista completa de tipos de bucket.

Renderize Markdoc no App Router#

Uma rota dinâmica típica carrega um documento e renderiza a árvore transformada. O repositório de demonstração expõe um helper simples:

ts
// src/lib/markdoc.ts
export async function loadDoc(
  locale: Locale,
  collection: "pages" | "blog",
  slug: string,
) {
  const raw = await fs.readFile(
    path.join(process.cwd(), "src/content", locale, collection, `${slug}.md`),
    "utf8",
  );
  const ast = Markdoc.parse(raw);
  const frontmatter = ast.attributes.frontmatter
    ? parseFrontmatter(ast.attributes.frontmatter)
    : {};
  const content = Markdoc.transform(ast, { ...schema, variables: { frontmatter } });
  return { frontmatter, content };
}

A página do App Router é um wrapper enxuto que combina o documento com strings de UI específicas do idioma:

tsx
// src/app/[lang]/page.tsx
export default async function Home({ params }: PageProps<"/[lang]">) {
  const { lang } = await params;
  const doc = await loadDoc(lang, "pages", "home");
  const { home } = await getMessages(lang);

  return (
    <main>
      <h1>{doc.frontmatter.title}</h1>
      {renderMarkdoc(doc.content)}
    </main>
  );
}

As tags personalizadas do Markdoc (callout, bento, blog-hero etc.) são declaradas em markdoc.schema.ts e conectadas a componentes React em src/components/markdoc/. Consulte a documentação do schema do Markdoc para ver a API completa.

Detecte o idioma no middleware#

O middleware do Next.js inspeciona a requisição antes que a rota seja renderizada. Use-o para redirecionar caminhos sem prefixo para o idioma com melhor correspondência com base no cabeçalho Accept-Language:

ts
// src/middleware.ts
export function middleware(request: NextRequest) {
  const { pathname } = request.nextUrl;
  const hasLocale = locales.some(
    (locale) => pathname === `/${locale}` || pathname.startsWith(`/${locale}/`),
  );
  if (hasLocale) return;

  const locale = pickLocale(request); // parses Accept-Language
  const url = request.nextUrl.clone();
  url.pathname = `/${locale}${pathname === "/" ? "" : pathname}`;
  return NextResponse.redirect(url);
}

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

Os visitantes chegam a /en, /es, /fr ou /de sem precisar digitar o prefixo.

Traduza localmente#

Defina sua chave de API e execute a CLI:

bash
export LINGO_API_KEY="your-api-key"
npx lingo.dev@latest run

A CLI lê todos os arquivos que correspondem aos padrões dos seus buckets, identifica entradas ainda não traduzidas usando o lockfile, traduz apenas o delta por meio do seu engine de localização e grava os resultados no diretório de cada idioma de destino. Chaves de frontmatter, tags personalizadas do Markdoc e estruturas JSON são preservadas — só o texto traduzível muda.

Para segmentar um idioma específico durante o desenvolvimento:

bash
npx lingo.dev@latest run --target-locale es

Automatize com GitHub Actions#

Adicione um arquivo de workflow em .github/workflows/translate.yml para traduzir a cada push:

As traduções são commitadas diretamente na main — zero atrito, ideal para equipes pequenas:

yaml
name: Translate
on:
  push:
    branches: [main]
permissions:
  contents: write
jobs:
  translate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Lingo.dev
        uses: lingodotdev/lingo.dev@main
        with:
          api-key: ${{ secrets.LINGODOTDEV_API_KEY }}

Armazene sua chave de API como LINGODOTDEV_API_KEY em Settings > Secrets and variables > Actions no repositório do GitHub.

Verifique antes de fazer deploy#

Use a flag --frozen como gate de deploy para garantir que nenhum conteúdo sem tradução chegue à produção. A CLI retorna um status diferente de zero se houver qualquer entrada que precise de tradução:

bash
npx lingo.dev@latest run --frozen

Adicione isso como uma etapa separada de CI antes do build do Next.js:

yaml
- name: Verify translations
  run: npx lingo.dev@latest run --frozen
- name: Build
  run: pnpm build

Próximos passos#

Static Content Localization
Tipos de bucket para Markdown, MDX, JSON, YAML e mais
Localização de aplicações web
Padrões de strings de UI em frameworks web comuns
CI/CD Workflows
Padrões para GitHub Actions, GitLab CI e Bitbucket Pipelines
Glossários
Proteja nomes de marca e termos técnicos contra tradução

Esta página foi útil?

Max PrilutskiyMax Prilutskiy·Atualizado há 4 dias·6 min de leitura