Portfolio multilingue : atteindre un public mondial
Un portfolio qui parle six langues, où le plus dur a été de décider ce qu'il ne fallait pas traduire.
La décision qui a tout structuré
Une personne qui développe au Brésil et lit « data pipelines » s'attend à voir data pipelines, pas canalizações de dados. Le terme anglais est celui du métier. Le traduire sonne maladroit au mieux, condescendant au pire.
Cet unique exemple a fixé la règle de tout le système : le travail n'est pas de traduire un portfolio en six langues. C'est de décider, terme par terme, ce qui doit survivre sans traduction — puis de rendre cette décision reproductible.
Ce que fait le système
Le site tourne sur next-intl avec localePrefix: 'always', donc chaque route est imbriquée sous un segment de locale. i18n/config.ts en définit six :
export const locales = ['en', 'pt-BR', 'es', 'ja', 'fr', 'de'] as const;
Le contenu vit dans des fichiers suffixés par locale. hello-world.mdx est la base anglaise ; hello-world.pt-BR.mdx et hello-world.ja.mdx se trouvent à côté. lib/content.ts cherche le fichier du locale demandé et bascule vers la base anglaise lorsqu'il est absent.
Les métadonnées de tri viennent toujours du fichier de base. Date, pinned et lastUpdated sont lus depuis la source anglaise quel que soit le locale rendu, de sorte qu'un article ne peut pas occuper une position différente dans la liste japonaise et dans la liste anglaise.
Les chaînes d'interface basculent par deep merge. i18n/request.ts charge messages/en.json comme base et fusionne le catalogue du locale par-dessus, clé par clé. Une clé manquante affiche la chaîne anglaise plutôt qu'une erreur MISSING_MESSAGE, et un catalogue incomplet peut être publié sans risque.
Le fallback est signalé, pas silencieux
Une version antérieure de cette page affirmait que le repli vers l'anglais se faisait silencieusement. C'était le mauvais objectif, et ce n'est pas ce que fait le site.
Quand une page bascule, getContentLocaleStatus() renvoie 'fallback', et deux choses suivent : l'élément de contenu est marqué lang="en", pour que lecteurs d'écran et moteurs de recherche sachent quelle langue ils reçoivent réellement, et un avertissement de traduction visible apparaît au-dessus du contenu.
Servir discrètement de l'anglais sous une URL /ja/ tromperait à la fois la personne qui lit et le crawler. Le dire coûte une ligne d'interface.
Deux pipelines, deux métiers
DeepL gère la traduction directe : rapide, cohérente, et encline à sur-traduire le vocabulaire technique. Un agent Claude gère la transcréation : il adapte les idiomes, réordonne les phrases pour un déroulé naturel, et garde les termes techniques en anglais selon les règles ci-dessous.
npm run translate # DeepL: messages/*.json
npm run translate:mdx # DeepL: MDX content
npm run i18n:mdx # Claude: transcreation
npm run i18n:sync # Claude: fill missing translations
Les deux écrivent des fichiers suffixés par locale à côté de la source anglaise. Aucun n'est utilisé les yeux fermés : la sortie est relue avant publication, en vérifiant que les clés du frontmatter restent en anglais, que les chemins d'images et les URLs sont intacts, que les blocs de code et les tableaux ont survécu, et que les valeurs de className n'ont pas été traduites.
Les règles de localisation en pratique
Toujours traduire : navigation et libellés d'interface, contenu des articles, champs de formulaire, appels à l'action.
Toujours garder en anglais : noms de produits (Next.js, TypeScript, Claude), noms d'entreprises (Nike, Meta), et le vocabulaire technique que chaque public emploie déjà en anglais — API, dashboard, data pipeline, template.
Par locale :
- pt-BR — "dashboard" et non "painel", "template" et non "modelo", "e-commerce" et non "comércio eletrônico"
- es — "dashboard" et non "panel de control", "marketers" et non "vendedores"
- ja — noms de produits en alphabet latin, pas en katakana ; katakana pour les emprunts courants
- fr — "dashboard" et non "tableau de bord" ; CTAs naturels ("Contactez-moi")
- de — "du" informel, emprunts anglais pour les termes techniques, noms avec majuscule
Projects
canalizações de dados
data pipelines
Ce que je me dirais au départ
La localisation est une décision produit déguisée en décision technique. Le pipeline était la partie facile ; les règles sur ce qu'il faut laisser tranquille étaient le vrai travail, et c'est la partie qu'il faut écrire, parce que c'est celle qu'un outil de traduction se trompera joyeusement à chaque fois.
La mesure du succès n'est pas que le site ait six langues. C'est qu'une personne à São Paulo ou à Tokyo y retrouve le vocabulaire qu'elle aurait employé.
Une note sur les traductions
Les traductions ici sont générées par machine, puis relues au regard des règles ci-dessus. La traduction automatique est un point de départ, pas un produit fini.
Si quelque chose sonne mal dans votre langue, la correction est bienvenue via le formulaire de contact. Les locuteurs natifs repèrent ce que l'automatisation manque.
Résultats
- Six locales : anglais, portugais (Brésil), espagnol, japonais, français et allemand
- Deux pipelines : DeepL pour la traduction directe, un agent Claude pour la transcréation
- Des URLs par locale avec des alternates hreflang pour chaque langue
- Les traductions manquantes basculent vers l'anglais, signalées plutôt que masquées
- Les règles de localisation gardent en anglais les termes techniques attendus par chaque public