Enforce lazy translations: add no-module-level-translations ESLint rule - #3688
Closed
sejas wants to merge 7 commits into
Closed
Enforce lazy translations: add no-module-level-translations ESLint rule#3688sejas wants to merge 7 commits into
sejas wants to merge 7 commits into
Conversation
Translations evaluated at module load are captured before the locale loads and never update when the language changes at runtime in the renderer. Add the studio/no-module-level-translations rule (off for the one-shot CLI), document the convention in AGENTS.md, wire the plugin tests into vitest, and make all flagged translations lazy. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Allow discarded translation statements (e.g. `__( 'Next' );`) that exist only to feed the translation extractor, removing the need for an inline eslint-disable in additional-phrases.ts. Drop the unused configurable `functions` option. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The pre-push hook lints changed files individually; the eslint-plugin-studio sources/tests and the vitest config files are not part of any tsconfig, so the typescript-eslint project service reported parsing errors. Add them to allowDefaultProject so they lint cleanly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nt-translate-constants
Member
Author
|
I think the direction is good. I'll create a fresh PR to cover new code and avoid resolving conflicts. |
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Related issues
How AI was used in this PR
AI assistance was used to author the new ESLint rule and to apply the repetitive "wrap the translation in a lazy getter" refactor across the affected files. Every change was reviewed by hand and verified with
npm run lint,npm run typecheck, andnpm test(1961 tests passing).Proposed Changes
Translatable strings are sometimes evaluated at module-load time (e.g.
const LABEL = __( 'Label' )). In the long-lived desktop renderer the user can change the app language at runtime, but a string captured at import time stays frozen in the language that was active when the module first loaded — so parts of the UI silently fail to translate after a language switch.This adds a lint rule that catches the mistake at author time and makes the existing offenders lazy so they react to language changes:
studio/no-module-level-translationsESLint rule flags__(),_x(),_n(), and_nx()calls that run at module scope. It allows translations that are wrapped in a function (evaluated at render/call time) and ignores bare discarded statements used only to feed the translation extractor. The one-shot CLI loads its locale before importing modules, so the rule is turned off forapps/cli.AGENTS.md.tools/commonhelpers, etc.), so they now follow the active language after a runtime switch.No user-visible text changes; the user-facing effect is that affected labels now translate correctly when the language is changed without a restart.
Testing Instructions
npm run lint— passes; try addingconst X = __( 'Test' )at module scope in a renderer file and confirm the rule reports it, then wrap it asconst getX = () => __( 'Test' )and confirm it passes.npm run typecheck— passes.npm test— passes (includes the rule's unit tests undertools/eslint-plugin-studio).Pre-merge Checklist