963 markdown files reformatted with the repository's pinned prettier so pnpm format:check covers the folded tree like every other repo file. The formatter's embedded-language pass also normalized code fences (TS semicolons, closed HTML tags in examples, lowercased CSS hex colors, one renumbered list that skipped an index). Alphanumeric token deltas vs the fold commit were audited file-by-file; all are formatter-equivalent markup normalizations plus the four sanitized skills.
5.2 KiB
5.2 KiB
name, description
| name | description |
|---|---|
| vitepress-internationalization | Setting up multi-language sites with locale configuration and RTL support |
Internationalization
VitePress supports multi-language sites through locale configuration.
Directory Structure
Organize content by locale:
docs/
├─ en/
│ ├─ guide.md
│ └─ index.md
├─ zh/
│ ├─ guide.md
│ └─ index.md
└─ fr/
├─ guide.md
└─ index.md
Or with root as default language:
docs/
├─ guide.md # English (root)
├─ index.md
├─ zh/
│ ├─ guide.md
│ └─ index.md
└─ fr/
├─ guide.md
└─ index.md
Configuration
// .vitepress/config.ts
import { defineConfig } from 'vitepress';
export default defineConfig({
locales: {
root: {
label: 'English',
lang: 'en',
},
zh: {
label: '简体中文',
lang: 'zh-CN',
link: '/zh/',
},
fr: {
label: 'Français',
lang: 'fr',
link: '/fr/',
},
},
});
Locale-Specific Config
Override site config per locale:
locales: {
root: {
label: 'English',
lang: 'en',
title: 'My Docs',
description: 'Documentation site',
themeConfig: {
nav: [
{ text: 'Guide', link: '/guide/' }
],
sidebar: {
'/guide/': [
{ text: 'Introduction', link: '/guide/' }
]
}
}
},
zh: {
label: '简体中文',
lang: 'zh-CN',
link: '/zh/',
title: '我的文档',
description: '文档站点',
themeConfig: {
nav: [
{ text: '指南', link: '/zh/guide/' }
],
sidebar: {
'/zh/guide/': [
{ text: '介绍', link: '/zh/guide/' }
]
}
}
}
}
Locale-Specific Properties
Each locale can override:
interface LocaleSpecificConfig {
lang?: string;
dir?: string; // 'ltr' or 'rtl'
title?: string;
titleTemplate?: string | boolean;
description?: string;
head?: HeadConfig[]; // Merged with existing
themeConfig?: ThemeConfig; // Shallow merged
}
Search i18n
Local Search
themeConfig: {
search: {
provider: 'local',
options: {
locales: {
zh: {
translations: {
button: {
buttonText: '搜索',
buttonAriaLabel: '搜索'
},
modal: {
noResultsText: '没有结果',
resetButtonTitle: '重置搜索',
footer: {
selectText: '选择',
navigateText: '导航',
closeText: '关闭'
}
}
}
}
}
}
}
}
Algolia Search
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...',
locales: {
zh: {
placeholder: '搜索文档',
translations: {
button: { buttonText: '搜索文档' }
}
}
}
}
}
}
Separate Locale Directories
For fully separated locales without root fallback:
docs/
├─ en/
│ └─ index.md
├─ zh/
│ └─ index.md
└─ fr/
└─ index.md
Requires server redirect for / → /en/. Netlify example:
/* /en/:splat 302 Language=en
/* /zh/:splat 302 Language=zh
/* /en/:splat 302
Persisting Language Choice
Set cookie on language change:
<!-- .vitepress/theme/Layout.vue -->
<script setup>
import DefaultTheme from 'vitepress/theme';
import { useData, inBrowser } from 'vitepress';
import { watchEffect } from 'vue';
const { lang } = useData();
watchEffect(() => {
if (inBrowser) {
document.cookie = `nf_lang=${lang.value}; expires=Mon, 1 Jan 2030 00:00:00 UTC; path=/`;
}
});
</script>
<template>
<DefaultTheme.Layout />
</template>
RTL Support (Experimental)
For right-to-left languages:
locales: {
ar: {
label: 'العربية',
lang: 'ar',
dir: 'rtl'
}
}
Requires PostCSS plugin like postcss-rtlcss:
// postcss.config.js
import rtlcss from 'postcss-rtlcss';
export default {
plugins: [
rtlcss({
ltrPrefix: ':where([dir="ltr"])',
rtlPrefix: ':where([dir="rtl"])',
}),
],
};
Organizing Config
Split config into separate files:
.vitepress/
├─ config/
│ ├─ index.ts # Main config, merges locales
│ ├─ en.ts # English config
│ ├─ zh.ts # Chinese config
│ └─ shared.ts # Shared config
// .vitepress/config/index.ts
import { defineConfig } from 'vitepress';
import { shared } from './shared';
import { en } from './en';
import { zh } from './zh';
export default defineConfig({
...shared,
locales: {
root: { label: 'English', ...en },
zh: { label: '简体中文', ...zh },
},
});
Key Points
- Use
localesobject in config withrootfor default language - Each locale can override title, description, and themeConfig
themeConfigis shallow merged (define complete nav/sidebar per locale)- Don't override
themeConfig.algoliaat locale level dir: 'rtl'enables RTL with PostCSS plugin- Language switcher appears automatically in nav