Skip to content

Commit 6a58415

Browse files
WIP: Tagi10n: new plugin
Signed-off-by: Dee.H.Y <[email protected]>
1 parent f5ff6af commit 6a58415

File tree

4 files changed

+18174
-0
lines changed

4 files changed

+18174
-0
lines changed

plugins/Tagi10n/Tagi10n.js

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
// Stash Tag Translation
2+
(async function () {
3+
"use strict";
4+
5+
const { waitForElement, PathElementListener, getConfiguration, baseURL } =
6+
window.csLib;
7+
8+
const defaultConfig = {
9+
defaultLanguage: "zh_CN",
10+
};
11+
12+
async function loadLanguageFile(lang) {
13+
try {
14+
const module = await import(
15+
`https://cdn.jsdelivr.net/gh/dongfengweixiao/CommunityScripts@tagi10n1/plugins/Tagi10n/i10n/tag_${lang}.js`
16+
);
17+
return module.default || {};
18+
} catch (error) {
19+
console.error(`Failed to load language file tag_${lang}.js`, error);
20+
return {};
21+
}
22+
}
23+
24+
function translateTags(languageMap, xpathArray) {
25+
if (!languageMap) {
26+
console.error("languageMap is undefined or null. Translation skipped.");
27+
return;
28+
}
29+
30+
xpathArray.forEach((xpath) => {
31+
const elements = document.evaluate(
32+
xpath,
33+
document,
34+
null,
35+
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
36+
null
37+
);
38+
for (let i = 0; i < elements.snapshotLength; i++) {
39+
const element = elements.snapshotItem(i);
40+
const originalText = element.textContent.trim();
41+
const translation = languageMap[originalText];
42+
console.log(translation);
43+
// 检查 translation 是否为数组且长度大于 0
44+
if (Array.isArray(translation) && translation.length > 0) {
45+
element.textContent = translation[0];
46+
} else {
47+
// 若没有翻译,可选择保留原始文本或记录日志
48+
console.warn(`No translation found for "${originalText}"`);
49+
}
50+
}
51+
});
52+
}
53+
54+
function translateTagDescriptions(languageMap) {
55+
if (!languageMap) {
56+
console.error(
57+
"languageMap is undefined or null. Description translation skipped."
58+
);
59+
return;
60+
}
61+
62+
const tagNameElements = document.evaluate(
63+
"//div[contains(@class, 'tag-card')]//div[@class='TruncatedText']",
64+
document,
65+
null,
66+
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
67+
null
68+
);
69+
70+
for (let i = 0; i < tagNameElements.snapshotLength; i++) {
71+
const tagNameElement = tagNameElements.snapshotItem(i);
72+
const tagName = tagNameElement.textContent.trim();
73+
74+
const descriptionElement = document.evaluate(
75+
"//div[contains(@class, 'tag-card')]//div[contains(@class, 'tag-description')]",
76+
tagNameElement.parentNode,
77+
null,
78+
XPathResult.FIRST_ORDERED_NODE_TYPE,
79+
null
80+
).singleNodeValue;
81+
82+
const translationEntry = languageMap[tagName];
83+
84+
if (
85+
descriptionElement &&
86+
Array.isArray(translationEntry) &&
87+
translationEntry.length > 1
88+
) {
89+
descriptionElement.textContent = translationEntry[1];
90+
}
91+
}
92+
}
93+
94+
async function main() {
95+
const config = await getConfiguration("Tagi10n", defaultConfig);
96+
const lang = config.defaultLanguage;
97+
const languageMap = await loadLanguageFile(lang);
98+
99+
const xpathArray = [
100+
"//div[contains(@span, 'tag-item')]//div",
101+
"//*[contains(@class, 'tag-item')]//div",
102+
"//div[contains(@class, 'tag-card')]//div[@class='TruncatedText']",
103+
"//*[contains(@class, 'tag-name')]",
104+
"//span[contains(@span, 'tag-item')]//div",
105+
];
106+
107+
PathElementListener(baseURL + "scenes", ".tag-item", () => {
108+
translateTags(languageMap, xpathArray);
109+
});
110+
PathElementListener(baseURL + "tags", ".card-section", () => {
111+
translateTagDescriptions(languageMap);
112+
translateTags(languageMap, xpathArray);
113+
});
114+
PathElementListener(baseURL + "tags/", ".tag-name", () => {
115+
translateTagDescriptions(languageMap);
116+
translateTags(languageMap, xpathArray);
117+
});
118+
PathElementListener(baseURL + "images", ".tag-item", () => {
119+
translateTags(languageMap, xpathArray);
120+
});
121+
PathElementListener(baseURL + "performers", ".tag-item", () => {
122+
translateTags(languageMap, xpathArray);
123+
});
124+
PathElementListener(baseURL + "groups", ".tag-item", () => {
125+
translateTags(languageMap, xpathArray);
126+
});
127+
PathElementListener(baseURL + "galleries", ".tag-item", () => {
128+
translateTags(languageMap, xpathArray);
129+
});
130+
}
131+
132+
main();
133+
})();

plugins/Tagi10n/Tagi10n.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
name: Tagi10n
2+
description: Display tag names in the given language.
3+
version: 0.0.1
4+
ui:
5+
requires:
6+
- CommunityScriptsUILibrary
7+
javascript:
8+
- https://cdn.jsdelivr.net/gh/dongfengweixiao/CommunityScripts@tagi10n1/plugins/Tagi10n/i10n/tag_zh_CN.js
9+
- Tagi10n.js
10+
11+
settings:
12+
defaultLanguage:
13+
displayName: Default Language
14+
description: Default Language
15+
type: STRING

0 commit comments

Comments
 (0)