React项目使用react-i18next时如何实现.md文件内容翻译?
可行解决方案
以下方案均不需要将现有md文件批量改写为React组件,适配开发时间紧张、存量md文件多的场景,改造成本极低。
方案1:占位符运行时替换(推荐,改动最小)
核心逻辑是在md文件中用特殊格式的占位符标记待翻译文本,渲染md内容前通过正则匹配占位符,调用react-i18next的t方法替换为对应语言文案即可。
- 第一步:统一占位符格式
选择和md原生语法、项目现有模板语法不冲突的占位符格式,比如{{t:你的翻译key}},将md中需要翻译的文本替换为对应占位符,以404.md为例:
对于md头部frontmatter里的字段(比如title),直接把字段值设为翻译key即可,不需要套占位符。存量md的替换可以写个简单的Node脚本批量扫描处理,不需要手动逐文件修改。--- path: "/404" title: "404_page_title" --- <section class="section section--gradient pb-0"> <div class="container apis-content"> <div class="documentation-links"> {{t:constant.404.tipText}} </div> </div> </section> - 第二步:编写通用替换工具函数
工具函数会自动识别html内容里的占位符完成替换,同时自动跳过代码块、行内代码区域,避免误替换代码示例中的同格式内容:const replaceI18nPlaceholder = (rawHtml, t) => { const codeStore = []; // 临时提取所有pre、code标签内容暂存 let processed = rawHtml.replace(/(<pre[\s\S]*?>[\s\S]*?<\/pre>|<code[\s\S]*?>[\s\S]*?<\/code>)/g, (match) => { codeStore.push(match); return `___CODE_TEMP_${codeStore.length - 1}___`; }); // 匹配替换i18n占位符 processed = processed.replace(/\{\{t:([a-zA-Z0-9_.]+)\}\}/g, (match, transKey) => { return t(transKey) || match; // 找不到翻译时兜底返回原内容,避免页面异常 }); // 还原暂存的代码块内容 processed = processed.replace(/___CODE_TEMP_(\d+)___/g, (_, idx) => codeStore[Number(idx)]); return processed; }; - 第三步:调整渲染逻辑
原来的渲染代码只需要加一层工具函数调用即可,frontmatter里的字段单独调用t方法翻译:// 翻译页面title const pageTitle = t(content.title); // 处理md正文内容 const translatedHtml = replaceI18nPlaceholder(content.html, t); return ( <div id="main" dangerouslySetInnerHTML={{ __html: translatedHtml }} /> )
方案2:构建层loader统一处理(适合用打包工具管理md资源的项目)
如果项目是通过Vite/Webpack的md-loader解析md文件,可以直接扩展loader逻辑:
- 同样使用上述
{{t:key}}占位符标记待翻译内容 - 在loader将md转换为html的环节,注入上述替换逻辑,不需要在每个渲染md的组件里重复写替换代码
- 如果是构建时按语言分包的多语言方案,甚至可以直接在loader阶段完成文本替换,运行时不需要额外处理,性能更好
注意事项
- 占位符不要使用单大括号格式,避免和md语法、JSX模板、其他第三方库的模板规则冲突
- 替换逻辑一定要加代码块跳过逻辑,防止代码示例中的内容被误翻译
- 所有翻译key提前在i18n的语言包中配置好对应文案即可,切换语言时因为组件会重新渲染,替换逻辑会自动执行,拿到对应语言的文案,不需要额外做适配
内容的提问来源于stack exchange,提问作者pageNotfoUnd
相关产品推荐
相关产品推荐

