已部署站点需要按访客语言展示导航与协议正文,因此把文案抽到语言包并加上语言选择。 Co-authored-by: Cursor <cursoragent@cursor.com>
167 lines
6.0 KiB
JavaScript
167 lines
6.0 KiB
JavaScript
(function () {
|
|
var CODES = ["zh-Hans", "zh-Hant", "en", "ja", "ko", "es", "fr", "de", "pt", "ru", "ar", "th", "vi", "id", "it"];
|
|
var NAMES = {
|
|
"zh-Hans": "简体中文",
|
|
"zh-Hant": "繁體中文",
|
|
en: "English",
|
|
ja: "日本語",
|
|
ko: "한국어",
|
|
es: "Español",
|
|
fr: "Français",
|
|
de: "Deutsch",
|
|
pt: "Português",
|
|
ru: "Русский",
|
|
ar: "العربية",
|
|
th: "ไทย",
|
|
vi: "Tiếng Việt",
|
|
id: "Bahasa Indonesia",
|
|
it: "Italiano"
|
|
};
|
|
var STORAGE = "sleepheart-lang";
|
|
|
|
function match(lang) {
|
|
var l = (lang || "").toLowerCase().replace(/_/g, "-");
|
|
if (l.indexOf("zh") === 0) {
|
|
if (l.indexOf("tw") >= 0 || l.indexOf("hk") >= 0 || l.indexOf("mo") >= 0 || l.indexOf("hant") >= 0) return "zh-Hant";
|
|
return "zh-Hans";
|
|
}
|
|
var base = l.split("-")[0];
|
|
return CODES.indexOf(base) >= 0 ? base : "";
|
|
}
|
|
|
|
function preferred() {
|
|
var saved = "";
|
|
try { saved = localStorage.getItem(STORAGE) || ""; } catch (e) {}
|
|
if (CODES.indexOf(saved) >= 0) return saved;
|
|
var list = navigator.languages || [navigator.language || ""];
|
|
for (var i = 0; i < list.length; i++) {
|
|
var hit = match(list[i]);
|
|
if (hit) return hit;
|
|
}
|
|
return "zh-Hans";
|
|
}
|
|
|
|
function esc(s) {
|
|
return String(s).replace(/[&<>"']/g, function (c) {
|
|
return { "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[c];
|
|
});
|
|
}
|
|
|
|
function repl(s, a, b) { return String(s).split(a).join(b); }
|
|
|
|
function linkify(s, ui) {
|
|
var html = esc(s);
|
|
html = repl(html, "{email}", '<a href="mailto:asd272940236@foxmail.com">asd272940236@foxmail.com</a>');
|
|
html = repl(html, "{home}", '<a href="/">' + esc(ui.backHome) + "</a>");
|
|
html = repl(html, "{delete}", '<a href="/delete">' + esc(ui.navDelete) + "</a>");
|
|
html = repl(html, "{privacyDoc}", '<a href="/privacy">' + esc(ui.privacyDoc) + "</a>");
|
|
html = repl(html, "{privacy}", '<a href="/privacy">' + esc(ui.navPrivacy) + "</a>");
|
|
html = repl(html, "{terms}", '<a href="/terms">' + esc(ui.navTerms) + "</a>");
|
|
return html;
|
|
}
|
|
|
|
function renderDoc(blocks, ui) {
|
|
var html = "";
|
|
var list = "";
|
|
function closeList() {
|
|
if (!list) return;
|
|
html += list === "ol" ? "</ol>" : "</ul>";
|
|
list = "";
|
|
}
|
|
blocks.forEach(function (block) {
|
|
var tag = block[0];
|
|
var inner = linkify(block[1], ui);
|
|
if (tag === "step" || tag === "li") {
|
|
var kind = tag === "step" ? "ol" : "ul";
|
|
if (list && list !== kind) closeList();
|
|
if (!list) {
|
|
html += kind === "ol" ? '<ol class="steps">' : "<ul>";
|
|
list = kind;
|
|
}
|
|
html += "<li>" + inner + "</li>";
|
|
return;
|
|
}
|
|
closeList();
|
|
if (tag === "meta") html += '<p class="meta">' + inner + "</p>";
|
|
else if (tag === "lead") html += '<p class="lead">' + inner + "</p>";
|
|
else if (tag === "note") html += '<p class="note">' + inner + "</p>";
|
|
else html += "<" + tag + ">" + inner + "</" + tag + ">";
|
|
});
|
|
closeList();
|
|
return html;
|
|
}
|
|
|
|
function apply(pack) {
|
|
var page = document.body.getAttribute("data-page") || "home";
|
|
var ui = pack.ui;
|
|
document.documentElement.lang = pack.htmlLang;
|
|
document.documentElement.dir = pack.dir || "ltr";
|
|
if (pack.titles && pack.titles[page]) document.title = pack.titles[page];
|
|
var desc = document.querySelector('meta[name="description"]');
|
|
if (desc && pack.desc && pack.desc[page]) desc.setAttribute("content", pack.desc[page]);
|
|
document.querySelectorAll("[data-i18n]").forEach(function (el) {
|
|
var key = el.getAttribute("data-i18n");
|
|
if (ui[key] == null) return;
|
|
if (el.getAttribute("data-i18n-mode") === "html") el.innerHTML = linkify(ui[key], ui);
|
|
else el.textContent = ui[key];
|
|
});
|
|
document.querySelectorAll("[data-i18n-alt]").forEach(function (el) {
|
|
var key = el.getAttribute("data-i18n-alt");
|
|
if (ui[key] != null) el.setAttribute("alt", ui[key]);
|
|
});
|
|
var doc = document.getElementById("doc");
|
|
if (doc && pack[page]) doc.innerHTML = renderDoc(pack[page], ui);
|
|
var select = document.getElementById("lang-select");
|
|
if (select) {
|
|
select.value = pack.code;
|
|
select.setAttribute("aria-label", ui.langLabel);
|
|
}
|
|
var label = document.querySelector(".lang-label span");
|
|
if (label) label.textContent = ui.langLabel;
|
|
var nav = document.querySelector(".nav");
|
|
if (nav) nav.setAttribute("aria-label", ui.navAria);
|
|
var foot = document.querySelector(".foot-links");
|
|
if (foot) foot.setAttribute("aria-label", ui.footAria);
|
|
}
|
|
|
|
function load(code) {
|
|
if (window.SH_PACKS && window.SH_PACKS[code]) return Promise.resolve(window.SH_PACKS[code]);
|
|
return new Promise(function (resolve, reject) {
|
|
var s = document.createElement("script");
|
|
s.src = "/assets/i18n/" + code + ".js?v=20261011lang";
|
|
s.onload = function () {
|
|
if (window.SH_PACKS && window.SH_PACKS[code]) resolve(window.SH_PACKS[code]);
|
|
else reject(new Error("missing pack"));
|
|
};
|
|
s.onerror = function () { reject(new Error("load")); };
|
|
document.head.appendChild(s);
|
|
});
|
|
}
|
|
|
|
function boot() {
|
|
var select = document.getElementById("lang-select");
|
|
if (select && !select.options.length) {
|
|
CODES.forEach(function (code) {
|
|
var opt = document.createElement("option");
|
|
opt.value = code;
|
|
opt.textContent = NAMES[code];
|
|
select.appendChild(opt);
|
|
});
|
|
select.addEventListener("change", function () {
|
|
var code = select.value;
|
|
try { localStorage.setItem(STORAGE, code); } catch (e) {}
|
|
load(code).then(apply).catch(function () {
|
|
if (window.SH_PACKS && window.SH_PACKS["zh-Hans"]) apply(window.SH_PACKS["zh-Hans"]);
|
|
});
|
|
});
|
|
}
|
|
var code = preferred();
|
|
load(code).then(apply).catch(function () {
|
|
if (window.SH_PACKS && window.SH_PACKS["zh-Hans"]) apply(window.SH_PACKS["zh-Hans"]);
|
|
});
|
|
}
|
|
|
|
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", boot);
|
|
else boot();
|
|
})();
|