javascript - 从没有服务器的 HTML Head 读取 JSON 文件
问题描述
我得到了一些翻译的 json 文件。我想在 JS 文件中使用这个文件来翻译一些字符串。但我没有一个好的解决方案来加载这个文件和数据。
到目前为止我得到的是我的 HTML 文件:
<script type='application/json' src='lang/translations.json'></script>
<script src="Javascript/translator.js" charset="UTF-8"></script>
JSON文件:
{
"language": {
"en": {
"closure": "Closure",
"documents": "Documents",
"overview": "Overview"
},
"de": {
"closure": "Abschluss",
"documents": "Dokumente",
"overview": "Übersicht"
}
}
}
还有我的 JS 文件:
let docLanguage = document.documentElement.lang;
let browserLanguage = navigator.language.substr(0, 2);
let lang = docLanguage ? docLanguage : browserLanguage;
let texts;
const Http = new XMLHttpRequest();
const url = "lang/" + lang + ".json";
Http.open("GET", url, false);
Http.send();
Http.onreadystatechange = function () {
texts = JSON.parse(Http.responseText);
return texts;
}
let getJson = jQuery.getJSON('lang/' + lang + '.json', {format: "json", async: false})
.done(function (data) {
// texts = data;
return data;
}).fail(function () {
console.log('empty');
});
class translator {
constructor(lang) {
this.lang = lang;
this.translations = texts;
}
_(keyName) {
// return texts.get(keyName);
// todo get by 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);
但问题是,翻译文件被读到很晚,在构造函数中我不能使用这部分,或者我做错了什么?
那么加载和读取存储在本地的 json 文件的最佳方法是什么。
我不想要服务器或其他任何东西,只想要可以在所有现代浏览器上运行的纯 Javascript。因为这是用户的导出,他们应该能够观看此页面而无需安装任何东西或需要互联网连接
解决方案
如果您想坚持使用同步 XHTTPRequest(不推荐),那么您只需要更改send()
函数的顺序,在附加事件侦听器之前调用它onreadystatechange
,它必须在之后调用:
Http.open("GET", url, false);
Http.onreadystatechange = function () {
texts = JSON.parse(Http.responseText);
return texts;
}
Http.send(); // called after onreadystatechange
它会起作用,但会在控制台中显示警告[Deprecation] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience.
建议在 JavaScript 中使用异步函数。异步构造函数不起作用,因此有一些模式可以帮助解决这个问题:https ://stackoverflow.com/a/43433773/3075373
例如,最好使用.init()
这样的函数:
let docLanguage = document.documentElement.lang;
let browserLanguage = navigator.language.substr(0, 2);
let lang = docLanguage ? docLanguage : browserLanguage;
class translator {
constructor(lang) {
this.lang = lang;
}
init(cb) {
jQuery.getJSON('lang/' + this.lang + '.json', { format: "json" })
.done(result => {
this.translations = result;
cb.bind(this)();
})
.fail(err => console.log(err))
}
_(keyName) {
// return texts.get(keyName);
// todo get by 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);
translate.init(() => {
// inside you can use methods that rely on translations being loaded e.g:
translate.transHtml();
})
@Answer 评论:
例如,可以添加另一个文件languages.js
const languages = {
"language": {
"en": {
"closure": "Closure",
"documents": "Documents",
"overview": "Overview"
},
"de": {
"closure": "Abschluss",
"documents": "Dokumente",
"overview": "Übersicht"
}
}
}
export default languages;
然后在你的主脚本中添加type="module"
,以便你可以导入另一个 js 文件(注意:它主要在现代浏览器中工作,通常它是在webpack等的帮助下完成的,以帮助旧浏览器,但它完全是另一个主题)
<script type="module">
import lngs from './languages.js'
let docLanguage = document.documentElement.lang;
...
...
...
rest of script
您也可以简单地将顶部的对象粘贴languages
到主脚本中,然后无需导入另一个 js 文件。
推荐阅读
- amazon-web-services - 在 Lambda 函数中查找请求的 URL
- sql - 语句中带有运算符的条件 WHERE 子句
- android - 仅为“群组”打开通知设置
- intellij-idea - 在演示模式下显示编辑器选项卡
- javascript - Javascript Div 类默认选项卡
- java - 将构造函数中的 System.getProperty 替换为 yml
- ios - 如何捆绑名称与捆绑显示名称与 AppStoreConnect 应用程序名称
- php - 在 Woocommerce 中获取所有客户手机号码
- html - 无法让我的页面滚动?
- nginx - 区分udp数据包的源地址