Skip to content

ACM-35629 Enable i18next linting#6349

Merged
openshift-merge-bot[bot] merged 6 commits into
stolostron:mainfrom
KevinFCormier:enable-i18next-linting
Jun 17, 2026
Merged

ACM-35629 Enable i18next linting#6349
openshift-merge-bot[bot] merged 6 commits into
stolostron:mainfrom
KevinFCormier:enable-i18next-linting

Conversation

@KevinFCormier

@KevinFCormier KevinFCormier commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

📝 Summary

Ticket Summary (Title):
Add ESLint rule to flag hardcoded English strings in JSX

Ticket Link:
https://redhat.atlassian.net/browse/ACM-35629

Type of Change:

  • 🐞 Bug Fix
  • ✨ Feature
  • 🔧 Refactor
  • 💸 Tech Debt
  • 🧪 Test-related
  • 📄 Docs

✅ Checklist

General

  • PR title follows the convention (e.g. ACM-12340 Fix bug with...)
  • Code builds and runs locally without errors
  • No console logs, commented-out code, or unnecessary files
  • All commits are meaningful and well-labeled
  • All new display strings are externalized for localization (English only)
  • (Nice to have) JSDoc comments added for new functions and interfaces

Summary by CodeRabbit

  • New Features
    • Expanded internationalization across the UI by replacing hardcoded text with translatable keys for labels, status text, modal content, and page/wizard headings, including new wizard validation messaging and localized “Unknown” engine wording.
  • Chores
    • Added and enabled an i18n-focused ESLint rule to prevent hardcoded literal strings, with targeted exceptions for specific UI, story, and test files.
  • Documentation
    • Updated i18n contribution guidance to clarify where English translations live and how to update them safely.
  • Refactor
    • Improved the error boundary to use localized messaging in its fallback UI.
  • Tests
    • Minor lint-comment cleanup in tests.

…les for wizards and test files. This includes disabling the 'no-literal-string' rule for specific file patterns to improve localization handling.

Generated-by: Cursor (Claude Opus 4.6 High)

Signed-off-by: Kevin Cormier <kcormier@redhat.com>
- Introduced a new string `inputMustBeArray` in `StringContext` for localization.
- Updated `WizItemSelector` to use the new string for error handling when input is not an array.
- Added corresponding translation in `wizardStrings.ts`.

This enhances user feedback for input validation in the wizard interface.

Generated-by: Cursor (Claude Opus 4.6 High)

Signed-off-by: Kevin Cormier <kcormier@redhat.com>
Assisted-by: Cursor (Claude Opus 4.6 High)
Signed-off-by: Kevin Cormier <kcormier@redhat.com>
Generated-by: Cursor (Claude Opus 4.6 High)
Signed-off-by: Kevin Cormier <kcormier@redhat.com>
Signed-off-by: Kevin Cormier <kcormier@redhat.com>
@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 66b7b997-ce8e-40c6-bbec-f64d2107681d

📥 Commits

Reviewing files that changed from the base of the PR and between 7aa2c9f and e7c5e63.

📒 Files selected for processing (3)
  • frontend/packages/eslint-config/index.mjs
  • frontend/src/atoms.test.ts
  • frontend/src/lib/search.test.ts
💤 Files with no reviewable changes (2)
  • frontend/src/lib/search.test.ts
  • frontend/src/atoms.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/packages/eslint-config/index.mjs

📝 Walkthrough

Walkthrough

Adds eslint-plugin-i18next to enforce internationalized strings, configures the rule with glob-based overrides for tests/stories/wizards, then replaces hardcoded strings with t() calls across ~25 components. Refactors AcmErrorBoundary with typed props/state and ErrorFallback component. Adds inputMustBeArray to WizardStrings and localizes it in WizItemSelector. Adds targeted eslint-disable comments for intentional literals.

Changes

i18next ESLint enforcement and component-wide string localization

Layer / File(s) Summary
ESLint plugin registration and rule configuration
package.json, frontend/packages/eslint-config/package.json, frontend/packages/eslint-config/index.mjs, frontend/packages/react-form-wizard/eslint.config.mjs
Adds eslint-plugin-i18next@^6.1.4 to root and package devDependencies, registers it in the shared flat config, enables i18next/no-literal-string with Trans/title JSX exclusions, and configures glob-based overrides for test/story files and wizard directories.
WizardStrings inputMustBeArray contract and wiring
frontend/packages/react-form-wizard/src/contexts/StringContext.tsx, frontend/src/lib/wizardStrings.ts, frontend/packages/react-form-wizard/src/inputs/WizItemSelector.tsx
Adds inputMustBeArray to WizardStrings interface and defaultStrings, wires it to a translation key in useWizardStrings, and updates WizItemSelector to read the localized message from useStringContext() instead of a hardcoded literal.
AcmErrorBoundary typed refactor with ErrorFallback component
frontend/src/ui-components/AcmErrorBoundary/AcmErrorBoundary.tsx
Introduces ErrorBoundaryProps/ErrorBoundaryState interfaces for explicit typing, extracts fallback UI into a new ErrorFallback functional component using useTranslation() for localized headings/labels, renames actions CSS variable to actionsStyle, and delegates rendering from the class component to the fallback component.
SimpleTimestamp and IdentityStatus string localization
frontend/src/lib/SimpleTimestamp.tsx, frontend/src/ui-components/IdentityStatus/IdentityStatus.tsx
Updates SimpleTimestamp to use useTranslation() for "Invalid Date" and IdentityStatus to localize "Active"/"Inactive" labels via t() instead of hardcoded strings.
Governance routes engine display localization
frontend/src/routes/Governance/common/util.tsx, frontend/src/routes/Governance/discovered/DiscoveredPolicies.tsx, frontend/src/routes/Governance/discovered/details/DiscoveredPolicyDetailsPage.tsx, frontend/src/routes/Governance/policies/policy-details/PolicyTemplateDetail/PolicyTemplateDetails.tsx
Adds t: TFunction parameter to getEngineWithSvg so the "Unknown" fallback is localized, and updates three governance route callers to pass the translation function through the call chain.
Applications Overview status group localization
frontend/src/routes/Applications/Overview.tsx
Adds t: TFunction parameter to renderPopoverContent and renderApplicationStatusGroup, localizes status labels ("Status", "OK", "Error"), and updates Health Status/Sync Status/Pod Status column cell renderers to pass t through the rendering chain.
DeleteResourceModal and InfraEnvironmentsPage localization
frontend/src/routes/Applications/components/DeleteResourceModal.tsx, frontend/src/routes/Infrastructure/InfraEnvironments/InfraEnvironmentsPage.tsx
Updates DeleteResourceModal to use i18next interpolation for app set placement text and InfraEnvironmentsPage to localize the "Cannot be deleted" popover/button labels via translation keys.
Search Details and Service Account page localization
frontend/src/routes/Search/Details/DetailsPage.tsx, frontend/src/routes/UserManagement/Identities/ServiceAccounts/ServiceAccount*.tsx
Localizes Search Details header labels (Cluster, Namespace) and all Service Account pages (Detail/Groups/RoleAssignments/Yaml/List) to use i18n translation keys with interpolation for page titles and descriptions.
Policy and RoleAssignment wizard template localization
frontend/src/wizards/Governance/Policy/PolicyWizard.tsx, frontend/src/wizards/RoleAssignment/ReviewStepContent.tsx
Localizes PolicyWizard "Certificate Policy" template heading and ReviewStepContent "Global access" scope text using t() calls.
Targeted eslint-disable comments
frontend/src/App.tsx, frontend/src/routes/Infrastructure/Clusters/ManagedClusters/components/LoginCredentials.tsx, frontend/src/routes/Search/components/Modals/SearchInfoModal.tsx
Adds eslint-disable-next-line i18next/no-literal-string comments for intentional literals: Configure client dropdown and masthead brand in App.tsx, credential mask bullets, and search query syntax examples.
Documentation expansion and test import cleanup
frontend/AGENTS.md, frontend/src/atoms.test.ts, frontend/src/lib/search.test.ts
Expands AGENTS.md with English translation location, npm run i18n:fix command, translation JSON editing rules, and prohibition on editing other language files. Removes obsolete eslint-disable comments from test imports.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • stolostron/console#6259: Both PRs modify frontend/packages/react-form-wizard/src/contexts/StringContext.tsx with additional wizard string fields, potentially impacting the same translations and context contract.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title "ACM-35629 Enable i18next linting" clearly and concisely describes the main objective: enabling ESLint linting for i18next, which is the primary technical debt work across all file changes.
Description check ✅ Passed The description completes the required template sections, including ticket summary, link, type of change (Tech Debt), and checklist confirmations for general requirements like code quality and externalized strings.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
frontend/src/routes/Applications/Overview.tsx (1)

18-18: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Use type-only import for TFunction.

Per coding guidelines, TypeScript types should use import type syntax to avoid runtime imports. Since TFunction is only used for type annotations (function parameter types), it should be imported as a type-only import.

♻️ Proposed fix
-import { TFunction } from 'react-i18next'
+import type { TFunction } from 'react-i18next'

As per coding guidelines: "Use import type syntax to avoid runtime imports of TypeScript types" applies to frontend/**/*.{ts,tsx} files.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/routes/Applications/Overview.tsx` at line 18, The import
statement for TFunction from react-i18next is currently using a regular import
syntax, but since TFunction is only used for type annotations (such as function
parameter types) and not as a runtime value, it should be changed to a type-only
import using the `import type` syntax. Update the import statement to use
`import type` to follow the TypeScript coding guidelines and avoid unnecessary
runtime imports.

Source: Coding guidelines

frontend/src/routes/Governance/common/util.tsx (1)

4-4: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use import type syntax for the TFunction type.

The TFunction import should use import type syntax since it's only used for type annotations, not as a runtime value.

📝 Suggested fix
-import { TFunction } from 'react-i18next'
+import type { TFunction } from 'react-i18next'

Based on learnings: In the stolostron/console frontend, when you need TFunction for type-only usage (e.g., helper function signatures), import it directly from react-i18next using a type-only import: import type { TFunction } from 'react-i18next'. As per coding guidelines: Use import type syntax to avoid runtime imports of TypeScript types.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/routes/Governance/common/util.tsx` at line 4, The TFunction
import from react-i18next is currently using regular import syntax but should
use import type syntax since it is only used for type annotations in function
signatures and not as a runtime value. Change the import statement for TFunction
to use the type keyword before the curly braces to indicate this is a type-only
import from react-i18next. This optimization helps with tree-shaking and makes
the codebase alignment with TypeScript best practices.

Sources: Coding guidelines, Learnings

frontend/src/lib/SimpleTimestamp.tsx (1)

18-26: ⚠️ Potential issue | 🟡 Minor

Externalize locale-specific strings and reconsider hardcoded 'en-US' locale.

The component hardcodes 'en-US' locale and embeds 'PM'/'AM' strings directly, preventing adaptation to user locale. This contradicts the codebase pattern (see table-row-helpers.ts) where other timestamp utilities use toLocaleString() without specifying a locale, respecting browser defaults.

Consider:

  • Removing the hardcoded 'en-US' locale to use the user's browser locale, or
  • Externalizing the AM/PM strings via t() calls for i18n consistency
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/lib/SimpleTimestamp.tsx` around lines 18 - 26, The
SimpleTimestamp component hardcodes the 'en-US' locale in the toLocaleString
call and embeds 'PM' and 'AM' strings directly, which prevents adaptation to the
user's browser locale. Remove the hardcoded 'en-US' locale argument from the
toLocaleString call to use the browser's default locale (matching the pattern
used elsewhere in the codebase like table-row-helpers.ts), and externalize the
'PM' and 'AM' strings in the ampm variable assignment by wrapping them with i18n
translation function calls (t()) instead of hardcoding them as string literals.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/packages/eslint-config/index.mjs`:
- Around line 162-163: The glob pattern `**/*.test.ts?` in the files array is
incorrect because the `?` wildcard matches exactly one optional character, which
means it only matches `.tsx` files and excludes plain `.ts` files. Fix this
pattern to properly match both `.ts` and `.tsx` test files by using the correct
glob syntax that captures both file extensions. The same issue exists on line
170 for story file patterns where `**/*.stories.ts?` also needs to be corrected
to include both `.ts` and `.tsx` files.

---

Outside diff comments:
In `@frontend/src/lib/SimpleTimestamp.tsx`:
- Around line 18-26: The SimpleTimestamp component hardcodes the 'en-US' locale
in the toLocaleString call and embeds 'PM' and 'AM' strings directly, which
prevents adaptation to the user's browser locale. Remove the hardcoded 'en-US'
locale argument from the toLocaleString call to use the browser's default locale
(matching the pattern used elsewhere in the codebase like table-row-helpers.ts),
and externalize the 'PM' and 'AM' strings in the ampm variable assignment by
wrapping them with i18n translation function calls (t()) instead of hardcoding
them as string literals.

In `@frontend/src/routes/Applications/Overview.tsx`:
- Line 18: The import statement for TFunction from react-i18next is currently
using a regular import syntax, but since TFunction is only used for type
annotations (such as function parameter types) and not as a runtime value, it
should be changed to a type-only import using the `import type` syntax. Update
the import statement to use `import type` to follow the TypeScript coding
guidelines and avoid unnecessary runtime imports.

In `@frontend/src/routes/Governance/common/util.tsx`:
- Line 4: The TFunction import from react-i18next is currently using regular
import syntax but should use import type syntax since it is only used for type
annotations in function signatures and not as a runtime value. Change the import
statement for TFunction to use the type keyword before the curly braces to
indicate this is a type-only import from react-i18next. This optimization helps
with tree-shaking and makes the codebase alignment with TypeScript best
practices.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 1d4b889e-32cc-42b5-b74e-1f3927ba2e71

📥 Commits

Reviewing files that changed from the base of the PR and between 5e9c664 and b2b506b.

⛔ Files ignored due to path filters (3)
  • frontend/package-lock.json is excluded by !**/package-lock.json
  • frontend/public/locales/en/translation.json is excluded by !frontend/public/locales/**
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (29)
  • frontend/AGENTS.md
  • frontend/packages/eslint-config/index.mjs
  • frontend/packages/eslint-config/package.json
  • frontend/packages/react-form-wizard/eslint.config.mjs
  • frontend/packages/react-form-wizard/src/contexts/StringContext.tsx
  • frontend/packages/react-form-wizard/src/inputs/WizItemSelector.tsx
  • frontend/src/App.tsx
  • frontend/src/lib/SimpleTimestamp.tsx
  • frontend/src/lib/wizardStrings.ts
  • frontend/src/routes/Applications/Overview.tsx
  • frontend/src/routes/Applications/components/DeleteResourceModal.tsx
  • frontend/src/routes/Governance/common/util.tsx
  • frontend/src/routes/Governance/discovered/DiscoveredPolicies.tsx
  • frontend/src/routes/Governance/discovered/details/DiscoveredPolicyDetailsPage.tsx
  • frontend/src/routes/Governance/policies/policy-details/PolicyTemplateDetail/PolicyTemplateDetails.tsx
  • frontend/src/routes/Infrastructure/Clusters/ManagedClusters/components/LoginCredentials.tsx
  • frontend/src/routes/Infrastructure/InfraEnvironments/InfraEnvironmentsPage.tsx
  • frontend/src/routes/Search/Details/DetailsPage.tsx
  • frontend/src/routes/Search/components/Modals/SearchInfoModal.tsx
  • frontend/src/routes/UserManagement/Identities/ServiceAccounts/ServiceAccountDetail.tsx
  • frontend/src/routes/UserManagement/Identities/ServiceAccounts/ServiceAccountGroups.tsx
  • frontend/src/routes/UserManagement/Identities/ServiceAccounts/ServiceAccountRoleAssignments.tsx
  • frontend/src/routes/UserManagement/Identities/ServiceAccounts/ServiceAccountYaml.tsx
  • frontend/src/routes/UserManagement/Identities/ServiceAccounts/ServiceAccounts.tsx
  • frontend/src/ui-components/AcmErrorBoundary/AcmErrorBoundary.tsx
  • frontend/src/ui-components/IdentityStatus/IdentityStatus.tsx
  • frontend/src/wizards/Governance/Policy/PolicyWizard.tsx
  • frontend/src/wizards/RoleAssignment/ReviewStepContent.tsx
  • package.json

Comment thread frontend/packages/eslint-config/index.mjs Outdated
Generated-by: Cursor (Claude Opus 4.6 High)
Signed-off-by: Kevin Cormier <kcormier@redhat.com>
@KevinFCormier KevinFCormier force-pushed the enable-i18next-linting branch from 7aa2c9f to e7c5e63 Compare June 17, 2026 18:49
@KevinFCormier

Copy link
Copy Markdown
Contributor Author

/test unit-tests-sonarcloud

@sonarqubecloud

Copy link
Copy Markdown

@openshift-ci

openshift-ci Bot commented Jun 17, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: fxiang1, KevinFCormier

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:
  • OWNERS [KevinFCormier,fxiang1]

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-merge-bot openshift-merge-bot Bot merged commit 5de84a7 into stolostron:main Jun 17, 2026
17 checks passed
@KevinFCormier KevinFCormier deleted the enable-i18next-linting branch June 18, 2026 13:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants