File: gettext-singularity

package info (click to toggle)
singularity 1.0.0%2Bgit20241231-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,492 kB
  • sloc: python: 12,985; sh: 172; makefile: 28
file content (231 lines) | stat: -rwxr-xr-x 8,449 bytes parent folder | download | duplicates (2)
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"
}