feat: lazy per-locale loading, frozen-lock check command, locale persistence - #4
Merged
Merged
Conversation
…istence - virtual:solid-translate/lazy + virtual:solid-translate/locale/<locale> virtual modules: each locale dictionary becomes its own code-split chunk via dynamic import; the eager virtual:solid-translate module is unchanged - TranslationProvider accepts either the eager translations record or the lazy manifest; lazy dictionaries load asynchronously with graceful source-language fallback (never throws, never suspends) and are cached - persistLocale prop (default off) persists the active locale to localStorage with SSR/no-storage guards - solid-translate check: zero-AI CI freshness primitive comparing extracted keys+hashes+contexts against .solid-translate.lock and verifying every target locale file contains every key; --json for machine output; exit 0 fresh / 1 stale - action.yml: command: check with stale output and fail-on-stale input - ship virtual.d.ts via solid-translate/virtual so consumers stop hand-writing virtual module declarations - defer the ai import in the CLI so ai-free commands (extract, check) run without the ai package installed - fix doubled shebang in dist/cli.js that made the built CLI fail on Node Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Peyton-Spencer
force-pushed
the
feat/lazy-locales-check
branch
from
July 19, 2026 20:06
a989d69 to
4a2c4c9
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 per-locale lazy loading, a zero-AI CI freshness gate, locale persistence, and shipped virtual-module types.
What's new
Lazy per-locale virtual modules (
src/vite.ts)virtual:solid-translateis unchanged (eager, back-compat).virtual:solid-translate/locale/<locale>— one module per locale exporting that locale's dict as default. Each becomes its own chunk via dynamic import (locale ids validated against[A-Za-z0-9_-]+so no path traversal).virtual:solid-translate/lazy— exports the manifest:Runtime: lazy-aware
TranslationProvider(src/index.ts,src/context.ts)translationsaccepts the eagerRecord<locale, dict>or the lazy manifest (TranslationsInput).setLocale; while pending (or on loader failure)t()/<T>return source text — never throw, never suspend. Loaded dicts are cached; loaders run once per locale.availableLocales()derives frommanifest.locales;sourceLocaledefaults from the manifest.Locale persistence
persistLocale?: boolean | { key?: string }(default false). Initial locale = validlocalStoragevalue, else auto-detect;setLocalewrites through. Explicitlocaleprop always wins. All storage access guarded for SSR/no-localStorage.solid-translate check— CI freshness primitive (src/cli.ts)aipackage needed (theaiimport is now deferred into the translate path).contexthints against.solid-translate.lock, and verifies every target locale file contains every key.--jsonfor machine-readable output.GitHub Action (
action.yml)command: checksupported; newstaleoutput ("true"/"false"); newfail-on-staleinput (default"true") — stale check fails the step unless softened. Exit codes >1 (crashes) always fail.check, and translate-on-main + PR viapeter-evans/create-pull-request.Shipped virtual-module types
virtual.d.tspublished viasolid-translate/virtual(exports+files): declares all three virtual specifiers. Consumers use/// <reference types="solid-translate/virtual" />or a tsconfigtypesentry instead of hand-writing declarations.Bug fix (pre-existing, blocking)
src/cli.tshad its own shebang and tsup's banner adds one, sodist/cli.jsshipped with a doubled shebang and failed under Node for every command. Removed the source shebang (the banner provides it) — required forcheckto actually run in CI vianpx.Tests
bun test: 67 pass, 0 fail (was 44) — new suites:tests/check.test.ts— fixture projects in temp dirs: fresh lock → exit 0; edited source string / new string / deleted string / changed context / missing target key / missing target file → exit 1 with the right report buckets.tests/lazy-provider.test.ts— source renders immediately; locale switch falls back to source while pending then swaps after the loader resolves; caching; loader rejection never throws; eager mode unchanged.tests/persist-locale.test.ts— default-off, valid/invalid persisted values, write-through, custom key, explicit-prop precedence.tests/vite-virtual.test.ts— eager/lazy/per-locale module generation, missing-file empty dict, path-unsafe locale rejection.bun run buildandbunx tsc --noEmitare clean. Deliberately avoids refactoring the translate/lock-write logic andextract.tsinternals (two PRs in flight there).🤖 Generated with Claude Code