Commented working code: Internationalization, i18n, gettext, and bash / shell scripts on CentOS 7.4

The following shows a working script with explanatory comments and Wikipedia illustration below to internationalize / i18n bash shell scripts on CentOS 7.4:

# set SCRIPT_DIR, -P means use physical links, no symlinks
SCRIPT_DIR="$(cd -P -- "$(dirname -- "$0")" && pwd -P)"

# set domain our translations to this script (must match .mo file below, sans .mo)
export TEXTDOMAIN=myscript

# set directory where translations are located
export TEXTDOMAINDIR=$"{SCRIPT_DIR}/locale"

# rather than echo, use gettext to allow for translations of text that don't have variables. Trailing echo inserts a newline.
echo $(gettext "Hello world") ; echo

# if your text needs to include a variable, instead use eval_gettext and escape them
echo $(eval_gettext "My variable: \$myvar") ; echo

# save your script, then in a shell, extract (the x in xgettext) its translations (gettext)
# into a portable object template (.pot). syntax: destination source
cd ${SCRIPT_DIR}
xgettext -L Shell -o myscript.pot myscript

# set the CHARSET to UTF-8
sed -i 's/charset=CHARSET/charset=UTF-8/' myscript.pot

# keep the .pot as a "master" but create and give .po to translators to create its msgstr's
cp myscript.pot myscript.fr.po

# convert the .po into machine obj files (.mo), which the script uses at run-time. syntax: destination source
msgfmt -o myscript.fr.mo myscript.fr.po

# as you update your script, update the .pot and .po if needed. syntax: source destination
msgmerge -U myscript.fr.po myscript.pot

# create folders for your language(s). NOTE: if you install a fr.mo and fr_FR.mo, the most specific culture wins
# but if you have just an fr or fr_FR, that .mo loads regardless of the directory you place it
mkdir -p locale/${fr,fr_FR}/LC_MESSAGES

# install your .mo in the (fr or fr_FR) locale section. NOTE: we REMOVE the .fr here, which was just FYI earlier
mv myscript.fr.mo locale/fr_FR/LC_MESSAGES/myscript.mo

# change your language to French
export LC_ALL="fr_FR.UTF-8" ; export LANG="fr_FR.UTF-8" ; export LANGUAGE="fr_FR:fr:en_US:en"

# Test in French
./myscript

# change your language to English
export LC_ALL="en_US.UTF-8" ; export LANG="en_US.UTF-8" ; export LANGUAGE="en_US:en:en_US:en"

# Test in English
./myscript

Flow from Wikipedia

Add new comment

Filtered HTML

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.