#!/usr/bin/env bash # audit-i18n-strings.sh — verifier for issue #23 / spec i18n-frontend-ui-strings. # # Greps the five files in scope for hard-coded user-visible CJK literals and # checks that locales/en.json and locales/zh.json have parity at every path. # # Annotation rules respected by this script: # - lines that are pure // line comments are skipped # - lines that contain `// i18n-allow:` are skipped (deliberate token) # - lines that contain `console.log/info/warn/error/debug(` are skipped # (developer logs, not user-visible UI; out of scope) # - lines between `// i18n-allow-block:` and `// i18n-allow-block-end` # are skipped (used for the REPORT_MARKERS and STAGE_PHASE_MAP blocks # that intentionally embed Chinese tokens for backend compatibility) # # Exits 0 on success; non-zero with a human-readable list of issues otherwise. set -euo pipefail REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)" FILES=( "frontend/src/views/Process.vue" "frontend/src/components/Step2EnvSetup.vue" "frontend/src/components/Step3Simulation.vue" "frontend/src/components/Step4Report.vue" "frontend/src/components/Step5Interaction.vue" ) CJK_RE='[\x{4e00}-\x{9fff}\x{3000}-\x{303f}\x{ff00}-\x{ffef}]' cd "$REPO_ROOT" fail=0 for f in "${FILES[@]}"; do if [[ ! -f "$f" ]]; then echo "audit: missing file $f" >&2 fail=1 continue fi # awk filters out comments and dev-only constructs, then strips inline # trailing comments before passing the surviving line to ripgrep. The # remaining hits are user-visible CJK literals. hits="$(awk ' BEGIN { in_allow = 0; in_html = 0; in_css = 0 } # Spec-controlled allowlist regions (REPORT_MARKERS, STAGE_PHASE_MAP). /\/\/ i18n-allow-block:/ { in_allow = 1; next } /\/\/ i18n-allow-block-end/ { in_allow = 0; next } in_allow { next } # Per-line allow annotation. /\/\/ i18n-allow:/ { next } # Vue template HTML comments (), single- or multi-line. { line = $0 # Strip pairs of on the same line. while (match(line, //)) { line = substr(line, 1, RSTART - 1) substr(line, RSTART + RLENGTH) } # Detect entering/leaving an HTML comment block. if (in_html) { if (match(line, /-->/)) { line = substr(line, RSTART + RLENGTH) in_html = 0 } else { next } } if (match(line, /