mirror of
https://ghfast.top/https://github.com/StarCitizenToolBox/StarCitizenBoxBrowserEx.git
synced 2025-05-09 21:51:25 +08:00
feat: 为chrome拓展添加手动调用翻译的功能 (#3)
* feat: 为chrome拓展添加手动调用翻译的功能
* feat: add SC-BOX-TRANSLATE-API-AVAILABLE message
* refactor: move content script logic to core.js
* feat: add context menu for translating pages
* chore: 🤖 使用extension.js
* chore: update package metadata
* chore: ensure context menu creation on extension install
* feat: add toggle translation functionality
* feat: add support for dynamic localization based on tab URL
* feat: add Chinese translation for Star Citizen browser extension
* docs: update README with new API usage instructions
* refactor: update translation logic to append original values
* typescript support
* feat: add manual URL handling for localization
* feat: add postMessage for toggling SC-BOX translate
* feat: add translation toggle event to postMessage
* feat: add translation status and message handling
* refactor: optimize localization version logging
This commit is contained in:
parent
75565c0ef0
commit
ebf6447507
29
.gitignore
vendored
29
.gitignore
vendored
@ -1,2 +1,31 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
/.idea/
|
/.idea/
|
||||||
|
|
||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
# testing
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# dist/
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env.local
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
|
||||||
|
# debug files
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# extension.js
|
||||||
|
extension-env.d.ts
|
||||||
|
|
||||||
|
.vscode/
|
11
.vscode/settings.json
vendored
Normal file
11
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"cSpell.words": [
|
||||||
|
"clazz",
|
||||||
|
"erkul",
|
||||||
|
"robertsspaceindustries",
|
||||||
|
"SWTT",
|
||||||
|
"timeago",
|
||||||
|
"uexcorp",
|
||||||
|
"WARBOND"
|
||||||
|
]
|
||||||
|
}
|
92
README.md
92
README.md
@ -3,12 +3,11 @@
|
|||||||
为您将星际公民官网及常用工具网站翻译为中文的浏览器拓展,所有翻译内容来自 星际公民中文社区汉化组。
|
为您将星际公民官网及常用工具网站翻译为中文的浏览器拓展,所有翻译内容来自 星际公民中文社区汉化组。
|
||||||
本插件也内置于 [星际公民盒子](https://github.com/xkeyC/StarCitizenToolBox) 。
|
本插件也内置于 [星际公民盒子](https://github.com/xkeyC/StarCitizenToolBox) 。
|
||||||
|
|
||||||
SC网站翻译项目:https://github.com/CxJuice/ScWeb_Chinese_Translate
|
SC网站翻译项目:[CxJuice/ScWeb_Chinese_Translate](https://github.com/CxJuice/ScWeb_Chinese_Translate)
|
||||||
|
|
||||||
## 本插件仅供大致浏览使用,不对任何有关本插件产生的问题负责!在涉及账号操作前请注意确认网站的原本内容!
|
## **本插件仅供大致浏览使用,不对任何有关本插件产生的问题负责!在涉及账号操作前请注意确认网站的原本内容!**
|
||||||
|
|
||||||
<img width="640" alt="8b9bdcc6d352639fd134df61e6e702ef" src="https://github.com/xkeyC/StarCitizenBoxBrowserEx/assets/39891083/9580f52a-13ea-4234-a0d3-b8d06f06dda2">
|
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## 安装
|
## 安装
|
||||||
|
|
||||||
@ -19,4 +18,87 @@ SC网站翻译项目:https://github.com/CxJuice/ScWeb_Chinese_Translate
|
|||||||
[Firefox ADD-ONS](https://addons.mozilla.org/zh-CN/firefox/addon/%E6%98%9F%E9%99%85%E5%85%AC%E6%B0%91%E7%9B%92%E5%AD%90%E6%B5%8F%E8%A7%88%E5%99%A8%E6%8B%93%E5%B1%95/)
|
[Firefox ADD-ONS](https://addons.mozilla.org/zh-CN/firefox/addon/%E6%98%9F%E9%99%85%E5%85%AC%E6%B0%91%E7%9B%92%E5%AD%90%E6%B5%8F%E8%A7%88%E5%99%A8%E6%8B%93%E5%B1%95/)
|
||||||
|
|
||||||
## 手动安装
|
## 手动安装
|
||||||
下载 zip 后使用插件的开发者功能手动安装 StarCitizenBoxBrowserEx 文件夹 Firefox 安装 StarCitizenBoxBrowserEx_Firefox 文件夹。
|
|
||||||
|
下载 zip 后使用插件的开发者功能手动安装 dist/chrome 文件夹 Firefox 安装 dist/firefox 文件夹。
|
||||||
|
|
||||||
|
### 开发者
|
||||||
|
|
||||||
|
#### 调用翻译Hook
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
enum SCBoxTranslateStatus {
|
||||||
|
Available,
|
||||||
|
Translated,
|
||||||
|
NotAvailable,
|
||||||
|
}
|
||||||
|
|
||||||
|
const [translateApiAvailable, setTranslateApiAvailable] = useState<SCBoxTranslateStatus>(SCBoxTranslateStatus.NotAvailable);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
function handleMessage(event: MessageEvent) {
|
||||||
|
if (event.source !== window) return;
|
||||||
|
// 在插件加载后会向页面发送消息
|
||||||
|
if (event.data?.type === 'SC-BOX-TRANSLATE-API-AVAILABLE') {
|
||||||
|
setTranslateApiAvailable(SCBoxTranslateStatus.Available);
|
||||||
|
}
|
||||||
|
// 在翻译状态改变时插件也会向页面发送消息
|
||||||
|
if (event.data?.type === 'TOGGLED-SC-BOX-TRANSLATE') {
|
||||||
|
switch (event.data.action) {
|
||||||
|
case 'on':
|
||||||
|
setTranslateApiAvailable(SCBoxTranslateStatus.Translated);
|
||||||
|
return;
|
||||||
|
case 'off':
|
||||||
|
setTranslateApiAvailable(SCBoxTranslateStatus.Available);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('message', handleMessage);
|
||||||
|
return () => window.removeEventListener('message', handleMessage);
|
||||||
|
}, []);
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// 触发翻译
|
||||||
|
window.postMessage({
|
||||||
|
type: 'SC_TRANSLATE_REQUEST',
|
||||||
|
action: 'translate',
|
||||||
|
requestId: Math.random().toString(36)
|
||||||
|
}, '*');
|
||||||
|
|
||||||
|
// 撤销翻译
|
||||||
|
window.postMessage({
|
||||||
|
type: 'SC_TRANSLATE_REQUEST',
|
||||||
|
action: 'undoTranslate',
|
||||||
|
requestId: Math.random().toString(36)
|
||||||
|
}, '*');
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 开发/调试
|
||||||
|
|
||||||
|
##### 安装依赖
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm install
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 开发模式
|
||||||
|
|
||||||
|
此命令在开发模式下运行您的扩展程序。它将启动一个新的浏览器实例,加载您的扩展程序。每当您对代码进行更改时,页面将自动重新加载,从而提供流畅的开发体验。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm dev
|
||||||
|
# firefox
|
||||||
|
pnpm dev:firefox
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 编译
|
||||||
|
|
||||||
|
此命令用于为生产环境构建您的扩展程序。它会优化和打包您的扩展程序,准备好部署到目标浏览器的商店。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm build
|
||||||
|
# firefox
|
||||||
|
pnpm build:firefox
|
||||||
|
```
|
||||||
|
@ -1,194 +0,0 @@
|
|||||||
let SCLocalizationReplaceLocalesMap = {};
|
|
||||||
let SCLocalizationEnableSplitMode = false;
|
|
||||||
|
|
||||||
function InitWebLocalization() {
|
|
||||||
// init script
|
|
||||||
LocalizationWatchUpdate();
|
|
||||||
// load Data
|
|
||||||
_loadLocalizationData();
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (window.location.href.includes("robertsspaceindustries.com")) {
|
|
||||||
console.log("SCLocalizationEnableSplitMode = true");
|
|
||||||
SCLocalizationEnableSplitMode = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window.location.hostname.includes("www.erkul.games")) {
|
|
||||||
document.body.addEventListener("click", function (event) {
|
|
||||||
setTimeout(function () {
|
|
||||||
allTranslate().then(_ => {
|
|
||||||
});
|
|
||||||
}, 200);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function WebLocalizationUpdateReplaceWords(w) {
|
|
||||||
let replaceWords = w.sort(function (a, b) {
|
|
||||||
return b.word.length - a.word.length;
|
|
||||||
});
|
|
||||||
replaceWords.forEach(({word, replacement}) => {
|
|
||||||
SCLocalizationReplaceLocalesMap[word] = replacement;
|
|
||||||
});
|
|
||||||
if (window.location.hostname.startsWith("issue-council.robertsspaceindustries.com")) {
|
|
||||||
SCLocalizationReplaceLocalesMap["save"] = "保存";
|
|
||||||
}
|
|
||||||
allTranslate().then(_ => {
|
|
||||||
});
|
|
||||||
// console.log("WebLocalizationUpdateReplaceWords ==" + w)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function allTranslate() {
|
|
||||||
async function replaceTextNode(node1) {
|
|
||||||
if (node1.nodeType === Node.TEXT_NODE) {
|
|
||||||
node1.nodeValue = GetSCLocalizationTranslateString(node1.nodeValue);
|
|
||||||
} 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';
|
|
||||||
}
|
|
||||||
el[k] = GetSCLocalizationTranslateString(el[k]);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
function GetSCLocalizationTranslateString(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 + " 战争债券版"
|
|
||||||
} else {
|
|
||||||
finalString = finalString + " 标准版"
|
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
} 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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return txtSrc
|
|
||||||
}
|
|
||||||
|
|
||||||
InitWebLocalization();
|
|
||||||
|
|
||||||
function _loadLocalizationData() {
|
|
||||||
chrome.runtime.sendMessage({action: "_loadLocalizationData", url: window.location.href}, function (response) {
|
|
||||||
WebLocalizationUpdateReplaceWords(response.result);
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,93 +0,0 @@
|
|||||||
// from https://github.com/cfdxkk/RSI-Hangar-Button
|
|
||||||
// LICENSE GLWT(Good Luck With That) Public License
|
|
||||||
(function () {
|
|
||||||
/**
|
|
||||||
* 寻找元素直到元素被加载
|
|
||||||
* @param dom 查找的根元素
|
|
||||||
* @param selector 元素的查找
|
|
||||||
* @param callback 查找到的回调
|
|
||||||
* @param interval 查找的间隔,默认 100 毫秒
|
|
||||||
*/
|
|
||||||
function waitForElement(dom, selector, callback, interval = 100) {
|
|
||||||
const checkExist = setInterval(() => {
|
|
||||||
const element = dom.querySelector(selector)
|
|
||||||
if (element) {
|
|
||||||
clearInterval(checkExist) // 停止轮询
|
|
||||||
callback(element)
|
|
||||||
}
|
|
||||||
}, interval)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 开始监听抽屉,如果监听到点击事件,则添加按钮
|
|
||||||
* @param element
|
|
||||||
*/
|
|
||||||
function startObserve(element) {
|
|
||||||
// 创建一个 MutationObserver 实例,监听元素的子元素变化
|
|
||||||
const observer = new MutationObserver((mutationsList) => {
|
|
||||||
for (const mutation of mutationsList) {
|
|
||||||
if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
|
|
||||||
mutation.addedNodes.forEach(node => {
|
|
||||||
if (node.nodeType === 1) { // 只处理元素节点 (忽略文本节点)
|
|
||||||
waitForElement(node, "a[data-cy-id=\"button\"][href=\"/account/settings\"]", (button) => {
|
|
||||||
copyAndAddButton(button)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 监听子节点变化,并对子树内的变化也进行监听
|
|
||||||
observer.observe(element, { childList: true, subtree: true })
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 复制原有按钮,将其修改为机库按钮并插入到原按钮的上方
|
|
||||||
* 在插入前先检查是否已经存在对应的按钮
|
|
||||||
* @param {HTMLElement} button 原始按钮
|
|
||||||
*/
|
|
||||||
function copyAndAddButton(button) {
|
|
||||||
if (!button) return
|
|
||||||
|
|
||||||
// 如果已经存在 href 为 /account/pledges 的按钮,则不再添加
|
|
||||||
if (button.parentNode.querySelector('a[data-cy-id="button"][href="/account/pledges"]')) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 复制元素
|
|
||||||
const hangarButton = button.cloneNode(true)
|
|
||||||
|
|
||||||
// 修改 href
|
|
||||||
hangarButton.href = "/account/pledges"
|
|
||||||
|
|
||||||
// 查找按钮中的文本部分
|
|
||||||
const hangarButtonText = hangarButton.querySelector('span[data-cy-id="button__text"]')
|
|
||||||
|
|
||||||
// 修改文本
|
|
||||||
if (hangarButtonText) {
|
|
||||||
hangarButtonText.innerText = "My Hangar"
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查找按钮中的图标部分
|
|
||||||
const hangarButtonIcon = hangarButton.querySelector('i[data-cy-id="button__icon"]')
|
|
||||||
|
|
||||||
// 修改图标
|
|
||||||
if (hangarButtonIcon) {
|
|
||||||
hangarButtonIcon.className = "a-button__icon a-icon -gridView"
|
|
||||||
}
|
|
||||||
|
|
||||||
// 插入到目标元素的前方
|
|
||||||
button.parentNode.insertBefore(hangarButton, button)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 开始查找抽屉,如果找到执行监听回调
|
|
||||||
waitForElement(document, "#sidePanel", (risSidePanel) => {
|
|
||||||
startObserve(risSidePanel)
|
|
||||||
|
|
||||||
// 初始检查:防止首次打开抽屉时按钮已经存在,MutationObserver 不触发
|
|
||||||
const button = sidePanel.querySelector('a[data-cy-id="button"][href="/account/settings"]')
|
|
||||||
if (button) {
|
|
||||||
copyAndAddButton(button)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})()
|
|
@ -1,153 +0,0 @@
|
|||||||
let dataVersion = null
|
|
||||||
|
|
||||||
chrome.runtime.onInstalled.addListener(function () {
|
|
||||||
_checkVersion().then(_ => {
|
|
||||||
});
|
|
||||||
console.log("SWTT init");
|
|
||||||
});
|
|
||||||
|
|
||||||
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
|
|
||||||
if (request.action === "_loadLocalizationData") {
|
|
||||||
_initLocalization(request.url).then(data => {
|
|
||||||
sendResponse({result: data});
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
async function _checkVersion() {
|
|
||||||
dataVersion = await _getJsonData("versions.json");
|
|
||||||
console.log("Localization Version ===");
|
|
||||||
console.log(dataVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function _initLocalization(url) {
|
|
||||||
console.log("url ===" + url);
|
|
||||||
if (dataVersion == null) {
|
|
||||||
await _checkVersion();
|
|
||||||
return _initLocalization(url);
|
|
||||||
}
|
|
||||||
let v = dataVersion
|
|
||||||
// TODO check version
|
|
||||||
let data = {};
|
|
||||||
|
|
||||||
if (url.includes("robertsspaceindustries.com")) {
|
|
||||||
data["zh-CN"] = await _getJsonData("zh-CN-rsi.json", {cacheKey: "zh-CN", version: v.rsi});
|
|
||||||
data["concierge"] = await _getJsonData("concierge.json", {cacheKey: "concierge", version: v.concierge});
|
|
||||||
data["orgs"] = await _getJsonData("orgs.json", v.orgs);
|
|
||||||
data["address"] = await _getJsonData("addresses.json", {cacheKey: "orgs", version: v.addresses});
|
|
||||||
data["hangar"] = await _getJsonData("hangar.json", {cacheKey: "hangar", version: v.hangar});
|
|
||||||
} else if (url.includes("uexcorp.space")) {
|
|
||||||
data["UEX"] = await _getJsonData("zh-CN-uex.json", {cacheKey: "uex", version: v.uex});
|
|
||||||
} else if (url.includes("erkul.games")) {
|
|
||||||
data["DPS"] = await _getJsonData("zh-CN-dps.json", {cacheKey: "dps", version: v.dps});
|
|
||||||
}
|
|
||||||
// update data
|
|
||||||
let replaceWords = [];
|
|
||||||
|
|
||||||
function addLocalizationResource(key) {
|
|
||||||
replaceWords.push(...getLocalizationResource(data, key));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (url.includes("robertsspaceindustries.com")) {
|
|
||||||
const org = "https://robertsspaceindustries.com/orgs";
|
|
||||||
const citizens = "https://robertsspaceindustries.com/citizens";
|
|
||||||
const organization = "https://robertsspaceindustries.com/account/organization";
|
|
||||||
const concierge = "https://robertsspaceindustries.com/account/concierge";
|
|
||||||
const referral = "https://robertsspaceindustries.com/account/referral-program";
|
|
||||||
const address = "https://robertsspaceindustries.com/account/addresses";
|
|
||||||
const hangar = "https://robertsspaceindustries.com/account/pledges";
|
|
||||||
const spectrum = "https://robertsspaceindustries.com/spectrum/community/";
|
|
||||||
if (url.startsWith(spectrum)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
addLocalizationResource("zh-CN");
|
|
||||||
if (url.startsWith(org) || url.startsWith(citizens) || url.startsWith(organization)) {
|
|
||||||
replaceWords.push({"word": 'members', "replacement": '名成员'});
|
|
||||||
addLocalizationResource("orgs");
|
|
||||||
}
|
|
||||||
if (url.startsWith(address)) {
|
|
||||||
addLocalizationResource("address");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (url.startsWith(referral)) {
|
|
||||||
replaceWords.push(
|
|
||||||
{"word": 'Total recruits: ', "replacement": '总邀请数:'},
|
|
||||||
{"word": 'Prospects ', "replacement": '未完成的邀请'},
|
|
||||||
{"word": 'Recruits', "replacement": '已完成的邀请'}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (url.startsWith(concierge)) {
|
|
||||||
replaceWords = [];
|
|
||||||
addLocalizationResource("concierge");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (url.startsWith(hangar)) {
|
|
||||||
addLocalizationResource("hangar");
|
|
||||||
}
|
|
||||||
} else if (url.includes("uexcorp.space")) {
|
|
||||||
addLocalizationResource("UEX");
|
|
||||||
} else if (url.includes("erkul.games")) {
|
|
||||||
addLocalizationResource("DPS");
|
|
||||||
}
|
|
||||||
return replaceWords;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function getLocalizationResource(localizationResource, key) {
|
|
||||||
const localizations = [];
|
|
||||||
const dict = localizationResource[key];
|
|
||||||
if (typeof dict === "object") {
|
|
||||||
for (const [k, v] of Object.entries(dict)) {
|
|
||||||
const trimmedKey = k
|
|
||||||
.toString()
|
|
||||||
.trim()
|
|
||||||
.toLowerCase()
|
|
||||||
.replace(/\xa0/g, ' ')
|
|
||||||
.replace(/\s{2,}/g, ' ');
|
|
||||||
localizations.push({"word": trimmedKey, "replacement": v.toString()});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return localizations;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function _getJsonData(fileName, {cacheKey = "", version = null} = {}) {
|
|
||||||
url = "https://git.scbox.xkeyc.cn/SCToolBox/ScWeb_Chinese_Translate/raw/branch/main/json/locales/" + fileName;
|
|
||||||
if (cacheKey && cacheKey !== "") {
|
|
||||||
const localVersion = await getLocalData(`${cacheKey}_version`);
|
|
||||||
const data = await getLocalData(cacheKey);
|
|
||||||
if (data && typeof data === 'object' && Object.keys(data).length > 0 && localVersion === version) {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const startTime = new Date();
|
|
||||||
const response = await fetch(url, {method: 'GET', mode: 'cors'});
|
|
||||||
const endTime = new Date();
|
|
||||||
const data = await response.json();
|
|
||||||
if (cacheKey && cacheKey !== "") {
|
|
||||||
console.log(`update ${cacheKey} v == ${version} time == ${(endTime - startTime) / 1000}s`);
|
|
||||||
await setLocalData(cacheKey, data);
|
|
||||||
await setLocalData(`${cacheKey}_version`, version);
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLocalData(key) {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
chrome.storage.local.get([key], (result) => {
|
|
||||||
const data = result[key];
|
|
||||||
resolve(data || null);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function setLocalData(key, data) {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
const newData = {};
|
|
||||||
newData[key] = data;
|
|
||||||
chrome.storage.local.set(newData, () => {
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,194 +0,0 @@
|
|||||||
let SCLocalizationReplaceLocalesMap = {};
|
|
||||||
let SCLocalizationEnableSplitMode = false;
|
|
||||||
|
|
||||||
function InitWebLocalization() {
|
|
||||||
// init script
|
|
||||||
LocalizationWatchUpdate();
|
|
||||||
// load Data
|
|
||||||
_loadLocalizationData();
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (window.location.href.includes("robertsspaceindustries.com")) {
|
|
||||||
console.log("SCLocalizationEnableSplitMode = true");
|
|
||||||
SCLocalizationEnableSplitMode = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window.location.hostname.includes("www.erkul.games")) {
|
|
||||||
document.body.addEventListener("click", function (event) {
|
|
||||||
setTimeout(function () {
|
|
||||||
allTranslate().then(_ => {
|
|
||||||
});
|
|
||||||
}, 200);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function WebLocalizationUpdateReplaceWords(w) {
|
|
||||||
let replaceWords = w.sort(function (a, b) {
|
|
||||||
return b.word.length - a.word.length;
|
|
||||||
});
|
|
||||||
replaceWords.forEach(({word, replacement}) => {
|
|
||||||
SCLocalizationReplaceLocalesMap[word] = replacement;
|
|
||||||
});
|
|
||||||
if (window.location.hostname.startsWith("issue-council.robertsspaceindustries.com")) {
|
|
||||||
SCLocalizationReplaceLocalesMap["save"] = "保存";
|
|
||||||
}
|
|
||||||
allTranslate().then(_ => {
|
|
||||||
});
|
|
||||||
// console.log("WebLocalizationUpdateReplaceWords ==" + w)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function allTranslate() {
|
|
||||||
async function replaceTextNode(node1) {
|
|
||||||
if (node1.nodeType === Node.TEXT_NODE) {
|
|
||||||
node1.nodeValue = GetSCLocalizationTranslateString(node1.nodeValue);
|
|
||||||
} 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';
|
|
||||||
}
|
|
||||||
el[k] = GetSCLocalizationTranslateString(el[k]);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
function GetSCLocalizationTranslateString(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 + " 战争债券版"
|
|
||||||
} else {
|
|
||||||
finalString = finalString + " 标准版"
|
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
} 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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return txtSrc
|
|
||||||
}
|
|
||||||
|
|
||||||
InitWebLocalization();
|
|
||||||
|
|
||||||
function _loadLocalizationData() {
|
|
||||||
chrome.runtime.sendMessage({action: "_loadLocalizationData", url: window.location.href}, function (response) {
|
|
||||||
WebLocalizationUpdateReplaceWords(response.result);
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,100 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>星际公民盒子浏览器拓展</title>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
background-color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
border-radius: 8px;
|
|
||||||
background-color: rgba(255, 255, 255, 0.3);
|
|
||||||
padding: 10px;
|
|
||||||
margin: 10px;
|
|
||||||
width: 250px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
text-align: center;
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card img,
|
|
||||||
.card svg {
|
|
||||||
height: 60px;
|
|
||||||
width: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card a {
|
|
||||||
text-decoration: none;
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card h3,
|
|
||||||
.card p {
|
|
||||||
margin: 5px 0;
|
|
||||||
/* 上下间距为5px,左右间距为0 */
|
|
||||||
}
|
|
||||||
|
|
||||||
.card a:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div class="card" style="padding-top: 0; padding-bottom: 0; border-radius: 0;">
|
|
||||||
<a href="https://github.com/xkeyC/StarCitizenBoxBrowserEx" target="_blank">
|
|
||||||
<div>
|
|
||||||
<h2>星际公民盒子浏览器拓展</h2>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card">
|
|
||||||
<a href="https://robertsspaceindustries.com/" target="_blank">
|
|
||||||
<svg viewBox="0 0 56 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
|
||||||
d="M16.0716 0C17.111 0 17.7697 0.734004 17.5824 1.65153L17.5516 1.77773L16.4646 5.68023C16.2499 6.48564 15.6763 7.15995 14.9845 7.52983L14.8228 7.6097L11.6546 9.08403L12.3485 11.8374C12.4102 12.0494 12.6179 12.227 12.8583 12.2638L12.9497 12.2708H15.0308L14.0135 16H10.7299C9.96799 16 9.22678 15.4621 8.98803 14.8024L8.94926 14.6774L7.95482 10.8185L5.17986 12.1191L4.11629 16H0L4.34743 0H16.0716ZM30.028 0L30.0255 0.00849999L29.0084 3.71374L29.0048 3.72704H29.0004L22.8229 3.71374C22.4538 3.71374 22.1768 3.84407 22.0843 4.19052C22.0024 4.49868 22.1027 4.73832 22.3854 4.94011L22.4999 5.01406L29.1008 9.10927C29.7285 9.49516 30.0921 10.3574 29.9828 11.0527L29.9546 11.1894L29.0084 14.6781C28.8348 15.3511 28.0883 15.9282 27.3084 15.9938L27.1619 16H18.8519L19.8686 12.2728H24.8772C25.2464 12.2728 25.5232 12.0346 25.5925 11.8178C25.6756 11.5644 25.6278 11.3636 25.3483 11.1522L25.2464 11.0812L18.5995 6.92095C17.9719 6.53476 17.6081 5.67281 17.7173 4.97743L17.7455 4.84076L18.6914 1.33023C18.8654 0.657352 19.5912 0.0802618 20.3495 0.0146972L20.492 0.00849999L30.0218 0H30.028ZM34.8758 0L39.0028 0.00849999L34.6207 16H30.4473L34.8566 0.00849999H34.8735L34.8758 0ZM17.698 12.2956L16.6916 16H16.0205L17.0206 12.2956H17.698ZM16.356 12.2956L15.313 16H14.5946L15.6471 12.3028L15.6493 12.2956H16.356ZM19.124 12.2956L18.0887 16H17.3625L18.398 12.2956H19.124ZM12.2017 3.70443H7.46927L6.45853 7.48768L12.0409 4.81988C12.5006 4.60106 12.6614 4.33872 12.7304 4.12006C12.8222 3.83596 12.5694 3.70443 12.2017 3.70443ZM34.1379 0L33.1305 3.70443H32.4604L33.474 0H34.1379ZM32.712 0L31.7062 3.70443H31.0345L32.0511 0H32.712ZM31.3537 0L31.3515 0.00844828H31.37L30.3313 3.69121L30.3277 3.70443H29.6086L29.6121 3.69121L30.6322 0.00844828L30.6346 0H31.3537Z"
|
|
||||||
fill="currentColor"></path>
|
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
|
||||||
d="M44.0993 0.5C45.1052 0.5 45.71 0.718656 46.0714 1.07635C46.4317 1.43287 46.6502 2.02678 46.6502 3.01365C46.6502 4.00008 46.4317 4.58521 46.0739 4.93447C45.7133 5.28641 45.1085 5.5 44.0993 5.5C43.0905 5.5 42.4701 5.28657 42.0962 4.9303C41.7277 4.57908 41.5 3.99382 41.5 3.01365C41.5 2.03297 41.7277 1.43898 42.0987 1.08055C42.4734 0.718531 43.0938 0.5 44.0993 0.5ZM47.1502 3.01365C47.1502 0.918004 46.2283 0 44.0993 0C41.9703 0 41 0.918004 41 3.01365C41 5.10816 41.9703 6 44.0993 6C46.2283 6 47.1502 5.10816 47.1502 3.01365ZM42.7675 1.363C43.2445 1.318 43.717 1.3 44.194 1.3C45.157 1.3 45.4855 1.633 45.4855 2.5105C45.4855 3.154 45.319 3.4555 44.842 3.577L45.607 4.7965C45.643 4.846 45.6205 4.8865 45.553 4.8865H44.725C44.6215 4.8865 44.59 4.855 44.545 4.7875L43.816 3.6355H43.645V4.8145C43.645 4.873 43.6315 4.8865 43.5775 4.8865H42.7675C42.7135 4.8865 42.7 4.873 42.7 4.8145V1.4215C42.7 1.381 42.7135 1.3675 42.7675 1.363ZM44.527 2.542C44.527 2.2495 44.428 2.1235 44.0905 2.1235H43.645V2.9425H44.0905C44.428 2.9425 44.527 2.839 44.527 2.542Z"
|
|
||||||
fill="currentColor"></path>
|
|
||||||
</svg>
|
|
||||||
<h3>星际公民官网</h3>
|
|
||||||
<p>罗伯茨航天工业公司,万物的起源</p>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card">
|
|
||||||
<a href="https://uexcorp.space" target="_blank">
|
|
||||||
<img src="https://assets.uexcorp.space/img/logo.svg" alt="">
|
|
||||||
<h3>UEX</h3>
|
|
||||||
<p>采矿、精炼、贸易计算器、价格、船信息</p>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card">
|
|
||||||
<a href="https://www.erkul.games/live/calculator" target="_blank">
|
|
||||||
<img src="https://www.erkul.games/assets/icons/icon-512x512.png">
|
|
||||||
<h3>DPS 计算器</h3>
|
|
||||||
<p>在线改船,查询伤害数值和配件购买地点</p>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card">
|
|
||||||
<a href="https://ccugame.app" target="_blank">
|
|
||||||
<img src="https://ccugame.app/assets/images/logo/logo.png">
|
|
||||||
<h3>CCUGame(官方汉化)</h3>
|
|
||||||
<p>资产管理和舰队规划,一定要理性消费.jpg</p>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,4 +1,20 @@
|
|||||||
let dataVersion = null
|
interface VersionData {
|
||||||
|
rsi: string;
|
||||||
|
concierge: string;
|
||||||
|
orgs: string;
|
||||||
|
addresses: string;
|
||||||
|
hangar: string;
|
||||||
|
uex: string;
|
||||||
|
dps: string;
|
||||||
|
[key: string]: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ReplaceWord {
|
||||||
|
word: string;
|
||||||
|
replacement: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
let dataVersion: VersionData | null = null
|
||||||
|
|
||||||
chrome.runtime.onInstalled.addListener(function () {
|
chrome.runtime.onInstalled.addListener(function () {
|
||||||
_checkVersion().then(_ => {
|
_checkVersion().then(_ => {
|
||||||
@ -15,13 +31,12 @@ chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
async function _checkVersion() {
|
async function _checkVersion(): Promise<void> {
|
||||||
dataVersion = await _getJsonData("versions.json");
|
dataVersion = await _getJsonData("versions.json") as VersionData;
|
||||||
console.log("Localization Version ===");
|
console.log("Localization Version ===", dataVersion);
|
||||||
console.log(dataVersion);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _initLocalization(url) {
|
async function _initLocalization(url: string): Promise<ReplaceWord[]> {
|
||||||
console.log("url ===" + url);
|
console.log("url ===" + url);
|
||||||
if (dataVersion == null) {
|
if (dataVersion == null) {
|
||||||
await _checkVersion();
|
await _checkVersion();
|
||||||
@ -29,23 +44,31 @@ async function _initLocalization(url) {
|
|||||||
}
|
}
|
||||||
let v = dataVersion
|
let v = dataVersion
|
||||||
// TODO check version
|
// TODO check version
|
||||||
let data = {};
|
let data: Record<string, any> = {};
|
||||||
|
|
||||||
if (url.includes("robertsspaceindustries.com")) {
|
if (url.includes("robertsspaceindustries.com")) {
|
||||||
data["zh-CN"] = await _getJsonData("zh-CN-rsi.json", {cacheKey: "zh-CN", version: v.rsi});
|
data["zh-CN"] = await _getJsonData("zh-CN-rsi.json", {cacheKey: "zh-CN", version: v.rsi});
|
||||||
data["concierge"] = await _getJsonData("concierge.json", {cacheKey: "concierge", version: v.concierge});
|
data["concierge"] = await _getJsonData("concierge.json", {cacheKey: "concierge", version: v.concierge});
|
||||||
data["orgs"] = await _getJsonData("orgs.json", v.orgs);
|
data["orgs"] = await _getJsonData("orgs.json", {cacheKey: "orgs", version: v.orgs});
|
||||||
data["address"] = await _getJsonData("addresses.json", {cacheKey: "orgs", version: v.addresses});
|
data["address"] = await _getJsonData("addresses.json", {cacheKey: "orgs", version: v.addresses});
|
||||||
data["hangar"] = await _getJsonData("hangar.json", {cacheKey: "hangar", version: v.hangar});
|
data["hangar"] = await _getJsonData("hangar.json", {cacheKey: "hangar", version: v.hangar});
|
||||||
} else if (url.includes("uexcorp.space")) {
|
} else if (url.includes("uexcorp.space")) {
|
||||||
data["UEX"] = await _getJsonData("zh-CN-uex.json", {cacheKey: "uex", version: v.uex});
|
data["UEX"] = await _getJsonData("zh-CN-uex.json", {cacheKey: "uex", version: v.uex});
|
||||||
} else if (url.includes("erkul.games")) {
|
} else if (url.includes("erkul.games")) {
|
||||||
data["DPS"] = await _getJsonData("zh-CN-dps.json", {cacheKey: "dps", version: v.dps});
|
data["DPS"] = await _getJsonData("zh-CN-dps.json", {cacheKey: "dps", version: v.dps});
|
||||||
|
} else if (url.includes("manual")) {
|
||||||
|
data["zh-CN"] = await _getJsonData("zh-CN-rsi.json", {cacheKey: "zh-CN", version: v.rsi});
|
||||||
|
data["concierge"] = await _getJsonData("concierge.json", {cacheKey: "concierge", version: v.concierge});
|
||||||
|
data["orgs"] = await _getJsonData("orgs.json", {cacheKey: "orgs", version: v.orgs});
|
||||||
|
data["address"] = await _getJsonData("addresses.json", {cacheKey: "orgs", version: v.addresses});
|
||||||
|
data["hangar"] = await _getJsonData("hangar.json", {cacheKey: "hangar", version: v.hangar});
|
||||||
|
data["UEX"] = await _getJsonData("zh-CN-uex.json", {cacheKey: "uex", version: v.uex});
|
||||||
|
data["DPS"] = await _getJsonData("zh-CN-dps.json", {cacheKey: "dps", version: v.dps});
|
||||||
}
|
}
|
||||||
// update data
|
// update data
|
||||||
let replaceWords = [];
|
let replaceWords: ReplaceWord[] = [];
|
||||||
|
|
||||||
function addLocalizationResource(key) {
|
function addLocalizationResource(key: string): void {
|
||||||
replaceWords.push(...getLocalizationResource(data, key));
|
replaceWords.push(...getLocalizationResource(data, key));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +82,7 @@ async function _initLocalization(url) {
|
|||||||
const hangar = "https://robertsspaceindustries.com/account/pledges";
|
const hangar = "https://robertsspaceindustries.com/account/pledges";
|
||||||
const spectrum = "https://robertsspaceindustries.com/spectrum/community/";
|
const spectrum = "https://robertsspaceindustries.com/spectrum/community/";
|
||||||
if (url.startsWith(spectrum)) {
|
if (url.startsWith(spectrum)) {
|
||||||
return;
|
return [];
|
||||||
}
|
}
|
||||||
addLocalizationResource("zh-CN");
|
addLocalizationResource("zh-CN");
|
||||||
if (url.startsWith(org) || url.startsWith(citizens) || url.startsWith(organization)) {
|
if (url.startsWith(org) || url.startsWith(citizens) || url.startsWith(organization)) {
|
||||||
@ -90,13 +113,27 @@ async function _initLocalization(url) {
|
|||||||
addLocalizationResource("UEX");
|
addLocalizationResource("UEX");
|
||||||
} else if (url.includes("erkul.games")) {
|
} else if (url.includes("erkul.games")) {
|
||||||
addLocalizationResource("DPS");
|
addLocalizationResource("DPS");
|
||||||
|
} else if (url.includes("manual")) {
|
||||||
|
addLocalizationResource("zh-CN");
|
||||||
|
replaceWords.push({"word": 'members', "replacement": '名成员'});
|
||||||
|
addLocalizationResource("orgs");
|
||||||
|
addLocalizationResource("address");
|
||||||
|
replaceWords.push(
|
||||||
|
{"word": 'Total recruits: ', "replacement": '总邀请数:'},
|
||||||
|
{"word": 'Prospects ', "replacement": '未完成的邀请'},
|
||||||
|
{"word": 'Recruits', "replacement": '已完成的邀请'}
|
||||||
|
);
|
||||||
|
addLocalizationResource("concierge");
|
||||||
|
addLocalizationResource("hangar");
|
||||||
|
addLocalizationResource("UEX");
|
||||||
|
addLocalizationResource("DPS");
|
||||||
}
|
}
|
||||||
return replaceWords;
|
return replaceWords;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function getLocalizationResource(localizationResource, key) {
|
function getLocalizationResource(localizationResource: Record<string, any>, key: string): ReplaceWord[] {
|
||||||
const localizations = [];
|
const localizations: ReplaceWord[] = [];
|
||||||
const dict = localizationResource[key];
|
const dict = localizationResource[key];
|
||||||
if (typeof dict === "object") {
|
if (typeof dict === "object") {
|
||||||
for (const [k, v] of Object.entries(dict)) {
|
for (const [k, v] of Object.entries(dict)) {
|
||||||
@ -106,14 +143,20 @@ function getLocalizationResource(localizationResource, key) {
|
|||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.replace(/\xa0/g, ' ')
|
.replace(/\xa0/g, ' ')
|
||||||
.replace(/\s{2,}/g, ' ');
|
.replace(/\s{2,}/g, ' ');
|
||||||
localizations.push({"word": trimmedKey, "replacement": v.toString()});
|
localizations.push({"word": trimmedKey, "replacement": String(v)});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return localizations;
|
return localizations;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _getJsonData(fileName, {cacheKey = "", version = null} = {}) {
|
interface JsonDataOptions {
|
||||||
url = "https://git.scbox.xkeyc.cn/SCToolBox/ScWeb_Chinese_Translate/raw/branch/main/json/locales/" + fileName;
|
cacheKey?: string;
|
||||||
|
version?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function _getJsonData(fileName: string, options: JsonDataOptions = {}): Promise<any> {
|
||||||
|
const { cacheKey = "", version = null } = options;
|
||||||
|
const url = "https://git.scbox.xkeyc.cn/SCToolBox/ScWeb_Chinese_Translate/raw/branch/main/json/locales/" + fileName;
|
||||||
if (cacheKey && cacheKey !== "") {
|
if (cacheKey && cacheKey !== "") {
|
||||||
const localVersion = await getLocalData(`${cacheKey}_version`);
|
const localVersion = await getLocalData(`${cacheKey}_version`);
|
||||||
const data = await getLocalData(cacheKey);
|
const data = await getLocalData(cacheKey);
|
||||||
@ -126,14 +169,15 @@ async function _getJsonData(fileName, {cacheKey = "", version = null} = {}) {
|
|||||||
const endTime = new Date();
|
const endTime = new Date();
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
if (cacheKey && cacheKey !== "") {
|
if (cacheKey && cacheKey !== "") {
|
||||||
console.log(`update ${cacheKey} v == ${version} time == ${(endTime - startTime) / 1000}s`);
|
const timeDiff = endTime.getTime() - startTime.getTime();
|
||||||
|
console.log(`update ${cacheKey} v == ${version} time == ${timeDiff / 1000}s`);
|
||||||
await setLocalData(cacheKey, data);
|
await setLocalData(cacheKey, data);
|
||||||
await setLocalData(`${cacheKey}_version`, version);
|
await setLocalData(`${cacheKey}_version`, version);
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getLocalData(key) {
|
function getLocalData(key: string): Promise<any> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
chrome.storage.local.get([key], (result) => {
|
chrome.storage.local.get([key], (result) => {
|
||||||
const data = result[key];
|
const data = result[key];
|
||||||
@ -142,12 +186,34 @@ function getLocalData(key) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function setLocalData(key, data) {
|
function setLocalData(key: string, data: any): Promise<void> {
|
||||||
return new Promise((resolve) => {
|
return new Promise<void>((resolve) => {
|
||||||
const newData = {};
|
const newData: Record<string, any> = {};
|
||||||
newData[key] = data;
|
newData[key] = data;
|
||||||
chrome.storage.local.set(newData, () => {
|
chrome.storage.local.set(newData, () => {
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chrome.runtime.onInstalled.addListener(function () {
|
||||||
|
chrome.contextMenus.create({
|
||||||
|
id: "translate",
|
||||||
|
title: "切换翻译",
|
||||||
|
contexts: ["all"]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
chrome.contextMenus.onClicked.addListener((info, tab) => {
|
||||||
|
console.log("contextMenus", info, tab);
|
||||||
|
let passedUrl = "manual";
|
||||||
|
const supportedSites = ["robertsspaceindustries.com", "erkul.games", "uexcorp.space"];
|
||||||
|
if (tab && tab.url && supportedSites.find(site => tab.url!.includes(site))) {
|
||||||
|
passedUrl = tab.url;
|
||||||
|
}
|
||||||
|
_initLocalization(passedUrl).then(data => {
|
||||||
|
if (tab && tab.id !== undefined) {
|
||||||
|
chrome.tabs.sendMessage(tab.id, {action: "_toggleTranslation", data});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
297
core.ts
Normal file
297
core.ts
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
declare const $: any;
|
||||||
|
declare const timeago: any;
|
||||||
|
|
||||||
|
let SCLocalizationReplaceLocalesMap: Record<string, string> = {};
|
||||||
|
let SCLocalizationEnableSplitMode = false;
|
||||||
|
let SCLocalizationTranslating = false;
|
||||||
|
|
||||||
|
function InitWebLocalization() {
|
||||||
|
// init script
|
||||||
|
LocalizationWatchUpdate();
|
||||||
|
// load Data
|
||||||
|
_loadLocalizationData();
|
||||||
|
}
|
||||||
|
|
||||||
|
function LocalizationWatchUpdate() {
|
||||||
|
const m = window.MutationObserver || (window as any).WebKitMutationObserver;
|
||||||
|
const observer = new m(function (mutations: MutationRecord[], observer: MutationObserver) {
|
||||||
|
for (let mutationRecord of mutations) {
|
||||||
|
for (let node of mutationRecord.addedNodes) {
|
||||||
|
traverseElement(node as Element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(document.body, {
|
||||||
|
subtree: true,
|
||||||
|
characterData: true,
|
||||||
|
childList: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (window.location.href.includes("robertsspaceindustries.com")) {
|
||||||
|
SCLocalizationEnableSplitMode = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.location.hostname.includes("www.erkul.games")) {
|
||||||
|
document.body.addEventListener("click", function (event) {
|
||||||
|
setTimeout(function () {
|
||||||
|
allTranslate().then(_ => {
|
||||||
|
});
|
||||||
|
}, 200);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function WebLocalizationUpdateReplaceWords(w: { word: string, replacement: string }[]) {
|
||||||
|
let replaceWords = w.sort(function (a, b) {
|
||||||
|
return b.word.length - a.word.length;
|
||||||
|
});
|
||||||
|
replaceWords.forEach(({ word, replacement }) => {
|
||||||
|
SCLocalizationReplaceLocalesMap[word] = replacement;
|
||||||
|
});
|
||||||
|
if (window.location.hostname.startsWith("issue-council.robertsspaceindustries.com")) {
|
||||||
|
SCLocalizationReplaceLocalesMap["save"] = "保存";
|
||||||
|
}
|
||||||
|
allTranslate().then(_ => {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function allTranslate() {
|
||||||
|
async function replaceTextNode(node: Node, parentNode?: Element) {
|
||||||
|
if (node.nodeType === Node.TEXT_NODE) {
|
||||||
|
// 保存原始文本内容
|
||||||
|
const originalText = node.nodeValue || '';
|
||||||
|
const translatedText = GetSCLocalizationTranslateString(originalText);
|
||||||
|
|
||||||
|
// 只有当文本发生变化时才保存原始文本
|
||||||
|
if (originalText !== translatedText && parentNode) {
|
||||||
|
const originalValue = parentNode.getAttribute('data-original-value') || "";
|
||||||
|
parentNode.setAttribute('data-original-value', originalValue + originalText);
|
||||||
|
node.nodeValue = translatedText;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let i = 0; i < node.childNodes.length; i++) {
|
||||||
|
await replaceTextNode(node.childNodes[i], node as Element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await replaceTextNode(document.body, document.body);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function undoTranslate(): Promise<{success: boolean}> {
|
||||||
|
SCLocalizationTranslating = false;
|
||||||
|
|
||||||
|
document.querySelectorAll('*[data-original-value]').forEach((element: Element) => {
|
||||||
|
(element as HTMLElement).innerText = element.getAttribute('data-original-value') || '';
|
||||||
|
element.removeAttribute('data-original-value');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 处理输入元素
|
||||||
|
const inputElements = document.querySelectorAll('input[type="button"], input[type="submit"], input[type="text"], input[type="password"]');
|
||||||
|
inputElements.forEach((el: Element) => {
|
||||||
|
// 尝试从 data-original-value 属性恢复原始值
|
||||||
|
if (el.hasAttribute('data-original-value')) {
|
||||||
|
if ((el as HTMLInputElement).type === 'button' || (el as HTMLInputElement).type === 'submit') {
|
||||||
|
(el as HTMLInputElement).value = el.getAttribute('data-original-value') || '';
|
||||||
|
} else {
|
||||||
|
(el as HTMLInputElement).placeholder = el.getAttribute('data-original-value') || '';
|
||||||
|
}
|
||||||
|
el.removeAttribute('data-original-value');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
window.postMessage({ type: 'TOGGLED-SC-BOX-TRANSLATE', action: 'off' }, '*');
|
||||||
|
|
||||||
|
return Promise.resolve({ success: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
function traverseElement(el: Element) {
|
||||||
|
if (!SCLocalizationTranslating) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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, el);
|
||||||
|
} else if (child.nodeType === Node.ELEMENT_NODE) {
|
||||||
|
if ((child as Element).tagName === "INPUT") {
|
||||||
|
translateElement(child, el);
|
||||||
|
} else {
|
||||||
|
traverseElement(child as Element);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function translateElement(el: any, parentNode: any) {
|
||||||
|
// Get the text field name
|
||||||
|
let k;
|
||||||
|
let translatedText;
|
||||||
|
if (el.tagName === "INPUT") {
|
||||||
|
if (el.type === 'button' || el.type === 'submit') {
|
||||||
|
k = 'value';
|
||||||
|
} else {
|
||||||
|
k = 'placeholder';
|
||||||
|
}
|
||||||
|
|
||||||
|
translatedText = GetSCLocalizationTranslateString(el[k]);
|
||||||
|
if (el[k] === translatedText) return;
|
||||||
|
|
||||||
|
const originalValue = parentNode.getAttribute('data-original-value') || "";
|
||||||
|
el.setAttribute('data-original-value', originalValue + el[k]);
|
||||||
|
} else {
|
||||||
|
k = 'data';
|
||||||
|
|
||||||
|
translatedText = GetSCLocalizationTranslateString(el[k]);
|
||||||
|
if (el[k] === translatedText) return;
|
||||||
|
|
||||||
|
const originalValue = parentNode.getAttribute('data-original-value') || "";
|
||||||
|
parentNode.setAttribute('data-original-value', originalValue + el[k]);
|
||||||
|
}
|
||||||
|
el[k] = translatedText;
|
||||||
|
}
|
||||||
|
|
||||||
|
function translateRelativeTimeEl(el: Element) {
|
||||||
|
const lang = (navigator.language || navigator.language);
|
||||||
|
const datetime = ($ as any)(el).attr('datetime');
|
||||||
|
($ as any)(el).text((timeago as any).format(datetime, lang.replace('-', '_')));
|
||||||
|
}
|
||||||
|
|
||||||
|
function shouldTranslateEl(el: Element) {
|
||||||
|
const blockIds: string[] = [];
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
function GetSCLocalizationTranslateString(txtSrc: string) {
|
||||||
|
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 + " 战争债券版"
|
||||||
|
} else {
|
||||||
|
finalString = finalString + " 标准版"
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
} 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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return txtSrc
|
||||||
|
}
|
||||||
|
|
||||||
|
InitWebLocalization();
|
||||||
|
|
||||||
|
function _loadLocalizationData() {
|
||||||
|
chrome.runtime.sendMessage({ action: "_loadLocalizationData", url: window.location.href }, function (response) {
|
||||||
|
// console.log("response ===" + JSON.stringify(response));
|
||||||
|
if (response.result.length > 0) {
|
||||||
|
SCLocalizationTranslating = true;
|
||||||
|
WebLocalizationUpdateReplaceWords(response.result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||||
|
if (request.action === "_toggleTranslation") {
|
||||||
|
if (SCLocalizationTranslating) {
|
||||||
|
SCLocalizationTranslating = false;
|
||||||
|
undoTranslate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SCLocalizationTranslating = true;
|
||||||
|
SCLocalizationEnableSplitMode = true;
|
||||||
|
window.postMessage({ type: 'TOGGLED-SC-BOX-TRANSLATE', action: 'on' }, '*');
|
||||||
|
WebLocalizationUpdateReplaceWords(request.data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('message', async (event) => {
|
||||||
|
if (event.source !== window || !event.data || event.data.type !== 'SC_TRANSLATE_REQUEST') return;
|
||||||
|
|
||||||
|
const { action } = event.data;
|
||||||
|
|
||||||
|
let response: {success: boolean, error?: string} = { success: false };
|
||||||
|
|
||||||
|
if (action === 'translate') {
|
||||||
|
try {
|
||||||
|
SCLocalizationEnableSplitMode = true;
|
||||||
|
chrome.runtime.sendMessage({ action: "_loadLocalizationData", url: "manual" }, function (response) {
|
||||||
|
SCLocalizationTranslating = true;
|
||||||
|
window.postMessage({ type: 'TOGGLED-SC-BOX-TRANSLATE', action: 'on' }, '*');
|
||||||
|
WebLocalizationUpdateReplaceWords(response.result);
|
||||||
|
});
|
||||||
|
response = { success: true };
|
||||||
|
} catch (error: any) {
|
||||||
|
response = { success: false, error: error.message };
|
||||||
|
}
|
||||||
|
} else if (action === 'undoTranslate') {
|
||||||
|
try {
|
||||||
|
response = await undoTranslate();
|
||||||
|
} catch (error: any) {
|
||||||
|
response = { success: false, error: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
window.postMessage({ type: 'SC-BOX-TRANSLATE-API-AVAILABLE' }, '*');
|
93
dist/chrome/action/default_popup.html
vendored
Normal file
93
dist/chrome/action/default_popup.html
vendored
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
<!DOCTYPE html><html><head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>星际公民盒子浏览器拓展</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: rgba(255, 255, 255, 0.3);
|
||||||
|
padding: 10px;
|
||||||
|
margin: 10px;
|
||||||
|
width: 250px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card img,
|
||||||
|
.card svg {
|
||||||
|
height: 60px;
|
||||||
|
width: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card h3,
|
||||||
|
.card p {
|
||||||
|
margin: 5px 0;
|
||||||
|
/* 上下间距为5px,左右间距为0 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.card a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="card" style="padding-top: 0; padding-bottom: 0; border-radius: 0;">
|
||||||
|
<a href="https://github.com/xkeyC/StarCitizenBoxBrowserEx" target="_blank">
|
||||||
|
<div>
|
||||||
|
<h2>星际公民盒子浏览器拓展</h2>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<a href="https://robertsspaceindustries.com/" target="_blank">
|
||||||
|
<svg viewBox="0 0 56 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.0716 0C17.111 0 17.7697 0.734004 17.5824 1.65153L17.5516 1.77773L16.4646 5.68023C16.2499 6.48564 15.6763 7.15995 14.9845 7.52983L14.8228 7.6097L11.6546 9.08403L12.3485 11.8374C12.4102 12.0494 12.6179 12.227 12.8583 12.2638L12.9497 12.2708H15.0308L14.0135 16H10.7299C9.96799 16 9.22678 15.4621 8.98803 14.8024L8.94926 14.6774L7.95482 10.8185L5.17986 12.1191L4.11629 16H0L4.34743 0H16.0716ZM30.028 0L30.0255 0.00849999L29.0084 3.71374L29.0048 3.72704H29.0004L22.8229 3.71374C22.4538 3.71374 22.1768 3.84407 22.0843 4.19052C22.0024 4.49868 22.1027 4.73832 22.3854 4.94011L22.4999 5.01406L29.1008 9.10927C29.7285 9.49516 30.0921 10.3574 29.9828 11.0527L29.9546 11.1894L29.0084 14.6781C28.8348 15.3511 28.0883 15.9282 27.3084 15.9938L27.1619 16H18.8519L19.8686 12.2728H24.8772C25.2464 12.2728 25.5232 12.0346 25.5925 11.8178C25.6756 11.5644 25.6278 11.3636 25.3483 11.1522L25.2464 11.0812L18.5995 6.92095C17.9719 6.53476 17.6081 5.67281 17.7173 4.97743L17.7455 4.84076L18.6914 1.33023C18.8654 0.657352 19.5912 0.0802618 20.3495 0.0146972L20.492 0.00849999L30.0218 0H30.028ZM34.8758 0L39.0028 0.00849999L34.6207 16H30.4473L34.8566 0.00849999H34.8735L34.8758 0ZM17.698 12.2956L16.6916 16H16.0205L17.0206 12.2956H17.698ZM16.356 12.2956L15.313 16H14.5946L15.6471 12.3028L15.6493 12.2956H16.356ZM19.124 12.2956L18.0887 16H17.3625L18.398 12.2956H19.124ZM12.2017 3.70443H7.46927L6.45853 7.48768L12.0409 4.81988C12.5006 4.60106 12.6614 4.33872 12.7304 4.12006C12.8222 3.83596 12.5694 3.70443 12.2017 3.70443ZM34.1379 0L33.1305 3.70443H32.4604L33.474 0H34.1379ZM32.712 0L31.7062 3.70443H31.0345L32.0511 0H32.712ZM31.3537 0L31.3515 0.00844828H31.37L30.3313 3.69121L30.3277 3.70443H29.6086L29.6121 3.69121L30.6322 0.00844828L30.6346 0H31.3537Z" fill="currentColor"></path>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M44.0993 0.5C45.1052 0.5 45.71 0.718656 46.0714 1.07635C46.4317 1.43287 46.6502 2.02678 46.6502 3.01365C46.6502 4.00008 46.4317 4.58521 46.0739 4.93447C45.7133 5.28641 45.1085 5.5 44.0993 5.5C43.0905 5.5 42.4701 5.28657 42.0962 4.9303C41.7277 4.57908 41.5 3.99382 41.5 3.01365C41.5 2.03297 41.7277 1.43898 42.0987 1.08055C42.4734 0.718531 43.0938 0.5 44.0993 0.5ZM47.1502 3.01365C47.1502 0.918004 46.2283 0 44.0993 0C41.9703 0 41 0.918004 41 3.01365C41 5.10816 41.9703 6 44.0993 6C46.2283 6 47.1502 5.10816 47.1502 3.01365ZM42.7675 1.363C43.2445 1.318 43.717 1.3 44.194 1.3C45.157 1.3 45.4855 1.633 45.4855 2.5105C45.4855 3.154 45.319 3.4555 44.842 3.577L45.607 4.7965C45.643 4.846 45.6205 4.8865 45.553 4.8865H44.725C44.6215 4.8865 44.59 4.855 44.545 4.7875L43.816 3.6355H43.645V4.8145C43.645 4.873 43.6315 4.8865 43.5775 4.8865H42.7675C42.7135 4.8865 42.7 4.873 42.7 4.8145V1.4215C42.7 1.381 42.7135 1.3675 42.7675 1.363ZM44.527 2.542C44.527 2.2495 44.428 2.1235 44.0905 2.1235H43.645V2.9425H44.0905C44.428 2.9425 44.527 2.839 44.527 2.542Z" fill="currentColor"></path>
|
||||||
|
</svg>
|
||||||
|
<h3>星际公民官网</h3>
|
||||||
|
<p>罗伯茨航天工业公司,万物的起源</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<a href="https://uexcorp.space" target="_blank">
|
||||||
|
<img src="https://assets.uexcorp.space/img/logo.svg" alt="">
|
||||||
|
<h3>UEX</h3>
|
||||||
|
<p>采矿、精炼、贸易计算器、价格、船信息</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<a href="https://www.erkul.games/live/calculator" target="_blank">
|
||||||
|
<img src="https://www.erkul.games/assets/icons/icon-512x512.png">
|
||||||
|
<h3>DPS 计算器</h3>
|
||||||
|
<p>在线改船,查询伤害数值和配件购买地点</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<a href="https://ccugame.app" target="_blank">
|
||||||
|
<img src="https://ccugame.app/assets/images/logo/logo.png">
|
||||||
|
<h3>CCUGame(官方汉化)</h3>
|
||||||
|
<p>资产管理和舰队规划,一定要理性消费.jpg</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</body></html>
|
1
dist/chrome/background/service_worker.js
vendored
Normal file
1
dist/chrome/background/service_worker.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
(()=>{var e={},s={};function r(t){var n=s[t];if(void 0!==n)return n.exports;var a=s[t]={exports:{}};return e[t](a,a.exports,r),a.exports}r.rv=()=>"1.3.8",r.ruid="bundler=rspack@1.3.8";let t=null;async function n(){console.log("Localization Version ===",t=await o("versions.json"))}async function a(e){if(console.log("url ==="+e),null==t)return await n(),a(e);let s=t,r={};e.includes("robertsspaceindustries.com")?(r["zh-CN"]=await o("zh-CN-rsi.json",{cacheKey:"zh-CN",version:s.rsi}),r.concierge=await o("concierge.json",{cacheKey:"concierge",version:s.concierge}),r.orgs=await o("orgs.json",{cacheKey:"orgs",version:s.orgs}),r.address=await o("addresses.json",{cacheKey:"orgs",version:s.addresses}),r.hangar=await o("hangar.json",{cacheKey:"hangar",version:s.hangar})):e.includes("uexcorp.space")?r.UEX=await o("zh-CN-uex.json",{cacheKey:"uex",version:s.uex}):e.includes("erkul.games")?r.DPS=await o("zh-CN-dps.json",{cacheKey:"dps",version:s.dps}):e.includes("manual")&&(r["zh-CN"]=await o("zh-CN-rsi.json",{cacheKey:"zh-CN",version:s.rsi}),r.concierge=await o("concierge.json",{cacheKey:"concierge",version:s.concierge}),r.orgs=await o("orgs.json",{cacheKey:"orgs",version:s.orgs}),r.address=await o("addresses.json",{cacheKey:"orgs",version:s.addresses}),r.hangar=await o("hangar.json",{cacheKey:"hangar",version:s.hangar}),r.UEX=await o("zh-CN-uex.json",{cacheKey:"uex",version:s.uex}),r.DPS=await o("zh-CN-dps.json",{cacheKey:"dps",version:s.dps}));let c=[];function i(e){c.push(...function(e,s){let r=[],t=e[s];if("object"==typeof t)for(let[e,s]of Object.entries(t)){let t=e.toString().trim().toLowerCase().replace(/\xa0/g," ").replace(/\s{2,}/g," ");r.push({word:t,replacement:String(s)})}return r}(r,e))}if(e.includes("robertsspaceindustries.com")){if(e.startsWith("https://robertsspaceindustries.com/spectrum/community/"))return[];i("zh-CN"),(e.startsWith("https://robertsspaceindustries.com/orgs")||e.startsWith("https://robertsspaceindustries.com/citizens")||e.startsWith("https://robertsspaceindustries.com/account/organization"))&&(c.push({word:"members",replacement:"名成员"}),i("orgs")),e.startsWith("https://robertsspaceindustries.com/account/addresses")&&i("address"),e.startsWith("https://robertsspaceindustries.com/account/referral-program")&&c.push({word:"Total recruits: ",replacement:"总邀请数:"},{word:"Prospects ",replacement:"未完成的邀请"},{word:"Recruits",replacement:"已完成的邀请"}),e.startsWith("https://robertsspaceindustries.com/account/concierge")&&(c=[],i("concierge")),e.startsWith("https://robertsspaceindustries.com/account/pledges")&&i("hangar")}else e.includes("uexcorp.space")?i("UEX"):e.includes("erkul.games")?i("DPS"):e.includes("manual")&&(i("zh-CN"),c.push({word:"members",replacement:"名成员"}),i("orgs"),i("address"),c.push({word:"Total recruits: ",replacement:"总邀请数:"},{word:"Prospects ",replacement:"未完成的邀请"},{word:"Recruits",replacement:"已完成的邀请"}),i("concierge"),i("hangar"),i("UEX"),i("DPS"));return c}async function o(e,s={}){let{cacheKey:r="",version:t=null}=s;if(r&&""!==r){let e=await c(`${r}_version`),s=await c(r);if(s&&"object"==typeof s&&Object.keys(s).length>0&&e===t)return s}let n=new Date,a=await fetch("https://git.scbox.xkeyc.cn/SCToolBox/ScWeb_Chinese_Translate/raw/branch/main/json/locales/"+e,{method:"GET",mode:"cors"}),u=new Date,l=await a.json();if(r&&""!==r){let e=u.getTime()-n.getTime();console.log(`update ${r} v == ${t} time == ${e/1e3}s`),await i(r,l),await i(`${r}_version`,t)}return l}function c(e){return new Promise(s=>{chrome.storage.local.get([e],r=>{s(r[e]||null)})})}function i(e,s){return new Promise(r=>{let t={};t[e]=s,chrome.storage.local.set(t,()=>{r()})})}chrome.runtime.onInstalled.addListener(function(){n().then(e=>{}),console.log("SWTT init")}),chrome.runtime.onMessage.addListener(function(e,s,r){if("_loadLocalizationData"===e.action)return a(e.url).then(e=>{r({result:e})}),!0}),chrome.runtime.onInstalled.addListener(function(){chrome.contextMenus.create({id:"translate",title:"切换翻译",contexts:["all"]})}),chrome.contextMenus.onClicked.addListener((e,s)=>{console.log("contextMenus",e,s);let r="manual";s&&s.url&&["robertsspaceindustries.com","erkul.games","uexcorp.space"].find(e=>s.url.includes(e))&&(r=s.url),a(r).then(e=>{s&&void 0!==s.id&&chrome.tabs.sendMessage(s.id,{action:"_toggleTranslation",data:e})})})})();
|
1
dist/chrome/content_scripts/content-0.js
vendored
Normal file
1
dist/chrome/content_scripts/content-0.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/chrome/content_scripts/content-1.js
vendored
Normal file
1
dist/chrome/content_scripts/content-1.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/chrome/content_scripts/content-2.js
vendored
Normal file
1
dist/chrome/content_scripts/content-2.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
(()=>{var e={},t={};function r(n){var o=t[n];if(void 0!==o)return o.exports;var a=t[n]={exports:{}};return e[n](a,a.exports,r),a.exports}r.rv=()=>"1.3.8",r.ruid="bundler=rspack@1.3.8",function(){function e(t,r,n,o=100){let a=setInterval(()=>{let e=t.querySelector(r);e&&(clearInterval(a),n(e))},o)}function t(e){if(!e||e.parentNode.querySelector('a[data-cy-id="button"][href="/account/pledges"]'))return;let t=e.cloneNode(!0);t.href="/account/pledges";let r=t.querySelector('span[data-cy-id="button__text"]');r&&(r.innerText="My Hangar");let n=t.querySelector('i[data-cy-id="button__icon"]');n&&(n.className="a-button__icon a-icon -gridView"),e.parentNode.insertBefore(t,e)}e(document,"#sidePanel",r=>{new MutationObserver(r=>{for(let n of r)"childList"===n.type&&n.addedNodes.length>0&&n.addedNodes.forEach(r=>{1===r.nodeType&&e(r,'a[data-cy-id="button"][href="/account/settings"]',e=>{t(e)})})}).observe(r,{childList:!0,subtree:!0});let n=r.querySelector('a[data-cy-id="button"][href="/account/settings"]');n&&t(n)})}()})();
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
60
dist/chrome/manifest.json
vendored
Normal file
60
dist/chrome/manifest.json
vendored
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"manifest_version": 3,
|
||||||
|
"name": "星际公民盒子浏览器拓展",
|
||||||
|
"version": "0.0.11",
|
||||||
|
"description": "为星际公民网站及工具站提供汉化",
|
||||||
|
"author": "xkeyC",
|
||||||
|
"icons": {
|
||||||
|
"16": "icons/icon.png",
|
||||||
|
"48": "icons/icon.png",
|
||||||
|
"192": "icons/icon.png"
|
||||||
|
},
|
||||||
|
"host_permissions": [
|
||||||
|
"https://git.scbox.xkeyc.cn/*"
|
||||||
|
],
|
||||||
|
"permissions": [
|
||||||
|
"storage",
|
||||||
|
"contextMenus"
|
||||||
|
],
|
||||||
|
"action": {
|
||||||
|
"default_popup": "action/default_popup.html"
|
||||||
|
},
|
||||||
|
"background": {
|
||||||
|
"service_worker": "background/service_worker.js"
|
||||||
|
},
|
||||||
|
"content_scripts": [
|
||||||
|
{
|
||||||
|
"matches": [
|
||||||
|
"*://*/*"
|
||||||
|
],
|
||||||
|
"exclude_matches": [
|
||||||
|
"https://robertsspaceindustries.com/spectrum/*"
|
||||||
|
],
|
||||||
|
"js": [
|
||||||
|
"content_scripts/content-0.js"
|
||||||
|
],
|
||||||
|
"run_at": "document_end",
|
||||||
|
"css": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"matches": [
|
||||||
|
"https://www.erkul.games/*"
|
||||||
|
],
|
||||||
|
"js": [
|
||||||
|
"content_scripts/content-1.js"
|
||||||
|
],
|
||||||
|
"run_at": "document_end",
|
||||||
|
"css": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"matches": [
|
||||||
|
"https://robertsspaceindustries.com/*"
|
||||||
|
],
|
||||||
|
"js": [
|
||||||
|
"content_scripts/content-2.js"
|
||||||
|
],
|
||||||
|
"run_at": "document_idle",
|
||||||
|
"css": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
93
dist/firefox/action/default_popup.html
vendored
Normal file
93
dist/firefox/action/default_popup.html
vendored
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
<!DOCTYPE html><html><head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>星际公民盒子浏览器拓展</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: rgba(255, 255, 255, 0.3);
|
||||||
|
padding: 10px;
|
||||||
|
margin: 10px;
|
||||||
|
width: 250px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card img,
|
||||||
|
.card svg {
|
||||||
|
height: 60px;
|
||||||
|
width: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card h3,
|
||||||
|
.card p {
|
||||||
|
margin: 5px 0;
|
||||||
|
/* 上下间距为5px,左右间距为0 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.card a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="card" style="padding-top: 0; padding-bottom: 0; border-radius: 0;">
|
||||||
|
<a href="https://github.com/xkeyC/StarCitizenBoxBrowserEx" target="_blank">
|
||||||
|
<div>
|
||||||
|
<h2>星际公民盒子浏览器拓展</h2>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<a href="https://robertsspaceindustries.com/" target="_blank">
|
||||||
|
<svg viewBox="0 0 56 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.0716 0C17.111 0 17.7697 0.734004 17.5824 1.65153L17.5516 1.77773L16.4646 5.68023C16.2499 6.48564 15.6763 7.15995 14.9845 7.52983L14.8228 7.6097L11.6546 9.08403L12.3485 11.8374C12.4102 12.0494 12.6179 12.227 12.8583 12.2638L12.9497 12.2708H15.0308L14.0135 16H10.7299C9.96799 16 9.22678 15.4621 8.98803 14.8024L8.94926 14.6774L7.95482 10.8185L5.17986 12.1191L4.11629 16H0L4.34743 0H16.0716ZM30.028 0L30.0255 0.00849999L29.0084 3.71374L29.0048 3.72704H29.0004L22.8229 3.71374C22.4538 3.71374 22.1768 3.84407 22.0843 4.19052C22.0024 4.49868 22.1027 4.73832 22.3854 4.94011L22.4999 5.01406L29.1008 9.10927C29.7285 9.49516 30.0921 10.3574 29.9828 11.0527L29.9546 11.1894L29.0084 14.6781C28.8348 15.3511 28.0883 15.9282 27.3084 15.9938L27.1619 16H18.8519L19.8686 12.2728H24.8772C25.2464 12.2728 25.5232 12.0346 25.5925 11.8178C25.6756 11.5644 25.6278 11.3636 25.3483 11.1522L25.2464 11.0812L18.5995 6.92095C17.9719 6.53476 17.6081 5.67281 17.7173 4.97743L17.7455 4.84076L18.6914 1.33023C18.8654 0.657352 19.5912 0.0802618 20.3495 0.0146972L20.492 0.00849999L30.0218 0H30.028ZM34.8758 0L39.0028 0.00849999L34.6207 16H30.4473L34.8566 0.00849999H34.8735L34.8758 0ZM17.698 12.2956L16.6916 16H16.0205L17.0206 12.2956H17.698ZM16.356 12.2956L15.313 16H14.5946L15.6471 12.3028L15.6493 12.2956H16.356ZM19.124 12.2956L18.0887 16H17.3625L18.398 12.2956H19.124ZM12.2017 3.70443H7.46927L6.45853 7.48768L12.0409 4.81988C12.5006 4.60106 12.6614 4.33872 12.7304 4.12006C12.8222 3.83596 12.5694 3.70443 12.2017 3.70443ZM34.1379 0L33.1305 3.70443H32.4604L33.474 0H34.1379ZM32.712 0L31.7062 3.70443H31.0345L32.0511 0H32.712ZM31.3537 0L31.3515 0.00844828H31.37L30.3313 3.69121L30.3277 3.70443H29.6086L29.6121 3.69121L30.6322 0.00844828L30.6346 0H31.3537Z" fill="currentColor"></path>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M44.0993 0.5C45.1052 0.5 45.71 0.718656 46.0714 1.07635C46.4317 1.43287 46.6502 2.02678 46.6502 3.01365C46.6502 4.00008 46.4317 4.58521 46.0739 4.93447C45.7133 5.28641 45.1085 5.5 44.0993 5.5C43.0905 5.5 42.4701 5.28657 42.0962 4.9303C41.7277 4.57908 41.5 3.99382 41.5 3.01365C41.5 2.03297 41.7277 1.43898 42.0987 1.08055C42.4734 0.718531 43.0938 0.5 44.0993 0.5ZM47.1502 3.01365C47.1502 0.918004 46.2283 0 44.0993 0C41.9703 0 41 0.918004 41 3.01365C41 5.10816 41.9703 6 44.0993 6C46.2283 6 47.1502 5.10816 47.1502 3.01365ZM42.7675 1.363C43.2445 1.318 43.717 1.3 44.194 1.3C45.157 1.3 45.4855 1.633 45.4855 2.5105C45.4855 3.154 45.319 3.4555 44.842 3.577L45.607 4.7965C45.643 4.846 45.6205 4.8865 45.553 4.8865H44.725C44.6215 4.8865 44.59 4.855 44.545 4.7875L43.816 3.6355H43.645V4.8145C43.645 4.873 43.6315 4.8865 43.5775 4.8865H42.7675C42.7135 4.8865 42.7 4.873 42.7 4.8145V1.4215C42.7 1.381 42.7135 1.3675 42.7675 1.363ZM44.527 2.542C44.527 2.2495 44.428 2.1235 44.0905 2.1235H43.645V2.9425H44.0905C44.428 2.9425 44.527 2.839 44.527 2.542Z" fill="currentColor"></path>
|
||||||
|
</svg>
|
||||||
|
<h3>星际公民官网</h3>
|
||||||
|
<p>罗伯茨航天工业公司,万物的起源</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<a href="https://uexcorp.space" target="_blank">
|
||||||
|
<img src="https://assets.uexcorp.space/img/logo.svg" alt="">
|
||||||
|
<h3>UEX</h3>
|
||||||
|
<p>采矿、精炼、贸易计算器、价格、船信息</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<a href="https://www.erkul.games/live/calculator" target="_blank">
|
||||||
|
<img src="https://www.erkul.games/assets/icons/icon-512x512.png">
|
||||||
|
<h3>DPS 计算器</h3>
|
||||||
|
<p>在线改船,查询伤害数值和配件购买地点</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<a href="https://ccugame.app" target="_blank">
|
||||||
|
<img src="https://ccugame.app/assets/images/logo/logo.png">
|
||||||
|
<h3>CCUGame(官方汉化)</h3>
|
||||||
|
<p>资产管理和舰队规划,一定要理性消费.jpg</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</body></html>
|
1
dist/firefox/background/scripts.js
vendored
Normal file
1
dist/firefox/background/scripts.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
(()=>{var e={},s={};function r(t){var n=s[t];if(void 0!==n)return n.exports;var a=s[t]={exports:{}};return e[t](a,a.exports,r),a.exports}r.rv=()=>"1.3.8",r.ruid="bundler=rspack@1.3.8";let t=null;async function n(){console.log("Localization Version ===",t=await o("versions.json"))}async function a(e){if(console.log("url ==="+e),null==t)return await n(),a(e);let s=t,r={};e.includes("robertsspaceindustries.com")?(r["zh-CN"]=await o("zh-CN-rsi.json",{cacheKey:"zh-CN",version:s.rsi}),r.concierge=await o("concierge.json",{cacheKey:"concierge",version:s.concierge}),r.orgs=await o("orgs.json",{cacheKey:"orgs",version:s.orgs}),r.address=await o("addresses.json",{cacheKey:"orgs",version:s.addresses}),r.hangar=await o("hangar.json",{cacheKey:"hangar",version:s.hangar})):e.includes("uexcorp.space")?r.UEX=await o("zh-CN-uex.json",{cacheKey:"uex",version:s.uex}):e.includes("erkul.games")?r.DPS=await o("zh-CN-dps.json",{cacheKey:"dps",version:s.dps}):e.includes("manual")&&(r["zh-CN"]=await o("zh-CN-rsi.json",{cacheKey:"zh-CN",version:s.rsi}),r.concierge=await o("concierge.json",{cacheKey:"concierge",version:s.concierge}),r.orgs=await o("orgs.json",{cacheKey:"orgs",version:s.orgs}),r.address=await o("addresses.json",{cacheKey:"orgs",version:s.addresses}),r.hangar=await o("hangar.json",{cacheKey:"hangar",version:s.hangar}),r.UEX=await o("zh-CN-uex.json",{cacheKey:"uex",version:s.uex}),r.DPS=await o("zh-CN-dps.json",{cacheKey:"dps",version:s.dps}));let c=[];function i(e){c.push(...function(e,s){let r=[],t=e[s];if("object"==typeof t)for(let[e,s]of Object.entries(t)){let t=e.toString().trim().toLowerCase().replace(/\xa0/g," ").replace(/\s{2,}/g," ");r.push({word:t,replacement:String(s)})}return r}(r,e))}if(e.includes("robertsspaceindustries.com")){if(e.startsWith("https://robertsspaceindustries.com/spectrum/community/"))return[];i("zh-CN"),(e.startsWith("https://robertsspaceindustries.com/orgs")||e.startsWith("https://robertsspaceindustries.com/citizens")||e.startsWith("https://robertsspaceindustries.com/account/organization"))&&(c.push({word:"members",replacement:"名成员"}),i("orgs")),e.startsWith("https://robertsspaceindustries.com/account/addresses")&&i("address"),e.startsWith("https://robertsspaceindustries.com/account/referral-program")&&c.push({word:"Total recruits: ",replacement:"总邀请数:"},{word:"Prospects ",replacement:"未完成的邀请"},{word:"Recruits",replacement:"已完成的邀请"}),e.startsWith("https://robertsspaceindustries.com/account/concierge")&&(c=[],i("concierge")),e.startsWith("https://robertsspaceindustries.com/account/pledges")&&i("hangar")}else e.includes("uexcorp.space")?i("UEX"):e.includes("erkul.games")?i("DPS"):e.includes("manual")&&(i("zh-CN"),c.push({word:"members",replacement:"名成员"}),i("orgs"),i("address"),c.push({word:"Total recruits: ",replacement:"总邀请数:"},{word:"Prospects ",replacement:"未完成的邀请"},{word:"Recruits",replacement:"已完成的邀请"}),i("concierge"),i("hangar"),i("UEX"),i("DPS"));return c}async function o(e,s={}){let{cacheKey:r="",version:t=null}=s;if(r&&""!==r){let e=await c(`${r}_version`),s=await c(r);if(s&&"object"==typeof s&&Object.keys(s).length>0&&e===t)return s}let n=new Date,a=await fetch("https://git.scbox.xkeyc.cn/SCToolBox/ScWeb_Chinese_Translate/raw/branch/main/json/locales/"+e,{method:"GET",mode:"cors"}),u=new Date,l=await a.json();if(r&&""!==r){let e=u.getTime()-n.getTime();console.log(`update ${r} v == ${t} time == ${e/1e3}s`),await i(r,l),await i(`${r}_version`,t)}return l}function c(e){return new Promise(s=>{chrome.storage.local.get([e],r=>{s(r[e]||null)})})}function i(e,s){return new Promise(r=>{let t={};t[e]=s,chrome.storage.local.set(t,()=>{r()})})}chrome.runtime.onInstalled.addListener(function(){n().then(e=>{}),console.log("SWTT init")}),chrome.runtime.onMessage.addListener(function(e,s,r){if("_loadLocalizationData"===e.action)return a(e.url).then(e=>{r({result:e})}),!0}),chrome.runtime.onInstalled.addListener(function(){chrome.contextMenus.create({id:"translate",title:"切换翻译",contexts:["all"]})}),chrome.contextMenus.onClicked.addListener((e,s)=>{console.log("contextMenus",e,s);let r="manual";s&&s.url&&["robertsspaceindustries.com","erkul.games","uexcorp.space"].find(e=>s.url.includes(e))&&(r=s.url),a(r).then(e=>{s&&void 0!==s.id&&chrome.tabs.sendMessage(s.id,{action:"_toggleTranslation",data:e})})})})();
|
1
dist/firefox/content_scripts/content-0.js
vendored
Normal file
1
dist/firefox/content_scripts/content-0.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/firefox/content_scripts/content-1.js
vendored
Normal file
1
dist/firefox/content_scripts/content-1.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/firefox/content_scripts/content-2.js
vendored
Normal file
1
dist/firefox/content_scripts/content-2.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
(()=>{var e={},t={};function r(n){var o=t[n];if(void 0!==o)return o.exports;var a=t[n]={exports:{}};return e[n](a,a.exports,r),a.exports}r.rv=()=>"1.3.8",r.ruid="bundler=rspack@1.3.8",function(){function e(t,r,n,o=100){let a=setInterval(()=>{let e=t.querySelector(r);e&&(clearInterval(a),n(e))},o)}function t(e){if(!e||e.parentNode.querySelector('a[data-cy-id="button"][href="/account/pledges"]'))return;let t=e.cloneNode(!0);t.href="/account/pledges";let r=t.querySelector('span[data-cy-id="button__text"]');r&&(r.innerText="My Hangar");let n=t.querySelector('i[data-cy-id="button__icon"]');n&&(n.className="a-button__icon a-icon -gridView"),e.parentNode.insertBefore(t,e)}e(document,"#sidePanel",r=>{new MutationObserver(r=>{for(let n of r)"childList"===n.type&&n.addedNodes.length>0&&n.addedNodes.forEach(r=>{1===r.nodeType&&e(r,'a[data-cy-id="button"][href="/account/settings"]',e=>{t(e)})})}).observe(r,{childList:!0,subtree:!0});let n=r.querySelector('a[data-cy-id="button"][href="/account/settings"]');n&&t(n)})}()})();
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
@ -1,57 +1,62 @@
|
|||||||
{
|
{
|
||||||
"manifest_version": 2,
|
"manifest_version": 3,
|
||||||
"name": "星际公民盒子浏览器拓展",
|
"name": "星际公民盒子浏览器拓展",
|
||||||
"version": "0.0.11",
|
"version": "0.0.11",
|
||||||
"description": "为星际公民网站及工具站提供汉化",
|
"description": "为星际公民网站及工具站提供汉化",
|
||||||
"author": "xkeyC",
|
"author": "xkeyC",
|
||||||
"icons": {
|
"icons": {
|
||||||
"192": "icon.png"
|
"16": "icons/icon.png",
|
||||||
|
"48": "icons/icon.png",
|
||||||
|
"192": "icons/icon.png"
|
||||||
},
|
},
|
||||||
"permissions": [
|
"host_permissions": [
|
||||||
"storage",
|
|
||||||
"https://git.scbox.xkeyc.cn/*"
|
"https://git.scbox.xkeyc.cn/*"
|
||||||
],
|
],
|
||||||
"browser_action": {
|
"permissions": [
|
||||||
"default_icon": "icon.png",
|
"storage",
|
||||||
"default_popup": "popup.html"
|
"contextMenus"
|
||||||
|
],
|
||||||
|
"action": {
|
||||||
|
"default_popup": "action/default_popup.html"
|
||||||
},
|
},
|
||||||
"background": {
|
"background": {
|
||||||
"scripts": [
|
"scripts": [
|
||||||
"background.js"
|
"background/scripts.js"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"content_scripts": [
|
"content_scripts": [
|
||||||
{
|
{
|
||||||
"matches": [
|
"matches": [
|
||||||
"https://robertsspaceindustries.com/*",
|
"*://*/*"
|
||||||
"https://*.robertsspaceindustries.com/*",
|
|
||||||
"https://www.erkul.games/*",
|
|
||||||
"https://uexcorp.space/*"
|
|
||||||
],
|
],
|
||||||
"exclude_matches": [
|
"exclude_matches": [
|
||||||
"https://robertsspaceindustries.com/spectrum/*"
|
"https://robertsspaceindustries.com/spectrum/*"
|
||||||
],
|
],
|
||||||
"js": [
|
"js": [
|
||||||
"core.js",
|
"content_scripts/content-0.js"
|
||||||
"thirdparty/timeago.full.min.js"
|
],
|
||||||
]
|
"run_at": "document_end",
|
||||||
|
"css": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"matches": [
|
"matches": [
|
||||||
"https://www.erkul.games/*"
|
"https://www.erkul.games/*"
|
||||||
],
|
],
|
||||||
"js": [
|
"js": [
|
||||||
"thirdparty/jquery.min.js"
|
"content_scripts/content-1.js"
|
||||||
]
|
],
|
||||||
|
"run_at": "document_end",
|
||||||
|
"css": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"matches": [
|
"matches": [
|
||||||
"https://robertsspaceindustries.com/*"
|
"https://robertsspaceindustries.com/*"
|
||||||
],
|
],
|
||||||
"js": [
|
"js": [
|
||||||
"rsi_hangar_fix.js"
|
"content_scripts/content-2.js"
|
||||||
],
|
],
|
||||||
"run_at": "document_idle"
|
"run_at": "document_idle",
|
||||||
|
"css": []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -1,39 +1,42 @@
|
|||||||
{
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/chrome-manifest.json",
|
||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"name": "星际公民盒子浏览器拓展",
|
"name": "星际公民盒子浏览器拓展",
|
||||||
"version": "0.0.11",
|
"version": "0.0.11",
|
||||||
"description": "为星际公民网站及工具站提供汉化",
|
"description": "为星际公民网站及工具站提供汉化",
|
||||||
"author": "xkeyC",
|
"author": "xkeyC",
|
||||||
"icons": {
|
"icons": {
|
||||||
|
"16": "icon.png",
|
||||||
|
"48": "icon.png",
|
||||||
"192": "icon.png"
|
"192": "icon.png"
|
||||||
},
|
},
|
||||||
"host_permissions": [
|
"host_permissions": [
|
||||||
"https://git.scbox.xkeyc.cn/*"
|
"https://git.scbox.xkeyc.cn/*"
|
||||||
],
|
],
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"storage"
|
"storage",
|
||||||
|
"contextMenus"
|
||||||
],
|
],
|
||||||
"action": {
|
"action": {
|
||||||
"default_popup": "popup.html"
|
"default_popup": "popup.html"
|
||||||
},
|
},
|
||||||
"background": {
|
"background": {
|
||||||
"service_worker": "background.js"
|
"chromium:service_worker": "background.ts",
|
||||||
|
"firefox:scripts": ["background.ts"]
|
||||||
},
|
},
|
||||||
"content_scripts": [
|
"content_scripts": [
|
||||||
{
|
{
|
||||||
"matches": [
|
"matches": [
|
||||||
"https://robertsspaceindustries.com/*",
|
"*://*/*"
|
||||||
"https://*.robertsspaceindustries.com/*",
|
|
||||||
"https://www.erkul.games/*",
|
|
||||||
"https://uexcorp.space/*"
|
|
||||||
],
|
],
|
||||||
"exclude_matches": [
|
"exclude_matches": [
|
||||||
"https://robertsspaceindustries.com/spectrum/*"
|
"https://robertsspaceindustries.com/spectrum/*"
|
||||||
],
|
],
|
||||||
"js": [
|
"js": [
|
||||||
"core.js",
|
"core.ts",
|
||||||
"thirdparty/timeago.full.min.js"
|
"thirdparty/timeago.full.min.js"
|
||||||
]
|
],
|
||||||
|
"run_at": "document_end"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"matches": [
|
"matches": [
|
||||||
@ -41,14 +44,15 @@
|
|||||||
],
|
],
|
||||||
"js": [
|
"js": [
|
||||||
"thirdparty/jquery.min.js"
|
"thirdparty/jquery.min.js"
|
||||||
]
|
],
|
||||||
|
"run_at": "document_end"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"matches": [
|
"matches": [
|
||||||
"https://robertsspaceindustries.com/*"
|
"https://robertsspaceindustries.com/*"
|
||||||
],
|
],
|
||||||
"js": [
|
"js": [
|
||||||
"rsi_hangar_fix.js"
|
"rsi_hangar_fix.ts"
|
||||||
],
|
],
|
||||||
"run_at": "document_idle"
|
"run_at": "document_idle"
|
||||||
}
|
}
|
33
package.json
Normal file
33
package.json
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/StarCitizenToolBox/StarCitizenBoxBrowserEx"
|
||||||
|
},
|
||||||
|
"name": "star-citizen-box-browser-ex",
|
||||||
|
"description": "为星际公民网站及工具站提供汉化",
|
||||||
|
"version": "0.0.11",
|
||||||
|
"keywords": [
|
||||||
|
"extension",
|
||||||
|
"browser-extension",
|
||||||
|
"web-extension",
|
||||||
|
"template"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"dev": "extension dev --polyfill",
|
||||||
|
"dev:firefox": "extension dev --browser firefox",
|
||||||
|
"build": "extension build --polyfill",
|
||||||
|
"build:firefox": "extension build --browser firefox --polyfill"
|
||||||
|
},
|
||||||
|
"dependencies": {},
|
||||||
|
"devDependencies": {
|
||||||
|
"extension": "^2.0.0-rc.23",
|
||||||
|
"@types/node": "^22.10.5",
|
||||||
|
"typescript": "5.3.3"
|
||||||
|
},
|
||||||
|
"private": true,
|
||||||
|
"author": {
|
||||||
|
"name": "xkeyC"
|
||||||
|
},
|
||||||
|
"packageManager": "pnpm@9.11.0+sha512.0a203ffaed5a3f63242cd064c8fb5892366c103e328079318f78062f24ea8c9d50bc6a47aa3567cabefd824d170e78fa2745ed1f16b132e16436146b7688f19b"
|
||||||
|
}
|
5310
pnpm-lock.yaml
generated
Normal file
5310
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -81,11 +81,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 开始查找抽屉,如果找到执行监听回调
|
// 开始查找抽屉,如果找到执行监听回调
|
||||||
waitForElement(document, "#sidePanel", (risSidePanel) => {
|
waitForElement(document, "#sidePanel", (rsiSidePanel) => {
|
||||||
startObserve(risSidePanel)
|
startObserve(rsiSidePanel)
|
||||||
|
|
||||||
// 初始检查:防止首次打开抽屉时按钮已经存在,MutationObserver 不触发
|
// 初始检查:防止首次打开抽屉时按钮已经存在,MutationObserver 不触发
|
||||||
const button = sidePanel.querySelector('a[data-cy-id="button"][href="/account/settings"]')
|
const button = rsiSidePanel.querySelector('a[data-cy-id="button"][href="/account/settings"]')
|
||||||
if (button) {
|
if (button) {
|
||||||
copyAndAddButton(button)
|
copyAndAddButton(button)
|
||||||
}
|
}
|
25
tsconfig.json
Normal file
25
tsconfig.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"allowJs": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"module": "esnext",
|
||||||
|
"noEmit": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"strict": true,
|
||||||
|
"target": "esnext",
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["./"],
|
||||||
|
"exclude": ["node_modules", "dist"],
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user