feat(app): extract the user slice into i18n, en+ru (CLEAN-37) - #31
Merged
maksymhryzodub-prog merged 2 commits intoAug 19, 2026
Merged
Conversation
maksymhryzodub-prog
added a commit
that referenced
this pull request
Aug 19, 2026
…N-37) The i18n work lands as a stack: each subtask branches off the previous one and the whole chain merges bottom-up at the end. With `pull_request: branches: [main]` none of those PRs triggers CI — #31 has zero workflow runs — so the first real check would happen at the final merge, on four slices at once. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This was referenced Aug 19, 2026
The auth screens were fully hardcoded and the slice had no i18n block at
all. Adds one (registering the shared LOCALES) plus en/ru locale files,
and moves all 39 strings out of the templates: the form, the marketing
panel on the auth layout, and the closed-registration state.
Applies the "script holds keys, not text" rule from the ADR, which this
slice is the reason for. Field validation now assigns
'account.email_invalid' rather than "Enter a valid email"; the
state-dependent title, subtitle and submit label became *Key computeds
rendered with $t. Both providers lose their hardcoded English failure
fallback — the form owns that copy and picks the key by mode, so a
provider now reports only whether the call failed and what the server
said. useI18n() is not used anywhere in the slice.
Adds a guard to i18n-sync for the bug this uncovered: "jane@example.com"
compiles to a linked-message reference in vue-i18n and fails the build.
The escaped literal {'@'} is now required, i18n:check reports a bare @
or | on either side, the translator prompt states the rule, and a reply
that breaks it is rejected before it reaches disk. Worth catching there
because CI runs typecheck/lint/test and this script — not nuxt build —
so a broken message would otherwise surface in production.
Verified: nuxt typecheck and nuxt build clean, ru strings in the client
chunks, i18n:check green over 5 slice/locale pairs, and a re-scan finds
zero hardcoded strings left in the slice.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…N-37) The i18n work lands as a stack: each subtask branches off the previous one and the whole chain merges bottom-up at the end. With `pull_request: branches: [main]` none of those PRs triggers CI — #31 has zero workflow runs — so the first real check would happen at the final merge, on four slices at once. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
maksymhryzodub-prog
force-pushed
the
feat/CLEAN-37-i18n-user-slice
branch
from
August 19, 2026 21:07
d07a1d3 to
1ced349
Compare
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.
Implements CLEAN-37 (subtask of CLEAN-33): https://dreamvention.atlassian.net/browse/CLEAN-37
Stacked on #30 — targets
feat/CLEAN-33-i18n-strategy, since theLOCALESconstant, the sync script and the CI check all live there. GitHub retargets this tomainonce #30 merges.The auth screens were fully hardcoded and the slice had no
i18nblock at all. This adds one, plusen/rufiles, and moves all 39 strings out: the form, the marketing panel on the auth layout, and the closed-registration state. A re-scan finds zero hardcoded strings left in the slice.The interesting part: copy that lives in script
This slice is the reason the ADR has the "script holds keys, not text" rule, and it exercises every shape of it:
errors.email = 'account.email_invalid'instead of"Enter a valid email"; the template renders{{ $t(errors.email!) }}.titleKey,subtitleKey,submitLabelKeyare computeds returning keys ("Welcome back" vs "Create your account", "Signing in…" vs "Sign in").failed) and what the server said (errorMessage, English by design per the ADR); the form owns the fallback wording and picks the key by mode.useI18n()appears nowhere in the slice — templates use the injected$t.app_nameis reused from thecommonslice rather than redefined: vue-i18n merges slice messages into one global scope, so brand tokens don't need duplicating.Bug this uncovered
"jane@example.com"breaks the production build. vue-i18n reads a bare@as a linked-message reference, so the message compiler fails — and CI would not have caught it, because CI runs typecheck / lint / test /i18n:check, notnuxt build.Fixed on four fronts:
jane{'@'}example.com;i18n:checkreports a bare@or|on either side (en or ru) — so CI catches it from now on;Verification
nuxt typecheckandnuxt buildclean; the Russian auth strings appear in the built client chunks.i18n:checkgreen across 5 slice/locale pairs, and it was seen failing on the unescaped@before the fix.bun run i18n:sync(40 keys), including localized example data — the name and email placeholders becomeИван Иванов/ivan{'@'}example.com.🤖 Generated with Claude Code