Support gettext pour un script shell

J’avais déjà utilisé gettext avec du C, mais pas avec un script shell, or sur ce dernier, il faut non seulement extraire les chaines et les traduire, mais aussi faire gaffe aux différentes expansions que peut effectuer le shell.

En tout cas, ça me permet de faire un petit mémo dessus qui peut aussi servir à des fins de test.

Fonctionnement

Gettext permet de traduire un message dans le language qu’utilise l’utilisateur, ceci en se basant sur les locales définies, plus précisément, la catégorie LC_MESSAGES.

Un catalogue pour gettext est un fichier .mo placé dans l’arborescence suivante:

repertoire_base/locale/LC_categorie/nom_de_domaine.mo
  • repertoire_base: par défaut, le répertoire est /usr/share/locale
  • locale: la locale définie par l’utilisateur, si l’une n’est pas définie, on passe à la suivante, dans l’ordre suivant:
    • LC_ALL
    • LC_MESSAGES
    • LANG

    Une locale est définie selon le motif suivant:

    langage[_pays][.encodage][@modification]

    si gettext ne trouve pas le motif complet, il cherche avec une option en moins, un programme s’exécutant avec une locale définie à fr_FR.utf8@euro et avec seulement un catalogue dans le répertoire fr/LC_MESSAGES/programme.mo fonctionnera.

  • LC_categorie: égale à LC_MESSAGES pour gettext.
  • nom_de_domaine: égale au nom spécifié dans le programme.

Modification d’un script

Prenons un script exemple:

#!/bin/sh
[ -z $1 ] && echo "Usage: $0 number" && exit 1
if ! let $1 2> /dev/null
then
  echo "$1 is not a number"
  exit 2
fi

nbr=$(($RANDOM % $1))
guess=-1
while [ $guess != $nbr ]
do
  echo -n "Enter a number:"
  read guess
  [ $guess -lt $nbr ] && echo "bigger"
  [ $guess -gt $nbr ] && echo "smaller"
done
echo "good job"

Il faut le modifier de la sorte:

#!/bin/sh
export TEXTDOMAIN=programme
export TEXTDOMAINDIR=$(pwd)
. gettext.sh
progname=$0
[ -z $1 ] && echo $(eval_gettext 'Usage: $progname number') && exit 1
if ! let $1 2> /dev/null
then
  arg=$1
  echo $(eval_gettext '$arg is not a number')
  exit 2
fi

nbr=$(($RANDOM % $1))
guess=-1
while [ $guess != $nbr ]
do
  echo -n $(eval_gettext "Enter a number:")
  read guess
  [ $guess -lt $nbr ] && echo $(eval_gettext "bigger")
  [ $guess -gt $nbr ] && echo $(eval_gettext "smaller")
done
echo $(eval_gettext "good job")

TEXTDOMAIN indique le catalogue à utiliser.
TEXTDOMAINDIR indique le répertoire du catalogue; afin de tester, nous indiquons le répertoire courant.
« . gettext.sh » fournit certaines fonctions (eval_gettext, $echo, etc…)
Et toutes les variables propres au shell, $0, $1, etc… doivent être remplacées, et la phrase échappée par des  » pour qu’elles soient prises en compte par gettext

Construction du fichier .po

Celle-ci se fait à l’aide du programme xgettext.
Le programme peut reconnaitre le langage du programme selon l’extension du fichier, sinon il faut le lui spécifier avec -L:

xgettext --from-code=utf-8 -L shell -o fr.po programme

ce qui nous donne dans le fr.po:

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR , YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2008-05-25 20:54+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

#: programme:6
#, sh-format
msgid "Usage: $progname nombre"
msgstr ""

#: programme:10
#, sh-format
msgid "$arg is not a number"
msgstr ""

#: programme:18
#, sh-format
msgid "Enter a number:"
msgstr ""

#: programme:20
#, sh-format
msgid "bigger"
msgstr ""

#: programme:21
#, sh-format
msgid "smaller"
msgstr ""

#: programme:23
#, sh-format
msgid "good job"
msgstr ""

Suffit ensuite de traduire les chaines…
Vous pouvez utiliser pour cela un simple éditeur de fichier, ou un programme spécifique tel que poedit, gtranslator ou kbabel.

Compilation du catalogue

Lancer la commande:

mkdir -p fr/LC_MESSAGES
msgfmt -o fr/LC_MESSAGES/programme.mo fr.po

Pour tester, on peut utiliser la commande:

TEXTDOMAINDIR=. gettext -s -d programme "Enter a number:"

Utilisation

Reste plus qu’à lancer le programme:

./programme
Usage: ./programme nombre

Commentaires (2)