Otro código que me ayudó con traducciones:

Busca traducciones dentro de la estructura de mi Tryton que estén en 
formato po (y que modifico usando sed), y las pone en un archivo zip para 
subirla en pootle. Crea un directorio "locale_po" con un archivo zip y 
otros po dentro. Las opciones no son requeridas, pero si no se dan, se usan 
los valores predefinidos. También puede "instalar" idiomas desde un zip 
bajado de pootle. Por favor, lea más sobre lo que hace el código al inicio 
del archivo (en inglés).

po2zip.sh:    MD5 = 52 87 C8 49 00 66 E2 A0  48 34 12
                    60 14 FA F6 AC
po2zip.sh:   SHA1 = 7BC8 AA37 C8FB 4F6E 621D  8044
                    7682 8C7F 7B45 47F1
po2zip.sh: RMD160 = 0D61 21F0 DABB 8F6D FB2D  3BE6
                    0549 6895 946F 44A4
po2zip.sh: SHA224 = 2A1CE8F0 EDF422D2 46C9DADA
                    1D998FD7 74B386C4 3344D971
                    95C4CF97
po2zip.sh: SHA256 = 1A41D3E2 FC000F8E 997A166A
                    F56B8EA9 956FD110 65409F21
                    9FE57C5C 718317AD
po2zip.sh: SHA384 = AE0D5765 B9AAA0A6 7A0519CB
                    EE19185D DC2B37F5 A7F7BB90
                    E1C07E9E 45F4DB6D 53A07B9E
                    6394ACA5 66D15BB0 C80C2759
po2zip.sh: SHA512 = 75344083 917FFA11 B1FFFA6D
                    9055679E E7B36621 0C38F4E8
                    C7A21902 4B032847 E5123996
                    26952081 4BD88FC7 71D3F54C
                    B142052D 302CFD72 DC9B58CB
                    09426780
#!/bin/bash
# This program is licensed under the GPL version 3 or any later
# version at your convenience.
#
# Searches the structure of my tryton installation for my translation
# files (which I mostly modify with sed) and puts them in a zip file
# for upload. It will create a directory "locale_po" with a zip and po
# files in it. Options are not mandatory, but if they are not
# provided, the defaults are used.
# run: this-file [p2z|z2p] [options]
#
# Command:
#
# p2z   Copies all the language files (see option -l or --lang) from a
#       path (indicated with -d or --dir) to po files within a
#       directory called locale_po within the current working
#       directory. The structure of the original directory is expected
#       to be something like: /dir1/ll_LL.po or /dir2/modules/ll_LL.po,
#       where the ll_LL.po are at the same depth from the original
#       directory (-d or --dir) as measured by GNU find (findutils). If
#       the deepest directory is called locale, it is removed. Also,
#       any modules/ section of the path is removed. So, for example,
#       if this program is executed as this-program -d /dir1/dir2/ -l
#       ll_LL.po:
#
#       /dir1/dir2/ll_LL.po becomes locale_po/dir2.po
#       /dir1/dir2/locale/ll_LL.po becomes locale_po/dir2.po
#       /dir1/modules/dir2/locale/ll_LL.po becomes locale_po/dir2.po
#
# z2p   Takes a zip with po sources (like the one provided by pootle
#       or this same script) and puts them in a list of directories.
#       The zip file is indicated with the -z or --zip option.
#
#       The user may choose to backup a series of directories with the
#       -D or --dir_resp option, each of which has a similar structure
#       as the one indicated in the *p2z* option. The backup is stored
#       in /tmp/tryton. The names of the files and base directories is
#       unchanged. *If the only file of the whole structure of the
#       directory is a ll_LL.po (see -l or --lang option), then the
#       directory is moved to /tmp/tryton*. Files can also be backed up
#       with the -z or --zip option.
#
#       The source files are preferably [module1].po, [module2].po,
#       etc., but it may be that the zip has other files inside. These
#       are skipped and reported with ??. The final directory structure
#       is mandated by -d or --dir. It will be something like
#       /dir1/dir2/module1/locale/ll_LL.po (module1 given by -d and
#       ll_LL by -l) if /dir1/dir2/module1/ exists and
#       /dir1/dir2/modules/module1/locale/ll_LL.po if that
#       exists. Note that if both exists, both apply.
#
#       For example, let's say that tryton_po.zip has two files named
#       account.po and renova.po
#
#       this-file z2p \
#           -z tryton_po.zip \
#           -d /usr/lib/python2.7/dist-packages/trytond \
#           -D /usr/share/locale/es_ES/LC_MESSAGES \
#           -d /usr/share/pyshared/trytond \
#           -z /usr/share/pyshared/trytond/ir/lang.xml
#
#       will unzip tryton_po.zip to /tmp/locale_tryton_es_MX.po
#       (because no -l or --lng was specified, and es_MX is the default
#       value); it will backup the es_MX.po files under
#       /usr/share/locale/es_ES/LC_MESSAGES (I don't know of any such
#       file); it will try to copy account.po to both the modules and
#       base directory:
#       /usr/lib/python2.7/dist-packages/trytond/modules/account/\
#       locale/es_MX.po
#       and
#       /usr/lib/python2.7/dist-packages/trytond/account/locale/es_MX.po
#       if either directories (not necessarily es_MX.po) exist, as well
#       as renova.po to
#       /usr/lib/python2.7/dist-packages/trytond/modules/renova/\
#       locale/es_MX.po
#       and
#       /usr/lib/python2.7/dist-packages/trytond/renova/locale/es_MX.po.
#
#       I'm sorry for the inconvenience, but I put sudo for the copy
#       command, because that's how I use it. You are obviously free
#       (thanks GPLv3) to change the code.
#
#
# Options:
# -d, --dir          DIR (-d DIR1 -d DIR2 ... is possible)
#                      path to a directory which has  your language
#                      translation.
#                      Default (all of):
#                        /usr/lib/python2.7/dist-packages/trytond
#                        /usr/share/pyshared/trytond
# -D, --dir_resp     (works with z2p; -D DIR1 -D DIR2 ... is possible)
#                      path to a directory which may have po files
#                      (indicated by -l or --lng; <ll_LL>.po) and
#                      which should be backed up.
#                      Default (all of):
#                      /usr/share/pyshared/tryton
#                      /usr/share/pyshared/trytond
#                      /usr/lib/python2.7/dist-packages/tryton
#                      /usr/lib/python2.7/dist-packages/trytond
#                      /usr/share/locale//LC_MESSAGES
# -x, --xtra         (-x FILE1 -x FILE2 is possible) extra files to be
#                      backed up.
#                      Default (all of):
#                        /usr/share/pyshared/trytond/ir/lang.xml
#                        /usr/share/pyshared/trytond/ir/gen_time_locale.py
#                        /usr/share/pyshared/trytond/ir/time_locale.py
#                        /usr/share/pyshared/trytond/protocols/dispatcher.py
#                        /usr/share/locale/es_MX/LC_MESSAGES/tryton.po
# -l, --lng          (only one) language code: es_MX, en_US, ru_RU
#                      Default: es_MX
# -z, --zip          (-z FILE1 -z FILE2 is possible)
#                      Default:
#                        tryton_ll_LL_po.zip (ll_LL given by -l or --lng)

function p2z_nrml () {
    # Dejar sólo el nombre del módulo a partir de su directorio (<módulo>.po)
    # Buscar en el directorio los archivos con extensión .po
    for i in $(find "$dtmp" -iname "$lng".po); do
        # Quitar el nombre del directorio raíz
        if [[ "$i" =~ "modules" ]]; then
            # /dir/dir/modules/mmm → mmm
            a=${i/*modules\/};
        else
            # /dir/dir/mmm → mmm
            a=${i#"$dtmp/"};
        fi;
        # Quitar /locale/ y el nombre del archivo .po del nombre del
        # módulo (lng=es_MX)
        a=${a/\/locale\/"$lng"/};
        # Copiar a locale_po/<módulo>.po
        cp "$i" locale_po/"$a";
    done;
}

function p2z_xtra () {
    cp "${xtra[@]}" locale_po
}

function p2z () {
    [[ ! -d locale_po ]] && mkdir locale_po;
    for dtmp in "${dir[@]}"; do
        p2z_nrml;
    done;
    p2z_xtra;
    cd locale_po && zip -r tryton_"$lng"_po.zip ./;
    printf "$(readlink -f tryton_"$lng"_po.zip)  :)";
}

function resp_lng() {
    for i in $(find "$drtmp" -mindepth 1 -maxdepth 1 -type d); do
        if [[ -f "$i"/locale/"$lng".po ]]; then
            b="$(basename "$i")";
            printf "$i/locale/$lng.po → /tmp/tryton ... ";
            n=$(find "$i"  -mindepth 1 -maxdepth 1 -type f| wc -l);
            if [[ "0" == "$n" ]]; then
                sudo mv "$i" /tmp/tryton && printf " :)\n";
            else
                [[ ! -d /tmp/tryton/"$b" ]] && mkdir -p /tmp/tryton/"$b"
                rsync -a "$i"/locale /tmp/tryton/"$b" && printf " :)\n"
            fi;
        fi;
    done;
}

function apl_lng() {
    for i in /tmp/locale_tryton_"$lng"/*.po; do
        a=$(basename -s .po "$i");
        if [[ -d "$drtmp"/"$a" ]]; then
            printf "$i → $drtmp/$a/locale/$lng.po\n ... ";
            sudo cp "$i" "$drtmp/$a/locale/$lng.po" && printf ":)\n";
        fi;
        if [[ -d "$drtmp"/modules/"$a" ]]; then
            printf "$i → $drtmp/modules/$a/locale/$lng.po\n ... ";
            sudo cp "$i" "$drtmp/modules/$a/locale/$lng.po" && printf ":)\n";
        # else
        #     if [[ -z "$noapl" ]]; then
        #         noapl="$a".po;
        #     else
        #         noapl=("${noapl[@]}" "$a".po);
        #     fi;
        fi;
    done;
}

function z2p () {
    # Respaldar estructura de archivos de traducción
    [[ ! -d /tmp/tryton/ ]] && mkdir -p /tmp/tryton/
    for drtmp in "${dir_resp[@]}"; do
        resp_lng "$drtmp";
    done;
    # Aplicar cambios
    noapl="";
    [[ ! -d /tmp/locale_tryton_"$lng" ]] && mkdir /tmp/locale_tryton_"$lng";
    for ztmp in "${zip[@]}"; do
        unzip -q "$ztmp" -d /tmp/locale_tryton_"$lng";
        for drtmp in "${dir[@]}"; do
            apl_lng "$ztmp";
        done;
    done;
    if [[ -z "${noapl[@]}" ]]; then
        noapl=$(find /tmp/locale_tryton_"$lng" -type f \! -iname '*.po' -print0);
    else
        noapl=(${noapl[@]} $(find /tmp/locale_tryton_"$lng" -type f \! -iname '*.po' -print0))
    fi;
    [[ -n "${noapl[@]}" ]] && printf "\n?? ${noapl[@]} →x $drtmp\n";
}

cmd="$1";
shift;
noapl="";

if [[ ! "$@" =~ "-l" || ! "$@" =~ "--lng" ]]; then
    lng="es_MX";
else
    lng="";
fi;

if [[ ! "$@" =~ "-d" || ! "$@" =~ "--dir" ]]; then
    dir=(/usr/{lib/python2.7/dist-packages/,share/pyshared/}trytond);
else
    dir="";
fi;

if [[ ! "$@" =~ "-D" && ! "$@" =~ "--dir_resp" ]]; then
    dir_resp=(
        /usr/{share/pyshared,lib/python2.7/dist-packages}/tryton{,d}
        /usr/share/locale/"$lng"/LC_MESSAGES
    );
else
    dir_resp="";
fi;

if [[ ! "$@" =~ "-x" && ! "$@" =~ "--xtra" ]]; then
    xtra=(/usr/share/pyshared/trytond/{ir/{lang.xml,{gen_,}time_locale.py},protocols/dispatcher.py} /usr/share/locale/es_MX/LC_MESSAGES/tryton.po);
else
    xtra="";
fi;

if [[ ! "$@" =~ "-z" && ! "$@" =~ "--zip" ]]; then
    zip=(tryton_"$lng"_po.zip);
else
    zip="";
fi;

while (( "$#" )); do
    case "$1" in
        -d|--dir)
            if [[ -z "$dir" ]]; then
                dir="$2"
            else
                dir=("${dir[@]}" "$2");
            fi;
            shift 2;
            ;;
        -D|--dir_resp)
            if [[ -z "$dir_resp" ]]; then
                dir_resp="$2"
            else
                dir_resp=("${dir_resp[@]}" "$2");
            fi;
            shift 2;
            ;;
        -l|--lng)
            lng="$2";
            shift 2;
            ;;
        -x|--xtra)
            if [[ -z "$xtra" ]]; then
                xtra="$2"
            else
                xtra=("${xtra[@]}" "$2");
            fi;
            shift 2;
            ;;
        -z|--zip)
            if [[ -z "$zip" ]]; then
                zip="$2"
            else
                zip=("${zip[@]}" "$2");
            fi;
            shift 2;
            ;;
        *)
            shift;
            ;;
    esac;
done

case "$cmd" in
    p2z)
        p2z
        ;;
    z2p)
        z2p;
        ;;
    *)
        printf "Please, read this file and see the instructions at ";
        printf "the top";
        ;;
esac;

Responder a