1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
|
#!/bin/bash
#
# gettext-singularity - gettext wrapper customized to Endgame: Singularity
#
# Copyright (C) 2012 Rodrigo Silva (MestreLion) <linux@rodrigosilva.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. See <http://www.gnu.org/licenses/gpl.html>
#
# Uses GNU's gettext tools to parse source code files for translatable
# strings, generate a template .POT file in data/messages.pot, update
# existing data/messages_ll_CC.po files, check them for syntax errors,
# and create a new one if requested.
# It is smart enough to properly find the source code files and output dir
# regardless of the current dir on invocation, provided this script is in
# tools/ dir of E:S tree source
#
# All gettext options are already properly set for the Endgame: Singularity
# project, so this script can be invoked without any options.
usage() {
cat <<- USAGE
Usage: $myname [options] [--new LANG | --check FILE]
USAGE
if [[ "$1" ]] ; then
cat <<- USAGE
Try '$myname --help' for more information.
USAGE
exit 1
fi
cat <<-USAGE
gettext wrapper customized to Endgame: Singularity project
Options:
-h|--help - show this page
-q|--quiet - suppress non-error, informative messages
--new LANG - create a new PO file. LANG must be in ll or
ll_CC format. Examples: en, en_US, pt, pt_BR
--check FILE - test FILE for syntax errors in the PO format and
print translation statistics (regardless of -q)
If used, does not perform any other actions.
--dir - The root directory of E:S where data file and i18n
are found. Default: __file__/../..
--catalog - The catalog to update (messages/data_str). Default: messages
By default this command reside in i18n/utils/ dir of E:S source tree,
so it can automatically find the source code files and output dir.
Uses the following GNU's gettext tools:
- xgettext : to create or update data/messages.pot template
- msgmerge : to update existing data/messages_ll_CC.po files
- msgfmt : to check existing PO files for syntax errors
- msginit : to create a new data/messages_ll_CC.po file
Copyright (C) 2012 Rodrigo Silva (MestreLion) <linux@rodrigosilva.com>
License: GPLv3 or later. See <http://www.gnu.org/licenses/gpl.html>
USAGE
exit 0
}
fatal() { printf "%s: error: %s\n" "$myname" "$1" >&2 ; exit "${2:-1}" ; }
argerr() { printf "%s: %s\n" "$myname" "${1:-error}" >&2 ; usage 1 ; }
invalid() { argerr "invalid option: $1" ; }
missing() { argerr "missing ${2:+$2 }operand${1:+ in $1}." ; }
message() { ((verbose)) && printf "%s\n" "$1"; }
rel() { python -c "import os.path; print os.path.relpath('$1','$dir')"; }
check() {
local stats=()
(($1)) && stats=( --statistics )
[[ "$2" ]] || missing "--check" "FILE"
msgfmt --check-accelerators \
--output-file=/dev/null \
--check \
"${stats[@]}" \
"$2"
}
PYTHON=${PYTHON:-python3}
myname="${0##*/}"
dir="$PWD"
mydir=$(dirname "$(readlink -f "$0")")
esdir="${mydir}/.."
codedir="${esdir}/singularity/code"
datadir="${esdir}/singularity/data"
i18ndir="${esdir}/singularity/i18n"
catalog="messages"
verbose=1
new=0
quiet=()
# Loop options
while (( $# )); do
case "$1" in
-h|--help ) usage ;;
-q|--quiet ) verbose=0 ; quiet=( -q ) ;;
--new=* ) new=1 ; lang="${1#*=}" ;;
--new ) new=1 ; shift ; lang="$1" ;;
--check=* ) check 1 "${1#*=}" ; exit ;;
--check ) shift ; check 1 "$1"; exit ;;
--dir=* ) esdir="${1#*=}" ;;
--dir ) shift ; esdir="$1" ;;
--catalog=* ) catalog="${1#*=}" ;;
--catalog ) shift ; catalog="$1" ;;
* ) invalid "$1" ;;
esac
shift
done
((new)) && {
[[ "$lang" ]] || missing "--new" "LANG"
[[ "$lang" =~ ^[[:lower:]][[:lower:]](_[[:upper:]][[:upper:]])?$ ]] ||
invalid "LANG format must be 'll' or 'll_CC'"
}
if [ -d "$esdir" ]; then
message "E:S root dir: $(rel "$esdir")"
else
invalid "E:S root dir $(rel "$esdir") does not exist"
fi
tempfile=$(mktemp) || fatal "could not create temporary file"
trap 'rm -f -- "$tempfile"' EXIT
# Create or update the POT template from source code
if [[ $catalog == "messages" ]]; then
potfile="${i18ndir}/messages.pot"
pofilename="messages.po"
message "updating template $(rel "$potfile") from sources in $(rel "$esdir")/code"
cd "${codedir}" || fatal "could not access source code dir '${esdir}/code'"
xgettext --language=Python \
--from-code=UTF-8 \
--force-po \
--add-comments \
--keyword=N_ \
--package-name=singularity \
--package-version=$(awk -F'['\'\"']' '/^version *= */{print $2}' g.py) \
--msgid-bugs-address="https://github.com/singularity/singularity/issues" \
--output="$tempfile" \
--files-from=<(find -type f -name "*.py")
cd "$dir"
elif [[ $catalog == "data_str" ]] || [[ $catalog == "story" ]] || [[ $catalog == "knowledge" ]]; then
potfile="${i18ndir}/${catalog}.pot"
pofilename="${catalog}.po"
message "updating template $(rel "$potfile") from string files in $(rel "$esdir")/data"
cd "${codedir}" || fatal "could not access source code dir '${esdir}/data'"
PYTHONPATH="${esdir}" "${PYTHON}" "${mydir}/data-translations.py" --catalog "${catalog}" -o $tempfile
cd "$dir"
else
invalid "Catalog $(rel "$catalog") does not exist"
fi
# Fix POT, as --from-code is currently ignored for Python
sed -i '/^"Content-Type:/s/CHARSET/UTF-8/;/^#, fuzzy$/d' "$tempfile"
# Compare new POT with existing one. Did only date change?
if [[ -f "$potfile" ]] &&
diff -I '^"POT-Creation-Date:' "$tempfile" "$potfile" > /dev/null
then
message "template was already up-to-date"
else
mv "$tempfile" "$potfile" || fatal "could update POT file"
fi
# Update existing PO files with new entries
pofiles=( "$i18ndir"/lang_*/"$pofilename" )
if [[ ${pofiles[0]} != "$i18ndir/lang_"'*'"/$pofilename" ]]; then
for pofile in "${pofiles[@]}"; do
message "updating translation $(rel "$pofile")"
msgmerge --no-fuzzy-matching \
--backup=off \
--previous \
--update \
"${quiet[@]}" \
"$pofile" \
"$potfile"
check $verbose "$(rel "$pofile")"
done
fi
# Create a new PO file, if requested
[[ "$lang" ]] && {
output_dir="${i18ndir}/lang_${lang}"
output="$output_dir/$pofilename"
[[ -f "$output" ]] && fatal "translation $(rel "$output") already exists!"
[[ -d "$output_dir" ]] || mkdir -p "$output_dir"
message "creating blank translation $(rel "$output")"
msginit --input="$potfile" \
--output-file="$(rel "$output")" \
--locale="${lang}.UTF-8"
# Ask user and add Language-Native-Name header
# So much work for so little gain...
name=$(awk -F': |"|\\\\| <' '$2=="Language-Team"{print $3}' "$output")
tempfile=$(mktemp) || fatal "could not create temporary file"
trap 'rm -f -- "$tempfile"' EXIT
awk -v name="$name" -F': |"|\\\\| <' '$2=="Language-Team"{
print "\"Language-Name: " name "\\n\""
print "\"Language-Native-Name: LANGUAGE\\n\""
} 1' "$output" > "$tempfile"
mv "$tempfile" "$output" || fatal "could update PO file"
native=""
echo
while [[ -z "$native" ]]; do
read -r -p "What is this language name in ${name}? " native
done
tempfile=$(mktemp) || fatal "could not create temporary file"
trap 'rm -f -- "$tempfile"' EXIT
awk -v native="$native" -F': |"|\\\\' '$2=="Language-Native-Name"{
sub(/LANGUAGE/,native)} 1' "$output" > "$tempfile"
mv "$tempfile" "$output" || fatal "could update PO file"
message "$(rel "$output") created and ready to be translated"
}
|