[i18n tooling] i18n:scan always exits 1 on a honeypot false-positive → tool can't surface new hardcoded strings #424

Closed
opened 2026-07-05 22:59:13 +00:00 by spikerj · 1 comment
Owner

Verified finding (low priority — dev tooling, not a build break)

pnpm run i18n:scan (tools/i18n/scan-hardcoded-strings.mjs) reports 1 suspect and exits 1:

projects/spikersoft/src/app/_components/contact/contact.component.html  (1 suspect)
  L188  [text]  Website

That string is an intentional honeypot label (added in #251), correctly hidden from real users:

<!-- Honeypot: hidden from real users; bots that fill it are dropped server-side. -->
<div class="honeypot" aria-hidden="true">
  <label for="contact-website">Website</label>
  <input id="contact-website" type="text" formControlName="website" tabindex="-1" autocomplete="off" />
</div>

It should not be translated (aria-hidden, visually hidden, never shown; a plausible English field name is the point).

Why it matters

  • i18n:scan is not wired into CI or husky (verified) — so this is not a build break.
  • But because the scan always exits 1 on this one false positive, the tool can no longer be used to catch new hardcoded strings distinguishably — every run is red regardless. That defeats the tool's purpose.

Suggested fix (pick one)

  1. Quick: add contact/contact.component.html to ALLOW_LIST (currently new Set([]), keyed by repo-relative path at scan-hardcoded-strings.mjs:124). Downside: coarse — suppresses future real strings in that file.
  2. Better: teach the scanner to skip aria-hidden="true" subtrees (and/or honeypot containers), so genuinely-hidden copy is never flagged anywhere.
  3. Best: support an inline ignore marker (e.g. an <!-- i18n-ignore --> comment on the preceding line) so a single intentional string can be excused without blanket-allowing a whole file.

Recommend (2) or (3) so the tool stays sharp. Small, self-contained, verified.

## Verified finding (low priority — dev tooling, not a build break) `pnpm run i18n:scan` (`tools/i18n/scan-hardcoded-strings.mjs`) reports **1 suspect and exits 1**: ``` projects/spikersoft/src/app/_components/contact/contact.component.html (1 suspect) L188 [text] Website ``` That string is an **intentional honeypot label** (added in #251), correctly hidden from real users: ```html <!-- Honeypot: hidden from real users; bots that fill it are dropped server-side. --> <div class="honeypot" aria-hidden="true"> <label for="contact-website">Website</label> <input id="contact-website" type="text" formControlName="website" tabindex="-1" autocomplete="off" /> </div> ``` It **should not** be translated (aria-hidden, visually hidden, never shown; a plausible English field name is the point). ### Why it matters - `i18n:scan` is **not** wired into CI or husky (verified) — so this is not a build break. - But because the scan **always exits 1** on this one false positive, the tool can no longer be used to catch *new* hardcoded strings distinguishably — every run is red regardless. That defeats the tool's purpose. ## Suggested fix (pick one) 1. **Quick:** add `contact/contact.component.html` to `ALLOW_LIST` (currently `new Set([])`, keyed by repo-relative path at `scan-hardcoded-strings.mjs:124`). Downside: coarse — suppresses *future* real strings in that file. 2. **Better:** teach the scanner to skip `aria-hidden="true"` subtrees (and/or honeypot containers), so genuinely-hidden copy is never flagged anywhere. 3. **Best:** support an inline ignore marker (e.g. an `<!-- i18n-ignore -->` comment on the preceding line) so a single intentional string can be excused without blanket-allowing a whole file. Recommend (2) or (3) so the tool stays sharp. Small, self-contained, verified.
Author
Owner

Already resolved on master (verified off origin/master @ 365320c) — no PR needed.

The recommended "best" option (3, inline ignore marker) is fully in place:

  • The scanner supports it — tools/i18n/scan-hardcoded-strings.mjs isIgnoreMarked() skips a flagged line (or the line immediately above it) carrying an i18n-ignore marker.
  • The honeypot is marked — contact/contact.component.html:188:
    <!-- i18n-ignore: honeypot label, aria-hidden and never shown to real users; the English text is intentional bait for bots. -->
    <label for="contact-website">Website</label>
    

pnpm run i18n:scan now reports 0 template(s) with suspect copy, 0 finding(s) total. and exits 0, so the tool is sharp again — the honeypot is excused precisely (that one line only) while any new hardcoded string, including elsewhere in the same file, would still be flagged. Closing as fixed.

Already resolved on `master` (verified off `origin/master` @ `365320c`) — no PR needed. The recommended "best" option (3, inline ignore marker) is fully in place: - The scanner supports it — `tools/i18n/scan-hardcoded-strings.mjs` `isIgnoreMarked()` skips a flagged line (or the line immediately above it) carrying an `i18n-ignore` marker. - The honeypot is marked — `contact/contact.component.html:188`: ```html <!-- i18n-ignore: honeypot label, aria-hidden and never shown to real users; the English text is intentional bait for bots. --> <label for="contact-website">Website</label> ``` `pnpm run i18n:scan` now reports **`0 template(s) with suspect copy, 0 finding(s) total.` and exits 0**, so the tool is sharp again — the honeypot is excused precisely (that one line only) while any *new* hardcoded string, including elsewhere in the same file, would still be flagged. Closing as fixed.
Sign in to join this conversation.