Aller au contenu principal

ai-translate & ai-summarize : des documents confidentiels, traités 100 % en local

Deux fonctions zsh qui traduisent ou résument un document Word, PDF, PowerPoint ou Excel sans qu'un seul octet ne quitte votre machine — Docling extrait le texte en local, un modèle Ollama local fait la traduction ou le résumé. Pensé pour le document que vous ne colleriez jamais dans un outil de traduction cloud.

· 8 minutes de lecture
Voir la source
Christophe
Amoureux de Markdown, WSL et Docker ~ Curieux insatiable.
Claude Code
Assistant IA
Cet article existe aussi en anglais — lire la version originale.

Traduction automatique

Cette traduction a été produite par une IA. Elle peut contenir des contresens ou des maladresses, en particulier sur les termes techniques. En cas de doute, consultez l'article de référence en anglais — c'est lui qui fait foi.

ai-translate & ai-summarize : des documents confidentiels, traités 100 % en local

⚡
TL;DR

Cet article ajoute ai-translate et ai-summarize à la série « Ollama daily use ». Les deux acceptent un fichier .pdf, .docx, .pptx, .xlsx ou .html — extrait en Markdown par Docling — ou directement un simple fichier .md/.txt, puis passent le texte au modèle Ollama local pour le traduire ou le condenser en points clés. Tout l'aller-retour reste sur votre machine : pas d'API de traduction cloud, aucun upload de document nulle part. C'est précisément l'intérêt pour un contrat, un document RH, ou tout ce que vous hésiteriez à coller dans Google Translate.

Je travaille dans un bureau où un .docx atterrit dans ma boîte mail en néerlandais, en anglais ou en français. Pour de très bonnes raisons, j'ai parfois besoin de traduire d'une langue vers une autre.

Quand ce n'est pas confidentiel du tout, le réflexe de tout le monde est d'ouvrir le navigateur, de coller dans un outil de traduction, et d'espérer que personne ne s'offusque qu'un contrat client vienne de transiter par les serveurs d'un tiers. Personne ne m'a jamais explicitement dit de ne pas le faire. C'est exactement le genre de chose pour laquelle vous ne devriez pas avoir besoin d'une permission.

Démo — ai-translate​

Traduction d'un contrat depuis n'importe quelle langue vers le français :

>user@machine: ~/yourproject

Et le même vers le néerlandais :

>user@machine: ~/yourproject

C'est un contrat de prestation fictif, converti depuis .docx et traduit en français/néerlandais, avec chaque titre et chaque terme en gras intact — le genre de document que je ne collerais vraiment pas dans un traducteur en ligne.

Même document, pour que vous puissiez l'essayer vous-même avant d'adapter l'une ou l'autre fonction à vos propres fichiers :

contract.docx — le document source

Démo — ai-summarize​

Le même contrat, condensé en quatre points clés plutôt que traduit :

>user@machine: ~/yourproject

Les délais de livraison, les conditions de paiement, la clause de résiliation et les parties du contrat-cadre qui sont remplacées — les quatre points qui comptent, sortis sans lire le document complet.

Réutiliser Docling pour l'extraction​

Les deux fonctions ci-dessous partagent une tâche avant même de parler à Ollama : transformer un document en texte brut. J'ai déjà construit cette brique dans mon article sur Docling — docling-convert file.docx produit file.md en local, avec accélération GPU si vous l'avez configuré ainsi. Plutôt que de dupliquer cette logique deux fois, elle vit dans un petit helper :

Pas besoin de copier quoi que ce soit pour l'instant : les fichiers .zsh montrés dans cet article sont là pour être lus, et L'installer à la fin les crée tous dans ~/.zsh/fns/ pour vous.

# Shared document-to-text extraction for ai-translate and ai-summarize.
# .pdf/.docx/.pptx/.xlsx/.html go through docling-convert (see /blog/docling)
# first; .md/.markdown/.txt files are read directly, no conversion needed.
#
# Leading underscore: loads after _ollama.zsh (still alphabetically before
# ai-summarize.zsh and ai-translate.zsh), so _ollama_query is always ready.
_ai_extract_text() {
local file="$1"
local ext="${file:e:l}"
case "$ext" in
md|markdown|txt)
cat "$file"
;;
pdf|docx|pptx|xlsx|html|htm)
if ! command -v docling-convert >/dev/null 2>&1; then
echo "_ai_extract_text: docling-convert not found — see /blog/docling to set it up" >&2
return 1
fi
local dir filename base mdfile
dir="${file:h}"
filename="${file:t}"
base="${filename%.*}"
mdfile="${dir}/${base}.md"
echo "→ Converting '$file' with docling-convert..." >&2
( cd "$dir" && docling-convert "$filename" >/dev/null 2>&1 ) || {
echo "_ai_extract_text: docling-convert failed on '$file'" >&2
return 1
}
cat "$mdfile"
;;
*)
echo "_ai_extract_text: unsupported extension .$ext (expected pdf/docx/pptx/xlsx/html/md/txt)" >&2
return 1
;;
esac
}

Cette fonction extrait le texte brut de différents formats de fichiers. Pour les fichiers markdown et texte, elle les lit directement ; pour les documents complexes (PDF, Word, PowerPoint, Excel, HTML), elle utilise d'abord docling-convert pour les convertir en markdown, puis retourne le contenu textuel.

Les fichiers Markdown et texte sautent la conversion

Si vous avez déjà un fichier .md ou .txt, _ai_extract_text fait juste un cat dessus — pas d'appel à Docling, pas de dépendance. L'étape de conversion ne se déclenche que pour les vrais formats bureautiques.

Pourquoi le subshell autour de docling-convert

docling-convert (de l'article précédent) monte le répertoire courant dans son container et attend un nom de fichier relatif à celui-ci — il n'a pas été conçu pour résoudre un chemin absolu arbitraire. ( cd "$dir" && docling-convert "$filename" ) l'exécute depuis le dossier du document, dans un subshell, de sorte que votre répertoire de travail réel reste intact au retour de la fonction.

ai-translate​

# ai-translate <file> [language] — translate a document into the given
# language (default: French), entirely locally. Accepts .pdf/.docx/.pptx/
# .xlsx/.html (via docling-convert) or plain .md/.txt files directly.
AI_COMMANDS[translate]="ai-translate <file> [language] — translate a document locally (default: French)"
ai-translate() {
local file="$1"
local lang="${2:-French}"
if [[ -z "$file" || ! -f "$file" ]]; then
echo "Usage: ai-translate <file> [target-language]" >&2
return 1
fi
local text
text=$(_ai_extract_text "$file") || return 1
local prompt="Translate the following document into $lang. Preserve the Markdown structure exactly — headings, lists, tables, emphasis. Output only the translated document, no commentary and no notes about the translation.
$text"
_ollama_query "$prompt"
}

Cette fonction traduit un document dans une langue donnée (français par défaut) en utilisant un modèle local. Elle extrait d'abord le texte du fichier fourni (qui peut être un PDF, DOCX, PPTX, XLSX, HTML ou fichier texte brut), puis envoie ce texte à un modèle avec des instructions pour préserver la structure Markdown lors de la traduction.

On extrait, puis on demande au modèle de traduire vers la langue passée en second argument (le français par défaut — celle dont j'ai le plus souvent besoin), avec une instruction explicite de préserver la structure Markdown pour que les titres, listes et tableaux survivent à l'aller-retour au lieu de s'écrouler en un pavé de texte.

ai-summarize​

# ai-summarize <file> [points] — summarize a document in N bullet points
# (default: 5), entirely locally. Accepts .pdf/.docx/.pptx/.xlsx/.html (via
# docling-convert) or plain .md/.txt files directly.
AI_COMMANDS[summarize]="ai-summarize <file> [points] — summarize a document locally (default: 5 points)"
ai-summarize() {
local file="$1"
local points="${2:-5}"
if [[ -z "$file" || ! -f "$file" ]]; then
echo "Usage: ai-summarize <file> [number-of-points]" >&2
return 1
fi
local text
text=$(_ai_extract_text "$file") || return 1
local prompt="Summarize the following document in exactly $points bullet points, written in the same language as the document. Prioritize decisions, numbers, deadlines and action items over generic description. Output only the bullet points, nothing else.
$text"
_ollama_query "$prompt"
}

Cette fonction bash résume un document en un nombre de points à puces spécifié (5 par défaut). Elle extrait d'abord le texte du fichier fourni via une fonction utilitaire, puis envoie ce texte à un modèle local via ollama avec une instruction précise pour générer uniquement les points à puces, en privilégiant les décisions, chiffres et éléments concrets plutôt que les descriptions génériques.

Même étape d'extraction, prompt différent : un nombre fixe de points clés (5 par défaut), avec la consigne explicite de privilégier les décisions, les chiffres, les échéances et les actions à mener plutôt qu'une description générique — et de répondre dans la langue du document source, plutôt que de basculer silencieusement en anglais.

Enregistrées dans le menu ai​

Deux lignes — AI_COMMANDS[translate]=... et AI_COMMANDS[summarize]=... — et les deux sont accessibles via ai translate / ai summarize, ou directement via ai-translate / ai-summarize, aux côtés de toutes les autres fonctions de cette série.

Les deux fonctions appellent _ollama_query et s'enregistrent dans AI_COMMANDS, qui vivent dans la base partagée _ollama.zsh introduite dans ai-test. Si vous avez déjà suivi un article précédent de cette série, elle est déjà dans ~/.zsh/fns/ et sourcée par votre autoloader — rien de plus à faire. Vous commencez ici ? C'est l'un des fichiers créés dans L'installer ci-dessous.

Docling et Ollama ne doivent pas être sur la même machine

docling-convert tourne toujours en local, sans GPU requis — convertir un document en Markdown fonctionne sur n'importe quel portable. Traduire ou résumer nécessite par contre un serveur Ollama joignable quelque part : les deux fonctions se connectent à OLLAMA_HOST, même configuration que dans accéder à Ollama depuis votre réseau local — un LAN partagé, ou un VPN/tunnel entre deux réseaux distincts.

À retenir​

ai-translate / ai-summarize en bref

  • Extraction partagée — _ai_extract_text dans _ai-docs.zsh, réutilisée par les deux fonctions
  • Docling pour les formats bureautiques — .pdf/.docx/.pptx/.xlsx/.html passent d'abord par docling-convert
  • Markdown/texte sautent la conversion — les fichiers .md/.txt sont lus directement
  • Rien ne quitte la machine — extraction et traduction/résumé tournent en local, de bout en bout
  • S'enregistrent dans ai — accessibles via ai translate et ai summarize

L'installer​

Tout tourne sur votre machine : zsh, curl et jq (qui construit la requête envoyée à Ollama), et un serveur Ollama que vous pouvez joindre — voyez installing Ollama si vous n'en avez pas encore. Pour les fichiers .pdf, .docx, .pptx, .xlsx et .html, il vous faut aussi docling-convert, issu de mon article sur Docling.

1. Créez les fichiers. Chaque fonction de cette série vit dans son propre fichier dans ~/.zsh/fns/. La commande ci-dessous crée ce dossier et les quatre fichiers d'un coup — ou téléchargez le ZIP, ou créez chaque fichier à la main et collez son contenu. _ollama.zsh est la base que toute la série partage : si un article précédent vous l'a déjà donnée, la copie ici est le même fichier.

📦 Mise en place du projet : ~/.zsh/fns
Aide

Besoin d'aide ? Cliquez sur le bouton « Aide » ci-dessus pour les instructions de mise en place.

2. Chargez le dossier depuis ~/.zshrc. Déjà fait si vous avez suivi un article précédent de cette série. Sinon, ajoutez ces lignes à la fin de ~/.zshrc — elles sourcent chaque fichier .zsh du dossier, donc la prochaine fonction que vous ajoutez ne demandera aucune modification ici :

~/.zshrc
for fn_file in ~/.zsh/fns/*.zsh; do
source "$fn_file"
done

3. Ouvrez un nouveau terminal (ou lancez exec zsh dans celui en cours), et vérifiez que le shell connaît les nouvelles fonctions :

type ai-translate ai-summarize

ai-translate is a shell function from …/ai-translate.zsh signifie que vous êtes prêt. ai-translate not found signifie que l'étape 2 manque.

Conclusion​

La vraie histoire de confidentialité ici n'est ni une politique ni une promesse — c'est une architecture. Un document entre, Docling le transforme en texte sans appel réseau, Ollama traite ce texte sans appel réseau, et le résultat atterrit dans mon terminal. Il n'y a aucune étape de cette chaîne où « faire confiance au fournisseur » est nécessaire, et c'est exactement ce qui la rend utilisable pour les documents que je n'aurais jamais risqués sur un outil cloud. Entre ça, ai-ci pour les pipelines, ai-standup pour le récap du matin et le reste de cette série, le modèle local que j'avais déjà en route pour d'autres raisons trouve sans cesse une chose de plus à faire, discrètement, en arrière-plan, sans rien me demander d'autre qu'un chemin de fichier.


Cet article vous a-t-il été utile ?
Avez-vous suivi les étapes de cet article ?