无需服务器从HTML头部读取本地JSON文件实现多语言翻译问题咨询
现有代码存在的问题
- 首先HTML中
<script type='application/json' src='lang/translations.json'>是无效写法:浏览器不会加载并解析type为application/json的外部脚本,这行代码没有任何作用。 - 异步请求的逻辑顺序错误:XMLHttpRequest的
onreadystatechange回调写在了send()之后,同步请求场景下该回调不会按预期触发,同时你注释了jQuery getJSON请求中给texts赋值的代码,导致texts始终为空。 - 同步AJAX请求在file协议下会被多数现代浏览器的安全策略拦截,即使设置了
async: false也大概率加载失败,同时会阻塞页面渲染。
最佳实现方案(无需服务器、纯前端、所有现代浏览器兼容)
最优解是将JSON翻译数据改写为JS全局变量导出,完全规避file协议下的跨域请求限制,不需要任何服务器环境,用户直接双击HTML即可运行。
步骤1:修改翻译文件格式
将原translations.json重命名为translations.js,内容修改为:
// 直接将翻译数据挂载到全局变量 window.__TRANSLATIONS__ = { "language": { "en": { "closure": "Closure", "documents": "Documents", "overview": "Overview" }, "de": { "closure": "Abschluss", "documents": "Dokumente", "overview": "Übersicht" } } };
步骤2:调整HTML引入顺序
先引入翻译数据JS,再引入翻译逻辑JS:
<script src='lang/translations.js'></script> <script src="Javascript/translator.js" charset="UTF-8"></script>
步骤3:简化translator.js代码
删掉所有AJAX请求逻辑,直接读取全局翻译数据:
let docLanguage = document.documentElement.lang; let browserLanguage = navigator.language.substr(0, 2); let lang = docLanguage ? docLanguage : browserLanguage; // 兜底如果没有对应语言就用英文 const allTrans = window.__TRANSLATIONS__.language; const texts = allTrans[lang] || allTrans['en']; class translator { constructor(lang) { this.lang = lang; this.translations = texts; } _(keyName) { // 找不到key就返回key本身避免空白 return this.translations[keyName] || keyName; } transHtml(attribute = 'data-lang') { let htmlElements = document.querySelectorAll('[' + attribute + ']'); for (let htmlElement of htmlElements) { let keyName = htmlElement.getAttribute(attribute); htmlElement.textContent = this._(keyName); } } } var translate = new translator(lang); // 页面加载完成后自动替换页面上的翻译文本 document.addEventListener('DOMContentLoaded', () => { translate.transHtml(); });
该方案完全符合要求:
- 不需要任何服务器环境,用户直接本地打开HTML即可正常运行
- 兼容所有现代浏览器,没有额外依赖
- 不存在加载时机问题,翻译数据在JS逻辑执行前就已经加载完成
- 后续新增语言仅需要在
translations.js的language字段里新增对应配置即可,无需修改其他逻辑。
内容的提问来源于stack exchange,提问作者Vergil
相关产品推荐
相关产品推荐

