Skip to content

[Agent] i18n: convert remaining hardcoded UI strings and add a no-literal-string guard #655

Closed

Description

@matteius

Problem and evidence

A first pass (commit f0f19245) moved about 120 hardcoded English strings to t() keys: the building plan, the setup wizard, and the specific titles and labels a frontend audit listed. Several surfaces are still mostly literal English:

  • web/js/components/preact/UI.jsx: the recording video modal, delete and snapshot dialogs, and fullscreen errors. Only the strings the audit listed were converted.
  • web/js/components/preact/timeline/CalendarPicker.jsx: month and day names and navigation labels.
  • FisheyeEptzCanvas.jsx: aria and title strings (partly done).
  • Anything else a sweep finds: JSX text nodes and title= / aria-label= / placeholder= literals across web/js/components/preact/**.

Expected behavior and scope

  1. Sweep web/js for user-visible literals and convert them to t('<namespace>.<key>'), adding the keys to web/public/locales/en.json only. Other locales fall back to English through web/js/i18n.js. Translations are tracked in a separate issue.
  2. Dates, months and weekdays should use Intl.DateTimeFormat with the active locale instead of translation keys where that's possible (CalendarPicker).
  3. Add a guard so the regression doesn't come back. For example, an ESLint rule such as eslint-plugin-i18next's no-literal-string in markup-only mode, scoped to web/js/components/** with an allowlist for technical strings. If the rule is too noisy, a Jest test that scans the JSX for >[A-Z][a-z]+ text nodes is acceptable.
  4. Don't translate log messages, console.* output, CSS class names or API paths.

Acceptance criteria

  • No user-visible English literals remain in UI.jsx or CalendarPicker.jsx.
  • The lint or test guard runs in CI and fails on a newly added literal.
  • en.json keys are named consistently with existing namespaces (recordings.*, timeline.*, live.*, etc.), and keys that already exist are reused, not duplicated.
  • t() is only called where it's in scope. Watch module-level helpers that have no t, and run eslint --rule 'no-undef: error' on touched files.

Validation

  • cd web && npx vite build (this is the JSX compile check; npx babel gives false errors), npm run lint, npm test.
  • Spot-check the UI with the language set to es: converted strings show English (fallback) without raw key names.

Constraints and rollback

  • Mechanical refactor. Keep PRs reviewable; splitting by directory is fine.
  • Rollback: revert.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestjavascriptPull requests that update javascript code

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions