Nous avons ajouté le japonais et le portugais brésilien à l'ensemble de notre site pour 31 €

Le 29 septembre, nous avons lancé globalize.now en japonais et en portugais brésilien. Chaque page, chaque grille tarifaire et les 61 articles de blog. La traduction en elle-même a pris huit minutes, et l'application a facturé environ 31 €. globalize.now est une infrastructure de localisation propulsée par l'IA, et voici ce que cela a donné sur notre propre site, avec chaque chiffre tiré de la page de la tâche et de l'historique Git plutôt que de notre mémoire.

Notre article sur ce qu'a coûté le playbook de croissance par la localisation en 2017 se termine en disant que nous ne publions pas encore nos propres chiffres. En voici le premier. C'est un chiffre de coût, pas un chiffre de croissance : personne n'a encore eu le temps de visiter /ja/.

Qu'avons-nous exactement traduit ?

Tout le site, deux fois. Voici l'inventaire, comptabilisé depuis le dépôt :

  • Interface : 1 782 chaînes anglaises réparties sur cinq catalogues de messages (le site principal, la tarification, les pages de comparaison, les intégrations et les exemples de traduction), soit environ 21 000 mots.
  • Blog : 61 articles, environ 110 000 mots.
  • Langues cibles : japonais (ja) et portugais brésilien (pt-BR).

Cela représente environ 130 000 mots source répartis sur deux langues. La pull request a touché 170 fichiers et ajouté 34 681 lignes. Après la fusion, le sitemap répertorie 811 URL réparties sur 11 locales, et le site génère 962 pages statiques.

Combien de temps cela a-t-il pris ?

Huit minutes de traduction, puis une passe de contrôle qualité plus longue. Arturs, notre CTO, a ajouté les deux langues au projet et la tâche a démarré le main à 08 h 56 UTC. La page de la tâche détaille tout :

ÉtapeDurée
Traduction (11 264 nouvelles chaînes, 5 632 par langue)8 min 1 s
Revue d'assurance qualité automatisée27 min 11 s
Livraison vers une pull request5 min 29 s

Le commit contenant les deux langues est arrivé à 09 h 29 UTC. Les 45 106 autres chaînes de la tâche provenaient de la mémoire de traduction, car les huit langues existantes n'avaient pas changé.

Arturs avait estimé dix minutes en en parlant sur notre chat d'équipe. Il avait raison pour la traduction et il était optimiste pour l'ensemble de la tâche ; l'écart, c'est la passe d'assurance qualité. Nous préférons passer 27 minutes de temps machine à vérifier plutôt que de sauter cette étape.

Qu'a détecté l'assurance qualité automatisée ?

72 signalements sur 11 264 nouvelles chaînes, tous classés mineurs. 11 192 ont été validées sans réserve, et l'assurance qualité a appliqué 182 corrections automatiques au passage.

Les signalements ouverts venaient surtout de la vérification de longueur, prudente face au japonais. « Pricing » devient 料金, deux caractères, et un ratio de longueur de 0,29 tombe juste sous le seuil de 0,3. C'est une traduction correcte qui déclenche une heuristique conçue pour les langues alphabétiques, pas une erreur. Nous laissons les signalements visibles quand même : un contrôle qui ne se déclenche jamais n'est pas un contrôle.

Combien cela a-t-il coûté ?

Environ 31 € : la vue des coûts par langue du projet affiche 15,72 € pour le japonais et 16,15 € pour le portugais brésilien. C'est ce que facture l'application, le même tarif qu'un client traduisant le même volume verrait. Ce n'est ni notre coût de modèle interne, ni une remise.

Sur environ 260 000 mots traduits, cela représente environ 12 centimes pour 1 000 mots. Rien d'autre n'a été facturé en plus. Il n'y a ni frais par langue ni frais par utilisateur, donc ajouter la douzième langue coûte le même prix qu'ajouter la troisième. Les offres actuelles sont détaillées sur la page tarifs.

Qu'a réellement impliqué le travail d'ingénierie ?

Une seule pull request, fusionnée le même après-midi, et rien à voir avec la traduction. À son ouverture, la tâche de traduction a été relancée sur celle-ci et a repris directement 56 370 des 56 390 chaînes depuis la mémoire de traduction, si bien que les catalogues déjà traduits sont arrivés dans les nouveaux fichiers en sept minutes. La traduction est la partie qui a été automatisée. Enregistrer une nouvelle locale sur un site Next.js reste votre code, et il vaut mieux savoir ce que « votre code » signifie avant de le planifier.

Ajouter une locale à next-intl tient en une ligne dans la config de routage. Tout ce qui construit une URL, lit une locale ou liste vos locales constitue le reste du diff :

  • Routage : la liste des locales, plus une surcharge de préfixe d'URL pour pt-BR (section suivante).
  • Métadonnées SEO : les clusters hreflang, les canonicals, og:locale (ja_JP, pt_BR) et la liste des locales sur laquelle bouclent les aides aux métadonnées.
  • Formatage : les balises Intl ja-JP et pt-BR, pour que les dates et les nombres s'affichent correctement.
  • Sélecteur de langue : il renvoie vers chaque locale avec un véritable <a href hreflang>, afin que les robots d'indexation puissent le suivre.
  • Sitemap et vérifications : le générateur de sitemap, la vérification du lastmod, la vérification des liens internes et le vérificateur de traduction ont tous dû apprendre les deux nouveaux codes.
  • Catalogues : fichiers .po vides, avec seulement l'en-tête, créés pour les deux locales, puis remplis dans la même pull request à partir de la mémoire de traduction.

Si votre site est moins personnalisé que le nôtre, la majeure partie de cette liste relève de la config. Si vous construisez des URL à la main quelque part, ce que fait presque tout site à un moment ou un autre, vous le découvrirez la première fois qu'un lien sortira faux. Le guide développeur couvre la configuration, et ce que fait réellement un agent de localisation IA couvre la répartition entre ce qui est automatisé et ce qui ne l'est pas.

Pourquoi le portugais brésilien est-il sur /pt-br/ et non /pt-BR/ ?

Parce qu'une étiquette de langue et un segment d'URL sont deux choses différentes, avec des rôles différents.

L'étiquette correcte est pt-BR, selon BCP 47. Nous l'utilisons partout où une machine lit la langue : noms de fichiers, <html lang>, hreflang, og:locale et Intl. Seule l'URL est mise en minuscules :

// i18n/routing.ts (trimmed)
const prefixes = {
  "pt-BR": "/pt-br",
} as const;

export const routing = defineRouting({
  locales: ["en", "it", "de", "fr", "es", "lv", "hi", "lt", "et", "ja", "pt-BR"],
  defaultLocale: "en",
  localePrefix: { mode: "always", prefixes },
});

/** The URL path segment for a locale: `pt-BR` → `pt-br`, `de` → `de`. */
export function localeUrlSegment(locale: string): string {
  const prefix = (prefixes as Record<string, string | undefined>)[locale];
  return prefix ? prefix.slice(1) : locale;
}

Les chemins à casse mixte sont mal saisis, et un site qui répond à la fois sur /pt-BR/ et /pt-br/ se retrouve avec deux copies de chaque page qui se font concurrence. Donc /pt-BR/ redirige vers /pt-br/, et localeUrlSegment() construit chaque URL faite à la main à partir de la table des préfixes. Une seule source de vérité signifie que le sélecteur de langue, les canonicals et le sitemap ne peuvent pas diverger.

Pourquoi le japonais et le portugais brésilien ?

Ce sont de grandes langues du web que nous ne couvrions pas encore. Selon le décompte de W3Techs le jour de notre déploiement, le japonais est la langue de contenu de 4,9 % des sites web, et le portugais de 4,1 %.

L'argument en faveur de cette démarche est plus ancien que nous. CSA Research a interrogé 8 709 consommateurs dans 29 pays en 2020, et 76 % ont déclaré préférer acheter des produits accompagnés d'informations dans leur propre langue. Ça, c'est le côté demande. Ce qui a changé, c'est le côté offre : deux langues, c'était autrefois une relation avec un prestataire ; aujourd'hui, cela coûte 31 €.

Notre propre règle pour choisir des langues est celle décrite dans l'article sur le playbook de croissance. Regardez d'où vient déjà votre trafic, ajoutez deux langues, ne changez rien d'autre et mesurez pendant un trimestre. C'est exactement ce que nous ferons avec ces deux-là.

Qu'avons-nous pas encore vérifié ?

La relecture native. Personne lisant le japonais ou le portugais brésilien nativement n'est encore passé sur le résultat.

Ce que nous avons vérifié : l'assurance qualité automatisée sur chaque chaîne, le build qui passe tous les contrôles de préconstruction, et les pages testées ponctuellement en préproduction qui renvoient un code 200 avec les bons lang, canonical et hreflang, et s'affichent intégralement. Ce qu'un build ne peut pas vérifier, c'est si une phrase sonne comme si une personne l'avait écrite. Nous l'avons appris à nos dépens en auditant notre propre allemand et notre propre français, et en découvrant un registre erroné sur des pages entières.

La relecture vient donc ensuite, et nous mettrons à jour cet article avec ce qu'elle révèle, y compris ce qui s'avérerait incorrect.

Pourriez-vous faire pareil sur votre site ?

Si vos chaînes vivent déjà dans des catalogues, oui, et la partie traduction ne prendra que quelques minutes. Si elles sont encore codées en dur dans les composants, la conversion vient d'abord. Elle s'exécute une seule fois, dans le flux de connexion intégré à l'app, et les jobs push traduisent ensuite les nouvelles chaînes au fil de l'eau. Le guide vibe coder couvre les apps construites avec Lovable, Bolt ou Cursor, où les chaînes codées en dur sont la norme.

Le coût évolue avec le nombre de mots traduits, pas avec le nombre de langues ni le nombre de personnes dans l'équipe. C'est pour cela que la réponse à « est-ce que ça vaut le coup d'ajouter une langue ? » a changé. La mesure coûte désormais moins cher que la réunion qui en parle.

Essayer sur votre propre dépôt

Deux langues nous ont coûté huit minutes de traduction et environ 31 €. Connectez votre dépôt, choisissez deux langues déjà ciblées par vos statistiques, et découvrez ce à quoi ressemble votre propre ticket de caisse.

globalize.now transforme le texte codé en dur de votre application en fichiers de traduction prêts à l'emploi et les maintient à jour au fur et à mesure de vos déploiements.

Essayer globalize.now gratuitement