8 octobre 2024
Notre workflow de traduction d’articles avec l’API OpenAI
3 minutes de lecture
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.
👋