AccueilClientsExpertisesBlogOpen SourceContact

8 octobre 2024

Notre workflow de traduction d’articles avec l’API OpenAI

3 minutes de lecture

Notre workflow de traduction d’articles avec l’API OpenAI
🇺🇸 This post is also available in english

Chez Premier Octet, nous aimons partager nos articles techniques avec le plus grand nombre. Pour toucher une audience internationale, nous avons mis en place un script maison qui nous permet de traduire automatiquement nos articles du français vers l’anglais, sans nous casser la tête. Une fois traduit, un bandeau s'affiche en haut de l'article pour signaler que l'article est disponible en anglais (comme au dessus de ce paragraphe).

Dans cet article, je vous propose de découvrir comment nous nous y prennons.

Notre structure

Notre site internet et donc le présent blog utilisent le framework Next.js. Nos articles de blog sont stockés sous forme de fichiers statiques au format MDX, un format qui combine Markdown et composants React.

Chaque article français est stocké dans le répertoire /src/pages/blog, et ceux en anglais dans le répertoire /src/pages/blog/en :

src/
  pages/
    blog/
      nouveautes-react-19.mdx
      en/
        nouveautes-react-19.mdx

Le routing de Next.js suit simplement la structure des dossiers.

Notre workflow de traduction

Afin de traduire automatique nos articles français en anglais, nous avons développé un script permettant d'effectuer cette tâche de manière automatisée. Il nous suffit de lancer la commande suivante pour créer une nouvelle page en anglais à partir du contenu français :

yarn post:translate src/pages/blog/mon-article.mdx

La commande est définie dans notre fichier package.json :

{
  "scripts": {
    "post:translate": "tsx scripts/translate.ts"
  }
}

Notre script, translate.ts expose une fonction "auto-exécutante" qui attend en argument le chemin du fichier MDX à traduire :

;(async () => {
  const mdxPath = process.argv?.[2]

  if (!mdxPath) {
    console.error('❌ no path')
    return
  }

  await translate(mdxPath)
})()

Voyons maintenant comment la fonction translate fonctionne.

Lecture du fichier MDX

Nous commençons par lire le contenu du fichier MDX en entier :

export const translate = async (mdxPath: string) => {
  const content = await fs.readFile(mdxPath, 'utf-8')
}

Appel à GPT pour la traduction

Une fois le fichier lu, le script initialise le client OpenAI à l’aide de la clé API stockée dans nos variables d’environnement. Ensuite, il envoie une requête pour traduire le contenu :

const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
})

const stream = await openai.chat.completions.create({
  model: 'gpt-4o',
  messages: [
    { role: 'system', content: 'Translate the provided MDX text from French to English...' },
    { role: 'user', content },
  ],
  stream: true,
})

Le paramètre stream: true nous permet d’obtenir une traduction en continu, idéale pour avoir un feedback en temps réel.

Feedback sur la progression

Avec un article assez conséquent, la traduction peut prendre plusieurs secondes. Nous avons donc ajouté une barre de progression indiquant l’état d’avancement de la traduction.

À chaque nouveau bloc de texte traduit, la barre se met à jour :

let translatedContent = ''
const bar = new ProgressBar('🇺🇸  Translating [:bar] :percent', { total: 100 })
let currentProgression = 0

for await (const part of stream) {
  translatedContent += part.choices[0]?.delta?.content || ''
  const percent = Math.floor((translatedContent.length * 100) / content.length)

  if (percent > currentProgression) {
    bar.tick()
    currentProgression = percent
  }
}

Nous utilisons le npm package progress pour gérer le rendu de la barre de progression.

Cela nous permet de suivre l’avancement de la traduction en temps réel :

$ tsx scripts/translate.ts src/pages/blog/notre-workflow-pour-traduire-nos-articles-avec-gpt.mdx
🇺🇸  Translating [░░░░░░----------------------------------------] 13%

Ajustement du contenu traduit

Une fois la traduction terminée, le script procède à quelques ajustements. Il modifie le chemin d’importation du composant BlogPost et ajoute l’attribut lang: en dans le frontmatter :

const updatedContent = translatedContent
  .replace('../../components/Layout/BlogPost', '../../../components/Layout/BlogPost')
  .replace(/^(---\s*\n)/, '$1lang: en\n')

Ces modifications garantissent que la version anglaise est correctement configurée et respecte la structure des dossiers.

Sauvegarde du fichier traduit

Enfin, le fichier traduit est enregistré dans un sous-dossier en, ce qui permet de séparer proprement les versions françaises et anglaises :

const enPath = path.join(path.dirname(mdxPath), 'en', path.basename(mdxPath))
await fs.mkdir(path.dirname(enPath), { recursive: true })
await fs.writeFile(enPath, updatedContent)
console.log(`✅ Translation saved to: ${enPath}`)

Une fois sauvegardé, un message de confirmation nous informe que tout s’est bien passé.

Grâce à cette automatisation, nous gérons facilement les versions multilingues de nos articles. La traduction devient un processus rapide et fluide, nous permettant de nous concentrer sur la création de contenu tout en touchant une audience plus large.

Et puisqu’on adore tous les moments d’inception, consultez cet article traduit par ce même script juste ici !

Enfin, vous pouvez retrouver le script complet sur ce gist.

👋

À découvrir également

AI et UI #1 - Filtres intelligents avec le SDK Vercel AI et Next.js

12 Jun 2024

AI et UI #1 - Filtres intelligents avec le SDK Vercel AI et Next.js

Dans ce premier article d’une série consacrée à l’IA et l’UI, je vous propose de découvrir différentes manières d’intégrer ces modèles d’IA dans vos applications React pour améliorer l’expérience utilisateur.

par

Baptiste

Premiers pas avec Replicate

05 Sep 2023

Premiers pas avec Replicate

Filtres, transformations, machine learning, Replicate vous propose des effets pour tous les goûts...

par

Laureen

Premier Octet vous accompagne dans le développement de vos projets avec gpt

En savoir plusNous contacter
18 avenue Parmentier
75011 Paris
+33 1 43 57 39 11
hello@premieroctet.com

Suivez nos aventures

GitHub
X (Twitter)
Flux RSS

Naviguez à vue