Add docs i18n support#50
Conversation
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughSummary by CodeRabbit
WalkthroughAdds a leadtype i18n helper module, publishes it via package exports/build, and threads normalized i18n through docs source selection, search indexing, LLM/readability artifact generation, and the CLI to produce per-locale outputs plus an i18n-manifest; includes tests and a changeset. ChangesMulti-Language Documentation Support
Sequence DiagramsequenceDiagram
participant Config as docs.config.ts
participant Generate as runGenerateCommand
participant I18n as normalizeDocsI18nConfig
participant Source as createDocsSource/readSourceDocs
participant Manifest as buildI18nManifest
participant Search as generateDocsSearchFiles
participant LLM as generateLlmsTxt/generateLLMFullContextFiles
Config->>Generate: provide i18n config (defaultLocale, locales)
Generate->>I18n: normalize & validate i18n config
I18n->>Generate: return NormalizedDocsI18nConfig
Generate->>Source: create source with i18n for default locale
Source->>Source: select localized pages per logical path
Generate->>Manifest: build i18n-manifest with artifact URLs/paths
Manifest->>Generate: write docs/i18n-manifest.json
loop for each non-default locale
Generate->>Source: create source with locale (use fallback rules)
Generate->>Search: generate search index for locale
Generate->>LLM: generate locale-scoped llms.txt and llms-full.txt
end
Generate->>Generate: return GenerateResult with i18nManifest path
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add Comment |
d4e377c to
2dfb231
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2dfb231d72
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (!normalized || locale === normalized.defaultLocale) { | ||
| return logicalPath.replace(MARKDOWN_EXTENSION_PATTERN, ""); | ||
| } | ||
| return `${locale}/${logicalPath.replace(MARKDOWN_EXTENSION_PATTERN, "")}`; |
There was a problem hiding this comment.
Preserve mount prefixes in localized output paths
When i18n is combined with mounted docs sources, this prepends the locale before the logical path, so a mounted source like --docs-dir api=/reference with api/zh/intro.mdx is represented as zh/api/intro instead of api/zh/intro. The CLI copies mounted sources under the mount path before conversion (copySourceFiles writes source.mountPath first), and later link rendering resolves mounts from the start of relativePath, so localized mounted pages produce links such as /docs/zh/api/intro.md that do not match the actual mirrored /reference/zh/intro.md output.
Useful? React with 👍 / 👎.
| const pathnameSegments = splitUrlPath(pathname); | ||
| const afterPrefix = pathnameSegments.slice(prefixSegments.length); | ||
| const first = afterPrefix[0]; | ||
| const matched = normalized.locales.find((locale) => locale.code === first); |
There was a problem hiding this comment.
Verify the docs prefix before resolving locale
For callers that pass site-wide pathnames into this helper, paths outside docsUrlPrefix can be misclassified because the code slices off prefixSegments.length without first checking that the pathname actually starts with those prefix segments. For example, with docsUrlPrefix = "/docs", /blog/fr/post returns fr when fr is configured, which can make non-doc routes look like localized docs routes.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Important
Root bun.lock is out of sync with package.json for the leadtype workspace devDep — CI on bun install --frozen-lockfile will fail. Also flagging a user-visible change to the search-index.json document id shape.
TL;DR — Adds optional i18n support to the docs pipeline: new leadtype/i18n subpackage with locale config + URL helpers, locale metadata threaded through source/search/LLM/agent-readability artifacts, and locale-scoped output paths under /docs/<locale>/... plus a top-level i18n-manifest.json. Monolingual projects are unaffected when i18n is absent.
Key changes
- New
leadtype/i18nsubpackage — Locale config normalization, locale-aware URL helpers, alternate-link helpers, and theDocsI18nManifesttype. Re-exported fromleadtyperoot andleadtype/llm. - Locale-scoped artifact generation in
generate—cli/generate.tsruns the LLM/search/readability generators once per locale; default-locale outputs stay at root paths, non-default land under/docs/<locale>/.... Writesdocs/i18n-manifest.json. - Localized source/markdown selection —
selectLocalizedFiles(inllm/llm.tsandsearch/node.ts) andselectSourceFiles(insource/index.ts) key by logical path and pick the requested locale with optional default-locale fallback. - Schema bumps for downstream consumers —
AgentReadabilityManifestgainslocaleandi18n.DocsSearchDocumentEntrygains 4 trailing optional fields.DocsSearchDocument.idinsearch/node.tsnow usesurlPathinstead ofstripDocsExtension(relativePath). - Ambiguity guard — Having both root
docs/*.mdxanddocs/<defaultLocale>/*.mdxthrows "Ambiguous i18n default-locale layout" in source reads and post-conversion.
Summary | 18 files | 1 commit | base: main ← i18n-docs-support
Lockfile mismatch on root leadtype devDep
Before:
bun.lockandpackage.jsonagreed onleadtype: workspace:*.
After:package.jsonstill saysworkspace:*butbun.locksays^0.1.2.
The workspace package itself bumped to 0.1.2, but the root devDep spec only moved positions in package.json — it still resolves through the workspace. The lockfile entry should still mirror that. bun install --frozen-lockfile (typical CI) will reject this; a plain bun install rewrites it.
Search index document id shape change
Before:
id: stripDocsExtension(relativePath)→ e.g.quickstart.
After:id: urlPath→ e.g./docs/quickstart.
This affects every project, not just i18n consumers. It does bring generateDocsSearchFiles in line with createDocsSource (which has always used meta.urlPath as the id), so the change is a normalization rather than a regression — but consumers reading search-index.json will see the document id and chunk documentId formats change. Worth a changelog callout.
packages/leadtype/src/search/node.ts
Ambiguity-check ordering across read paths
Before:
readSourceDocsasserts unambiguous layout before selecting files; the path didn't exist forreadMarkdownDocs.
After:readMarkdownDocsperformsselectLocalizedFilesfirst, then runsassertUnambiguousDefaultLocaleLayoutafter.
Not a correctness bug — both branches still throw the expected error — but the inverted order in readMarkdownDocs (vs readSourceDocs) means the assertion runs after extra work that may be discarded. Worth aligning so a future reader doesn't infer a different invariant.
packages/leadtype/src/llm/llm.ts
Claude Opus | 𝕏
| "@vitest/coverage-v8": "4.1.5", | ||
| "husky": "^9.1.7", | ||
| "leadtype": "workspace:*", | ||
| "leadtype": "^0.1.2", |
There was a problem hiding this comment.
This entry says "leadtype": "^0.1.2" but the matching package.json devDep is "leadtype": "workspace:*". The lockfile should mirror the manifest spec — bun install --frozen-lockfile (the typical CI setting) will fail here, and a plain bun install will silently overwrite this back to workspace:*. Re-run bun install locally and commit the regenerated lockfile.
| : toDocsUrlPath(relativePath, mounts); | ||
| docs.push({ | ||
| id: stripDocsExtension(relativePath), | ||
| id: urlPath, |
There was a problem hiding this comment.
id switched from stripDocsExtension(relativePath) to urlPath, which changes the document id and chunk documentId shape in search-index.json for every project (not just i18n ones). It does match what createDocsSource already emits, so this is a deliberate normalization — but please call it out in the changelog since downstream consumers reading the index may pin to the old quickstart-style ids.
| localeCodes, | ||
| localeRead.i18n.defaultLocale | ||
| ); | ||
| } |
There was a problem hiding this comment.
readSourceDocs runs assertUnambiguousDefaultLocaleLayout before selectLocalizedFiles (lines 708-714), but here the assertion runs after selection. Both still throw correctly, but moving this check up keeps the invariant consistent across the two read paths and avoids doing selection work that will be discarded on the error path.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
packages/leadtype/src/source/index.ts (1)
332-332:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUseless conditional:
includeFallbackis always true.The
includeFallbackparameter (line 261) defaults totrueand is never reassigned. RemoveincludeFallback &&from the condition.Simplified condition
const fallback = - includeFallback && outputLocale !== normalized.defaultLocale + outputLocale !== normalized.defaultLocale ? localeFiles.get(normalized.defaultLocale) : undefined;🤖 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 `@packages/leadtype/src/source/index.ts` at line 332, The conditional currently checks "includeFallback && outputLocale !== normalized.defaultLocale" but includeFallback defaults to true and is never changed; remove the redundant "includeFallback &&" so the condition becomes just "outputLocale !== normalized.defaultLocale" (update the condition where it appears in the code referencing includeFallback, outputLocale, and normalized.defaultLocale).
🤖 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 `@packages/leadtype/src/i18n/index.ts`:
- Around line 170-175: The code slices pathnameSegments by prefixSegments length
without checking that pathname actually starts with docsUrlPrefix, so locales
can be resolved on non-docs URLs; update the logic in the function using
splitUrlPath, docsUrlPrefix, pathname, prefixSegments, pathnameSegments and
afterPrefix to first verify that pathnameSegments begins with prefixSegments
(e.g., compare each segment or check a starts-with condition) before computing
afterPrefix and reading first; if the pathname does not start with the docs
prefix, return normalized.defaultLocale immediately, otherwise proceed to find a
matching locale from normalized.locales by comparing locale.code and return
matched?.code ?? normalized.defaultLocale.
In `@packages/leadtype/src/llm/llm.ts`:
- Around line 839-845: Move the call to assertUnambiguousDefaultLocaleLayout so
it runs before selectLocalizedFiles to match readSourceDocs' ordering;
specifically, call assertUnambiguousDefaultLocaleLayout(relativePaths,
localeCodes, localeRead.i18n.defaultLocale) right after confirming
localeRead.i18n && localeRead.locale and before invoking selectLocalizedFiles,
so the assertion can fail fast and avoid doing work in selectLocalizedFiles.
---
Duplicate comments:
In `@packages/leadtype/src/source/index.ts`:
- Line 332: The conditional currently checks "includeFallback && outputLocale
!== normalized.defaultLocale" but includeFallback defaults to true and is never
changed; remove the redundant "includeFallback &&" so the condition becomes just
"outputLocale !== normalized.defaultLocale" (update the condition where it
appears in the code referencing includeFallback, outputLocale, and
normalized.defaultLocale).
🪄 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: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 861b3749-0409-4544-a748-621f8bfcdc2c
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (17)
package.jsonpackages/leadtype/package.jsonpackages/leadtype/rollup.config.tspackages/leadtype/src/cli.test.tspackages/leadtype/src/cli/generate.tspackages/leadtype/src/i18n/i18n.test.tspackages/leadtype/src/i18n/index.tspackages/leadtype/src/index.tspackages/leadtype/src/internal/package-surface.test.tspackages/leadtype/src/llm/index.tspackages/leadtype/src/llm/llm.test.tspackages/leadtype/src/llm/llm.tspackages/leadtype/src/llm/readability.tspackages/leadtype/src/search/node.tspackages/leadtype/src/search/search.tspackages/leadtype/src/source/index.tspackages/leadtype/src/source/source.test.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use explicit types for function parameters and return values when they enhance clarity
Preferunknownoveranywhen the type is genuinely unknown
Use const assertions (as const) for immutable values and literal types
Leverage TypeScript's type narrowing instead of type assertions
Files:
packages/leadtype/rollup.config.tspackages/leadtype/src/i18n/i18n.test.tspackages/leadtype/src/llm/index.tspackages/leadtype/src/internal/package-surface.test.tspackages/leadtype/src/index.tspackages/leadtype/src/llm/llm.test.tspackages/leadtype/src/source/source.test.tspackages/leadtype/src/search/search.tspackages/leadtype/src/cli.test.tspackages/leadtype/src/source/index.tspackages/leadtype/src/search/node.tspackages/leadtype/src/cli/generate.tspackages/leadtype/src/llm/readability.tspackages/leadtype/src/i18n/index.tspackages/leadtype/src/llm/llm.ts
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{js,ts,jsx,tsx}: Use meaningful variable names instead of magic numbers - extract constants with descriptive names
Use arrow functions for callbacks and short functions
Preferfor...ofloops over.forEach()and indexedforloops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Useconstby default,letonly when reassignment is needed, nevervar
Alwaysawaitpromises in async functions - don't forget to use the return value
Useasync/awaitsyntax instead of promise chains for better readability
Handle errors appropriately in async code with try-catch blocks
Don't use async functions as Promise executors
Removeconsole.log,debugger, andalertstatements from production code
ThrowErrorobjects with descriptive messages, not strings or other values
Usetry-catchblocks meaningfully - don't catch errors just to rethrow them
Prefer early returns over nested conditionals for error cases
Extract complex conditions into well-named boolean variables
Use early returns to reduce nesting
Prefer simple conditionals over nested ternary operators
Don't useeval()or assign directly todocument.cookie
Avoid spread syntax in accumulators within loops
Use top-level regex literals instead of creating them in loops
Prefer specific imports over namespace imports
Use descriptive names for functions, variables, and types for meaningful naming
Add comments for complex logic, but prefer self-documenting code
Files:
packages/leadtype/rollup.config.tspackages/leadtype/src/i18n/i18n.test.tspackages/leadtype/src/llm/index.tspackages/leadtype/src/internal/package-surface.test.tspackages/leadtype/src/index.tspackages/leadtype/src/llm/llm.test.tspackages/leadtype/src/source/source.test.tspackages/leadtype/src/search/search.tspackages/leadtype/src/cli.test.tspackages/leadtype/src/source/index.tspackages/leadtype/src/search/node.tspackages/leadtype/src/cli/generate.tspackages/leadtype/src/llm/readability.tspackages/leadtype/src/i18n/index.tspackages/leadtype/src/llm/llm.ts
**/*.{test,spec}.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{test,spec}.{js,ts,jsx,tsx}: Write assertions insideit()ortest()blocks
Avoid done callbacks in async tests - use async/await instead
Don't use.onlyor.skipin committed code
Keep test suites reasonably flat - avoid excessivedescribenesting
Files:
packages/leadtype/src/i18n/i18n.test.tspackages/leadtype/src/internal/package-surface.test.tspackages/leadtype/src/llm/llm.test.tspackages/leadtype/src/source/source.test.tspackages/leadtype/src/cli.test.ts
**/index.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Avoid barrel files (index files that re-export everything)
Files:
packages/leadtype/src/llm/index.tspackages/leadtype/src/index.tspackages/leadtype/src/source/index.tspackages/leadtype/src/i18n/index.ts
🔇 Additional comments (35)
package.json (1)
8-10: LGTM!packages/leadtype/rollup.config.ts (1)
10-10: LGTM!packages/leadtype/src/i18n/index.ts (1)
1-169: LGTM!Also applies to: 176-311
packages/leadtype/src/index.ts (1)
12-26: LGTM!packages/leadtype/package.json (1)
36-39: LGTM!packages/leadtype/src/internal/package-surface.test.ts (1)
13-13: LGTM!packages/leadtype/src/i18n/i18n.test.ts (1)
1-173: LGTM!packages/leadtype/src/llm/readability.ts (1)
9-9: LGTM!Also applies to: 57-57, 84-84, 107-107, 115-116
packages/leadtype/src/llm/index.ts (1)
3-16: LGTM!packages/leadtype/src/llm/llm.test.ts (2)
209-248: LGTM!
346-385: LGTM!packages/leadtype/src/source/source.test.ts (1)
274-319: LGTM!packages/leadtype/src/cli.test.ts (1)
330-419: LGTM!packages/leadtype/src/cli/generate.ts (4)
717-727: LGTM!
729-764: LGTM!
766-807: LGTM!
937-1077: LGTM!packages/leadtype/src/source/index.ts (2)
199-244: LGTM!Also applies to: 469-474
504-523: LGTM!packages/leadtype/src/search/node.ts (2)
97-209: LGTM!
276-351: LGTM!packages/leadtype/src/search/search.ts (3)
1-1: LGTM!Also applies to: 107-154, 210-210
750-770: LGTM!
808-869: LGTM!packages/leadtype/src/llm/llm.ts (11)
11-20: LGTM!Also applies to: 77-91, 147-158, 168-179, 181-201, 213-229, 231-238
569-683: LGTM!
685-800: LGTM!
1119-1160: LGTM!
1166-1209: LGTM!
1211-1259: LGTM!
1267-1345: LGTM!
1347-1408: LGTM!
1486-1519: LGTM!
1527-1569: LGTM!
1571-1598: LGTM!
There was a problem hiding this comment.
No new issues. Reviewed the following changes:
- Removed the duplicate
leadtype: ^0.1.2entry frombun.lockso the workspace devDep again matchespackage.json'sworkspace:*spec. - Moved
assertUnambiguousDefaultLocaleLayoutahead ofselectLocalizedFilesinreadMarkdownDocs, matching the ordering inreadSourceDocs. - Called out the search-index document
idshape change (stripDocsExtension(relativePath)→urlPath) in the changeset. - Guarded
resolveDocsLocaleso paths outside the docs URL prefix returnundefinedinstead of mis-resolving a locale, with a test for/blog/zh/quickstart. - Dropped the always-true
includeFallbackparameter fromselectSourceFilesand simplified the fallback condition.
Claude Opus | 𝕏
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 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 `@packages/leadtype/src/llm/llm.ts`:
- Around line 644-649: The current logic lets a later file overwrite an earlier
localized entry because you call localeFiles.set(resolvedSourceLocale, ...)
unconditionally; instead, before calling localeFiles.set(...) check whether
localeFiles already has(resolvedSourceLocale) for the same logicalPath and
reject/throw (or otherwise surface an error) when a duplicate is detected;
update the code surrounding byLogicalPath.get(logicalPath), localeFiles, and the
localeFiles.set(...) call to perform this guard using resolvedSourceLocale and
filePath so duplicates are rejected rather than silently winning.
In `@packages/leadtype/src/source/index.ts`:
- Around line 215-217: The slug is being derived from selected.logicalPath which
omits the locale; instead derive locale-prefixed slugs by passing the route that
includes the locale (e.g. urlPath or the localized relative path) into
deriveSlug so the slug matches the localized url; update the deriveSlug call(s)
(currently using selected.logicalPath + path.extname(relativePath)) to use the
locale-aware path (urlPath or relativePath that includes the /docs/<locale>/
segment) and apply the same change for the other occurrence referenced (lines
229-231) so listPages() returns locale-prefixed page.slug values.
- Around line 309-324: The code currently overwrites entries in byLogicalPath
when multiple files map to the same logicalPath and resolvedSourceLocale (e.g.,
.md and .mdx or duplicate locale files), losing the earlier file; update the
block that builds localeFiles (the Map assigned to localeFiles and set via
byLogicalPath.set) to detect an existing entry for the same resolvedSourceLocale
and throw or surface an error instead of calling localeFiles.set silently; use
the existing symbols resolvedSourceLocale, logicalPath, localeFiles, filePath
and outputRelativePathForLocale to produce a clear error message that includes
the conflicting file paths and the locale so duplicates are rejected early.
🪄 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: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: c7bb868a-321d-4597-9704-ffc8f854baef
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (5)
.changeset/i18n-docs-support.mdpackages/leadtype/src/i18n/i18n.test.tspackages/leadtype/src/i18n/index.tspackages/leadtype/src/llm/llm.tspackages/leadtype/src/source/index.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use explicit types for function parameters and return values when they enhance clarity
Preferunknownoveranywhen the type is genuinely unknown
Use const assertions (as const) for immutable values and literal types
Leverage TypeScript's type narrowing instead of type assertions
Files:
packages/leadtype/src/i18n/i18n.test.tspackages/leadtype/src/source/index.tspackages/leadtype/src/i18n/index.tspackages/leadtype/src/llm/llm.ts
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{js,ts,jsx,tsx}: Use meaningful variable names instead of magic numbers - extract constants with descriptive names
Use arrow functions for callbacks and short functions
Preferfor...ofloops over.forEach()and indexedforloops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Useconstby default,letonly when reassignment is needed, nevervar
Alwaysawaitpromises in async functions - don't forget to use the return value
Useasync/awaitsyntax instead of promise chains for better readability
Handle errors appropriately in async code with try-catch blocks
Don't use async functions as Promise executors
Removeconsole.log,debugger, andalertstatements from production code
ThrowErrorobjects with descriptive messages, not strings or other values
Usetry-catchblocks meaningfully - don't catch errors just to rethrow them
Prefer early returns over nested conditionals for error cases
Extract complex conditions into well-named boolean variables
Use early returns to reduce nesting
Prefer simple conditionals over nested ternary operators
Don't useeval()or assign directly todocument.cookie
Avoid spread syntax in accumulators within loops
Use top-level regex literals instead of creating them in loops
Prefer specific imports over namespace imports
Use descriptive names for functions, variables, and types for meaningful naming
Add comments for complex logic, but prefer self-documenting code
Files:
packages/leadtype/src/i18n/i18n.test.tspackages/leadtype/src/source/index.tspackages/leadtype/src/i18n/index.tspackages/leadtype/src/llm/llm.ts
**/*.{test,spec}.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{test,spec}.{js,ts,jsx,tsx}: Write assertions insideit()ortest()blocks
Avoid done callbacks in async tests - use async/await instead
Don't use.onlyor.skipin committed code
Keep test suites reasonably flat - avoid excessivedescribenesting
Files:
packages/leadtype/src/i18n/i18n.test.ts
**/index.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Avoid barrel files (index files that re-export everything)
Files:
packages/leadtype/src/source/index.tspackages/leadtype/src/i18n/index.ts
🪛 markdownlint-cli2 (0.22.1)
.changeset/i18n-docs-support.md
[warning] 5-5: First line in a file should be a top-level heading
(MD041, first-line-heading, first-line-h1)
| relativePath: file.outputRelativePath, | ||
| groups, |
There was a problem hiding this comment.
Keep source-relative paths separate from localized output paths.
relativePath now holds values like zh/changelog/v1, but downstream markdown-link builders still treat it as the source-relative path used for mount resolution. That breaks localized mounted artifacts: a page under changelog/v1.mdx will stop matching pathPrefix: "changelog" and llms/readability links will be emitted under /docs/zh/... instead of /changelog/zh/....
Also applies to: 877-877
There was a problem hiding this comment.
No new issues. Reviewed the following changes:
- Added duplicate-source-file detection in both
selectLocalizedFiles(llm/llm.ts) andselectSourceFiles(source/index.ts) — colliding(logicalPath, sourceLocale)pairs now throw with a message naming both files instead of silently letting the later file win. - Switched
readPageMetaslug derivation toselected.outputRelativePath, so localized pages emit locale-prefixed slugs (e.g.["zh", "quickstart"]) matching their/docs/<locale>/...URLs. - Broadened
loadPageslug resolution to try the slug as-is, then strip a leading locale segment, then prepend the active locale, so callers can address pages by logical, fully-qualified, or fallback paths. - Added integration tests for the duplicate-rejection paths and for the logical-path
loadPage("setup")→/docs/zh/setupfallback lookup.
Claude Opus | 𝕏

Summary
Adds first-class i18n support to the Leadtype docs pipeline.
leadtype/i18nwith locale config normalization, localized URL helpers, locale detection, alternate link helpers, and i18n manifest types.leadtype generateto preserve default-locale URLs while generating locale-scoped artifacts under/docs/<locale>/...plus/docs/i18n-manifest.json.DX and Compatibility
i18nis absent.docs/*.mdxand add translations under folders likedocs/zh/*.mdx.docs/<defaultLocale>default docs are present.Validation
bunx vitest run src/i18n/i18n.test.ts --coverage --coverage.include=src/i18n/index.ts --coverage.thresholds.lines 90 --coverage.thresholds.functions 90 --coverage.thresholds.branches 90 --coverage.thresholds.statements 90bun run --filter leadtype check-typesbun test packages/leadtype/srcbun x ultracite checkbun run --filter leadtype buildCloses #38.