|
Documentation
Réserver une démoPlateforme
PlateformeMCPCLIAPIWorkflows
Guides
Changelog

Localisation

  • Aperçu
  • API de traduction
  • Localisation d’applications web
  • Localisation d’apps mobiles
  • iOS avec String Catalogs
  • Android avec strings.xml
  • Localisation des e-mails
  • Contenu statique (ex. : .md, .json)
  • Next.js avec Markdoc
  • Rails avec i18n

Workflows

  • Configurer un moteur avec le MCP
  • Triage Jira
  • CI/CD

Localisation de l’App Router de Next.js avec Markdoc

Le CLI de Lingo.dev traduit les fichiers Markdoc et les catalogues JSON de chaînes d’interface via un moteur de localisation configuré. Markdoc est un format de rédaction basé sur Markdown, avec des balises personnalisées typées propulsées par React — idéal pour les sites Next.js App Router qui combinent contenus longs et composants interactifs.

Ce guide vous accompagne de bout en bout dans la localisation d’un site Next.js App Router : configuration du CLI, organisation du contenu par langue, rendu de Markdoc dans des routes dynamiques et automatisation des traductions avec l’application GitHub de Lingo.dev.

Dépôt de démonstration

Clonez ou forkez lingodotdev/markdoc-nextjs-localization-example pour suivre ce guide pas à pas. Le dépôt contient une application Next.js App Router prête à l’emploi avec du contenu Markdoc, une configuration du CLI Lingo.dev et un workflow CI.

Comment fonctionne la localisation avec Next.js + Markdoc#

La plupart des sites Next.js App Router répartissent leur contenu localisé en deux couches :

CoucheCe qu’elle contientFichier d’exemple
Contenus longsPages marketing, documentation, articles de blogsrc/content/en/pages/home.md
Chaînes d’interfaceLibellés de navigation, CTA, états de boutonssrc/content/en/ui.json

Les routes se trouvent sous src/app/[lang]/ et chargent, au moment de la requête, les fichiers correspondant à la langue cible. Un middleware détermine une langue par défaut à partir de l’en-tête Accept-Language du navigateur et redirige les chemins nus comme / vers /en (ou vers la meilleure correspondance).

Le CLI analyse les fichiers Markdoc tout en préservant le frontmatter et les balises personnalisées, et gère le catalogue des chaînes d’interface en JSON. Il traduit le delta via votre moteur de localisation et génère des fichiers par langue à côté de la source.

Prérequis#

1

Créer un moteur de localisation

À chaque exécution du CLI, le contenu passe par un moteur de localisation — la configuration qui détermine quel modèle de LLM, glossaire, voix de marque et règles s’appliquent. Créez-en un dans le tableau de bord Lingo.dev et générez une clé API pour la CI.

2

Vérifier Node.js

Le CLI nécessite Node.js 22 ou version ultérieure :

bash
node -v
3

Configurer votre projet Next.js

Votre projet doit utiliser l’App Router (src/app/) et un répertoire de contenu par langue. Le dépôt de démonstration utilise un répertoire par langue sous src/content/ (par exemple src/content/en/), avec deux sous-dossiers (pages/ et blog/) ainsi qu’un fichier ui.json. Consultez l’internationalisation de Next.js pour les bases du routage.

Organiser le contenu#

Organisez le contenu selon son rôle. Les pages et articles longs sont rédigés en Markdoc ; les chaînes d’interface plus courtes sont stockées en JSON afin que les composants puissent les charger directement.

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/

Les fichiers Markdoc prennent en charge le frontmatter pour les métadonnées de page (titre, description, date, auteur), ainsi que des balises personnalisées rendues sous forme de composants React. Voici à quoi ressemble une page minimale :

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.

Configurer le CLI#

Installez le CLI et connectez-vous :

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

Ensuite, générez la configuration et reliez-la à votre moteur :

bash
lingo init
lingo link

lingo init crée .lingo/config.json avec vos langues source et cibles, ainsi que les motifs de fichiers à traduire ; lingo link ajoute votre orgId et votre engineId. Validez .lingo/config.json afin que toute l’équipe et chaque exécution CI partagent la même configuration.

Pour ce projet, la configuration définit deux motifs de fichiers : un pour le contenu Markdoc et un pour le catalogue de chaînes d’interface :

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" }
  ]
}

Le segment de langue dans chaque chemin est remplacé pour chaque langue cible : src/content/en/pages/home.md devient src/content/es/pages/home.md, et src/content/en/ui.json devient src/content/de/ui.json. Le chemin source doit contenir le code langue. Les formats sont détectés automatiquement à partir de l’extension du fichier ; les fichiers Markdoc (.md) et JSON (.json) n’ont donc pas besoin de type explicite. Consultez Configuration et Formats pour en savoir plus.

Catalogues monofichier

Le nouveau CLI attend un fichier par langue, avec le code langue dans le chemin (comme ci-dessus). Si vos chaînes d’interface se trouvent dans un seul fichier JSON multilingue, cette structure (l’ancien bucket json-per-locale) n’est pas encore prise en charge par le nouveau CLI – conservez-la avec le legacy CLI et suivez le changelog pour savoir quand ce sera pris en charge. La séparation en un fichier par langue est l’approche recommandée.

Rendre Markdoc dans l’App Router#

Une route dynamique typique charge un document et affiche l’arbre transformé. Le dépôt de démonstration expose un petit utilitaire :

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 };
}

La page App Router est une fine couche d’adaptation qui associe le document à des chaînes d’interface propres à chaque langue :

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>
  );
}

Les balises Markdoc personnalisées (callout, bento, blog-hero, etc.) sont déclarées dans markdoc.schema.ts et reliées à des composants React sous src/components/markdoc/. Consultez la documentation du schéma Markdoc pour l’API complète.

Détecter la langue dans le middleware#

Le middleware Next.js inspecte la requête avant le rendu d’une route. Utilisez-le pour rediriger les chemins nus vers la langue la plus pertinente en fonction de l’en-tête 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|.*\\..*).*)", ],
};

Les visiteurs arrivent sur /en, /es, /fr ou /de sans jamais avoir à saisir le préfixe.

Traduire en local#

Après lingo login, lancez un push. Lors de la première exécution – ou après l’ajout d’une nouvelle langue cible – remplissez d’abord l’historique complet :

bash
lingo push --backfill-missing

Lors des exécutions suivantes, poussez simplement le delta :

bash
lingo push

lingo push lit tous les fichiers correspondant à vos motifs, identifie les entrées non traduites à l’aide du fichier de verrouillage (.lingo/lock.json, versionné), traduit le delta via votre moteur de localisation, attend la fin du traitement, puis écrit les résultats dans le répertoire de chaque langue cible. Les clés du frontmatter, les balises personnalisées Markdoc et la structure du JSON sont préservées – seul le texte traduisible change. Pour récupérer des traductions produites ailleurs (par exemple par la CI), exécutez lingo pull.

Pour limiter une exécution à certains fichiers, passez un glob :

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

Automatiser en CI#

Installez l’application GitHub Lingo.dev et connectez-la à votre dépôt. Elle lit .lingo/config.json et le engineId associé côté serveur, puis ouvre une pull request de traduction à chaque modification du contenu source – sans fichier de workflow, sans runner, sans secret de clé API et sans avoir à jongler avec le fichier de verrouillage.

Vérifier avant le déploiement#

Utilisez lingo check comme garde-fou au déploiement pour vous assurer qu’aucun contenu non traduit ne parte en production. La commande renvoie un statut non nul si certaines entrées nécessitent encore une traduction :

bash
lingo check

Ajoutez ceci comme étape de CI distincte avant votre build Next.js :

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

Étapes suivantes#

Static Content Localization
Markdown, MDX, JSON, YAML et bien d’autres formats de fichier
Web App Localization
Modèles de chaînes d’interface dans les frameworks web les plus courants
CI/CD Workflows
Application GitHub et patterns de runners auto-hébergés
Glossaires
Verrouillez les noms de marque et les termes techniques pour éviter toute traduction

Cette page vous a-t-elle été utile ?

Max PrilutskiyMax Prilutskiy·Mis à jour il y a 13 jours·7 min de lecture