From a32f618fe529f289cb3ef298980549979ae12dbb Mon Sep 17 00:00:00 2001 From: lllleolin-max Date: Sun, 13 Sep 2026 22:01:01 +0800 Subject: [PATCH] fix(node): use page locales in content loaders (#5434) --- __tests__/unit/node/contentLoader.test.ts | 53 +++++++++++++++++++++++ src/node/contentLoader.ts | 3 +- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/__tests__/unit/node/contentLoader.test.ts b/__tests__/unit/node/contentLoader.test.ts index 701d948b8..d82982a5b 100644 --- a/__tests__/unit/node/contentLoader.test.ts +++ b/__tests__/unit/node/contentLoader.test.ts @@ -4,10 +4,15 @@ import path from 'node:path' import { resolveConfig } from 'node/config' import { createContentLoader } from 'node/contentLoader' +import { disposeMdItInstance } from 'node/markdown/markdown' describe('node/contentLoader', () => { let root: string | undefined + beforeEach(() => { + disposeMdItInstance() + }) + afterEach(async () => { if (root) { await rm(root, { recursive: true, force: true }) @@ -76,4 +81,52 @@ describe('node/contentLoader', () => { expect(data[0].excerpt).toContain('Intro says My Post.') }) + + test.each([false, true])( + 'uses the rewritten locale for rendered content and excerpts (render: %s)', + async (render) => { + await setup(false) + await mkdir(path.join(root!, '.vitepress')) + await writeFile( + path.join(root!, '.vitepress/config.mjs'), + `export default { + rewrites: { 'translated.md': 'fr/post.md' }, + locales: { + root: { label: 'English', lang: 'en' }, + fr: { + label: 'French', lang: 'fr', + markdown: { container: { tipLabel: 'Conseil' } } + } + } + }` + ) + const content = '# Post\n\n::: tip\nSome advice.\n:::\n\n---\n\nBody.\n' + await writeFile(path.join(root!, 'translated.md'), content) + await writeFile(path.join(root!, 'original.md'), content) + await mkdir(path.join(root!, 'fr')) + await writeFile(path.join(root!, 'fr/native.md'), content) + ;(global as any).VITEPRESS_CONFIG = await resolveConfig( + root!, + 'build', + 'production' + ) + + const data = await createContentLoader( + ['translated.md', 'original.md', 'fr/native.md'], + { render, excerpt: true } + ).load() + const translated = data.find((page) => page.url === '/fr/post.html')! + const native = data.find((page) => page.url === '/fr/native.html')! + const original = data.find((page) => page.url === '/original.html')! + + expect(translated.excerpt).toContain('Conseil') + expect(native.excerpt).toContain('Conseil') + expect(original.excerpt).toContain('TIP') + if (render) { + expect(translated.html).toContain('Conseil') + expect(native.html).toContain('Conseil') + expect(original.html).toContain('TIP') + } + } + ) }) diff --git a/src/node/contentLoader.ts b/src/node/contentLoader.ts index b9f9d3e6d..5fc4f6219 100644 --- a/src/node/contentLoader.ts +++ b/src/node/contentLoader.ts @@ -10,7 +10,7 @@ import { createMarkdownRenderer, mergeMarkdownLocales } from './markdown/markdown' -import type { Awaitable, MarkdownEnv } from './shared' +import { getLocaleForPath, type Awaitable, type MarkdownEnv } from './shared' import { readTextFile } from './utils/fs' import { glob, normalizeGlob, type GlobOptions } from './utils/glob' @@ -149,6 +149,7 @@ export function createContentLoader( const env: MarkdownEnv = { path: file, relativePath, + localeIndex: getLocaleForPath(config.site, relativePath), cleanUrls: !!config.cleanUrls, realPath: file, // excerpts are rendered on their own, without the frontmatter