Using gettext in bash
Asked Answered
E

5

7

How to use gettext in bash script?

I only found this page, but I don't understand it.

Localization

My script is written like this:

 #!/bin/bash
 . lang_file.sh
 echo $LANG_HELLO_WORLD

And lang_file.sh look like that:

 #!/bin/bash
 LANG_HELLO_WORLD="Hello World"

I want to change lang_file.sh to something using gettext, like this:

 #!/bin/bash
 LANG_HELLO_WORLD=`some gettext command to get string in user language`

I want to use the code in Launchpad, so other users can translate it (.po, .pot files)

Sorry for bad English, any suggestions?

Emmyemmye answered 8/2, 2010 at 12:38 Comment(0)
C
7

You need to preform following steps:

  1. Determine what's your project name, gettext calls it textdomain, you will need it to retrieve the translations for your project. Let's call it "PRJ".
  2. Mark the strings to be translated. Following snippet gives example:

    Let's call it PRJ.sh:

    #!/bin/sh
    alias GETTEXT='gettext "PRJ"'
    
    ## Use GETTEXT to mark the string you want to translate
    HELLO_WORLD=$(GETTEXT "Hello world") 
    
    echo "$HELLO_WORLD"
    
  3. Produce .pot file so translators can work on it.

    Run the following command, it only looks for GETTEXT, the ones you actually want to translate.

    xgettext -o PRJ.pot  -L Shell --keyword --keyword=GETTEXT  PRJ.sh
    
  4. Optional: Generate .po files.

    For each locale you want to cover.

    msginit -i PRJ.pot -l fr.UTF-8
    

    Note that "UTF-8" is sugggested, otherwise msginit may mistakenly choose some obsoleted encoding for you.

  5. Retrieve completed .po files, and convert them to .mo file (the file that machine can read it)

    msgfmt -v  fr.po -o fr.mo
    
  6. Install .mo files. Run:

    sudo install fr.mo /usr/share/locale/fr/LC_MESSAGES/PRJ.mo 
    

    Now you can try the result:

    LANGUAGE=fr  ./PRJ.sh
    

    and you should see French translation for Hello world.

Charmaincharmaine answered 9/10, 2014 at 7:49 Comment(0)
C
6

There is a long-lost, never-documented and almost-deprecated builtin solution in bash.

LANG=foo_BAR.utf8
TEXTDOMAIN="test" 
TEXTDOMAINDIR="/usr/share/locale"
echo $"fooMsgid"
# bash --dump-po-strings <scriptfile>
Cappuccino answered 31/3, 2015 at 0:25 Comment(1)
Nice find. The closest thing to documentation seems to be man -P cat bash | grep -EC3 'translat|gettext'.Navarra
M
2

The gettext translation make use of an editable format *.po to store translation, and a compiled format *.mo for loading.

For info of the files format, reference here: section "3 The Format of PO Files" and "10 Producing Binary MO Files" of https://www.gnu.org/software/gettext/manual/html_node/index.html

Here I focus on how to try the gettext command to get a translation in short.

After you prepared a folder /path/to/your/locale with inside-hierarchy like <lang>/LC_MESSAGES/<textdomain>.mo (where <lang> is e.g. ko_KR for Korean), use the following code in your lang_file.sh:

#!/bin/bash
export LC_ALL=ko_KR.UTF-8   # if LC_ALL not work, you could try also "LANG" and "LANGUAGE"
export TEXTDOMAINDIR=/path/to/your/locale
# export TEXTDOMAIN="<textdomain>"   # <- optional, set this to save the "<textdomain>" argument for `gettext` below
LANG_HELLO_WORLD="$( gettext "<textdomain>" "Your message to translate" )"
Moe answered 14/8, 2018 at 10:33 Comment(0)
P
1

What you are looking to do is I think ask the user in the appropriate language? You would probably want the user to pick the language first. The other part of what you are asking is simply just embedding commands like $(get_some_str_func) inside of your variable.

I did not write this code but it might be along the lines of what you are trying to do? I'm not sure, i don't understand fully what you are asking.

    function _configure_locale() { # [profile]
        local profile=${1:-EN}
        case ${profile} in
          DE|DE_DE|de_DE)
              LC_ALL="de_DE.UTF-8"
              LANG="de_DE.UTF-8"
              LANGUAGE="de_DE:de:en_US:en"
              ;;
          EN|EN_US|en|en_US)
              LC_ALL="en_US.UTF-8"
              LANG="en_US.UTF-8"
              LANGUAGE="en_US:en"
              ;;
          *)
              echo "ALERT" "${FUNCNAME}: unknown profile '${profile}'"
              ;;
          esac
          LC_PAPER="de_DE.UTF-8"; # independent from locale
          LESSCHARSET="utf-8";    # independent from locale
          MM_CHARSET="utf-8"      # independent from locale
          echo "locale settings" "${LANG}";
          export LC_ALL LANG LANGUAGE LC_PAPER LESSCHARSET MM_CHARSET
    }
Philcox answered 6/6, 2014 at 14:42 Comment(1)
took only 4 years, damnEmmyemmye
R
0

Here is my attempt to create a demo example code for Creating Internationalized Scripts section from Bash Reference Manual.

  1. Create a script file script.sh:
#!/bin/bash
# script.sh

TEXTDOMAIN=script
TEXTDOMAINDIR="$PWD"

LANG=$1
# or use following
LC_MESSAGES=$1

echo $"hi"

Make it executable chmod +x script.sh.

  1. Create template(.pot) and PO(.po) files:
bash --dump-po-strings script.sh > script.pot
# spanish
cp script.pot es.po
# french
cp script.pot fr.po
  1. Edit the es.po and fr.po files and add translations.
    For example es.po:
#: script.sh:8
msgid "hi"
msgstr "hola"
  1. Compile PO files to create .mo files
msgfmt -o es.mo es.po
msgfmt -o fr.mo fr.po

# copy to following folder structure in pwd
cp es.mo es/LC_MESSAGES/script.mo
cp fr.mo fr/LC_MESSAGES/script.mo
  1. Run the script to use the locales:
# find valid locale names
locale -a | egrep 'es|fr'

# use the valid locales to execute script
./script.sh spanish
hola
./script.sh french
salut
./script.sh es_ES
hola
./script.sh fr_FR
salut

NOTE: The example used the translation files from local directory. And installation to other common place is not required.

Replay answered 20/12, 2022 at 9:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.