diff --git a/tools/build_strings-test.sh b/tools/build_strings-test.sh index a8ad6bd..980ae3c 100755 --- a/tools/build_strings-test.sh +++ b/tools/build_strings-test.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # -# Exercise build_strings.sh on catalogs keyed by a lang.def symbol instead of by -# English text. No shipped catalog uses one yet, so this is the only cover. +# Exercise build_strings.sh on catalogs keyed by a symbol instead of by English +# text. No shipped catalog uses one yet, so this is the only cover. set -euo pipefail HERE="$(cd "$(dirname "$0")" && pwd)" @@ -9,36 +9,24 @@ SUT="$HERE/build_strings.sh" tmp="$(mktemp -d)" trap 'rm -rf "$tmp"' EXIT -# lang.def pairs a symbol with its English text, symbol first. This fixture -# copies the real file, including its LANGUAGE_ header rows and two symbols -# sharing one English text, as 27 of its texts do. +# lang-symbols.tsv gives kind, symbol and text, one row each. Two string symbols +# share one English text here, as 27 of the real texts do. The columns are +# tab-separated, so write the file with printf rather than a quoted heredoc. mkdir -p "$tmp/lang" "$tmp/res/values" -cat >"$tmp/lang.def" <<'DEF' -Francais -LANGUAGE_1 -LANGUAGE_NAME -LANGUAGE_NAME -LANGUAGE_FILE -LANGUAGE_FILE -LANGUAGE_ISO -LANGUAGE_ISO -LANG_OK -OK -LANG_CANCEL -Cancel -LANG_B3 -Cancel -LANG_START -Start -LISTDEF_1 -One\nTwo -LANG_LITERAL -LANG_OK -LANG_B3 -Cancel -LANG_INFO -Info type: -DEF +printf '# a comment row, as the real file carries five of\n' >"$tmp/lang-symbols.tsv" +printf '%s\t%s\t%s\n' \ + language LANGUAGE_1 Francais \ + meta LANGUAGE_NAME LANGUAGE_NAME \ + meta LANGUAGE_FILE LANGUAGE_FILE \ + meta LANGUAGE_ISO LANGUAGE_ISO \ + string LANG_OK OK \ + string LANG_CANCEL Cancel \ + string LANG_B3 Cancel \ + string LANG_START Start \ + string LISTDEF_1 'One\nTwo' \ + string LANG_LITERAL LANG_OK \ + string LANG_B3 Cancel \ + string LANG_INFO 'Info type:' >>"$tmp/lang-symbols.tsv" cat >"$tmp/res/values/strings.xml" <<'XML' @@ -122,16 +110,16 @@ has "a LISTDEF_ symbol splits on \\n, second line" two Deux # fragment filled, because a fragment belongs to the symbol that carried it. has "a split fragment keeps its symbol's claim" one Un missing "a string no catalog line carries stays empty" start Start -# lang.def gives "LANG_OK" as a string's own English text, so a line keyed that +# The table gives "LANG_OK" as a string's own English text, so a line keyed that # way is text, not the symbol of the same name. -has "a key lang.def knows as text is not read as a symbol" literal TexteLitteral -# lang.def spells this text with a trailing colon and strings.xml does not, so -# the resolved key matches only when lang.def goes through lang_filter as well. -has "lang.def text is cleaned up like a catalog key" info "Type info" +has "a key the table knows as text is not read as a symbol" literal TexteLitteral +# The table spells this text with a trailing colon and strings.xml does not, so +# the resolved key matches only when the text column goes through lang_filter too. +has "table text is cleaned up like a catalog key" info "Type info" if grep -q 'LANG_NOSUCH' "$err"; then - pass "a symbol absent from lang.def is reported" + pass "a symbol absent from the table is reported" else - bad "a symbol absent from lang.def is reported" + bad "a symbol absent from the table is reported" fi # A catalog mid-re-key holds both kinds of line for one string. The symbol must @@ -196,14 +184,46 @@ else diff "$tmp/text-keyed.xml" "$out" || true fi -# The symbol-to-text table comes from lang.def, so a missing one must stop the -# run rather than quietly drop every symbol-keyed line. +# A missing table must stop the run rather than quietly drop every symbol-keyed +# line. rc=0 -bash "$SUT" "$tmp/lang" "$tmp/res" /nonexistent/lang.def >/dev/null 2>&1 || rc=$? -if test "$rc" -eq 1; then - pass "a missing lang.def fails the run" +bash "$SUT" "$tmp/lang" "$tmp/res" /nonexistent/lang-symbols.tsv >/dev/null 2>"$err" || rc=$? +if test "$rc" -eq 1 && grep -q 'lang-symbols.tsv not found' "$err"; then + pass "a missing table fails the run and says so" else - bad "a missing lang.def fails the run (exit $rc)" + bad "a missing table fails the run and says so (exit $rc)" + cat "$err" || true +fi + +# Every case above runs on a fixture, so none would notice the pinned engine losing +# lang-symbols.tsv or changing its shape. Resolve one of the real table's own symbols. +engine="$HERE/../app/src/main/jni/httrack" +if ! test -d "$engine/lang"; then + echo "SKIP: no engine submodule, so the pinned table is unchecked" >&2 +elif ! test -f "$engine/lang-symbols.tsv"; then + bad "the pinned engine carries lang-symbols.tsv" +else + table="$engine/lang-symbols.tsv" + sym="$(awk -F'\t' '$1 == "string" { print $2; exit }' "$table")" + text="$(awk -F'\t' '$1 == "string" { print $3; exit }' "$table")" + # A glob, not find piped to head, which pipefail turns into a failure. + catalogs=("$engine"/lang/*.txt) + catalog="${catalogs[0]}" + pin="$tmp/pin" + mkdir -p "$pin/lang" "$pin/res/values" + printf '\n\n %s\n\n' \ + "$text" >"$pin/res/values/strings.xml" + { + printf 'LANGUAGE_NAME\nFrancais\nLANGUAGE_FILE\nFrancais\nLANGUAGE_ISO\nfr\n' + printf '%s\nTraduit\n' "$sym" + } >"$pin/lang/$(basename "$catalog")" + bash "$SUT" "$pin/lang" "$pin/res" "$table" >/dev/null 2>&1 + if grep -qF 'Traduit' "$pin/res/values-fr/string.xml"; then + pass "the pinned table resolves its own first symbol ($sym)" + else + bad "the pinned table resolves its own first symbol ($sym)" + grep -F 'name="probe"' "$pin/res/values-fr/string.xml" || true + fi fi test "$fail" -eq 0 && echo "build_strings-test: all cases pass" diff --git a/tools/build_strings.sh b/tools/build_strings.sh index a17d4d3..b7e593e 100755 --- a/tools/build_strings.sh +++ b/tools/build_strings.sh @@ -3,19 +3,19 @@ # Convert httrack lang/*;txt files into android xml resources -# usage: $0 path-to/lang path-to/res [path-to/lang.def] -# lang.def defaults to the one next to the lang directory +# usage: $0 path-to/lang path-to/res [path-to/lang-symbols.tsv] +# lang-symbols.tsv defaults to the one next to the lang directory # example: # rm -rf res/values-?? res/values-??-r?? # language dirs only: values-* also takes the # # hand-kept values-v34, values-night and the rest -# bash tools/build_strings.sh /temp/httrack-3.47.21/lang res/ +# bash tools/build_strings.sh app/src/main/jni/httrack/lang app/src/main/res/ function norm_key { echo "$1" | sed -e 's/[^a-zA-Z0-9]/_/g' } -# Clean up catalog text. lang.def goes through it too, so a symbol resolves to -# the same key as its English text. +# Clean up catalog text. A table text goes through it too, so a symbol resolves +# to the same key as its English text. function lang_filter { tr -d '\r' \ | sed -e 's/\\r//g' \ @@ -26,7 +26,7 @@ function lang_filter { | sed -e "s/(C)/\©/g" } -# Store one translation, keyed by the lang.def symbol in $3, or by its text when +# Store one translation, keyed by the table symbol in $3, or by its text when # $3 is empty. A symbol line beats a text line, and is skipped only when the same # symbol already set this key, so several symbols sharing a text keep the last. function put_str { @@ -39,23 +39,22 @@ function put_str { arr["$1"]="$2" } -test -d "$1" || ! echo "lang directory not found: $1" || exit 1 -test -d "$2" || ! echo "res directory not found: $2" || exit 1 -langdef="${3:-$1/../lang.def}" -test -f "$langdef" || ! echo "lang.def not found: $langdef (give its path as the 3rd argument)" || exit 1 +test -d "$1" || ! echo "lang directory not found: $1" >&2 || exit 1 +test -d "$2" || ! echo "res directory not found: $2" >&2 || exit 1 +symtab="${3:-$1/../lang-symbols.tsv}" +test -f "$symtab" || ! echo "lang-symbols.tsv not found: $symtab (give its path as the 3rd argument)" >&2 || exit 1 -# lang.def pairs each string's LANG_ symbol with its English text, symbol first. +# The string rows are the translatable ones, in file order, so a text several +# symbols share resolves to the last of them. # sym_text resolves a symbol, english_text answers "is this key a known text?". declare -A sym_text declare -A english_text -while IFS= read -r dk && IFS= read -r dv; do +while IFS=$'\t' read -r dk dv; do if test -n "$dk" -a -n "$dv"; then english_text["$dv"]=1 -case "$dk" in -LANG_*|LISTDEF_*) sym_text["$dk"]="$dv" ;; -esac +sym_text["$dk"]="$dv" fi -done < <(lang_filter < "$langdef") +done < <(awk -F'\t' '$1 == "string" { print $2 "\t" $3 }' "$symtab" | lang_filter) for i in $1/*.txt ; do echo -n "processing $i .. " >&2 @@ -86,7 +85,7 @@ LANG_*|LISTDEF_*) if test -z "${english_text[$rk]}"; then if test -z "${sym_text[$rk]}"; then # No resource is keyed by a bare symbol, so drop the line rather than store it. -echo "warning: $i: no lang.def entry for key $rk, line skipped" >&2 +echo "warning: $i: no string row for symbol $rk, line skipped" >&2 continue fi symbol="$rk"