Mkdocs
多语言
为 MkDocs 添加多语言翻译功能
💾 AI智能摘要 (GLM-4)
本文介绍了为 MkDocs 网站添加基于 JavaScript 的客户端翻译功能,支持多种语言的实时切换,无需刷新页面,优化了移动端和桌面端显示。
📖 阅读信息
阅读时间:3 分钟 | 中文字符:1148 | 有效代码行数:328
在全球化的今天,为网站添加多语言支持已成为提升用户体验的重要手段。本文将详细介绍如何为 MkDocs 网站添加基于 JavaScript 的客户端翻译功能,支持多种语言的实时切换。
快速查看效果
🌍 方案概述
我们采用的翻译方案具有以下特点:
🚀 客户端翻译 :使用 translate.js
库实现前端翻译
🌐 多语言支持 :支持中文、英文、日文、韩文、阿拉伯文等 9 种语言
⚡ 实时切换 :无需刷新页面即可切换语言
🎨 样式优化 :针对不同语言进行样式适配
📱 响应式支持 :移动端和桌面端都有优化
📋 实现步骤
1. 引入翻译库
首先在页脚或头部模板(例如:docs/overrides/partials/footer.html )中引入 translate.js
库:
<!-- 引入翻译库 -->
< script src = "https://cdn.staticfile.net/translate.js/3.12.0/translate.js" ></ script >
2. 配置翻译参数
创建翻译配置脚本,设置基本参数:
< script >
( function () {
// 设置不翻译的元素类名
translate . ignore . class . push (
'md-select' , // Material 选择框
'footer-highlight' , // 页脚高亮文本
'md-footer-copyright' , // 版权信息
'no-translate' // 通用不翻译类
);
// 设置本地语种(默认中文简体)
translate . language . setLocal ( 'chinese_simplified' );
// 自动识别用户首选语言
translate . setAutoDiscriminateLocalLanguage ();
// 隐藏默认语言选择框
translate . selectLanguageTag . show = false ;
// 设置翻译服务通道
translate . service . use ( 'client.edge' );
// 执行翻译初始化
translate . execute ();
console . log ( '翻译功能已初始化' );
})();
< /script>
目录结构如下:
$ tree -a
.
├── .github
│ ├── .DS_Store
│ └── workflows
│ └── ci.yml
├── docs
│ └── index.md
│ └──overrides
│ └──assets
│ └──partials
│ └──footer.html
│
└── mkdocs.yml
footer.html示例代码(无需修改,直接复制粘贴即可使用)
{#-
This file was automatically generated - do not edit
-#}
< footer class = "md-footer" >
{% if "navigation.footer" in features %}
{% if page.previous_page or page.next_page %}
{% if page.meta and page.meta.hide %}
{% set hidden = "hidden" if "footer" in page.meta.hide %}
{% endif %}
< nav class = "md-footer__inner md-grid" aria-label = "{{ lang.t('footer') }}" {{ hidden }} >
{% if page.previous_page %}
{% set direction = lang.t("footer.previous") %}
< a href = "{{ page.previous_page.url | url }}" class = "md-footer__link md-footer__link--prev" aria-label = "{{ direction }}: {{ page.previous_page.title | e }}" >
< div class = "md-footer__button md-icon" >
{% set icon = config.theme.icon.previous or "material/arrow-left" %}
{% include ".icons/" ~ icon ~ ".svg" %}
</ div >
< div class = "md-footer__title" >
< span class = "md-footer__direction" >
{{ direction }}
</ span >
< div class = "md-ellipsis" >
{{ page.previous_page.title }}
</ div >
</ div >
</ a >
{% endif %}
{% if page.next_page %}
{% set direction = lang.t("footer.next") %}
< a href = "{{ page.next_page.url | url }}" class = "md-footer__link md-footer__link--next" aria-label = "{{ direction }}: {{ page.next_page.title | e }}" >
< div class = "md-footer__title" >
< span class = "md-footer__direction" >
{{ direction }}
</ span >
< div class = "md-ellipsis" >
{{ page.next_page.title }}
</ div >
</ div >
< div class = "md-footer__button md-icon" >
{% set icon = config.theme.icon.next or "material/arrow-right" %}
{% include ".icons/" ~ icon ~ ".svg" %}
</ div >
</ a >
{% endif %}
</ nav >
{% endif %}
{% endif %}
< div class = "md-footer-meta md-typeset" >
< div class = "md-footer-meta__inner md-grid" >
{% include "partials/copyright.html" %}
< script src = "https://cdn.staticfile.net/translate.js/3.12.0/translate.js" ></ script >
< script >
// 翻译配置 - 包装在立即执行函数中避免全局污染
( function () {
// 通过 class 设置不翻译的元素
translate . ignore . class . push ( 'md-select' , 'footer-highlight' , 'md-footer-copyright' );
// 自定义术语库,纠正翻译结果
translate . nomenclature . append ( 'chinese_simplified' , 'english' , `
快讯=Newsflash
访问量=Page Views
本站已经运行=Site has been running
天=days
时=hours
分=minutes
秒=seconds
萌ICP备=Moe ICP
版权所有=Copyright
制作工具=Made with
` );
// 设置本地语种
translate . language . setLocal ( 'chinese_simplified' );
// 设置首次使用时自动识别语种
translate . setAutoDiscriminateLocalLanguage ();
// 不显示 select 语言选择框
translate . selectLanguageTag . show = false ;
// 设置机器翻译服务通道
translate . service . use ( 'client.edge' );
// 执行翻译
translate . execute ();
// 监听语言切换事件,确保动态内容也能被翻译
window . addEventListener ( 'translate.languagechange' , function () {
// 延迟重新翻译动态更新的内容
setTimeout (() => {
translate . execute ();
}, 500 );
});
console . log ( '翻译功能已初始化' );
})();
</ script >
{% if config.extra.social %}
{% include "partials/social.html" %}
{% endif %}
</ div >
</ div >
</ footer >
3. 在 mkdocs.yml 中配置语言切换
首先在mkdocs.yml文件中添加custom_dir:
theme:
name: material
custom_dir: docs/overrides #覆写路径
然后在配置文件中添加多语言切换选项:
theme :
name : material
language : zh
features :
- navigation.tabs
- navigation.sections
extra :
alternate :
- name : 中文
link : "javascript:translate.changeLanguage('chinese_simplified');"
lang : zh
- name : English
link : "javascript:translate.changeLanguage('english');"
lang : en
- name : 한국어
link : "javascript:translate.changeLanguage('korean');"
lang : ko
- name : 日本語
link : "javascript:translate.changeLanguage('japanese');"
lang : ja
- name : بالعربية
link : "javascript:translate.changeLanguage('arabic');"
lang : ar
- name : Deutsch
link : "javascript:translate.changeLanguage('german');"
lang : de
- name : Français
link : "javascript:translate.changeLanguage('french');"
lang : fr
- name : Español
link : "javascript:translate.changeLanguage('spanish');"
lang : es
- name : português
link : "javascript:translate.changeLanguage('portuguese');"
lang : pt
至此已经配置完成。简单!快速!
后续步骤皆为可选,根据需求进行配置。可以不看。
4. 添加自定义术语库
为了提高翻译准确性,添加专业术语映射:
// 自定义术语库配置
const nomenclatures = {
english : `
访问量=Page Views
本站已经运行=Site has been running for
天=days
时=hours
分=minutes
秒=seconds
版权所有=Copyright
制作工具=Made with
统计中=Loading
` ,
japanese : `
访问量=アクセス数
本站已经运行=サイト運営期間
天=日
时=時間
分=分
秒=秒
版权所有=著作権
制作工具=制作ツール
` ,
korean : `
访问量=방문수
本站已经运行=사이트 운영 기간
天=일
时=시간
分=분
秒=초
版权所有=저작권
制作工具=제작 도구
`
// ... 其他语言配置
};
// 批量添加术语库
Object . entries ( nomenclatures ). forEach (([ lang , terms ]) => {
translate . nomenclature . append ( 'chinese_simplified' , lang , terms );
});
5. 处理动态内容翻译
对于实时更新的内容(如计时器、访问量等),需要特殊处理:
// 监听语言切换事件
window . addEventListener ( 'translate.languagechange' , function () {
// 延迟重新翻译动态内容
setTimeout (() => {
translate . execute ();
}, 500 );
});
// 在动态内容更新时触发翻译
function updateDynamicContent () {
// 更新内容...
// 如果当前不是中文,重新执行翻译
if ( window . translate && translate . currentLanguage !== 'chinese_simplified' ) {
setTimeout (() => translate . execute (), 100 );
}
}
🎨 多语言样式优化
1. 基础响应式样式
为不同语言文本长度进行适配:
/* 为翻译后的元素添加基础样式 */
[ data-translate-lang ] : not ([ data-translate-lang = "chinese_simplified" ]) . footer-item {
text-align : center ;
justify-content : center ;
min-height : 2.5 rem ;
padding : 0.5 rem 1 rem ;
line-height : 1.4 ;
}
/* 移动端长文本优化 */
@ media ( max-width : 768px ) {
[ data-translate-lang ] : not ([ data-translate-lang = "chinese_simplified" ]) . footer-visit-count-mobile {
flex-direction : column ;
gap : 0.4 em ;
line-height : 1.6 ;
}
}
2. 特定语言样式优化
针对不同语言的特殊需求:
/* 英文样式优化 */
[ data-translate-lang = "english" ] . footer-item {
font-size : 0.75 rem ;
word-spacing : 0.15 em ;
}
/* 日文样式优化 */
[ data-translate-lang = "japanese" ] . footer-item {
font-size : 0.8 rem ;
letter-spacing : 0.05 em ;
line-height : 1.5 ;
}
/* 阿拉伯文 RTL 支持 */
[ data-translate-lang = "arabic" ] . footer-wrapper {
direction : rtl ;
text-align : center ;
}
[ data-translate-lang = "arabic" ] . footer-item {
direction : rtl ;
text-align : center ;
word-spacing : 0.2 em ;
}
3. 深色模式兼容
确保所有语言在深色模式下的显示效果:
/* 深色模式下的翻译优化 */
[ data-md-color-scheme = "slate" ] . footer-counter-value ,
[ data-md-color-scheme = "slate" ] . no-translate {
color : #e2e8f0 !important ;
}
/* 高对比度模式支持 */
@ media ( prefers-contrast : high ) {
[ data-translate-lang ] : not ([ data-translate-lang = "chinese_simplified" ]) . footer-item {
border-width : 2 px ;
font-weight : 600 ;
}
}
🔧 高级功能
1. 语言检测与样式应用
function applyLanguageStyles ( lang ) {
// 设置语言属性
document . documentElement . setAttribute ( 'data-translate-lang' , lang || 'chinese_simplified' );
// RTL 语言处理
if ( lang === 'arabic' ) {
document . documentElement . setAttribute ( 'dir' , 'rtl' );
document . body . classList . add ( 'rtl-language' );
} else {
document . documentElement . setAttribute ( 'dir' , 'ltr' );
document . body . classList . remove ( 'rtl-language' );
}
}
2. 数字和特殊内容保护
确保数字、链接等不被误翻译:
function protectSpecialContent () {
// 保护数字不被翻译
const highlightElements = document . querySelectorAll ( '.footer-highlight' );
highlightElements . forEach ( el => {
if ( ! el . classList . contains ( 'no-translate' )) {
el . classList . add ( 'no-translate' );
}
});
// 保护 ICP 号码
const icpLinks = document . querySelectorAll ( '.icp-link' );
icpLinks . forEach ( el => {
const icpNumber = el . textContent . match ( /\d+/ );
if ( icpNumber ) {
el . innerHTML = el . innerHTML . replace (
/(\d+)/g ,
'<span class="no-translate">$1</span>'
);
}
});
}
🚀 最佳实践
1. 性能优化
延迟执行 :翻译操作延迟执行,避免阻塞页面渲染
避免重复翻译 :检查是否已翻译过相同内容
清理资源 :页面切换时正确清理翻译相关资源
2. 用户体验优化
记住用户选择 :使用 localStorage 保存用户的语言偏好
平滑过渡 :添加过渡动画使语言切换更自然
加载状态 :在翻译过程中显示加载提示
3. 可访问性考虑
屏幕阅读器支持 :正确设置 lang
属性
键盘导航 :确保语言切换按钮可通过键盘访问
对比度 :保证翻译后文本的可读性
📱 移动端适配
1. 响应式布局
@ media ( max-width : 768px ) {
/* 长语言文本换行优化 */
[ data-translate-lang = "german" ] . footer-visit-count-mobile ,
[ data-translate-lang = "french" ] . footer-visit-count-mobile {
gap : 0.6 em ;
line-height : 1.7 ;
}
/* 移动端语言切换优化 */
. md-header__option {
min-width : auto ;
}
}
2. 触摸友好设计
确保语言切换按钮在移动设备上易于点击:
/* 移动端按钮优化 */
@ media ( max-width : 768px ) {
. md-header__option {
padding : 0.5 rem ;
min-height : 44 px ; /* iOS 推荐的最小触摸目标 */
}
}
🔍 故障排除
常见问题及解决方案
翻译不生效
检查 translate.js
是否正确加载
确认没有 JavaScript 错误阻止执行
动态内容不翻译
在内容更新后调用 translate.execute()
检查动态元素是否被忽略类名覆盖
样式错乱
为不同语言添加对应的 CSS 规则
检查文本长度差异导致的布局问题
RTL 语言显示异常
正确设置 dir="rtl"
属性
为 RTL 语言添加特殊样式
📊 效果展示
实现后的效果:
✅ 多语言切换 :支持 9 种语言实时切换
✅ 样式适配 :每种语言都有优化的显示效果
✅ 响应式设计 :桌面端和移动端都完美适配
✅ 性能优良 :客户端翻译,服务器无额外负担
✅ 用户友好 :无需刷新页面,切换流畅
🎯 总结
通过以上步骤,我们成功为 MkDocs 网站添加了完整的多语言翻译功能。这个方案具有以下优势:
实现简单 :仅需几个文件修改即可完成
功能完整 :支持多种语言和样式适配
性能优秀 :客户端翻译,不增加服务器负担
用户体验佳 :切换流畅,样式美观
虽然客户端翻译在 SEO 方面不如服务端多语言方案,但对于技术文档、个人博客等场景,这种方案提供了极佳的性价比和用户体验。
🔗 相关资源
希望这个教程能帮助你为自己的 MkDocs 网站添加多语言支持!如果遇到问题,欢迎在评论区讨论。
💬 评论
2025-07-26
2025-07-26
GitHub