|
Documentação
Marcar uma demonstraçãoPlataforma
PlataformaMCPCLIAPIWorkflows
Guias
Changelog

Localização

  • Visão geral
  • API de Tradução
  • Localização de aplicações web
  • Localização de Apps Mobile
  • iOS com String Catalogs
  • Android com strings.xml
  • Localização de emails
  • Conteúdo Estático (ex.: .md, .json)
  • Next.js com Markdoc
  • Rails com i18n

Workflows

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

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

A CLI da Lingo.dev traduz ficheiros Markdoc e catálogos JSON de strings de UI através de um motor de localização configurado. O Markdoc é um formato de autoria baseado em Markdown, com tags personalizadas tipadas e suportadas por 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 Next.js App Router: configurar a CLI, organizar conteúdo por idioma, renderizar Markdoc em rotas dinâmicas e automatizar traduções com a GitHub App da Lingo.dev.

Repositório de demonstração

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

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 incluiFicheiro de exemplo
Conteúdo extensoPáginas de marketing, documentação, artigos de bloguesrc/content/en/pages/home.md
Strings de UIRótulos da barra de navegação, CTAs, estados de botõessrc/content/en/ui.json

As rotas ficam em src/app/[lang]/ e leem os ficheiros do idioma correspondente no momento do pedido. Um middleware escolhe um idioma predefinido com base no cabeçalho Accept-Language do navegador e redireciona caminhos sem prefixo, como /, para /en (ou para a melhor correspondência).

A CLI analisa ficheiros Markdoc mantendo o frontmatter e as tags personalizadas intactos, e trata o catálogo de strings de UI como JSON. Em ambos os casos, traduz o delta através do seu motor de localização e escreve ficheiros por idioma lado a lado com a origem.

Pré-requisitos#

1

Criar um motor de localização

Cada execução da CLI envia conteúdo através de um motor de localização — a configuração que define que modelo de LLM, glossário, voz da marca e regras são aplicados. Crie um no dashboard do Lingo.dev e gere uma chave de API para CI.

2

Verificar o Node.js

A CLI requer Node.js 22 ou superior:

bash
node -v
3

Configurar o seu projeto em Next.js

O 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 um diretório por idioma em src/content/ (por exemplo, src/content/en/) com duas subpastas (pages/ e blog/) e um ficheiro ui.json. Consulte internationalization do Next.js para as noções básicas de routing.

Organizar o conteúdo#

Separe o conteúdo por função. As páginas e os artigos mais longos são escritos em Markdoc; as strings curtas de UI ficam em JSON para que os componentes as possam carregar 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/

Os ficheiros Markdoc suportam frontmatter para metadados por página (título, descrição, data, autor) e tags personalizadas que são renderizadas como componentes React. Uma página mínima é assim:

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.

Configurar a CLI#

Instale a CLI e inicie sessão:

bash
npm install -g @lingo.dev/cli
lingo login

Depois, gere a configuração e ligue-a ao seu motor:

bash
lingo init
lingo link

lingo init cria .lingo/config.json com os seus idiomas de origem e destino, além dos padrões de ficheiro a traduzir; lingo link adiciona o seu orgId e engineId. Faça commit de .lingo/config.json para que toda a equipa e todas as execuções de CI partilhem a mesma configuração.

Neste projeto, a configuração define dois padrões de ficheiro — um para conteúdo Markdoc e outro para o catálogo de strings de UI:

json
{
  "orgId": "org_...",
  "engineId": "eng_...",
  "sourceLocale": "en",
  "targetLocales": ["es", "fr", "de"],
  "files": [
    { "pattern": "src/content/en/pages/*.md" },
    { "pattern": "src/content/en/blog/*.md" },
    { "pattern": "src/content/en/ui.json" }
  ]
}

O segmento de idioma em cada caminho é substituído por idioma de destino: src/content/en/pages/home.md passa a src/content/es/pages/home.md e src/content/en/ui.json passa a src/content/de/ui.json. O caminho de origem tem de incluir o código do idioma. Os formatos são detetados automaticamente a partir da extensão do ficheiro, por isso os ficheiros Markdoc (.md) e JSON (.json) não precisam de um tipo explícito. Consulte Configuration e Formats para mais detalhes.

Catálogos num único ficheiro

A nova CLI espera um ficheiro por idioma, com o código do idioma no caminho (como acima). Se as suas strings de UI estiverem num único ficheiro JSON multi-idioma, esse formato (o antigo bucket json-per-locale) ainda não é suportado pela nova CLI — mantenha-o na legacy CLI e acompanhe o changelog para saber quando haverá suporte. Dividir em um ficheiro por idioma é a abordagem recomendada.

Renderizar Markdoc no App Router#

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

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 simples que combina o documento com strings de UI específicas de cada 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 ligadas a componentes React em src/components/markdoc/. Consulte a documentação do schema do Markdoc para conhecer a API completa.

Detetar o idioma no middleware#

O middleware do Next.js inspeciona o pedido antes de a rota ser 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 terem de escrever o prefixo.

Traduzir localmente#

Depois de lingo login, execute um push. Na primeira execução — ou depois de adicionar um novo idioma de destino — preencha tudo retroativamente:

bash
lingo push --backfill-missing

Nas execuções seguintes, envie apenas o delta:

bash
lingo push

lingo push lê todos os ficheiros que correspondem aos seus padrões, identifica entradas por traduzir com o ficheiro lock (.lingo/lock.json, com commit feito), traduz o delta através do seu motor de localização, aguarda a conclusão e escreve os resultados no diretório de cada idioma de destino. As chaves de frontmatter, as tags personalizadas de Markdoc e as estruturas JSON são preservadas — apenas o texto traduzível muda. Para obter traduções produzidas noutro local (por exemplo, por CI), execute lingo pull.

Para limitar uma execução a ficheiros específicos, passe um glob:

bash
lingo push "src/content/en/blog/*.md"

Automatize em CI#

Instale a GitHub App da Lingo.dev e aponte-a ao seu repositório. Lê .lingo/config.json e o engineId associado no servidor e abre um pull request de tradução sempre que o conteúdo de origem muda — sem ficheiro de workflow, sem runner, sem segredo de API key e sem gerir ficheiros lock.

Verificar antes do deploy#

Use lingo check como barreira de deployment para garantir que nenhum conteúdo por traduzir chega à produção. Sai com um código diferente de zero se ainda houver entradas por traduzir:

bash
lingo check

Adicione isto como um passo de CI separado antes do build em Next.js:

yaml
- name: Verify translations
  run: lingo check
  env:
    LINGO_API_KEY: ${{ secrets.LINGO_API_KEY }}
- name: Build
  run: pnpm build

Próximos passos#

Static Content Localization
Markdown, MDX, JSON, YAML e muitos outros formatos de ficheiro
Web App Localization
Padrões de strings de UI em frameworks web comuns
CI/CD Workflows
Padrões para GitHub App e runners self-hosted
Glossários
Proteja nomes de marcas e termos técnicos contra tradução

Esta página foi útil?

Max PrilutskiyMax Prilutskiy·Atualizado há 8 dias·7 min de leitura