# shellcheck shell=sh # SPDX-FileCopyrightText: 2026 GPForum Contributors # SPDX-License-Identifier: BSD-3-Clause # # The command line's words for the shell scripts that run before Perl's # dependencies exist (script/gpforum-system-perl, script/system-preflight): # the same catalogs GPForum::Service::I18N::CliCatalog reads, locale/cli/en.po # and it.po, in the language LC_ALL, LC_MESSAGES or LANG names, read with # awk. Sourced, not run; the sourcing script sets $root to the checkout. # # words_say KEY 'English text with {name}' name=value ... # # prints the key's text in the operator's language with each {name} filled # in. The English given is what en.po says (t/492 holds them equal); it is # used when the catalogs are not there, as in a bare copy of the script. # it or en: the first of LC_ALL, LC_MESSAGES and LANG that is set decides, # as it does for every other program; Italian for it, it_IT.UTF-8 and the # like, English for anything else. words_language() { for words_value in "${LC_ALL:-}" "${LC_MESSAGES:-}" "${LANG:-}"; do [ -n "$words_value" ] || continue case "$words_value" in [Ii][Tt] | [Ii][Tt][_.@-]*) echo it ;; *) echo en ;; esac return 0 done echo en } # The msgstr of a msgctxt in a PO file, its continuation lines joined and # its escapes read; nothing when the file lacks it. words_lookup() { awk -v key="$1" ' function unquote(text) { sub(/^[ \t]*"/, "", text) sub(/"[ \t]*$/, "", text) gsub(/\\"/, "\"", text) gsub(/\\\\/, "\\", text) return text } $0 == "msgctxt \"" key "\"" { found = 1; next } found && /^msgstr / { taking = 1; sub(/^msgstr /, ""); out = unquote($0); next } found && taking && /^[ \t]*"/ { out = out unquote($0); next } found && taking { exit } END { if (taking) printf "%s", out } ' "$2" 2>/dev/null } words_say() { words_key=$1 words_text=$2 shift 2 words_file="${root:-.}/locale/cli/$(words_language).po" if [ -r "$words_file" ]; then words_found=$(words_lookup "$words_key" "$words_file") if [ -n "$words_found" ]; then words_text=$words_found fi fi for words_pair in "$@"; do words_name=${words_pair%%=*} words_value=${words_pair#*=} while :; do case "$words_text" in *"{$words_name}"*) words_text="${words_text%%"{$words_name}"*}$words_value${words_text#*"{$words_name}"}" ;; *) break ;; esac done done printf '%s\n' "$words_text" } # A finding's line, marked as GPForum::Service::Operations::Findings marks # it: ok, degraded or fail, then the text. words_mark() { case "$1" in ok) printf '\342\234\223 %s\n' "$2" ;; degraded) printf '! %s\n' "$2" ;; *) printf '\342\234\227 %s\n' "$2" ;; esac } # The fixes under a problem: the first behind "Fix: " in the operator's # language, each one after it aligned under the first's text. words_fixes() { words_first=1 words_prefix=$(words_say findings.fix 'Fix: {fix}' fix=) words_pad=$(printf '%s' "$words_prefix" | sed 's/./ /g') for words_fix in "$@"; do if [ "$words_first" -eq 1 ]; then printf ' %s%s\n' "$words_prefix" "$words_fix" words_first=0 else printf ' %s%s\n' "$words_pad" "$words_fix" fi done } # The closing line: nothing to fix, one thing, or how many. words_summary() { case "$1" in 0) words_say findings.summary_none 'Nothing to fix.' ;; 1) words_say findings.summary_one '1 thing to fix.' ;; *) words_say findings.summary_many '{count} things to fix.' "count=$1" ;; esac }