Provided by: po4a_0.52-1_all 

NOM
po4a - Cadre de travail pour la traduction de documentations et autres documents
Introduction
L'objectif du projet po4a [PO for anything -- PO pour tout] est de simplifier la traduction (et de façon
plus intéressante, la maintenance des traductions) en utilisant les outils gettext dans des domaines pour
lesquels ils n'étaient pas destinés, comme la documentation.
Table des matières
Ce document est organisé de la manière suivante :
1 Pourquoi utiliser po4a ? À quoi cela sert-il ?
Cette section d'introduction explique les motivations du projet et sa philosophie. Vous devriez le
lire si vous cherchez à évaluer po4a pour vos traductions.
2 Comment utiliser les fonctionnalités de po4a ?
Cette section est une sorte de manuel de référence qui cherche à répondre aux questions des
utilisateurs et qui vous donnera une meilleure compréhension de son fonctionnement. Il vous donnera
les bases de l'utilisation de po4a et sert d'introduction à la documentation des outils spécifiques.
Comment commencer une nouvelle traduction ?
Comment convertir la traduction en un fichier de documentation ?
Comment mettre à jour une traduction faite avec po4a ?
Comment convertir une traduction pré-existante à ce système ?
Comment ajouter des choses n'étant pas des traductions (comme le nom du traducteur) ?
Comment automatiser tout ceci ?
Comment personaliser po4a ?
3 Comment ça marche ?
Cette section vous donne un bref aperçu des rouages internes de po4a afin que vous vous sentiez plus
à même de nous aider à le maintenir et l'améliorer. Elle peut également vous permettre de comprendre
pourquoi cela ne fait pas ce que vous souhaitez et corriger vos problèmes par vous-même.
4 FAQ
Cette section regroupe les questions le plus souvent posées. En fait, la plupart d'entre elles sont
des questions de design du projet. Si vous pensez que po4a n'est pas la bonne réponse au problème de
traduction de documentation, lisez cette section avant de nous donner votre avis sur la liste de
diffusion <po4a-devel@lists.alioth.debian.org>. Votre avis nous intéresse.
5 Notes spécifiques à certains modules
Cette section présente les spécificités de chaque module du point de vue du traducteur et de l'auteur
original. Lisez le pour prendre connaissance du format des traductions pour ce module et les règles à
suivre dans le document original pour rendre le travail des traducteurs plus simple.
Cette section ne fait pas vraiment partie de ce document, mais elle est placée dans chaque
documentation des modules. Ceci permet de s'assurer que les informations sont à jour en conservant la
documentation et le code ensemble.
Why should I use po4a? What is it good for?
J'aime le concept des logiciels à sources ouverts, qui permettent de donner à tous un accès au logiciel
et à son code source. Mais, étant moi-même français, je suis conscient que la licence n'est pas le seul
frein à l'ouverture d'un logiciel : les logiciels non traduits, même s'ils sont libres, sont sans aucune
utilité pour ceux qui ne comprennent pas l'anglais, et il y a encore beaucoup de travail pour les rendre
accessibles à vraiment tout le monde.
La perception du problème par les acteurs du développement libre s'est fortement accélérée récemment.
Nous, les traducteurs, avons gagné une première bataille et avons convaincu tout le monde de l'importance
des traductions. Mais c'est malheureusement la partie la plus facile. Il faut maintenant réaliser tout le
travail et traduire tous les documents.
Les logiciels aux sources ouverts bénéficient d'un niveau de traduction relativement bon, grâce à la
formidable suite d'outils gettext. Ces outils permettent d'extraire les chaînes à traduire du programme,
de les présenter sous une forme standard pour les traducteurs, puis d'utiliser le résultat de leur
travail lors de l'exécution pour afficher les messages traduits aux utilisateurs.
Mais cette situation est assez différente en ce qui concerne les documentations. Trop souvent, la
documentation traduite n'est pas assez visible (pas distribuée avec le programme), seulement partielle ou
pas à jour. Cette dernière situation est de loin la moins bonne. Les traductions pas à jour peuvent se
révéler plus embêtantes pour les utilisateurs que l'absence de traduction parce que d'anciens
comportements d'un programme peuvent y être décrits, mais ne plus être en vigueur.
La problématique
La traduction des documentations n'est pas une tâche difficile en elle-même. Les textes sont bien plus
longs que les messages des programmes ce qui rend leur traduction plus longue, mais il n'y a aucune
difficulté technique à faire ceci. La difficulté vient en fait de la maintenance de la traduction. La
détection des parties ayant été modifiées et nécessitant une mise à jour est une tâche très difficile, ce
qui explique que tant de traductions ne correspondent plus à la version originale.
La réponse de po4a
La maintenance de la traduction est donc la raison première de po4a. La façon de faire de gettext a été
réutilisée dans ce but. Comme avec gettext, des chaînes de texte sont extraites de leur emplacement
d'origine de façon à être présentées de façon standardisée aux traducteurs. Les outils pour gettext sont
ensuite utilisés pour aider le traducteur à faire son travail lorsqu'une nouvelle version du document est
disponible. Mais, à la différence de l'utilisation classique de gettext, les traductions sont réinjectée
dans la structure du document d'origine de façon à pouvoir les utiliser ou les distribuer comme les
documents de la version anglaise.
Grâce à ceci, la détection des parties du document qui nécessitent une mise à jour est très facile. Un
autre avantage est que l'outil va faire une bonne partie du travail lorsque seule la structure du
document à été modifiée et que des chapitres ont été déplacés, rassemblés ou redécoupés. En extrayant le
texte à traduire de la structure du document, il permet également de masquer la complexité de la mise en
page et réduit les chances d'avoir un document défectueux (même s'il reste un risque).
Veuillez également consulter la FAQ plus bas dans ce document pour une liste plus complète des avantages
et inconvénients de cette approche.
Formats pris en charge
Actuellement, cette approche a été implémentée avec succès pour un certain nombre de formats de mise en
page de texte.
man
Le bon vieux format des pages de manuel, utilisé par beaucoup de programmes. Le support de po4a pour ce
format est très utile parce que ce format est assez compliqué, surtout pour les débutants. Le module
Locale::Po4a::Man(3pm) supporte également le format mdoc, utilisé par les pages de manuel BSD (elles sont
également assez fréquentes sous Linux).
pod
C'est le format pour la documentation en ligne de Perl (« Perl Online Documentation »). Le langage et ses
documentations sont documentés de cette façon, ainsi que la plupart des scripts Perl existants. Il permet
de garder la documentation plus fidèle au code en les intégrant tous deux au même fichier. Il rend la vie
du programmeur plus simple, mais malheureusement pas celle du traducteur.
sgml
Même s'il est de plus en plus remplacé par le XML, ce format est encore assez utilisé pour les documents
dont la taille dépasse plusieurs écrans. Il permet de faire des livres complets. La mise à jours de
documents aussi longs est un vrai cauchemar. diff se montre souvent inutile quand le document original a
été réindenté après une mise à jour. Heureusement, po4a vous aide dans cette tâche.
Actuellement, seules les DTD DebianDoc et DocBook sont prises en charge, mais l'ajout d'une nouvelle est
très facile. Il est même possible d'utiliser po4a avec une DTD SGML inconnue sans modifier le code en
fournissant les informations nécessaires sur la ligne de commande. Veuillez consulter
Locale::Po4a::Sgml(3pm) pour plus de détails.
TeX / LaTeX
Le format LaTeX est un format majeur utilisé pour les documentations dans le monde du logiciel libre ou
pour des publications. Le module Locale::Po4a::LaTeX(3pm) a été testé avec la documentation de Python, un
livre et avec quelques présentations.
texinfo
Toutes les documentations du projet GNU sont écrites dans ce format (c'est même une des exigences pour
devenir un projet officiel du projet GNU). Le support pour Locale::Po4a::Texinfo(3pm) dans po4a en est
encore à ses début. Veuillez nous envoyer des rapports de bogue ou des demandes de nouvelle
fonctionnalité.
xml
Le format XML est à la base de beaucoup de formats pour la documentation.
À ce jour, la DTD DocBook est prise en charge par po4a. Veuillez consulter Locale::Po4a::Docbook(3pm)
pour plus de détails.
autres
Po4a can also handle some more rare or specialized formats, such as the documentation of compilation
options for the 2.4+ Linux kernels or the diagrams produced by the dia tool. Adding a new one is often
very easy and the main task is to come up with a parser of your target format. See
Locale::Po4a::TransTractor(3pm) for more information about this.
Formats non supportés
Malheureusement, po4a ne supporte pas encore certains formats utilisés pour les documentations.
Il y a une quantité d'autres formats que nous aimerions supporter avec po4a, et pas seulement des formats
de documentation. En fait, nous visons toutes les « niches » laissées par les outils gettext classiques.
Cela va de la traduction de la documentation des descriptions des paquets Debian et paquetages rpm, aux
les questions posées par les scripts d'installation, ex passant par les fichiers changelog, et de tous
les formats spécifiques tels que les scénarios de jeux ou les fichiers de ressource pour wine.
Comment utiliser po4a ?
Cette section est une sorte de manuel de référence qui cherche à répondre aux questions des utilisateurs
et qui vous donnera une meilleure compréhension de son fonctionnement. Il vous donnera les bases de
l'utilisation de po4a et sert d'introduction à la documentation des outils spécifiques.
Résumé graphique
Le schéma suivant donne un aperçu du processus mis en oeuvre pour la traduction de documents avec po4a.
Ne soyez pas effrayé par son apparente complexité, qui est due au fait que le processus complet y est
présenté. Une fois que vous avez converti votre projet à po4a, seule la partie de droite du graphique est
utilisée.
Note that master.doc is taken as an example for the documentation to be translated and translation.doc is
the corresponding translated text. The suffix could be .pod, .xml, or .sgml depending on its format. Each
part of the picture will be detailed in the next sections.
master.doc
|
V
+<-----<----+<-----<-----<--------+------->-------->-------+
: | | :
{translation} | { update of master.doc } :
: | | :
XX.doc | V V
(optional) | master.doc ->-------->------>+
: | (new) |
V V | |
[po4a-gettextize] doc.XX.po -->+ | |
| (old) | | |
| ^ V V |
| | [po4a-updatepo] |
V | | V
translation.pot ^ V |
| | doc.XX.po |
| | (fuzzy) |
{ translation } | | |
| ^ V V
| | {manual editing} |
| | | |
V | V V
doc.XX.po --->---->+<---<-- doc.XX.po addendum master.doc
(initial) (up-to-date) (optional) (up-to-date)
: | | |
: V | |
+----->----->----->------> + | |
| | |
V V V
+------>-----+------<------+
|
V
[po4a-translate]
|
V
XX.doc
(up-to-date)
La partie gauche illustre la conversion d'une traduction n'utilisant pas po4a. En haut de la partie
droite est présenté ce qui est du ressort de l'auteur du document d'origine (la mise à jour de la
documentation). Au milieu de la partie de droite se trouve la partie automatisée par po4a. Les nouvelles
chaînes sont extraites et comparées avec la traduction existante. Pour celles qui n'ont pas changé, la
traduction précédente est utilisée. Celles qui ont été en partie modifiées sont également associées à
leur ancienne traduction, mais avec un marquage spécifique indiquant que la traduction doit être mise à
jour. La partie du bas indique comment le document formaté est construit.
En fait, en tant que traducteur, la seule opération manuelle consiste en l'étape indiquée par {édition
manuelle}. En effet, nous nous en excusons, po4a aide à la traduction, mais il ne traduit rien pour
vous...
Comment commencer une nouvelle traduction ?
Cette section présente les étapes nécessaires pour débuter une nouvelle traduction avec po4a. Les
modifications à appliquer pour la conversion d'un projet existant sont détaillées dans la section
correspondante.
Voici les étapes permettant de commencer une traduction avec po4a :
- Extraction du texte du document d'origine <maitre.doc> qui doit être traduit dans <traduction.pot>, un
nouveau fichier POT (le format utilisé par gettext). Pour ceci, utilisez po4a-gettextize de cette
façon :
$ po4a-gettextize -f <format> -m <maître.doc> -p <traduction.pot>
Naturellement, <format> est le format du document maître.doc et la sortie est placée dans
traduction.pot. Veuillez consulter po4a-gettextize(1) pour plus de détails concernant les options
existantes.
- Actually translate what should be translated. For that, you have to rename the POT file for example to
doc.XX.po (where XX is the ISO 639-1 code of the language you are translating to, e.g. fr for French),
and edit the resulting file. It is often a good idea to not name the file XX.po to avoid confusion with
the translation of the program messages, but this your call. Don't forget to update the PO file
headers, they are important.
La traduction peut être réalisée avec Emacs ou Vi et leur mode PO, Lokalize (basé sur KDE), Gtranslator
(basé sur GNOME) ou n'importe quel programme que vous préférez utiliser (par exemple Virtaal).
Si vous voulez en apprendre plus à ce sujet, vous voudrez probablement consulter la documentation de
gettext, disponible dans le paquet gettext-doc.
Comment convertir la traduction en un fichier de documentation ?
Une fois que la traduction est effectuée, il faut générer la documentation traduite et la distribuer avec
l'original. Pour cela, utilisez po4a-translate(1) de cette façon (XX représente le code de la langue) :
$ po4a-translate -f <format> -m <maître.doc> -p <doc.XX.po> -l <XX.doc>
As before, <format> is the format used in the master.doc document. But this time, the PO file provided
with the -p flag is part of the input. This is your translation. The output goes into XX.doc.
Veuillez consulter po4a-translate(1) pour plus de détails.
Comment mettre à jour une traduction faite avec po4a ?
Pour mettre à jour votre traduction lorsque l'original maître.doc a changé, utilisez po4a-updatepo(1)
comme ceci :
$ po4a-updatepo -f <format> -m <nouveau_maître.doc> -p <ancien.XX.po>
(Veuillez consulter po4a-updatepo(1) pour plus de détails)
Naturellement, les nouveaux paragraphes de ce document ne seront pas traduits par magie dans le fichier
PO par cette opération, et vous devrez mettre à jour le fichier PO manuellement. De la même façon, vous
devrez vérifier les traductions des paragraphes qui ont été légèrement modifiés. Pour vous assurer que
vous n'en oubliez pas, ils sont marqués comme approximatifs (fuzzy) pendant cette phase, et vous devrez
retirer cette marque avant d'utiliser la traduction avec po4a-translate. Comme pour la traduction
originelle, vous pouvez utiliser votre éditeur de fichier PO préféré.
Une fois que votre fichier PO est de nouveau à jour, sans aucune chaîne non traduite ou marquée comme
approximative (fuzzy), vous pouvez générer un fichier de documentation traduit, comme expliqué dans la
section précédente.
Comment convertir une traduction pré-existante à ce système ?
Souvent, vous traduisez manuellement le document sans difficulté, jusqu'à ce qu'une réorganisation
majeure du document d'origine maître.doc apparaisse. Alors, après quelques essais infructueux en
utilisant diff ou des outils similaires, vous voulez convertir la traduction à po4a. Mais bien sûr, vous
ne souhaitez pas perdre votre traduction existante dans le même temps. Pas de panique, ce cas est aussi
géré par les outils de po4a et est appelé gettextization.
Le point important pour ceci est d'avoir la même structure de document pour l'original et la version
traduite, de façon à ce que les outils associent leur contenu correctement.
Si vous avez de la chance (c.-à-d., si les structures des deux documents se correspondent parfaitement),
ceci fonctionnera sans soucis, et vous n'en aurez que pour quelques secondes. Sinon, vous allez
comprendre pourquoi ce processus a un nom si barbare, et vous devriez vous préparer à une tâche ingrate.
Dans tous les cas, souvenez-vous que c'est le prix à payer pour bénéficier du confort que po4a vous
apportera par la suite. Le point positif est que vous n'aurez à faire cela qu'une seule fois.
I cannot emphasize this too much. In order to ease the process, it is thus important that you find the
exact version which were used to do the translation. The best situation is when you noted down the VCS
revision used for the translation and you didn't modify it in the translation process, so that you can
use it.
Ça ne fonctionnera pas très bien si vous utilisez le document d'origine mis à jour avec l'ancienne
traduction. Ça reste possible, mais sera plus compliqué et doit être évité autant que possible. En fait,
je pense que si vous n'arrivez pas à trouver le document original, la meilleure solution est de trouver
quelqu'un pour faire la gettextization pour vous (mais, s'il vous plaît, pas moi ;).
Je dramatise peut-être un peu trop ici. Même lorsque tout ne se passe pas bien, c'est bien plus rapide
que de tout retraduire. J'ai pu réaliser une gettextization de la traduction française de Perl en un
jour, même si les choses ne se sont pas bien passées. Il y avait plus de deux mégaoctets de textes, et
une nouvelle traduction aurait pris des mois.
Voici d'abord la procédure, puis nous reviendrons sur les astuces qui permettent d'y parvenir avec succès
lorsqu'il y a un problème. Pour faciliter la compréhension, réutilisons encore une fois l'exemple
précédent.
Une fois que vous avez l'ancien maître.doc correspondant à la traduction XX.doc, la gettextization peut
être faite directement dans le fichier PO doc.XX.po sans traduction manuelle du fichier traduction.pot :
$ po4a-gettextize -f <format> -m <ancien_maître.doc> -l <XX.doc> -p <doc.XX.po>
Si vous avez de la chance, c'est fini. Vous avez converti votre ancienne traduction pour po4a et pouvez
commencer la phase de mise à jour qui suit. Utiliser la procédure décrite quelques sections auparavant
pour synchroniser votre fichier PO avec le nouveau document original, et mettez à jour votre traduction
en conséquence.
Veuillez noter que même si tout semble s'être bien passé, il reste une possibilité que des erreurs se
soient introduites au cours du processus. En fait, po4a est incapable de vérifier que les chaînes
correspondent à l'original, et il marque toutes les chaînes comme approximatives (fuzzy) au cours de
cette procédure. Vous devriez vérifier chacune d'elle soigneusement avant de retirer ces marques.
Souvent, la structure du document ne correspond pas exactement, ce qui empêche po4a-gettextize de faire
son travail correctement. Pour contourner cela, vous pouvez éditer les fichiers afin de faire
correspondre leur structure.
La section Gettextization : Comment ça marche ? ci-dessous pourra vous aider. La compréhension du
fonctionnement interne vous aidera à réaliser cette tâche. Par chance, po4a-gettextize est relativement
bavard sur ce qui s'est mal passé. Dans un premier temps, il indique où, dans les documents, se trouve la
différence des structures. Vous obtiendrez les chaînes qui ne correspondent pas, leur position dans le
texte, et leur type De plus, le fichier PO généré ainsi sera écrit dans gettextization.failed.po.
- Retirez toutes les parties propres à la traduction, telles que les sections dans lesquelles vous avez
indiqué le nom du traducteur et les remerciements envers toutes les personnes qui ont contribué à la
traduction. Les addenda qui sont décrits dans la section suivante vous permettront de les rajouter
par la suite.
- N'hésitez pas à éditer les deux fichiers. Le plus important est d'obtenir le fichier PO. Vous pourrez
le mettre à jour par la suite. Cela dit, il est tout de même préférable d'éditer la traduction quand
c'est possible, puisque ça simplifiera les étapes suivantes.
- Si besoin, supprimez des parties de l'original s'il se trouve qu'elles n'ont pas été traduites. Elles
reviendront par la suite lorsque vous synchroniserez le PO avec le document.
- Si vous avez un peu modifié la structure (pour combiner deux paragraphes ou pour en découper un
autre), enlevez ces modifications. S'il y a des problèmes avec l'original, vous devriez en informer
son auteur. Faire la correction dans votre traduction n'en fait bénéficier qu'une partie de la
communauté. Et de plus, ce n'est pas possible lorsque po4a est utilisé.
- Parfois, le contenu des paragraphes correspond, mais pas leur type. Corriger cela dépend du format.
Pour les formats POD et man, cela provient souvent du fait qu'un des deux contient une ligne
commençant par des espaces et pas l'autre. Pour ces formats, cela signifie que ce paragraphe ne doit
pas être reformaté, il a donc un type différent. Retirez simplement les espaces et vous serez
tranquille. Il se peut aussi qu'il s'agisse d'une petite erreur dans le nom d'une balise.
De la même façon, deux paragraphes peuvent avoir été combinés, dans le format POD, si la ligne qui
les sépare contient des espaces, ou s'il n'y a pas de ligne vide entre la ligne =item et le contenu
de cet élément.
- Il arrive également qu'il se produise une désynchronisation entre les fichiers, et la traduction se
retrouve alors attachée au mauvais paragraphe. C'est le signe que le problème se situe avant dans le
fichier. Consultez gettextization.failed.po pour voir quand la désynchronisation s'est produite, et
corrigez-la.
- D'autres fois, vous aurez l'impression que po4a a oublié des parties du texte original ou de la
traduction. gettextization.failed.po indique que les deux correspondent correctement, mais la
gettextization échoue parce que po4a essaie de faire correspondre un paragraphe avec le paragraphe
suivant (ou précédant) de celui qui devrait lui être associé, comme si celui-ci avait disparu. Vous
pesterez sûrement contre po4a comme je l'ai fait quand ça m'est arrivé.
Cette situation malheureuse se manifeste quand un même paragraphe est répété dans le document. Dans
ce cas, aucune nouvelle entrée n'est créée dans le fichier PO, mais une nouvelle référence est
ajoutée à l'entrée existante.
So, when the same paragraph appears twice in the original but both are not translated in the exact
same way each time, you will get the feeling that a paragraph of the original disappeared. Just kill
the new translation. If you prefer to kill the first translation instead when the second one was
actually better, replace the first one with the second.
De la même façon, si deux paragraphes légèrement différents ont été traduits de façon identique, vous
aurez l'impression qu'un paragraphe de la traduction a disparu. Une solution consiste à ajouter une
certaine chaîne dans le paragraphe du document original (« I'm different » par exemple). Ne vous
inquiétez pas, ces modifications disparaîtront pendant la synchronisation, et quand le texte ajouté
est suffisamment court, gettext associera votre traduction au texte existant de toute façon (en le
marquant comme approximatif (fuzzy), ce qui n'a pas d'importance puisque toutes les chaînes sont
marquées fuzzy après la gettextization).
Avec un peu de chance, ces astuces vous permettront de réaliser la gettextization et d'obtenir le
précieux PO. Vous serez alors prêt pour synchroniser votre fichier et commencer la traduction. Veuillez
noter que pour les gros fichiers, la synchronisation peut prendre beaucoup de temps.
Par exemple, la première exécution de po4a-updatepo pour la traduction de la documentation Perl (un
fichier PO de 5,5 Mo) a pris presque deux jours sur un G5 à 1GHz. Eh oui, 48 heures. Mais les mises à
jour suivantes n'ont pris que quelques secondes sur un vieux portable. Ceci parce que la première fois,
la plupart des msgid du PO ne correspondent à aucun dans le fichier POT. Ce qui oblige gettext à
rechercher la chaîne la plus proche avec un algorithme de recherche coûteux.
Comment ajouter des choses n'étant pas des traductions (comme le nom du traducteur) ?
Du fait de l'approche de type gettext, faire ceci est plus compliqué avec po4a que ça ne l'était en
éditant simplement le nouveau fichier et en lisant l'original à côté. Mais ceci reste possible en
utilisant les « addenda ».
Pour aider à leur compréhension, on peut considérer les addenda comme des sortes de rustines à appliquer
sur le document traduit à la fin du processus. Ils sont assez différents des rustines usuelles (il n'y a
qu'une seule ligne de contexte, qui peut contenir une expression rationnelle Perl, et ne peuvent que
rajouter du texte, sans en enlever), mais la fonctionnalité qu'ils apportent est la même.
Leur but est de permettre au traducteur d'ajouter au document du texte qui ne soit pas une traduction,
mais quelque chose de spécifique à la version traduite. De cette façon, ils peuvent ajouter une section
indiquant qui a participé à cette traduction ou expliquer comment rapporter des bogues de traduction.
Un addendum est fourni dans un fichier séparé. La première ligne constitue un en-tête indiquant où le
texte qu'il contient doit être placé dans le document. Le reste du fichier est ajouté tel quel à cette
position dans le document résultant.
Les en-têtes ont une syntaxe relativement rigide : ils doivent commencer par la chaîne PO4A-HEADER:,
suivie par une liste de champs de la forme clef=valeur séparés par des points-virgules. Les espaces sont
importants. Notez qu'il n'est pas possible d'utiliser de point-virgule dans la valeur, même en la plaçant
entre des guillemets.
Encore une fois, ça paraît peut-être effrayant, mais les exemples ci-dessous devraient vous aider à
écrire les en-têtes dont vous avez besoin. Supposons que nous voulons ajouter une section « À propos de
cette traduction » après la section « À propos de ce document ».
Voici les différentes clefs d'en-tête existantes :
position (obligatoire)
une expression rationnelle Perl. L'addendum sera placé près de la ligne correspondant à cette
expression rationnelle. Notez qu'il s'agit ici du document traduit, et non pas du document original.
Si plus d'une ligne correspond à cette expression (ou si aucune ne correspond), l'ajout échouera. Il
est préférable de donner un message d'erreur que d'ajouter l'addendum au mauvais endroit.
La ligne est appelée point de position par la suite. L'endroit où est ajouté l'addendum est appelé
point d'insertion. Ces deux points sont proches, mais pas identiques. Par exemple, si vous voulez
insérer une nouvelle section, il est plus simple de placer le point de position au niveau du titre de
la section précédente, et d'expliquer à po4a où se termine la section (souvenez-vous que le point de
position doit être donné par une expression rationnelle ne correspondant qu'à une seule ligne.
La localisation du point d'insertion par rapport au point de position est contrôlée par les champs
mode, beginboundary et endboundary, comme expliqué par la suite.
Dans notre cas, nous aurons :
position=<title>À propos de ce document</title>
mode (obligatoire)
It can be either the string before or after, specifying the position of the addendum, relative to the
position point. In case before is given the insertion point will placed exactly before the position
point. The after behaviour is detailed bellow.
Comme nous voulons placer la nouvelle section sous celle qui correspond, nous utilisons :
mode=after
beginboundary (utilisé uniquement avec mode=after, et obligatoire dans ce cas)
endboundary (idem)
expression rationnelle correspondant à la fin de la section après laquelle l'addendum doit être
placé.
Lorsque le mode vaut after (après), le point d'insertion se trouvera après le point de position, mais
pas juste après ! Il est placé à la fin de la section qui débute par le point de position,
c'est-à-dire après la ligne correspondant à l'expression rationnelle donnée par le champ
beginboundary ou avant la ligne correspondant à l'expression rationnelle donnée par le champ
endboundary.
Dans notre cas, nous pouvons choisir d'indiquer la fin de la section qui doit correspondre en
ajoutant :
endboundary=</section>
ou en indiquant le début de la section suivante en indiquant :
beginboundary=<section>
Dans les deux cas, notre addendum sera placé après </section> et avant <section>. La première
solution est meilleure puisqu'elle fonctionnera toujours, même si le document est réorganisé.
Les deux existent parce que les formats des documentations sont différents. Dans certains d'entre
eux, il est possible d'indiquer la fin d'une section comme </section> que nous avons utilisé), et
dans d'autres les fins de section ne sont pas spécifiées explicitement (c'est le cas du format man).
Dans le premier cas, la « frontière » (boundary) est la fin de section, et le point d'insertion vient
après. Dans le second cas, la frontière correspond au début de la section suivante, et le point
d'insertion vient juste avant.
Tout ceci peut sembler confus, mais l'exemple suivant devrait vous éclairer.
Pour résumer l'exemple utilisé, pour ajouter une section appelée « À propos de cette traduction » après
la section « À propos de ce document » dans un document SGML, vous pouvez utiliser une de ces lignes
d'en-tête.
PO4A-HEADER: mode=after; position=À propos de ce document; endboundary=</section>
PO4A-HEADER: mode=after; position=À propos de ce document; beginboundary=<section>
Si vous voulez ajouter quelque chose après la section nroff suivante :
.SH "AUTEURS"
vous devez utiliser un champ position correspondant à cette ligne, et un champ beginboundary
correspondant au début de la section suivante (c'est-à-dire ^\.SH). L'addendum sera placé après le
point de position et immédiatement avant la première ligne correspondant au champ beginboundary.
C'est-à-dire :
PO4A-HEADER:mode=after;position=AUTEURS;beginboundary=\.SH
Si vous voulez ajouter quelque chose à une section (par exemple après « Copyright Tralala ») au lieu
d'ajouter une section entière, vous pouvez fournir une position correspondant à cette ligne, et un champ
beginboundary correspondant à n'importe quelle ligne.
PO4A-HEADER:mode=after;position=Copyright Tralala, 2004;beginboundary=^
Si vous voulez ajouter quelque chose à la fin du document, donnez une position correspondant à n'importe
quelle ligne du document (mais à une seule ligne, puisque po4a n'acceptera pas que la position ne
corresponde pas à une ligne unique), et donnez un champ endboundary ne correspondant à aucune ligne.
N'utilisez pas de chaîne simple, comme "EOF", mais préférez-en une qui a une chance moindre de se trouver
dans votre document.
PO4A-HEADER:mode=after;position=<title>Au sujet de...</title>;beginboundary=FausseLimitePo4a
Dans tous les cas, rappelez-vous qu'il s'agit d'une expression rationnelle. Par exemple, si vous voulez
pointer la fin d'une section nroff qui se termine par la ligne :
.fi
N'utilisez pas .fi comme valeur pour endboundary, parce que cette expression rationnelle correspond
également à « ce[ fi]chier », ce qui n'est évidemment pas ce que vous voulez. La valeur du champ
endboundary dans ce cas est ^\.fi$.
Si l'addendum n'est pas positionné là où vous l'escomptiez, essayez en fournissant l'option -vv aux
outils, ce qui vous donnera des indications sur ce qui est fait pour le placement de l'addendum.
Voici un exemple plus détaillé.
Document original (au format POD) :
|=head1 NAME
|
|dummy - a dummy program
|
|=head1 AUTHOR
|
|me
Voici maintenant un addendum qui s'assure qu'une section est ajoutée à la fin du fichier pour indiquer le
traducteur.
|PO4A-HEADER:mode=after;position=AUTEUR;beginboundary=^=head
|
|=head1 TRADUCTEUR
|
|moi
|
De façon à placer l'addendum avant l'AUTEUR (section nommée AUTHOR dans le document original), utilisez
l'en-tête suivant :
PO4A-HEADER:mode=after;position=NOM;beginboundary=^=head1
This works because the next line matching the beginboundary /^=head1/ after the section "NAME"
(translated to "NOM" in French), is the one declaring the authors. So, the addendum will be put between
both sections. Note that if later some other section will be added between NAME and AUTHOR sections, it
will break this example making the addenda to be added before this newly added section.
To avoid this you may accomplish the same using mode=before:
PO4A-HEADER:mode=before;position=^=head1 AUTEUR
Comment automatiser tout ceci ?
L'utilisation de po4a s'est montrée propice aux erreurs pour les utilisateurs parce que deux programmes
doivent être appelés dans le bon ordre (po4a-updatepo puis po4a-translate), chacun d'eux prenant au moins
troisparamètres. De plus, il était difficile avec ce système d'utiliser un seul fichier PO pour tous les
documents quand plusieurs formats étaient utilisés.
Le programme po4a(1) a été conçu pour répondre à ces difficultés. Une fois que votre projet a été
converti à po4a, vous écrivez un petit fichier de configuration indiquant où se trouvent vos fichiers de
traduction (les fichiers PO et POT), où se trouvent les documents originaux, leurs formats, et où doivent
être placées leur traduction.
Then, calling po4a(1) on this file ensures that the PO files are synchronized against the original
document, and that the translated document are generated properly. Of course, you will want to call this
program twice: once before editing the PO files to update them and once afterward to get a completely
updated translated document. But you only need to remember one command line.
Comment personaliser po4a ?
Les modules po4a ont des options (fournies à l'aide de l'option -o) qui peuvent être utilisées pour
modifier le comportement du module.
You can also edit the source code of the existing modules or even write your own modules. To make them
visible to po4a, copy your modules into a path called "/bli/blah/blu/lib/Locale/Po4a/" and then adding
the path "/bli/blah/blu" in the "PERLIB" or "PERL5LIB" environment variable. For example:
PERLLIB=$PWD/lib po4a --previous po4a/po4a.cfg
Note : le nom du répertoire « lib » n'est pas important.
Comment ça marche ?
Cette section vous donne un bref aperçu des rouages internes de po4a afin que vous vous sentiez plus à
même de nous aider à le maintenir et l'améliorer. Elle peut également vous permettre de comprendre
pourquoi cela ne fait pas ce que vous souhaitez et corriger vos problèmes par vous-même.
Quel est le plan général ici ?
L'architecture po4a est orientée objet (en Perl, n'est-ce pas formidable ?). L'ancêtre commun de tous les
classes d'analyseur est appelé Transtractor. Ce nom étrange provient du fait qu'il est à la fois chargé
de la traduction et de l'extraction des chaînes du document.
Plus formellement, il prend un document à traduire et un fichier PO contenant les traductions en entrée
et produit en sortie deux autres fichiers : un autre fichier PO (résultant de l'extraction des chaînes à
traduire du document d'entrée), et un document traduit (avec la même structure que le document d'entrée,
mais dont toutes les chaînes à traduire ont été remplacées par leur traduction donnée par le PO fournit
en entrée). Voici une représentation graphique de tout ceci :
document entrée --\ /---> document sortie
\ TransTractor:: / (traduit)
+-->-- parse() --------+
/ \
PO entrée --------/ \---> PO sortie
(extrait)
Cette forme d'os est le cœur de l'architecture de po4a. Sans le fichier PO en entrée et le document en
sortie, cela donne po4a-gettextize. Si vous fournissez les deux entrées et ignorez le PO de sortie, vous
aurez po4a-translate.
TransTractor::parse() est une fonction virtuelle implémentée dans chaque module. Voici un petit exemple
pour montrer comment elle fonctionne. Cet exemple analyse une liste de paragraphes qui débutent tous par
<p>.
1 sub parse {
2 PARAGRAPH: while (1) {
3 $my ($paragraph,$pararef,$line,$lref)=("","","","");
4 $my $first=1;
5 while (($line,$lref)=$document->shiftline() && defined($line)) {
6 if ($line =~ m/<p>/ && !$first--; ) {
7 $document->unshiftline($line,$lref);
8
9 $paragraph =~ s/^<p>//s;
10 $document->pushline("<p>".$document->translate($paragraph,$pararef));
11
12 next PARAGRAPH;
13 } else {
14 $paragraph .= $line;
15 $pararef = $lref unless(length($pararef));
16 }
17 }
18 return; # Did not got a defined line? End of input file.
19 }
20 }
À la ligne 6, <p> est rencontré pour la seconde fois. Cela indique le passage un paragraphe suivant. Nous
replaçons donc la ligne, qui vient juste d'être obtenue, dans le document d'origine (ligne 7) et envoyons
le paragraphe ainsi construit dans les sorties. Après avoir retiré le <p> de tête en ligne 9, nous
envoyons la concaténation de cette balise avec la traduction du reste du paragraphe.
Cette fonction translate() est très pratique. Elle envoie son paramètre dans le fichier PO de sortie
(l'extraction) et renvoie sa traduction telle qu'elle a été trouvée dans le fichier PO d'entrée (la
traduction). Comme elle est utilisée dans le paramètre de pushline(), cette traduction se retrouve dans
le document de sortie.
N'est-ce pas génial ? Il est possible de construire un module complet pour po4a en moins de 20 lignes, si
le format est suffisamment simple...
Vous trouverez plus de détails à ce sujet dans Locale::Po4a::TransTractor(3pm).
Gettextization : Comment ça marche ?
L'idée ici est de prendre à la fois le document d'origine et sa traduction, et de supposer que la énième
chaîne extraite du document traduit correspond à la traduction de la énième chaîne du document original.
Pour que cela fonctionne, il faut donc que les deux documents aient exactement la même structure. Par
exemple, si les fichiers ont la structure suivante, il y a très peu de chance pour que la quatrième
chaîne de la traduction (qui est de type « chapitre ») soit la traduction de la quatrième chaîne du
document original (de type « paragraphe »).
Original Traduction
chapitre chapitre
paragraphe paragraphe
paragraphe paragraphe
paragraphe chapitre
chapitre paragraphe
paragraphe paragraphe
Pour cela, les analyseurs po4a sont utilisés à la fois sur l'original et sur la traduction pour extraire
des fichiers PO, et un troisième fichier PO est construit à partir d'eux en utilisant les chaînes du
second comme traductions des chaînes du premier. Pour s'assurer que les chaînes ainsi associées sont bien
les traductions, les analyseurs de po4a doivent ajouter des informations sur le type syntaxique des
chaînes extraites du document (les analyseurs existants le font, les vôtres devraient également).
Ensuite, ces informations sont utilisées pour s'assurer que les deux documents ont la même syntaxe. Dans
l'exemple précédent, cela permet de détecter que la quatrième chaîne est dans un cas un paragraphe et
dans l'autre un titre de chapitre, et le problème est affiché.
En théorie, il devrait être possible de détecter le problème, puis de resynchroniser les fichiers par la
suite (comme le fait diff). Mais il est alors difficile de savoir quoi faire des chaînes précédant la
désynchronisation, et le résultat pourrait parfois ne pas être bon. C'est pourquoi l'implémentation
actuelle ne resynchronise rien et échoue avec un message d'erreur complet quand quelque chose se passe
mal, indiquant qu'une modification manuelle des fichiers est nécessaire pour corriger le problème.
Même avec ces précautions, des erreurs peuvent survenir. C'est la raison pour laquelle toutes les
traductions trouvées de cette façon sont marquées fuzzy, pour s'assurer que le traducteur les relira et
vérifiera.
Fonctionnement d'un Addendum
Bien, il n'y a rien de bien compliqué ici. La traduction n'est pas directement écrite sur le disque, mais
est conservée en mémoire jusqu'à ce que tous les addenda soient ajoutés. Les algorithmes utilisés sont
assez simples. Une ligne correspondant à l'expression rationnelle de la position est recherchée, et
l'addendum est ajouté juste avant si mode=before. Sinon, la première ligne trouvée à partir de cette
position correspondant à l'expression rationnelle donnée par le champ boundary est recherchée et
l'addendum est inséré juste après cette ligne s'il s'agit d'un endboundary ou juste avant s'il s'agit
d'un beginboundary.
FAQ
Cette section regroupe les questions le plus souvent posées. En fait, la plupart d'entre elles sont des
questions de design du projet. Si vous pensez que po4a n'est pas la bonne réponse au problème de
traduction de documentation, lisez cette section avant de nous donner votre avis sur la liste de
diffusion <po4a-devel@lists.alioth.debian.org>. Votre avis nous intéresse.
Pourquoi traduire chaque paragraphe séparément ?
En effet, avec po4a, tous les paragraphes sont traduits séparément (en fait, c'est au choix de chaque
module, mais tous les modules existants font ainsi, et les vôtres devraient également). Il y a deux
avantages principaux à cette approche :
• Quand les parties techniques du document sont masquées, le traducteur ne peut pas faire de bêtises
avec. Moins nous présentons de marqueurs au traducteur, moins il pourra faire d'erreurs.
• Découper le document aide à isoler les changements apparaissant dans le document original. Lorsque
l'original est modifié, la mise à jour des parties modifiées est plus facile.
Même avec ces avantages, certains n'aiment pas l'idée de traduire chaque paragraphe séparément. Voici
quelques réponses à leurs inquiétudes :
• Cette approche a été couronnée de succès dans le cadre du projet KDE et a permis de produire la plus
grosse documentation traduite et mise à jour à notre connaissance.
• Les traducteurs peuvent toujours utiliser le contexte pour traduire, puisque les chaînes du fichier PO
se trouvent dans le même ordre que dans le document original. La traduction séquentielle est donc
relativement comparable qu'elle soit faite avec ou sans po4a. Et dans tous les cas, la meilleure façon
reste de convertir le document dans un format imprimable puisque les indications de formatage ne sont
pas vraiment lisibles.
• C'est l'approche utilisée par les traducteurs professionnels. Même si je l'admets, leurs buts peuvent
être différents des traducteurs de logiciels à source ouvert. La maintenance étant par exemple souvent
moins critique puisque le contenu change rarement.
Pourquoi ne pas découper au niveau des phrases (ou à un niveau plus petit) ?
Les outils des traducteurs professionnels découpent parfois les documents au niveau des phrases, de façon
à maximiser la réutilisation de traductions précédentes et à accélérer leur travail. Le problème est
qu'une même phrase peut avoir plusieurs traductions en fonction du contexte.
Les paragraphes sont par définition plus longs que les phrases. Cela permet la plupart du temps d'assurer
que deux paragraphes dans deux documents différents auront le même sens (et la même traduction),
indépendamment du contexte.
Un découpage à un niveau encore plus petit qu'une phrase pourrait être très gênant. Ce serait un peu long
d'expliquer pourquoi ici, mais les lecteurs intéressés pourront par exemple consulter la page de manuel
Locale::Maketext::TPJ13(3pm) (qui est fournie avec la documentation de Perl). Pour faire court, chaque
langue a ses propres règles syntaxiques, et il n'y a aucun moyen de construire des phrases à partir de
morceaux de phrases pour toutes les langues existantes (ou pour les 5 à 10 langues les plus parlées, et
même moins).
Pourquoi ne pas mettre la version originelle en commentaire avec la traduction (ou l'inverse) ?
À première vue, gettext ne semble pas adapté à tous les types de traduction. Par exemple, il ne semblait
pas adapté à debconf, l'interface que tous les paquets Debian utilisent pour l'interaction avec
l'utilisateur pendant l'installation. Dans ce cas, les textes à traduire étaient assez courts (une
dizaine de lignes pour chaque fichier), et il était difficile de placer la traduction dans un fichier
séparé parce qu'il doit être disponible avant l'installation du paquet.
C'est pourquoi les concepteurs de debconf ont décidé d'implémenter une autre solution, plaçant les
traductions dans le même fichier que l'original. C'est une solution plutôt séduisante. Certains voudront
également faire ainsi pour les fichiers XML, par exemple. Voici à quoi cela ressemblerait :
<section>
<title lang="en">My title</title>
<title lang="fr">Mon titre</title>
<para>
<text lang="en">My text.</text>
<text lang="fr">Mon texte.</text>
</para>
</section>
Mais cette solution a été si problématique que l'approche basée sur PO est désormais utilisée. Seul
l'original peut être édité dans le fichier, et les traductions sont placées dans des fichiers PO générés
à partir du modèle maître (et replacés au cours de la compilation). L'ancien système a été abandonné à
cause de plusieurs problèmes :
• problèmes de maintenance
Si plusieurs traducteurs fournissent une rustine (patch) au même moment, il est difficile de les
appliquer ensemble.
Comment détecter les modifications dans l'original qui doivent être appliquées à une traduction ?
Pour pouvoir utiliser diff, il faut noter la version du document original traduit. C'est-à-dire qu'il
faut un fichier PO dans le fichier ;)
• problèmes d'encodage
Cette solution n'est envisageable que quand seules des langues européennes sont impliquées, mais la
traduction pour le coréen, le russe ou l'arabe peuvent compliquer la situation. UTF peut être une
solution, mais il y a également des problèmes avec.
De plus, ces problèmes sont difficiles à détecter (c.-à-d. que seules les personnes capables de lire
le coréen pourront s'apercevoir que l'encodage pour le coréen est défectueux [ce qui aurait été causé
par un traducteur russe]).
gettext résout tous ces problèmes.
Mais gettext n'a pas été conçu pour faire ça !
C'est vrai, mais à ce jour, personne n'a apporté de meilleure solution. La seule solution alternative est
la traduction manuelle, avec tous les problèmes de maintenance qu'elle comporte.
Qu'en est-il des autres outils de traduction de documentation utilisant gettext ?
Il n'y en à notre connaissance que deux :
poxml
C'est l'outil développé au sein du projet KDE pour gérer les XML DocBook. C'est à notre connaissance
le premier programme qui a extrait des chaînes à traduire d'une documentation pour les mettre dans un
fichier PO, et les réinjecter ensuite dans le document après la traduction.
Il ne peut gérer que le format XML, avec une DTD particulière. Je n'aime pas beaucoup la façon dont
les listes sont gérées, elles sont rassemblées en un seul gros msgid. Lorsque la liste est de taille
importante, les éléments sont assez durs à gérer.
po-debiandoc
Ce programme écrit par Denis Barbier est un précurseur du module SGML de po4a, qui le remplace plus
ou moins. Comme son nom l'indique, il ne gère que la DTD DebianDoc, qui est en voie d'extinction.
Le principal avantage de po4a par rapport à eux est la facilité d'ajouter du contenu additionnel (ce qui
est encore plus difficile avec ces outils) et la possibilité de faire une gettextization.
Éduquer les développeurs au problème des traductions
Lors de la traduction de documentations ou de programmes, trois types de difficultés sont rencontrés ;
des problèmes linguistiques (tout le monde ne parle pas deux langues), des problèmes techniques (la
raison d'être de po4a) et des problèmes de type relationnel et humain. Tous les développeurs ne voient
pas la nécessité de réaliser des traductions. Même avec la meilleure volonté, ils peuvent aussi ignorer
comment faciliter le travail des traducteurs. C'est pour cela que po4a fournit une bonne quantité de
documentation que vous pouvez leur indiquer.
Un autre point important est que chaque fichier traduit contient un petit commentaire indiquant ce qu'est
le fichier et comment l'utiliser. Ceci devrait aider les pauvres développeurs inondés de tonnes de
fichiers contenant les traductions pour des langues qu'ils ne parlent quasiment pas, et qui devrait les
aider à gérer ces fichiers correctement.
In the po4a project, translated documents are not source files anymore, in the sense that these files are
not the preferred form of the work for making modifications to it. Since this is rather unconventional,
that's a source of easy mistakes. That's why all files present this header:
| *****************************************************
| * GENERATED FILE, DO NOT EDIT *
| * THIS IS NO SOURCE FILE, BUT RESULT OF COMPILATION *
| *****************************************************
|
| This file was generated by po4a-translate(1). Do not store it (in VCS,
| for example), but store the PO file used as source file by po4a-translate.
|
| In fact, consider this as a binary, and the PO file as a regular source file:
| If the PO gets lost, keeping this translation up-to-date will be harder ;)
De la même façon, les fichiers PO usuels n'ont qu'à être copiés dans le répertoire po/. Mais ce n'est pas
le cas de ceux manipulés par po4a. Le principal risque étant que le développeur écrase la traduction
existante de son programme avec la traduction de sa documentation. (Les deux ne peuvent pas être stockées
dans le même fichier PO parce que le programme doit installer sa traduction en tant que fichier mo et que
la documentation n'a besoin de la traduction qu'au moment de la compilation). C'est pourquoi les fichiers
PO créés par le module po-debiandoc contient l'en-tête suivant :
#
# ADVISES TO DEVELOPERS:
# - you do not need to manually edit POT or PO files.
# - this file contains the translation of your debconf templates.
# Do not replace the translation of your program with this !!
# (or your translators will get very upset)
#
# ADVISES TO TRANSLATORS:
# If you are not familiar with the PO format, gettext documentation
# is worth reading, especially sections dedicated to this format.
# For example, run:
# info -n '(gettext)PO Files'
# info -n '(gettext)Header Entry'
#
# Some information specific to po-debconf are available at
# /usr/share/doc/po-debconf/README-trans
# or http://www.debian.org/intl/l10n/po-debconf/README-trans
#
RÉSUMÉ des avantages de l'approche basée sur gettext
• Les traductions ne sont pas stockées indépendamment de l'original, ce qui rend possible la détection
des parties à mettre à jour.
• Les traductions sont stockées dans des fichiers différents pour chaque langue, ce qui évite les
interférences entre traducteurs. Que ce soit pour la soumission de rustines ou pour le choix d'un
encodage.
• En interne, tout est basé sur gettext (mais po4a offre une interface simple qui ne nécessite pas de
comprendre comment ça marche en interne pour pouvoir l'utiliser). Ce qui permet de ne pas réinventer la
roue, et du fait de leur utilisation importante, nous pouvons supposer qu'ils ont peu ou pas de bogue.
• Pour l'utilisateur final, rien ne change (à part que les documentations seront probablement mieux
maintenues :). La documentation distribuée reste la même.
• Il n'est pas nécessaire pour les traducteurs d'apprendre une nouvelle syntaxe et leur éditeur de
fichier PO préféré (qui peut être le mode PO d'Emacs, Lokalize ou Gtranslator) sera parfait.
• gettext permet d'obtenir facilement des statistiques sur ce qui a été fait, ce qui doit être revu et
mis à jour, et sur ce qu'il reste à faire. Vous trouverez des exemples à ces adresses :
- http://kv-53.narod.ru/kaider1.png
- http://www.debian.org/intl/l10n/
Mais tout n'est pas rose, et cette approche a aussi quelques désavantages que nous devons gérer.
• Les addenda sont... surprenants au premier abord.
• Il n'est pas possible d'adapter le texte traduit à votre goût, comme de décomposer ou recomposer des
paragraphes. Mais d'un autre côté, s'il s'agit d'un problème dans le document original, celui-ci doit
être signalé de toute façon.
• Même s'il a une interface simple, il reste un nouvel outil qu'il faudra apprendre à maîtriser.
One of my dreams would be to integrate somehow po4a to Gtranslator or Lokalize. When a documentation
file is opened, the strings are automatically extracted, and a translated file + po file can be written
to disk. If we manage to do an MS Word (TM) module (or at least RTF) professional translators may even
use it.
AUTEURS
Denis Barbier <barbier,linuxfr.org>
Martin Quinson (mquinson#debian.org)
TRADUCTION
Martin Quinson (mquinson#debian.org)
Outils po4a 2017-08-26 PO4A(7)