mirror of
https://github.com/forkless/Piperless.git
synced 2026-08-16 00:46:38 +02:00
109 lines
3.6 KiB
Bash
Executable File
109 lines
3.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# sync-translations.sh — Generate / update per-locale JSON translation files
|
|
# from the master translations.json.
|
|
#
|
|
# Usage:
|
|
# ./tools/sync-translations.sh [locale...]
|
|
#
|
|
# With no arguments: syncs all known locales.
|
|
# With one or more locale codes: syncs only those (e.g. de_DE fr_FR).
|
|
#
|
|
# The master file (languages/translations.json) keys on the original English
|
|
# string. Each locale file gets a _meta block and a "strings" object.
|
|
# Existing translations are preserved; new keys from master are added with
|
|
# empty values. Removed keys are dropped.
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
|
LANG_DIR="${PROJECT_DIR}/languages"
|
|
MASTER="${LANG_DIR}/translations.json"
|
|
|
|
# ── Known target locales ──────────────────────────────────────────────
|
|
DEFAULT_LOCALES=("de_DE" "fr_FR" "es_ES" "ja" "nl_NL")
|
|
|
|
if [[ $# -gt 0 ]]; then
|
|
LOCALES=("$@")
|
|
else
|
|
LOCALES=("${DEFAULT_LOCALES[@]}")
|
|
fi
|
|
|
|
# ── Validate master ───────────────────────────────────────────────────
|
|
if [[ ! -f "$MASTER" ]]; then
|
|
echo "Error: master translations.json not found. Run pot2json.sh first." >&2
|
|
exit 1
|
|
fi
|
|
|
|
if ! command -v jq &>/dev/null; then
|
|
echo "Error: jq is required. Install with: sudo apt install jq" >&2
|
|
exit 1
|
|
fi
|
|
|
|
TODAY=$(date +%Y-%m-%d)
|
|
|
|
# ── Count keys in master ──────────────────────────────────────────────
|
|
MASTER_COUNT=$(jq 'keys | length' "$MASTER")
|
|
|
|
for LOCALE in "${LOCALES[@]}"; do
|
|
LOCALE_FILE="${LANG_DIR}/piperless-${LOCALE}.json"
|
|
|
|
if [[ -f "$LOCALE_FILE" ]]; then
|
|
# ── Merge: keep existing translations, add new keys, drop removed ──
|
|
OLD_TRANSLATED=$(jq '._meta.translated // 0' "$LOCALE_FILE")
|
|
OLD_LOCKED=$(jq '._meta.locked // false' "$LOCALE_FILE")
|
|
|
|
# Build a new strings object: for every key in master, use the
|
|
# existing translation if present; otherwise empty string.
|
|
jq -n --slurpfile master "$MASTER" --slurpfile local "$LOCALE_FILE" '
|
|
($local[0].strings // {}) as $existing |
|
|
{
|
|
_meta: {
|
|
locale: "'"$LOCALE"'",
|
|
source: "translations.json",
|
|
generated: "'"$TODAY"'",
|
|
total_strings: ($master[0] | keys | length),
|
|
translated: 0,
|
|
locked: '"$OLD_LOCKED"'
|
|
},
|
|
strings: ($master[0] | to_entries | map({
|
|
key: .key,
|
|
value: ($existing[.key] // "")
|
|
}) | from_entries)
|
|
}
|
|
' > "${LOCALE_FILE}.tmp"
|
|
|
|
# Re-count translated (non-empty values).
|
|
NEW_TRANSLATED=$(jq '[.strings[] | select(. != "")] | length' "${LOCALE_FILE}.tmp")
|
|
jq --argjson t "$NEW_TRANSLATED" '._meta.translated = $t' "${LOCALE_FILE}.tmp" > "$LOCALE_FILE"
|
|
rm -f "${LOCALE_FILE}.tmp"
|
|
|
|
echo "Updated ${LOCALE}: ${NEW_TRANSLATED} / ${MASTER_COUNT} translated (was ${OLD_TRANSLATED})"
|
|
|
|
else
|
|
# ── Create new locale file ─────────────────────────────────────
|
|
jq -n --slurpfile master "$MASTER" '
|
|
{
|
|
_meta: {
|
|
locale: "'"$LOCALE"'",
|
|
source: "translations.json",
|
|
generated: "'"$TODAY"'",
|
|
total_strings: ($master[0] | keys | length),
|
|
translated: 0,
|
|
locked: false
|
|
},
|
|
strings: ($master[0] | to_entries | map({
|
|
key: .key,
|
|
value: .value
|
|
}) | from_entries)
|
|
}
|
|
' > "$LOCALE_FILE"
|
|
|
|
echo "Created ${LOCALE}: 0 / ${MASTER_COUNT} translated"
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
echo "Done. Locale files in ${LANG_DIR}/"
|