Skip to content

i18n guard test_i18n.py only scans showToast/showConfirm — extend to textContent / innerHTML / HTML literals #698

@memtomem

Description

@memtomem

Summary

The Korean UI mode shows large amounts of untranslated English copy — header counters, search filter buttons, tag empty states, settings labels, and timeline filters all leak through. The existing i18n guard test (tests/test_i18n.py) misses them because it only inspects showToast(...) and showConfirm(...) call sites in 6 specific JS modules, not textContent / innerHTML assignments or HTML literals.

Found by Playwright UX review of v0.1.34 prod (2026-05-02). See docs/reports/mm-web-prod-v0.1.34-playwright-review.md (P1 — Korean UI contains many untranslated English strings).

Evidence — strings bypassing the dictionary

Hardcoded textContent templates:

  • packages/memtomem/src/memtomem/web/static/app.js:931-932 — header counter

    qs('stat-chunks').textContent  = `${data.total_chunks} chunks`;
    qs('stat-sources').textContent = `${data.total_sources} sources`;

    Translation keys (header.stat_chunks, header.stat_sources) exist in the locales but are never invoked.

  • packages/memtomem/src/memtomem/web/static/app.js:2561${n} chunks · ${m} files template (no plural key in either locale).

  • packages/memtomem/src/memtomem/web/static/settings-config.js:187Max chunk: ${n} tokens.

Hardcoded innerHTML empty states:

  • packages/memtomem/src/memtomem/web/static/app.js:3793emptyState('🏷', 'No tags yet', 'Run Auto-Tag to generate tags') — both strings absent from en.json / ko.json.

HTML literal button text without data-i18n:

  • "Advanced", "Delete Selected" buttons in packages/memtomem/src/memtomem/web/static/index.html — no data-i18n attribute.

Evidence — guard scope

packages/memtomem/tests/test_i18n.py scans only:

  • showToast(\...`)` template literals
  • showToast('English ...', ...) literals
  • showConfirm({ title: 'English...' }) titles

…in 6 explicit files (app.js, settings-*.js, context-gateway.js). Direct DOM updates (textContent =, innerHTML =, attribute assignment) and HTML literals are unscanned.

Suggested fix

  1. Extend test_i18n.py to AST-scan / regex-scan for:
    • el.textContent = "<English string>" or `${expr} <English suffix>` patterns.
    • el.innerHTML = "..." containing English sentences.
    • HTML files with element text not wrapped in data-i18n.
  2. Cover the static HTML templates as well as JS — the audit shows HTML-side hardcoding is just as common.
  3. Patch the offenders listed above. The header counters likely need plural-form keys ({n, plural, ...} or two keys for one/other) since "1 chunks" reads poorly.

This is the canonical-fixture approach (per repo's feedback_docs_parity_canonical_fixture.md): the guard should fail loudly with the file:line so contributors don't have to grep the whole tree.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions