Skip to content

Commit d91ad29

Browse files
committed
Make fish_xgettext sorta work with rust
This is absolutely disgusting code, but it works out okay-ish. The problem is xgettext has no rust support (it's stuck in review limbo). So we use cargo-expand to extract all invocations of gettext, and massage all that to generate a messages.pot ourselves. We also assume any string constant could be translated.
1 parent 97e7e73 commit d91ad29

File tree

1 file changed

+37
-32
lines changed

1 file changed

+37
-32
lines changed

build_tools/fish_xgettext.fish

Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,40 @@
11
#!/usr/bin/env fish
22
#
33
# Tool to generate messages.pot
4-
# Extended to replace the old Makefile rule which did not port easily to CMake
54

6-
# This script was originally motivated to work around a quirk (or bug depending on your viewpoint)
7-
# of the xgettext command. See https://lists.gnu.org/archive/html/bug-gettext/2014-11/msg00006.html.
8-
# However, it turns out that even if that quirk did not exist we would still need something like
9-
# this script to properly extract descriptions. That's because we need to normalize the strings to
10-
# a format that xgettext will handle correctly. Also, `xgettext -LShell` doesn't correctly extract
11-
# all the strings we want translated. So we extract and normalize all such strings into a format
12-
# that `xgettext` can handle.
5+
# Create temporary directory for these operations. OS X `mktemp` is somewhat restricted, so this block
6+
# works around that - based on share/functions/funced.fish.
7+
set -q TMPDIR
8+
or set -l TMPDIR /tmp
9+
set -l tmpdir (mktemp -d $TMPDIR/fish.XXXXXX)
10+
or exit 1
11+
12+
# This is a gigantic crime.
13+
# xgettext still does not support rust *at all*, so we use cargo-expand to get all our wgettext invocations.
14+
set -l expanded (cargo expand --lib; for f in fish{,_indent,_key_reader}; cargo expand --bin $f; end)
15+
16+
# Extract any gettext call
17+
set -l strs (printf '%s\n' $expanded | grep -A1 wgettext_static_str |
18+
grep 'widestring::internals::core::primitive::str =' |
19+
string match -rg '"(.*)"' | string match -rv '^%ls$|^$' |
20+
# escaping difference between gettext and cargo-expand: single-quotes
21+
string replace -a "\'" "'" | sort -u)
1322

14-
# Start with the C++ source
15-
xgettext -k -k_ -kN_ -LC++ --no-wrap -o messages.pot src/*.cpp src/*.h
23+
# Extract any constants
24+
set -a strs (string match -rv 'BUILD_VERSION:|PACKAGE_NAME' -- $expanded |
25+
string match -rg 'const [A-Z_]*: &str = "(.*)"' | string replace -a "\'" "'")
26+
27+
# We construct messages.pot ourselves instead of forcing this into msgmerge or whatever.
28+
# The escaping so far works out okay.
29+
for str in $strs
30+
# grep -P needed for string escape to be compatible (PCRE-style),
31+
# -H gives the filename, -n the line number.
32+
# If you want to run this on non-GNU grep: Don't.
33+
echo "#:" (grep -PHn -r -- (string escape --style=regex -- $str) src/ |
34+
head -n1 | string replace -r ':\s.*' '')
35+
echo "msgid \"$str\""
36+
echo 'msgstr ""'
37+
end >messages.pot
1638

1739
# This regex handles descriptions for `complete` and `function` statements. These messages are not
1840
# particularly important to translate. Hence the "implicit" label.
@@ -22,39 +44,22 @@ set -l implicit_regex '(?:^| +)(?:complete|function).*? (?:-d|--description) (([
2244
# than messages which should be implicitly translated.
2345
set -l explicit_regex '.*\( *_ (([\'"]).+?(?<!\\\\)\\2) *\).*'
2446

25-
# Create temporary directory for these operations. OS X `mktemp` is somewhat restricted, so this block
26-
# works around that - based on share/functions/funced.fish.
27-
set -q TMPDIR
28-
or set -l TMPDIR /tmp
29-
set -l tmpdir (mktemp -d $TMPDIR/fish.XXXXXX)
30-
or exit 1
31-
3247
mkdir -p $tmpdir/implicit/share/completions $tmpdir/implicit/share/functions
3348
mkdir -p $tmpdir/explicit/share/completions $tmpdir/explicit/share/functions
3449

3550
for f in share/config.fish share/completions/*.fish share/functions/*.fish
3651
# Extract explicit attempts to translate a message. That is, those that are of the form
3752
# `(_ "message")`.
38-
string replace --filter --regex $explicit_regex 'echo $1' <$f | fish >$tmpdir/explicit/$f.tmp 2>/dev/null
39-
while read description
40-
echo 'N_ "'(string replace --all '"' '\\"' -- $description)'"'
41-
end <$tmpdir/explicit/$f.tmp >$tmpdir/explicit/$f
42-
rm $tmpdir/explicit/$f.tmp
53+
string replace --filter --regex $explicit_regex '$1' <$f | string unescape \
54+
| string replace --all '"' '\\"' | string replace -r '(.*)' 'N_ "$1"' >$tmpdir/explicit/$f
4355

4456
# Handle `complete` / `function` description messages. The `| fish` is subtle. It basically
4557
# avoids the need to use `source` with a command substitution that could affect the current
4658
# shell.
47-
string replace --filter --regex $implicit_regex 'echo $1' <$f | fish >$tmpdir/implicit/$f.tmp 2>/dev/null
48-
while read description
49-
# We don't use `string escape` as shown in the next comment because it produces output that
50-
# is not parsed correctly by xgettext. Instead just escape double-quotes and quote the
51-
# resulting string.
52-
echo 'N_ "'(string replace --all '"' '\\"' -- $description)'"'
53-
end <$tmpdir/implicit/$f.tmp >$tmpdir/implicit/$f
54-
rm $tmpdir/implicit/$f.tmp
59+
string replace --filter --regex $implicit_regex '$1' <$f | string unescape \
60+
| string replace --all '"' '\\"' | string replace -r '(.*)' 'N_ "$1"' >$tmpdir/implicit/$f
5561
end
5662

57-
xgettext -j -k -kN_ -LShell --from-code=UTF-8 -cDescription --no-wrap -o messages.pot $tmpdir/explicit/share/*/*.fish
58-
xgettext -j -k -kN_ -LShell --from-code=UTF-8 -cDescription --no-wrap -o messages.pot $tmpdir/implicit/share/*/*.fish
63+
xgettext -j -k -kN_ -LShell --from-code=UTF-8 -cDescription --no-wrap -o messages.pot $tmpdir/{ex,im}plicit/share/*/*.fish
5964

6065
rm -r $tmpdir

0 commit comments

Comments
 (0)