Traducteur de Markdown AI-Powered
🌍 Français | English | Español | 中文 | Deutsch | 日本語 | 한국어 | العربية | हिन्दी | Italiano | Nederlands | Polski | Português | Română | Svenska
📊 Qualité du code
Traducteur de fichiers Markdown utilisant OpenAI, Mistral AI, Claude (Anthropic), Google Gemini et Grok (xAI) — par API, sur le quota d'un abonnement ChatGPT (Codex) ou Grok sans facturation à l'usage, ou via OpenCode, l'agent open source, vers le fournisseur de votre choix : modèle local (Ollama), gratuit, abonnement (GitHub Copilot…) ou clé.
Ce script Python traduit des fichiers Markdown d'une langue source vers une langue cible tout en préservant le formatage, les blocs de code et les métadonnées front matter.
Caractéristiques Principales
- Multi-Provider: 5 API (OpenAI, Mistral, Claude, Gemini, Grok) + 2 CLI sur abonnement, sans facturation à l'usage — Codex (ChatGPT) et Grok — + OpenCode (open source, MIT) vers n'importe quel fournisseur configuré dans OpenCode, y compris un modèle local
- Modèles 2026: GPT-5.6 Terra, Claude Sonnet 5, Gemini 3.7 Flash
- Mode Économique: Option
--ecopour utiliser des modèles plus rapides et moins coûteux - Fichier Unique: Option
--filepour traduire un seul fichier - Segmentation Intelligente: Gestion des textes longs avec limites de tokens par modèle
- Préservation du Code: Les blocs de code ET le code inline (
`...`) sont préservés - Nom de Fichier: Option
--keep_filenamepour conserver le nom original - Mode News: Option
--newspour protéger les citations anglaises et gérer les drapeaux dans les articles d'actualité - Configuration .env: Support du fichier
.envpour les clés API - Note de Traduction: Ajout optionnel d'une note en fin de document
Installation
Pour utiliser l'outil
pip install ai-powered-markdown-translator
La commande aipmt est alors disponible partout. Si le répertoire des scripts
de Python n'est pas dans votre PATH, python -m aipmt fait exactement la même
chose. Python 3.10 ou plus récent.
Pour une installation isolée du reste de vos paquets :
pipx install ai-powered-markdown-translator
Pour contribuer au projet
Le dépôt cloné reste nécessaire pour développer : c'est là que vivent les tests, les 28 traductions et tout l'outillage qualité.
git clone https://github.com/jls42/ai-powered-markdown-translator.git
cd ai-powered-markdown-translator
python3 -m venv venv && source venv/bin/activate
pip install -r requirements.txt
requirements.txt est un lock entièrement épinglé, reflet exact de
l'environnement testé. Les bornes publiées dans pyproject.toml sont
volontairement plus larges : elles n'imposent rien à vos autres paquets.
Outillage qualité (optionnel mais recommandé)
Le projet utilise pre-commit pour empêcher de committer du code mal formaté, vulnérable ou contenant un secret. Installation :
pip install -r requirements-dev.txt # detect-secrets, pip-audit, mypy, lizard
pre-commit install # hooks rapides à chaque commit
pre-commit install --hook-type pre-push # hooks lourds avant chaque push
Hooks actifs : ruff (lint+format), shellcheck (bash), prettier (markdown/yaml/json), Lizard (complexité), detect-secrets (clés API), mypy (typage progressif), Opengrep (SAST), pip-audit (CVE deps), unittest. Voir CLAUDE.md section Quality / pre-commit pour les détails.
Configuration
Les clés sont cherchées à trois endroits, du plus prioritaire au moindre. Chacun ne fait que combler ce que le précédent laisse vide.
| Où | Pour quoi | |
|---|---|---|
| 1 | Variables d'environnement | CI, conteneurs, dérogation ponctuelle |
| 2 | .env du répertoire courant (ou d'un parent) |
une clé propre à un projet |
| 3 | ~/.config/aipmt/.env |
installé une fois, vaut partout |
Le plus simple après un pip install est le troisième :
mkdir -p ~/.config/aipmt
cat > ~/.config/aipmt/.env <<'EOF'
OPENAI_API_KEY=votre-clé-api-openai
XAI_API_KEY=votre-clé-api-xai
MISTRAL_API_KEY=votre-clé-api-mistral
ANTHROPIC_API_KEY=votre-clé-api-anthropic
GOOGLE_API_KEY=votre-clé-api-google
OPENROUTER_API_KEY=votre-clé-api-openrouter
EOF
chmod 600 ~/.config/aipmt/.env
Ce fichier suit XDG_CONFIG_HOME quand la variable désigne un chemin absolu
(sinon elle est ignorée, comme le prescrit la spécification), et %APPDATA%
sous Windows.
Le second reste utile quand un dépôt a sa propre clé : un .env à sa racine
l'emporte alors sur la configuration utilisateur, sans la modifier. Et une
variable déjà définie dans l'environnement l'emporte sur les deux :
export OPENAI_API_KEY='une-clé-le-temps-d-une-commande'
Si aucune clé n'est trouvée, la commande n'affiche pas de trace d'appel : elle énumère les trois emplacements avec leur chemin exact.
GEMINI_API_KEY est accepté comme alternative à GOOGLE_API_KEY (convention AI
Studio). Variables optionnelles : XAI_BASE_URL (endpoint xAI, défaut
https://api.x.ai/v1), CLAUDE_TIMEOUT (secondes par appel Anthropic, défaut
900), CODEX_BIN / CODEX_TIMEOUT, GROK_BIN / GROK_HOME / GROK_TIMEOUT,
GROK_TRANSLATE_SANDBOX (voir la section Grok CLI), OPENCODE_BIN /
OPENCODE_TIMEOUT (voir la section OpenCode) et OPENROUTER_BASE_URL /
OPENROUTER_TIMEOUT / OPENROUTER_PREFLIGHT_TIMEOUT (voir la section
OpenRouter). Côté
regen_translations.sh : REGEN_PROVIDER (défaut codex, sur abonnement),
REGEN_MODEL, REGEN_ALLOW_PAID_API (dérogation obligatoire pour une API
facturée) et REGEN_JOB_TIMEOUT (plafond par job, défaut 600 s, 1 800 s sur Codex).
Utilisation
Traduire un fichier unique
aipmt --file 'document.md' --target_dir 'output/' --target_lang 'en'
Traduire un répertoire
# Avec OpenAI (défaut: gpt-5.6-terra)
aipmt --source_dir 'content/fr' --target_dir 'content/en' --source_lang 'fr' --target_lang 'en'
# Avec Mistral AI
aipmt --use_mistral --source_dir 'content/fr' --target_dir 'content/es' --target_lang 'es'
# Avec Claude
aipmt --use_claude --source_dir 'content/fr' --target_dir 'content/de' --target_lang 'de'
# Avec Gemini
aipmt --use_gemini --source_dir 'content/fr' --target_dir 'content/ja' --target_lang 'ja'
# Avec Codex (sur le quota de l'abonnement ChatGPT, sans facturation à l'usage)
aipmt --use_codex --eco --file 'README.md' --target_dir . --target_lang 'it'
# Avec Grok par l'API xAI (nécessite XAI_API_KEY, facturé à l'usage)
aipmt --use_grok --source_dir 'content/fr' --target_dir 'content/pt' --target_lang 'pt'
# Avec Grok sur le quota de l'abonnement Grok (nécessite `grok login`)
aipmt --use_grok_cli --eco --file 'README.md' --target_dir . --target_lang 'pl'
# Avec OpenRouter (routeur vers ~430 modèles ; --model obligatoire)
aipmt --use_openrouter --model 'z-ai/glm-5.2' --source_dir 'content/fr' --target_dir 'content/en' --source_lang 'fr' --target_lang 'en'
# Avec OpenCode (open source), vers le fournisseur de votre choix — ici un modèle local Ollama
aipmt --use_opencode --model ollama/qwen2.5:7b --file 'README.md' --target_dir . --target_lang 'nl'
Traduire sur son abonnement ChatGPT (--use_codex)
Ce provider ne consomme aucune clé API : il pilote le CLI Codex officiel en mode
non-interactif, donc la traduction est décomptée du quota de l'abonnement
ChatGPT (Plus, Pro, Business…) déjà payé. C'est la seule voie documentée par
OpenAI pour cet usage — les tokens de ~/.codex/auth.json n'authentifient pas
les appels à l'API Platform, et ne sont d'ailleurs jamais lus par ce script.
Prérequis :
# Le binaire `codex`, au choix :
pip install openai-codex-cli-bin # package officiel OpenAI (~250 Mo)
npm install -g @openai/codex # ou l'installation npm globale
codex login # connexion avec le compte ChatGPT
Le binaire est cherché dans cet ordre : la variable CODEX_BIN, le PATH,
puis le package Python openai-codex-cli-bin. Ce dernier n'est volontairement
pas dans requirements.txt : il pèse ~250 Mo, ce qui serait imposé à tous les
utilisateurs pour un provider optionnel.
À savoir :
- Aucune clé API n'est utilisée.
OPENAI_API_KEYetCODEX_API_KEYsont retirées de l'environnement du sous-processus, ce qui garantit qu'une clé présente dans.envne fera jamais basculer la traduction en facturation à l'usage. - Un segment = un « message local » de la fenêtre de 5 heures du plan.
Utiliser
--eco(modèlegpt-5.6-luna, 250-2 000 messages/5 h sur Plus) plutôt que le modèle qualité (gpt-5.6-sol, 10-100 messages/5 h). - Plus lent qu'un appel API : compter ~45 s pour un README complet, contre quelques secondes en direct.
- Refusé en CI (
CIouGITHUB_ACTIONSdéfini) : l'abonnement s'authentifie par un fichier de session personnel, et le porter sur un runner partagé revient à y déposer une identité réutilisable par tout ce qui s'y exécute. Utiliser une clé API sur ce chemin. - Variables d'environnement :
CODEX_BIN(chemin explicite du binaire) etCODEX_TIMEOUT(secondes par segment, défaut600).
Traduire sur son abonnement Grok (--use_grok_cli)
Même principe que --use_codex, avec le CLI officiel Grok Build : la
traduction est décomptée de l'abonnement Grok (SuperGrok / X Premium+) au lieu
d'être facturée au token.
curl -fsSL https://x.ai/cli/install.sh | bash # le binaire `grok`
grok login # ou `grok login --device-code`
Confinement — à lire avant usage. Ce provider est structurellement plus
faible que --use_codex, et c'est assumé :
- Codex tourne en
--sandbox read-only, une frontière imposée par le système. - Le sandbox de Grok ne peut pas s'appliquer sur beaucoup de postes Linux
récents : AppArmor bloque les user namespaces non privilégiés depuis Ubuntu
24.04, et la deny-list des sockets de runtime conteneur échoue si
/run/podmanest en0700. Or un profil intégré qui ne peut pas s'appliquer démarre non confiné, en silence. - Le script ne demande donc aucun profil par défaut, et ne retombe jamais
silencieusement : il affiche un avertissement. Le confinement repose sur les
règles
--denydu CLI (dont le catch-all*), la seule couche mesurée fail-closed — une règle inconnue fait refuser le démarrage plutôt que de retirer la protection sans le dire. - Pour exiger le sandbox OS :
GROK_TRANSLATE_SANDBOX=read-only. Le démarrage échouera si la machine ne peut pas l'honorer, ce qui est le comportement voulu.
Quota : le pool Grok est hebdomadaire et partagé avec Chat, Imagine et
Voice, et aucune commande ne permet de le lire. Un traitement par lot peut donc
entamer ton usage conversationnel sans que rien ne le signale — d'où une
concurrence limitée à 2 et un avertissement dans regen_translations.sh.
Autres variables : GROK_BIN (chemin du binaire), GROK_TIMEOUT (défaut 900 s).
Pour la régénération des 28 traductions :
# Défaut : Codex sur l'abonnement ChatGPT, modèle qualité gpt-5.6-sol, 0 € à l'usage
./regen_translations.sh --force
# Le modèle éco de Codex, si le volume l'impose
REGEN_MODEL=gpt-5.6-luna ./regen_translations.sh --force
# Sur le quota de l'abonnement Grok
REGEN_PROVIDER=grok_cli ./regen_translations.sh --force
# Une API facturée (openai, gemini, grok, openrouter) est REFUSÉE sans cette dérogation nommée
REGEN_PROVIDER=openai REGEN_ALLOW_PAID_API=1 ./regen_translations.sh --force
# Via OpenCode, vers le modèle de son choix (REGEN_MODEL obligatoire, 2 jobs en parallèle)
REGEN_PROVIDER=opencode REGEN_MODEL=ollama/qwen2.5:7b ./regen_translations.sh --force
# Via OpenRouter : API facturée, donc dérogation ET modèle obligatoires
REGEN_PROVIDER=openrouter REGEN_ALLOW_PAID_API=1 REGEN_MODEL=z-ai/glm-5.2 ./regen_translations.sh --force
Traduire avec OpenCode, vers le fournisseur de son choix (--use_opencode)
OpenCode est un agent de code open source (MIT) en
terminal. Il n'est pas un fournisseur de modèles mais un routeur vers ceux
que vous avez configurés dans OpenCode lui-même : une clé API, un abonnement,
la passerelle OpenCode Zen — qui sert des modèles gratuits sans compte — ou
un modèle local. Ce provider pilote opencode run en mode non-interactif et
confine l'appel à un seul aller-retour, sans aucun outil.
Deux de ces voies ont été mesurées de bout en bout ici : la passerelle Zen et Ollama en local. Les autres qu'OpenCode annonce (GitHub Copilot, LM Studio, llama.cpp) devraient fonctionner par construction, puisque le provider ne parle qu'à OpenCode — mais elles ne sont pas éprouvées, et ce README ne dit que ce qui a été vérifié.
curl -fsSL https://opencode.ai/install | bash # ou : npm install -g opencode-ai
opencode models # les modèles disponibles, au format provider/modèle
opencode auth login # facultatif : brancher un fournisseur ou un abonnement
--model est obligatoire, au format provider/modèle. OpenCode n'est pas
un fournisseur, et aucun défaut n'est choisi à votre place : son propre repli
serait un modèle gratuit dont les échanges peuvent servir à l'entraînement.
# Gratuit, sans compte ni clé (passerelle Zen ; données utilisables pour l'entraînement)
aipmt --use_opencode --model opencode/mimo-v2.5-free --file README.md --target_dir . --target_lang en
# Local, hors ligne, sans aucune clé (Ollama déclaré dans ~/.config/opencode/opencode.json)
aipmt --use_opencode --model ollama/qwen2.5:7b --file README.md --target_dir . --target_lang de
# Sur un abonnement déjà payé (après `opencode auth login`)
aipmt --use_opencode --model github-copilot/gpt-5 --file README.md --target_dir . --target_lang ja
Confinement — ce que fait le script à chaque appel :
- Une configuration inline (
OPENCODE_CONFIG_CONTENT), prioritaire sur la vôtre, définit un agentaipmtdont tous les outils sont refusés (permission: { "*": "deny" }) : le modèle ne peut ni lire, ni écrire, ni lancer de commande — mesuré, il ne le tente même pas. Le partage de session est désactivé,--pureécarte les plugins externes, jamais--auto. - L'appel tourne dans un répertoire jetable et vide, avec les interrupteurs
OPENCODE_DISABLE_PROJECT_CONFIGetOPENCODE_DISABLE_CLAUDE_CODE: sans eux, OpenCode injecte dans chaque prompt l'AGENTS.mddu répertoire courant et votre~/.claude/CLAUDE.md— mesuré, une consigne « finir chaque réponse par BANANA » posée dans unAGENTS.mdétait appliquée à la traduction. Les règles globales de~/.config/opencode/AGENTS.mdrestent en revanche appliquées : OpenCode ne permet pas de les écarter. - Le contrat de sortie exige tout à la fois : code retour 0, aucun événement
error, aucun appel d'outil, un dernier pas terminé enstop, un texte non vide, et l'agent effectivement chargé — un--agentinconnu ne fait pas échouer OpenCode, il retombe en silence sur l'agent de codage, outils actifs. Unexit 0ne prouve rien ici non plus. - Aucune clé d'aipmt n'est transmise au sous-processus (même filtrage
qu'avec Codex et Grok), à une exception nominative près :
OPENCODE_API_KEY, la clé d'OpenCode lui-même (Zen, Go). Les fournisseurs se configurent dans OpenCode (opencode auth login,opencode.json), pas dans le.envd'aipmt.
À savoir :
- Les modèles gratuits de Zen sont des modèles « stealth » ou contributeurs,
changeants, aux limites non documentées, et leurs échanges peuvent servir à
l'entraînement : parfaits pour une documentation publique, à éviter pour un
contenu privé. Mesuré :
opencode/mimo-v2.5-freetraduit ce README en une passe ;opencode/big-pickleest plus lent et deux requêtes simultanées y sont restées sans réponse. - Un modèle local doit offrir au moins 16 k de contexte — les segments font
jusqu'à 16 000 caractères — alors qu'Ollama en configure souvent 4 096 par
défaut. Avec Ollama : un
ModelfileavecPARAMETER num_ctx 32768, puisollama create. La qualité suit le modèle : un 7B a inversé une liste et abîmé une clôture de bloc de code sur un fichier d'essai là où un modèle de la passerelle a tout préservé. --ecoest sans effet (le modèle est celui de--model) ;--reasoning_effortest transmis tel quel comme--variantd'OpenCode, à ne demander que si le modèle le connaît.- Les sessions sont journalisées par OpenCode dans sa base
(
~/.local/share/opencode/), comme toute session OpenCode. - Variables d'environnement :
OPENCODE_BIN(chemin explicite du binaire, sinon lePATHpuis~/.opencode/bin/opencode) etOPENCODE_TIMEOUT(secondes par segment, défaut600).OPENCODE_CONFIG, s'il est exporté, n'est pas lu paraipmt: il passe tel quel à OpenCode, qui l'honore.
Exemple mesuré : un modèle local via Ollama (RTX 3060 12 Go, 62 Go de RAM, Ollama 0.33.3)
curl -fsSL https://ollama.com/install.sh | sh # conserve les modèles déjà téléchargés
ollama pull gpt-oss:20b # 13 Go, Apache 2.0 — le seul modèle local retenu ici
# Sous 24 Go de VRAM, Ollama plafonne le contexte à 4 096 tokens, et son API OpenAI-compatible
# ne permet pas de le régler par requête : on le fixe dans un Modelfile.
printf 'FROM gpt-oss:20b\nPARAMETER num_ctx 32768\n' > gpt-oss-20b-32k.Modelfile
ollama create gpt-oss-20b-32k -f gpt-oss-20b-32k.Modelfile
Puis le fournisseur dans ~/.config/opencode/opencode.json :
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"ollama": {
"npm": "@ai-sdk/openai-compatible",
"name": "Ollama (local)",
"options": { "baseURL": "http://127.0.0.1:11434/v1" },
"models": {
"gpt-oss-20b-32k": {
"name": "gpt-oss 20B (32k, sans réflexion)",
"limit": { "context": 32768, "output": 8192 },
"options": { "reasoningEffort": "none" }
}
}
}
}
}
reasoningEffort: "none" n'est pas un détail : Ollama active la réflexion par
défaut sur ces modèles, et un Modelfile ne peut pas la couper. Mesuré à
travers OpenCode : sans l'option, « Le chat dort sur le tapis » coûte 919 tokens
de raisonnement et 68 s ; avec, 9 tokens.
aipmt --use_opencode --model ollama/gpt-oss-20b-32k --news --keep_filename \
--add_translation_note --file article.mdx --target_dir out/ --target_lang en
Résultats sur un article de blog réel de 589 lignes (140 liens, 21 sections,
3 citations anglaises protégées par le mode --news), même commande, trois
modèles :
| Modèle | Durée | Structure | Écarts |
|---|---|---|---|
opencode/mimo-v2.5-free (Zen, gratuit) |
4 min 26 s | identique à la source | aucun |
ollama/gemma4-12b-32k (local) |
10 min 10 s | liens, URL, tableaux, tags, gras et code inline identiques | une ligne de citation inventée (🇺🇸 + paraphrase), une attribution dupliquée |
ollama/qwen3.5-9b-32k (local) |
8 min 18 s | liens, URL, tableaux et tags identiques | une ligne de citation inventée, quelques gras et codes inline ajoutés, un segment repassé |
Ces deux modèles locaux ont depuis été écartés : une liberté par article
suffit à disqualifier un modèle pour de la traduction publiée. Cinq autres l'ont
été pour les mêmes raisons ou par dépassement de délai (gemma4:26b-a4b,
qwen3.6:35b-a3b, ministral-3:14b, mistral-small3.2, hy-mt2:7b). Seul
gpt-oss:20b a été conservé — et lui-même laisse des passages en français sur
un article dense, cf. le tableau des modèles conseillés.
Pendant la traduction locale : GPU à 98 % et 170 W, 10 Go de VRAM occupés (modèle et cache de 32 k tokens, rien déchargé en RAM), 7,5 Go de RAM pour le serveur Ollama. Un modèle de 9 à 12 milliards de paramètres respecte la structure mais s'accorde une liberté par article, là où le modèle de passerelle n'en a pris aucune : à relire avant publication, ou à réserver aux brouillons.
Traduire via OpenRouter (--use_openrouter)
OpenRouter est un routeur devant plus de 400 modèles hébergés par des tiers, facturé à l'usage sur un crédit unique. Il donne accès en une clé à des modèles qu'aucun des autres providers n'expose, notamment les modèles chinois ouverts.
# --model est OBLIGATOIRE : aucun défaut n'est choisi à votre place
aipmt --use_openrouter --model 'z-ai/glm-5.2' --file README.md \
--target_dir . --source_lang fr --target_lang en
Deux particularités du routage ont dicté l'implémentation, et toutes deux se mesurent :
- Un même modèle est servi par des dizaines d'hébergeurs aux plafonds
différents. Sur
z-ai/glm-5.3-flash, 23 hébergeurs, dont un plafonné à 2 048 tokens de sortie : sans précaution, une traduction longue sur 23 partait tronquée, au hasard du routage et sans le moindre signal. Un préflight lit/api/v1/models/{modèle}/endpoints, écarte les hébergeurs sous 8 000 tokens de sortie ou au statut dégradé, puis épingle les autres avecallow_fallbacks: false— sans quoi le routeur repart vers un hébergeur écarté. - Le raisonnement est facturé au tarif de sortie. Même requête sur
z-ai/glm-5.2, réponse « OK » : 107 tokens de complétion au défaut du modèle, 2 avec le raisonnement coupé. Il est donc coupé par défaut, sur les modèles qui l'autorisent. Ceux qui l'imposent —reasoning.mandatory, 288 des 431 modèles du catalogue — reçoivent le plus bas effort qu'ils déclarent accepter, et non leur réglage par défaut : celui dez-ai/glm-5.3-flashestmax, et il saturait les 32 768 tokens de sortie avant la fin de la traduction. Monter l'enveloppe n'y aurait rien changé, l'effort en alloue un pourcentage.--reasoning_effortreste prioritaire, etnonesur un modèle qui impose le raisonnement est signalé plutôt que contourné.
Le préflight est fail-closed et affiche ce qu'il a retenu :
→ OpenRouter : 30 hébergeur(s) épinglé(s) sur 33, contexte 1048576 tokens,
sortie plafonnée à 32768, raisonnement coupé
Un slug absent du catalogue, un catalogue injoignable ou l'absence d'hébergeur tenant le plafond arrêtent la commande avant toute facturation.
Autres points :
- La fenêtre de contexte vient du catalogue, pas d'une constante : la segmentation s'y adapte réellement, y compris pour les modèles à 4 095 tokens.
--ecoest sans effet (le modèle est celui de--model).finish_reason=lengthavec une sortie vide n'est pas une troncature mais un budget consommé par le raisonnement ; le message le dit, parce que les deux cas appellent des gestes opposés.- Variables d'environnement :
OPENROUTER_API_KEY(clé, sur https://openrouter.ai/keys),OPENROUTER_BASE_URL(défauthttps://openrouter.ai/api/v1,https://exigé),OPENROUTER_TIMEOUT(secondes par appel, défaut900) etOPENROUTER_PREFLIGHT_TIMEOUT(défaut30).
Mode économique
Utilise des modèles plus rapides et moins coûteux (gpt-5.6-luna, claude-haiku-4-5, gemini-3.1-flash-lite) :
aipmt --eco --source_dir 'content/fr' --target_dir 'content/en'
Options
| Option | Description |
|---|---|
--file |
Fichier Markdown unique à traduire |
--source_dir |
Répertoire source contenant les fichiers Markdown |
--target_dir |
Répertoire de sortie pour les fichiers traduits |
--source_lang |
Langue source (défaut: fr) |
--target_lang |
Langue cible (défaut: en) |
--model |
Modèle spécifique à utiliser |
--eco |
Utiliser les modèles économiques |
--use_mistral |
Utiliser l'API Mistral AI |
--use_claude |
Utiliser l'API Claude |
--use_gemini |
Utiliser l'API Gemini |
--use_codex |
Utiliser le CLI Codex sur le quota de l'abonnement ChatGPT |
--use_grok |
Utiliser l'API xAI (Grok) — nécessite XAI_API_KEY |
--use_openrouter |
Utiliser OpenRouter — nécessite OPENROUTER_API_KEY et --model fournisseur/modèle |
--use_grok_cli |
Utiliser le CLI Grok sur le quota de l'abonnement Grok |
--use_opencode |
Utiliser OpenCode (open source) vers le fournisseur configuré dans OpenCode ; exige --model provider/modèle |
--force |
Forcer la re-traduction |
--keep_filename |
Conserver le nom de fichier original |
--news |
Mode actualités : protège les citations EN, gère les drapeaux par langue |
--add_translation_note |
Ajouter une note de traduction |
--note_position |
Position de la note : top, bottom (défaut), ou both |
--note_format |
Format de la note : legacy (défaut, paragraphe gras) ou marker |
--include_model |
Inclure le nom du modèle dans le fichier de sortie |
--reasoning_effort |
Effort de raisonnement GPT-5.x : none/low/medium/high/xhigh |
Les huit flags de provider sont mutuellement exclusifs. En combiner deux était auparavant accepté en silence et résolvait vers le premier testé : une traduction demandée sur quota d'abonnement (
--use_codex,--use_grok_cli) pouvait ainsi partir en facturation à l'usage sans aucun avertissement.argparserefuse désormais la combinaison.
Note de traduction : positions et formats
Avec --add_translation_note, le translator peut placer la note en haut, en bas, ou aux deux endroits, et la rendre soit en format texte simple (rétrocompatible) soit en format marker consommable par un plugin Markdown.
Position (--note_position) :
bottom(défaut) : note en fin de fichier, comme historiquement.top: note insérée après le frontmatter YAML (sécurité Astro Content Collections, gray-matter, etc.).both: note insérée en haut ET en bas (un seul appel LLM, contenu réutilisé pour les deux placements).
Format (--note_format) :
legacy(défaut) : paragraphe gras**...**— comportement strictement identique à v1.8, byte-for-byte. Compatible avec Hugo, GitHub, GitLab, et tout renderer Markdown.marker: link reference definition Markdown invisible ([ai-translation-note-<placement>]: <> "v=1 source=… target=… model=… date=…") suivie d'un blockquote en gras. Lisible nativement sur GitHub/GitLab, et exploitable au build par un plugin remark côté Astro pour produire une bannière stylisée (cf. blog jls42.org).
# Compatibilité legacy (rien ne change vs v1.8)
aipmt --file article.mdx --target_lang en --add_translation_note
# Format marker, note en haut uniquement (Astro)
aipmt --file article.mdx --target_lang en \
--add_translation_note --note_format marker --note_position top
# Format marker en haut ET en bas
aipmt --file article.mdx --target_lang en \
--add_translation_note --note_format marker --note_position both
Modèles par défaut (2026)
| Provider | Qualité (défaut) | Économique (--eco) |
|---|---|---|
| OpenAI | gpt-5.6-terra |
gpt-5.6-luna |
| Claude | claude-sonnet-5 |
claude-haiku-4-5 |
| Mistral | mistral-large-latest |
mistral-small-latest |
| Gemini | gemini-3.7-flash |
gemini-3.1-flash-lite |
| Codex | gpt-5.6-sol |
gpt-5.6-luna |
| Grok API | grok-4.6 |
grok-4.3 |
| Grok CLI | grok-4.6 |
grok-4.5 |
| OpenCode | --model provider/modèle obligatoire |
idem — --eco sans effet |
| OpenRouter | --model fournisseur/modèle obligatoire |
idem — --eco sans effet |
Quels modèles tiennent la route
Un modèle qui traduit bien un paragraphe ne préserve pas forcément la structure d'un document entier. Ces mesures viennent de traductions réellement exécutées, avec la commande que vous liriez plus haut, sur trois jeux de documents et quatorze langues cibles : en, es, de, it, pt, nl, pl, sv, ro, ja, ko, zh, ar, hi.
Deux colonnes, et elles ne disent pas la même chose. Écrites compte les traductions qui aboutissent — les gardes anti-échec-silencieux du script laissent passer le fichier. Sans écart compte celles dont la structure est identique à la source : mêmes sections, mêmes liens, mêmes URL, mêmes blocs et codes en ligne, mêmes tableaux, mêmes citations, mêmes drapeaux.
Article de blog dense, mode --news
589 lignes, 140 liens, 21 sections, 3 citations anglaises protégées. C'est le
document le plus exigeant des trois : le mode --news ajoute des contraintes de
drapeaux et de citations par-dessus la structure Markdown.
| Modèle | Accès | Écrites | Sans écart | Médiane/langue |
|---|---|---|---|---|
gemini-3.7-flash |
API Google | 14/14 | 14/14 | 1 min 18 s |
gpt-5.6-sol (--use_codex) |
abonnement ChatGPT | 14/14 | 14/14 | 11 min 28 s |
z-ai/glm-5.2 |
OpenRouter | 14/14 | 14/14 | 5 min 37 s |
qwen/qwen3.8-flash |
OpenRouter | 14/14 | 13/14 | 26 min 23 s |
z-ai/glm-5.3-flash |
OpenRouter | 12/14 | 12/14 | 15 min 49 s |
qwen/qwen3.5-27b |
OpenRouter | 7/9 | 7/9 | 20 min 33 s |
claude-sonnet-5 |
API Anthropic | 14/14 | 11/14 | 6 min 31 s |
opencode/mimo-v2.5-free |
OpenCode Zen | 13/14 | 11/14 | 9 min 27 s |
qwen/qwen3.7-flash |
OpenRouter | 13/14 | 7/14 | 10 min 09 s |
ollama/gpt-oss-20b-32k |
local | 10/14 | 7/14 | 12 min 39 s |
mistral-large-latest |
API Mistral | 11/14 | 5/14 | 5 min 32 s |
deepseek/deepseek-v4-flash-0731 |
OpenRouter | 4/14 | 3/14 | 37 min 27 s |
grok-4.6 (--use_grok_cli) |
abonnement Grok | 1/14 | 1/14 | 23 min 11 s |
moonshotai/kimi-k2.6 |
OpenRouter | 1/4 | 1/4 | 23 min 00 s |
Deux lots ont été interrompus faute de crédit et leur dénominateur le dit :
qwen3.5-27b s'est arrêté à neuf langues, kimi-k2.6 à quatre — ce dernier
après un dépassement de délai de quarante minutes et deux refus, à près de
0,33 $ la langue.
Une réserve de méthode sur les lignes OpenRouter : elles ont été mesurées avec
les réglages par défaut du routeur, avant que --use_openrouter n'existe.
z-ai/glm-5.2 a été remesuré depuis avec le provider livré, raisonnement coupé,
et rend exactement le même 14/14. z-ai/glm-5.3-flash a échoué deux fois par
budget de sortie épuisé au défaut du routeur ; le provider demande désormais à
ces modèles le plus bas effort qu'ils acceptent, et la contre-épreuve sur les
langues fautives passe.
README de ce projet, Markdown standard
508 lignes, 219 codes en ligne, 40 clôtures de blocs, 45 lignes de tableau. Pas
de mode --news ici : la difficulté vient de la densité en code.
| Modèle | Écrites | Sans écart | Médiane/langue |
|---|---|---|---|
z-ai/glm-5.2 (OpenRouter) |
14/14 | 11/14 | 1 min 22 s |
gemini-3.7-flash |
14/14 | 13/14 | 21 s |
gpt-5.6-sol (--use_codex) |
14/14 | 12/14 | 2 min 04 s |
opencode/mimo-v2.5-free |
9/14 | 7/14 | 3 min 25 s |
ollama/gpt-oss-20b-32k |
9/14 | 1/14 | 3 min 38 s |
Quatre README de projets connus
FastAPI, Ollama, tldr-pages et Vue.js, pris tels quels sur GitHub. Ces documents sont plus faciles que les deux précédents, et le tableau le montre.
| Modèle | Périmètre | Écrites | Sans écart |
|---|---|---|---|
opencode/mimo-v2.5-free |
4 projets × 14 langues | 55/56 | 47/56 |
grok-4.6 (abonnement) |
4 projets × ar, hi, ja, zh | 16/16 | 14/16 |
ollama/gpt-oss-20b-32k |
4 projets × ar, hi, ja, zh | 15/16 | 9/16 |
Ce qu'on en retient
- Trois modèles n'ont jamais perdu d'information sur les deux documents
denses :
gemini-3.7-flash,gpt-5.6-solpar l'abonnement ChatGPT, etz-ai/glm-5.2par OpenRouter. Leurs seuls écarts en mode standard sont une paire de**non reportée sur une ou deux langues, jamais une URL, un bloc de code ou une citation. - Le facteur discriminant est la densité du document, pas le mode
--news. Grok par abonnement échoue 13 fois sur 14 sur l'article de blog et réussit 14 README publics sur 16 : sa cause d'échec est un décrochage sur segment long, vérifié par contre-épreuve — le passage isolé est traduit correctement. - Les écritures non latines ne sont pas le clivage attendu.
gpt-osslaisse des passages en français en arabe, japonais, polonais et roumain ; Mistral et MiMo ne perdent des codes en ligne que sur les écritures non latines. - Couper le raisonnement ne coûte rien en qualité.
z-ai/glm-5.2fait quatorze langues sans un écart dans les deux conditions — raisonnement actif par défaut du routeur, puis coupé par--use_openrouter— pour dix-huit fois moins de tokens de sortie facturés. C'est la mesure qui justifie le réglage par défaut du provider. - Un modèle lent n'est pas un modèle sûr.
deepseek-v4-flash-0731prend 37 minutes par langue pour 4 traductions sur 14,qwen3.8-flash26 minutes pour un résultat presque parfait, et Gemini 1 minute 18 pour un sans-faute.
Ce que ce tableau n'est pas
- Ce n'est pas un classement exhaustif. OpenRouter propose à lui seul plus de quatre cents modèles ; une quinzaine a été mesurée ici. L'absence d'un modèle ne dit rien de sa qualité, seulement qu'il n'a pas été essayé.
- Ces mesures ont une date : 4 et 5 septembre 2026. Les modèles changent sous le même nom, les hébergeurs ajustent quantifications et plafonds, et de nouveaux modèles sortent chaque semaine.
- Les durées ne classent rien. Le parallélisme allait de 3 à 6 traductions simultanées selon les campagnes, et le débit d'un fournisseur varie dans la journée. Elles donnent un ordre de grandeur, pas une comparaison.
- Un résultat dépend du document autant que du modèle. Le même modèle réussit quatorze langues sur un article et neuf sur ce README. Vos fichiers ne sont pas les nôtres.
- La bonne démarche reste de mesurer chez vous : traduisez un de vos
documents vers vos langues cibles, puis comparez la structure — nombre de
sections, de liens, d'URL distinctes, de blocs de code, de codes en ligne, de
lignes de tableau. C'est exactement ce que fait le protocole ci-dessus, et il
tient en une boucle sur
aipmt.
Projets utilisant ce script
- jls42.org - Blog personnel multilingue (15 langues)
Auteur
Julien LE SAUX Email : contact@jls42.org
Licence
GNU GENERAL PUBLIC LICENSE Version 3. Voir LICENSE.
Metadata
Release files for ai-powered-markdown-translator 1.13.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| ai_powered_markdown_translator-1.13.1.tar.gz | 211.2 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ai_powered_markdown_translator-1.13.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 330.9 kB
Release files / ai_powered_markdown_translator-1.13.1.tar.gz
| Download URL | ai_powered_markdown_translator-1.13.1.tar.gz |
|---|---|
| Size | 211.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a83290b31026533beaf1b0a9ef11b10ff2d641e81b3946a3c0046ab4d9e83295
|
|
BLAKE2b-256 checksum How to use checksums |
2950c424d3ef8d8ef253aa21748bd131184763464fe721009ba554868d2b544f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 9, 2026.
Transparency logRelease files / ai_powered_markdown_translator-1.13.1-py3-none-any.whl
| Download URL | ai_powered_markdown_translator-1.13.1-py3-none-any.whl |
|---|---|
| Size | 119.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
96a528ca880ea3f957f27e1858e11352dfd98d8e524a2eafc9df84945fbafec5
|
|
BLAKE2b-256 checksum How to use checksums |
df3302dd56cdd15e5ecf4fd31d0494f5c88c1782b89798d964f5040725e3b315
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 9, 2026.
Transparency logSecurity for ai-powered-markdown-translator 1.13.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for ai_powered_markdown_translator-1.13.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 9, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.