fix(intl-pipeline): manifest paths, LLM adapter, P1 follow-ups#17982
Merged
Conversation
Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
Move manifests from inline with content to dedicated
.manifests/ directory. Structure:
.manifests/{dest-path}/source.json | translation.json
Fixes multi-JSON-namespace collision where one shared
manifest per locale dir lost data. Each file now gets
its own manifest pair. MANIFESTS_DIR in constants.ts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
Rename english/ to english-a/ and english-b/. Rename fixture-a/b to fixture-1 across all dirs. Prepares for fixture-2 (second JSON namespace). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
Second JSON namespace (4 keys, no mutations between english-a and english-b). Tests no-drift detection and manifest path isolation for multiple JSON files. 811 tests passing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
getManifestPath returns relative path (no process.cwd). Absolute path used only for local fs reads. GitHub tree API rejects paths starting with /. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
Define LlmAdapter interface in lib/llm/adapters.ts with models, name, coAuthor, isAvailable. Active adapter selected in constants.ts. Removes hardcoded Gemini references from main.ts, config.ts, commits. Commit messages: i18n(lang): LLM translation with Co-Authored-By from adapter. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
- Validate TARGET_PATH before filesystem reads - Wire AbortController signal to Gemini SDK call - stamp-only tasks now trigger squash/merge/PR - Sanitize all glossary fields (english, translation, note) against prompt injection Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
✅ Deploy Preview for ethereumorg ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
pettinarip
approved these changes
Apr 17, 2026
Member
pettinarip
left a comment
There was a problem hiding this comment.
@myelinated-wackerow LGTM.
| test("manifest paths are distinct for different JSON files in same locale", () => { | ||
| // Import the helper indirectly by testing the path pattern | ||
| const path1 = `.manifests/src/intl/ko/fixture-1.json/source.json` | ||
| const path2 = `.manifests/src/intl/ko/fixture-2.json/source.json` |
Member
There was a problem hiding this comment.
this test is always true. Probably we want to load the content?
<span dir="ltr"> tags embedded in JSON values break next-intl's t() function: the tags render literally on screen because ICU MessageFormat treats them as rich markup that only t.rich() understands. JSON values must use plain-text BiDi isolation. Changes: - Per-file-type RTL prompt rules in getSiteSpecificNotes(): markdown keeps <span dir="ltr"> convention, JSON uses raw Unicode U+2066 (LRI) / U+2069 (PDI) with explicit anti-span directive. - Thread fileType through buildIncrementalPrompt so incremental JSON translations get the JSON rule (main.ts caller updated). - New sanitizer convertSpansToJsonBidi() safety net in processJsonFile: catches legacy spans (raw, JSON-escaped, or single-quoted dir attribute) and converts to raw bidi chars. - Move "state" polysemy rule from RTL-only section to common site notes (affects 8+ non-Latin locales, not just ar/ur). Tests: 10 new (7 sanitizer + 3 prompt), 841/841 passing. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
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.

Summary
Follow-up to #17963. Fixes manifest path collisions for multiple JSON namespaces, introduces LLM adapter abstraction, reorganizes test fixtures, and addresses remaining P1 review findings.
Manifest paths:
.manifests/directory.manifests/{dest-file-path}/source.json | translation.jsonMANIFESTS_DIRconstant inconstants.ts, excluded from Next.js bundle viaoutputFileTracingExcludesLLM adapter abstraction:
LlmAdapterinterface inlib/llm/adapters.ts(models, name, coAuthor, isAvailable)constants.ts-- swap LLM providers by changing one linei18n(lang): LLM translationwithCo-Authored-Byfrom adapterP1 follow-up fixes (from #17963 (review)):
TARGET_PATHbefore any filesystem reads (path traversal)AbortControllersignal to Gemini SDK calls (timeout was no-op)note)Test fixtures:
fixture-a->fixture-1,english/->english-a/+english-b/fixture-2.json(second JSON namespace, no drift between A and B)Test plan
.manifests/paths with separate files per JSON namespaceGenerated with Claude Code