Merge branch 'video-log-statements' into 'stable'
[tails.git] / refresh-translations
blobf5510cc37f8867ef817a4ffc5b22df26418d6bcc
1 #! /bin/bash
3 set -e
4 set -u
6 PERL_PROGS="/usr/local/bin/tails-security-check \
7 /usr/local/lib/tails-htp-notify-user \
8 $(find \
9 config/chroot_local-includes/usr/src/iuk/bin \
10 -type f \
11 | perl -p -E 's{^config/chroot_local-includes}{}' \
12 ) \
13 $(find \
14 config/chroot_local-includes/usr/src/iuk/lib \
15 config/chroot_local-includes/usr/src/perl5lib/lib \
16 -type f -name '*.pm' \
17 | perl -p -E 's{^config/chroot_local-includes}{}' \
19 PYTHON_PROGS="\
20 /usr/local/bin/electrum \
21 /usr/local/bin/replace-su-with-sudo \
22 /usr/local/bin/tails-about \
23 /usr/local/bin/tails-additional-software-config \
24 /usr/local/bin/tails-screen-locker \
25 /usr/local/bin/tails-upgrade-frontend-wrapper \
26 /usr/local/sbin/tails-additional-software \
27 /usr/lib/python3/dist-packages/tails_installer/creator.py \
28 /usr/lib/python3/dist-packages/tails_installer/gui.py \
29 /usr/lib/python3/dist-packages/tails_installer/source.py \
30 /usr/lib/python3/dist-packages/tails_installer/utils.py \
31 /usr/lib/python3/dist-packages/tailsgreeter/settings/persistence.py \
32 /usr/lib/python3/dist-packages/tailsgreeter/ui/add_settings_dialog.py \
33 /usr/lib/python3/dist-packages/tailsgreeter/ui/additional_settings.py \
34 /usr/lib/python3/dist-packages/tailsgreeter/ui/main_window.py \
35 /usr/lib/python3/dist-packages/tailsgreeter/ui/persistent_storage.py \
36 /usr/lib/python3/dist-packages/tailsgreeter/ui/region_settings.py \
37 /usr/lib/python3/dist-packages/tca/config.py \
38 /usr/lib/python3/dist-packages/tca/ui/main_window.py \
39 /usr/lib/python3/dist-packages/tps_frontend/application.py \
40 /usr/lib/python3/dist-packages/tps_frontend/change_passphrase_dialog.py \
41 /usr/lib/python3/dist-packages/tps_frontend/error_dialog.py \
42 /usr/lib/python3/dist-packages/tps_frontend/feature.py \
43 /usr/lib/python3/dist-packages/tps_frontend/passphrase_strength_hint.py \
44 /usr/lib/python3/dist-packages/tps_frontend/window.py \
45 /usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume.py \
46 /usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume_list.py \
47 /usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume_manager.py \
48 /usr/lib/python3/dist-packages/whisperBack/exceptions.py \
49 /usr/lib/python3/dist-packages/whisperBack/gui.py \
50 /usr/lib/python3/dist-packages/whisperBack/whisperback.py \
51 /usr/local/bin/tca \
52 /usr/local/lib/tails-additional-software-notify \
53 /usr/local/lib/tails-virt-notify-user \
54 /usr/local/sbin/tails-additional-software"
55 SHELL_PROGS=" \
56 /usr/local/bin/keepassxc \
57 /usr/local/lib/tails-spoof-mac \
58 /usr/local/bin/thunderbird \
59 /usr/bin/tor-browser \
60 /usr/local/sbin/unsafe-browser"
61 JAVASCRIPT_PROGS=" \
62 /usr/share/gnome-shell/extensions/status-menu-helper@tails.boum.org/extension.js \
63 /usr/share/gnome-shell/extensions/torstatus@tails.boum.org/extension.js \
65 GLADE_UI="\
66 /usr/share/tails/additional-software/configuration-window.ui \
69 LOCALE_BASEDIR=config/chroot_local-includes/usr/share/locale
71 ### External libraries
73 . config/chroot_local-includes/usr/local/lib/tails-shell-library/common.sh
74 . config/chroot_local-includes/usr/local/lib/tails-shell-library/po.sh
76 ### Functions
78 normalize_pot () {
79 sed --regexp-extended \
80 -i 's@^"Content-Type: text/plain; charset=CHARSET\\n"@"Content-Type: text/plain; charset=UTF-8\\n"@' \
81 "${@}"
84 prog_potfile () {
85 prog=$1
87 progpath="config/chroot_local-includes$prog"
88 case $prog in
89 /usr/share/gnome-shell/extensions/status-menu-helper@tails.boum.org/extension.js)
90 domain=status-menu-helper-extension.js
92 /usr/share/gnome-shell/extensions/torstatus@tails.boum.org/extension.js)
93 domain=torstatus-extension.js
95 /usr/lib/python3/dist-packages/tps/*)
96 domain="tps-$(basename "$prog")"
98 /usr/lib/python3/dist-packages/tps_frontend/*)
99 domain="tps-frontend-$(basename "$prog")"
101 /usr/lib/python3/dist-packages/unlock_veracrypt_volumes/*)
102 domain="unlock-veracrypt-volumes-$(basename "$prog")"
104 /usr/lib/python3/dist-packages/tailsgreeter/*)
105 domain="greeter-$(basename "$prog")"
107 /usr/lib/python*/dist-packages/tails_installer/*)
108 domain="installer-$(basename "$prog")"
110 /usr/lib/python*/dist-packages/tca/*)
111 domain="tca-$(basename "$prog")"
113 /usr/local/bin/tca)
114 domain="tca-bin"
116 /usr/lib/python3/dist-packages/whisperBack/*)
117 domain="whisperBack-$(basename "$prog")"
120 domain=$(basename "$prog")
122 esac
123 echo "tmp/pot/${domain}.pot"
126 create_pot () {
127 prog=$1
128 proglang=$2
129 progpath="config/chroot_local-includes${prog}"
130 if [ -e "${progpath}" ]; then
131 pot="$(prog_potfile "${prog}")"
132 mkdir -p "$(dirname "${pot}")"
133 case "$proglang" in
134 Perl)
135 # XXX: once we can assume libintl-perl 1.28+,
136 # generate this list of options with:
137 # perl -MLocale::TextDomain -E 'print Locale::TextDomain->options'
138 xgettext_args='--keyword'
139 xgettext_args="$xgettext_args --keyword=__"
140 xgettext_args="$xgettext_args --keyword='\$__'"
141 xgettext_args="$xgettext_args --keyword=__x"
142 xgettext_args="$xgettext_args --keyword=__n:1,2"
143 xgettext_args="$xgettext_args --keyword=__nx:1,2"
144 xgettext_args="$xgettext_args --keyword=__xn:1,2"
145 xgettext_args="$xgettext_args --keyword=__p:1c,2"
146 xgettext_args="$xgettext_args --keyword=__np:1c,2,3"
147 xgettext_args="$xgettext_args --keyword=__npx:1c,2,3"
148 xgettext_args="$xgettext_args --keyword=N__"
149 xgettext_args="$xgettext_args --keyword=N__n:1,2"
150 xgettext_args="$xgettext_args --keyword=N__p:1c,2"
151 xgettext_args="$xgettext_args --keyword=N__np:1c,2,3"
152 xgettext_args="$xgettext_args --keyword=%__'"
155 xgettext_args=
157 esac
158 # shellcheck disable=SC2086
159 xgettext --language="${proglang}" --from-code=UTF-8 \
160 $xgettext_args \
161 --add-comments="Translators:" -o "${pot}" "${progpath}"
162 if [ -f "${pot}" ]; then
163 normalize_pot "${pot}"
165 else
166 echo "error: We are supposed to create a POT file for '${prog}'" \
167 "but '${progpath}' does not exist"
168 exit 1
172 po_file () {
173 locale=$1
175 echo "po/${locale}.po"
178 mo_file () {
179 locale=$1
181 echo "${LOCALE_BASEDIR}/${locale}/LC_MESSAGES/tails.mo"
184 refresh_mo () {
185 for locale in "$@" ; do
186 po=$(po_file "$locale")
187 mo=$(mo_file "$locale")
188 mkdir -p "$(dirname "$mo")"
189 if ! msgfmt --check -o "${mo}" "${po}"; then
190 echo "Errors for locale '${locale}': restoring old file"
191 if [ -n "$(git ls-files "${po}")" ]; then
192 git restore "${po}"
193 msgfmt --check -o "${mo}" "${po}"
194 else
195 rm "${po}"
198 done
201 no_left_out_files () {
202 (cd po && intltool-update --maintain)
203 [ ! -e po/missing ] || return 1
204 return 0
207 intltool_update_pot () {
209 cd po
210 cp -a tails.pot tails.pot.orig
211 intltool-update --pot --gettext-package=tails
212 normalize_pot tails.pot tails.pot.orig
214 if [ "${FORCE:-}" = yes ]; then
215 echo "Force-updating 'tails.pot'."
216 rm tails.pot.orig
217 elif diff_without_pot_creation_date_and_comments -q tails.pot.orig tails.pot; then
218 echo "Only header or comment changes in tails.pot: keeping the old one"
219 mv tails.pot.orig tails.pot
220 else
221 echo "Real changes in tails.pot: switching to the updated one"
222 rm tails.pot.orig
227 intltool_merge_desktop () {
228 extract_from_file_between_markers po/POTFILES.in \
229 '^# Files updated by intltool-update --desktop-style' '^$' \
230 | while read -r infile ; do
231 intltool-merge --quiet --desktop-style --utf8 \
232 po "$infile" "${infile%.in}"
233 done
236 intltool_merge_xml () {
237 extract_from_file_between_markers po/POTFILES.in \
238 '^# Files updated by intltool-update --xml-style' '^$' \
239 | while read -r infile ; do
240 intltool-merge --quiet --xml-style --utf8 \
241 po "$infile" "${infile%.in}"
242 done
245 ### Main
247 FORCE=no
248 KEEP_TMP_POT=no
249 while [ -n "${1:-}" ]; do
250 case "${1:-}" in
251 '--force')
252 FORCE=yes
254 '--keep-tmp-pot')
255 KEEP_TMP_POT=yes
258 echo "Unknown option: ${1}"
259 exit 1
261 esac
262 shift
263 done
265 # Schedule clean up
266 # shellcheck disable=SC2064
267 trap "rm -fr po/*.new po/*.orig ; [ '$KEEP_TMP_POT' = yes ] || rm -fr tmp/pot" EXIT
268 trap "echo refresh-translations: failed" ERR
270 # Update POT files
271 mkdir -p tmp/pot
272 for prog in $PERL_PROGS ; do create_pot "$prog" Perl ; done
273 for prog in $PYTHON_PROGS ; do create_pot "$prog" Python ; done
274 for prog in $SHELL_PROGS ; do create_pot "$prog" Shell ; done
275 for prog in $JAVASCRIPT_PROGS ; do create_pot "$prog" JavaScript ; done
276 for prog in $GLADE_UI ; do create_pot "$prog" Glade ; done
277 intltool_update_pot
279 # If left out files are detected, intltool-update --maintain writes
280 # them to po/missing.
281 if ! no_left_out_files; then
282 echo "E: These files should be listed in POTFILES.in or POTFILES.skip:" >&2
283 cat po/missing
284 exit 3
287 # Update PO files
288 # shellcheck disable=SC2046
289 intltool_update_po $(po_languages)
291 # Update files that are actually used at runtime
292 # shellcheck disable=SC2046
293 refresh_mo $(po_languages)
294 intltool_merge_desktop
295 intltool_merge_xml
296 chmod +x config/chroot_local-includes/etc/skel/Desktop/*.desktop