J. Localisation

La localisation est une fonctionnalité non documentée de Bash.

Un script shell adapté (« localisé ») affiche son texte dans la langue définie par le paramètre « locale » du système. Pour un même script, un utilisateur de GNU/Linux à Berlin (Allemagne) verra l'affichage en allemand tandis que son cousin à Berlin (Maryland, USA), verra l'affichage en anglais.

Pour créer un script autochtone, utilisez le modèle suivant pour écrire tous les messages pour l'utilisateur (messages d'erreur, invite, etc.).

#!/bin/bash
# localized.sh
# Script écrit par Stéphane Chazelas,
# modifié par Bruno Haible et corrigé par Alfredo Pironti

. gettext.sh

E_CDERROR=65

error()
{
  printf "$@" >&2
  exit $E_CDERROR
}

cd $var || error "`eval_gettext \"Ne peut pas entrer dans \$var.\"`"
#  Le triple antislash (échappements) en face de $var est nécessaire
#+ "parce que eval_gettext attend une chaîne là où les valeurs des
#+ variables n'ont pas encore été substituées."
#    -- par Bruno Haible
read -p "`gettext \"Entrez la valeur : \"`" var
# ...


#  ------------------------------------------------------------------
#  Alfredo Pironti commente :

#  Ce script a été modifié pour ne pas utiliser la syntaxe $"..."
#+ en faveur de la syntaxe "`gettext \"...\"`".
#  C'est OK mais, avec le nouveau programme localized.sh, les commandes
#+ "bash -D fichier" et "bash --dump-po-string fichier" ne produiront
#+ aucune sortie
#+ (car ces commandes recherchent seulement les chaînes $"...") !
#  L'UNIQUE façon d'extraire les chaînes du nouveau fichier est d'utiliser
# le programme 'xgettext'. Néanmoins, le programme xgettext est boguée.

# Notez qu'xgettext a un autre bogue.
#
# Le fragment de shell :
#    gettext -s "I like Bash"
# sera correctement extrait mais...
#    xgettext -s "I like Bash"
# ... échoue!
#  'xgettext' extraiera "-s" parce que
#+ la commande extrait seulement le tout premier argument
#+ après le mot 'gettext'.


#  Caractère d'échappement :
#
#  Pour adapter une phrase comme
#     echo -e "Bonjour\tmonde!"
#+ vous devez utiliser
#     echo -e "`gettext \"Bonjour\\tmonde\"`"
#  Le "caractère d'échappement double" avant le `t' est nécessaire parce que
#+ 'gettext' cherchera une chaîne identique à : 'Bonjour\tmonde'
#  Ceci est dû au fait que gettext lira un littéral `\')
#+ et affichera une chaîne comme "Bonjour\tmonde",
#+ donc la commande 'echo' affichera le message correctement.
#
#  Vous ne pouvez pas utiliser
#     echo "`gettext -e \"Bonjour\tmonde\"`"
#+ à cause du bogue d'xgettext expliqué ci-dessus.


# Localisons le fragment de shell suivant :
#     echo "-h display help and exit"
#
# Tout d'abord, vous pourriez faire ceci :
#     echo "`gettext \"-h display help and exit\"`"
#  De cette façon, 'xgettext' fonctionnera bien
#+ mais le programme 'gettext' lira "-h" comme une option !
#
# Une solution serait
#     echo "`gettext -- \"-h display help and exit\"`"
#  De cette façon, 'gettext' fonctionnera
#+ mais 'xgettext' extraiera "--" comme indiqué ci-dessus.
#
#  Le contournement que vous pourriez utiliser
#+ pour obtenir l'adaptation de la chaîne est
#     echo -e "`gettext \"\\0-h display help and exit\"`"
#  Nous avons ajouté un \0 (NULL) au début de la phrase.
#  De cette façon, 'gettext' fonctionnera bien ainsi que 'xgettext.'
#  De plus, le caractère NULL ne modifiera pas le comportement de la commande
#+ 'echo'.
#  ------------------------------------------------------------------
bash$ bash -D localized.sh
"Can't cd to %s."
 "Enter the value: "

Ceci liste tout le texte adapté (l'option -D liste les chaînes de caractères mises entre double guillemets préfixées par un $ sans exécuter le script).

bash$ bash --dump-po-strings localized.sh
#: a:6
 msgid "Can't cd to %s."
 msgstr ""
 #: a:7
 msgid "Enter the value: "
 msgstr ""

L'option --dump-po-strings de Bash ressemble à l'option -D mais utilise le format « po » de gettext.

[Note]

Note

Bruno Haible précise :

À partir de gettext-0.12.2, xgettext -o - localized.sh est recommandé à la place de bash --dump-po-strings localized.sh parce que xgettext . . .

1. comprend les commandes gettext et eval_gettext (alors que bash --dump-po-strings comprend seulement la syntaxe obsolète $"...")

2. peut extraire les commentaires placés par le développeur à l'intention du traducteur.

Ce code shell n'est donc pas spécifique à Bash ; il fonctionne de la même façon avec Bash 1.x et sous les autres implémentations de /bin/sh.

Maintenant, construisez un fichier langage.po pour chaque langage dans lequel le script sera traduit, en spécifiant le msgstr. Alfredo Pironti donne l'exemple suivant :

fr.po:

#: a:6
msgid "Can't cd to $var."
msgstr "Impossible de se positionner dans le répertoire $var."
#: a:7
msgid "Enter the value: "
msgstr "Entrez la valeur : "

#  Les chaînes sont affichées avec les noms de variable, et non pas avec la
#+ syntaxe %s similaire aux programmes C.
#+ C'est une fonctionnalité géniale si le développeur utilise des noms de
#+ variables qui ont un sens !

Ensuite, lancez msgfmt.

msgfmt -o localized.sh.mo fr.po

Placez le fichier résultant localized.sh.mo dans le répertoire /usr/local/share/locale/fr/LC_MESSAGES et ajoutez les lignes suivantes au début du script :

TEXTDOMAINDIR=/usr/local/share/locale
TEXTDOMAIN=localized.sh

Si un utilisateur d'un système français lance le script, il obtiendra des messages en français.

[Note]

Note

Avec les anciennes versions de Bash ou d'autres shells, gettext avec l'option -s est obligatoire. Dans ce cas, le script devient :

#!/bin/bash
# localized.sh

E_CDERROR=65

error() {
  local format=$1
  shift
  printf "$(gettext -s "$format")" "$@" >&2
  exit $E_CDERROR
}
cd $var || error "Can't cd to %s." "$var"
read -p "$(gettext -s "Enter the value: ")" var
# ...

Les variables TEXTDOMAIN et TEXTDOMAINDIR doivent être initialisées et exportées dans l'environnement. Cela doit être fait à l'intérieur du script.

---

Cette annexe a été écrite par Stéphane Chazelas avec quelques améliorations suggérées par Alfredo Pironti et Bruno Haible, le mainteneur de gettext.