app/assets/localization_web_script.js

219 lines
7.8 KiB
JavaScript
Raw Normal View History

2023-10-09 09:32:07 +08:00
/// https://github.com/CxJuice/Uex_Chinese_Translate
2023-10-14 20:46:05 +08:00
let SCLocalizationReplaceLocalesMap = {};
2023-10-09 09:32:07 +08:00
let enable_webview_localization_capture = false;
2023-10-14 20:46:05 +08:00
let SCLocalizationEnableSplitMode = false;
2023-10-09 09:32:07 +08:00
function InitWebLocalization() {
let scriptTimeAgo = document.createElement('script');
scriptTimeAgo.src = 'https://cdn.bootcdn.net/ajax/libs/timeago.js/4.0.2/timeago.full.min.js';
document.head.appendChild(scriptTimeAgo);
if (typeof $ === 'undefined') {
let scriptJquery = document.createElement('script');
scriptJquery.src = 'https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js';
document.head.appendChild(scriptJquery);
}
LocalizationWatchUpdate();
}
function LocalizationWatchUpdate() {
const m = window.MutationObserver || window.WebKitMutationObserver;
const observer = new m(function (mutations, observer) {
for (let mutationRecord of mutations) {
for (let node of mutationRecord.addedNodes) {
traverseElement(node);
}
}
});
observer.observe(document.body, {
subtree: true,
characterData: true,
childList: true,
});
2023-10-14 20:46:05 +08:00
if (window.location.href.includes("robertsspaceindustries.com")) {
console.log("SCLocalizationEnableSplitMode = true");
SCLocalizationEnableSplitMode = true;
}
2023-10-09 09:32:07 +08:00
if (window.location.hostname.includes("www.erkul.games") || window.location.hostname.includes("ccugame.app")) {
document.body.addEventListener("click", function (event) {
setTimeout(function () {
allTranslate().then(_ => {
2023-10-14 20:46:05 +08:00
});
2023-10-09 09:32:07 +08:00
}, 200);
});
}
}
function WebLocalizationUpdateReplaceWords(w, b) {
enable_webview_localization_capture = b;
let replaceWords = w.sort(function (a, b) {
return b.word.length - a.word.length;
});
replaceWords.forEach(({word, replacement}) => {
2023-10-14 20:46:05 +08:00
SCLocalizationReplaceLocalesMap[word] = replacement;
2023-10-09 09:32:07 +08:00
});
if (window.location.hostname.startsWith("issue-council.robertsspaceindustries.com")) {
SCLocalizationReplaceLocalesMap["save"] = "保存";
}
2023-10-09 09:32:07 +08:00
allTranslate().then(_ => {
2023-10-14 20:46:05 +08:00
});
2023-10-09 09:32:07 +08:00
// console.log("WebLocalizationUpdateReplaceWords ==" + w)
}
async function allTranslate() {
async function replaceTextNode(node1) {
if (node1.nodeType === Node.TEXT_NODE) {
2023-10-14 20:46:05 +08:00
node1.nodeValue = GetSCLocalizationTranslateString(node1.nodeValue);
2023-10-09 09:32:07 +08:00
} else {
for (let i = 0; i < node1.childNodes.length; i++) {
await replaceTextNode(node1.childNodes[i]);
}
}
}
await replaceTextNode(document.body);
}
function traverseElement(el) {
if (!shouldTranslateEl(el)) {
return
}
for (const child of el.childNodes) {
if (["RELATIVE-TIME", "TIME-AGO"].includes(el.tagName)) {
translateRelativeTimeEl(el);
return;
}
if (child.nodeType === Node.TEXT_NODE) {
translateElement(child);
} else if (child.nodeType === Node.ELEMENT_NODE) {
if (child.tagName === "INPUT") {
translateElement(child);
} else {
traverseElement(child);
}
} else {
// pass
}
}
}
function translateElement(el) {
// Get the text field name
let k;
if (el.tagName === "INPUT") {
if (el.type === 'button' || el.type === 'submit') {
k = 'value';
} else {
k = 'placeholder';
}
} else {
k = 'data';
}
2023-10-14 20:46:05 +08:00
el[k] = GetSCLocalizationTranslateString(el[k]);
2023-10-09 09:32:07 +08:00
}
function translateRelativeTimeEl(el) {
const lang = (navigator.language || navigator.userLanguage);
const datetime = $(el).attr('datetime');
$(el).text(timeago.format(datetime, lang.replace('-', '_')));
}
function shouldTranslateEl(el) {
const blockIds = [];
const blockClass = [
"css-truncate" // 过滤文件目录
];
const blockTags = ["IMG", "svg", "mat-icon"];
if (blockTags.includes(el.tagName)) {
return false;
}
if (el.id && blockIds.includes(el.id)) {
return false;
}
if (el.classList) {
for (let clazz of blockClass) {
if (el.classList.contains(clazz)) {
return false;
}
}
}
return true;
}
2023-10-14 20:46:05 +08:00
function GetSCLocalizationTranslateString(txtSrc) {
let oldTxtSrc = txtSrc
const key = txtSrc.toLowerCase().replace(/\xa0/g, ' ').replace(/\s{2,}/g, ' ').trim();
const sourceKey = txtSrc.replace(/\xa0/g, ' ').replace(/\s{2,}/g, ' ').trim();
let noTheKey = key.replace("the ", "");
let noHorizontalKey = key.replace("- ", "");
if (SCLocalizationReplaceLocalesMap[key]) {
txtSrc = SCLocalizationReplaceLocalesMap[key]
} else if (SCLocalizationEnableSplitMode) {
if (sourceKey.includes(" - ")) {
let nodeValue = txtSrc
let splitKey = sourceKey.split(" - ");
if (splitKey[0].toLowerCase() === "upgrade" && key.includes("to") && key.endsWith("edition")) {
// 升级包规则
let noVersionStr = key.replace("STANDARD EDITION".toLowerCase(), "").replace("upgrade", "").replace("WARBOND EDITION".toLowerCase(), "")
let shipNames = noVersionStr.split(" to ")
let finalString = "升级包 " + GetSCLocalizationTranslateString(shipNames[0]) + " 到 " + GetSCLocalizationTranslateString(shipNames[1]);
if (key.endsWith("WARBOND EDITION".toLowerCase())) {
finalString = finalString + " 战争债券版"
2023-10-14 20:46:05 +08:00
} else {
finalString = finalString + " 标准版"
2023-10-14 20:46:05 +08:00
}
txtSrc = finalString
} else {
// 机库通用规则
splitKey.forEach(function (splitKey) {
if (SCLocalizationReplaceLocalesMap[splitKey.toLowerCase()]) {
nodeValue = nodeValue.replace(splitKey, SCLocalizationReplaceLocalesMap[splitKey.toLowerCase()])
} else {
nodeValue = nodeValue.replace(splitKey, GetSCLocalizationTranslateString(splitKey))
}
});
txtSrc = nodeValue
}
2023-10-14 20:46:05 +08:00
} else if (key.endsWith("starter pack") || key.endsWith("starter package")) {
let shipName = key.replace("starter package", "").replace("starter pack", "").trim()
if (SCLocalizationReplaceLocalesMap[shipName.toLowerCase()]) {
shipName = SCLocalizationReplaceLocalesMap[shipName.toLowerCase()];
}
txtSrc = shipName + " 新手包";
} else if (key.startsWith("the ") && SCLocalizationReplaceLocalesMap[noTheKey]) {
txtSrc = SCLocalizationReplaceLocalesMap[noTheKey];
} else if (key.startsWith("- ") && SCLocalizationReplaceLocalesMap[noHorizontalKey]) {
txtSrc = "- " + SCLocalizationReplaceLocalesMap[noHorizontalKey];
}
}
if (oldTxtSrc === txtSrc) {
ReportUnTranslate(key, txtSrc);
}
return txtSrc
}
InitWebLocalization();
2023-10-09 09:32:07 +08:00
function ReportUnTranslate(k, v) {
2023-10-14 20:46:05 +08:00
2023-10-09 09:32:07 +08:00
if (enable_webview_localization_capture) {
2023-10-14 20:46:05 +08:00
const cnPattern = /[\u4e00-\u9fa5]/;
const enPattern = /[a-zA-Z]/;
const htmlPattern = /<[^>]*>/;
const cssRegex = /(?:^|[^<])<style[^>]*>[\s\S]*?<\/style>(?:[^>]|$)/i;
const jsRegex = /(?:^|[^<])<script[^>]*>[\s\S]*?<\/script>(?:[^>]|$)/i;
2023-10-09 09:32:07 +08:00
if (k.trim() !== "" && !cnPattern.test(k) && !htmlPattern.test(k) && !cssRegex.test(k) && !jsRegex.test(k)
&& enPattern.test(k) && !k.startsWith("http://") && !k.startsWith("https://")) {
window.chrome.webview.postMessage({action: 'webview_localization_capture', key: k, value: v});
}
}
}
InitWebLocalization();