Skip to content

Commit 6ef29ee

Browse files
committed
feat: add two translate buttons
1 parent 8a5fac8 commit 6ef29ee

File tree

4 files changed

+200
-87
lines changed

4 files changed

+200
-87
lines changed

apps/tampermonkey/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,5 @@ tampermonkey.js
3131
*.njsproj
3232
*.sln
3333
*.sw?
34+
35+
src/nextjs.html

apps/tampermonkey/dist/script.iife.js

Lines changed: 75 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// @name Next.js i18n Tampermonkey Script
33
// @namespace https://github.com/xiaoyu2er/nextjs-i18n-docs
44
// @website https://github.com/xiaoyu2er/nextjs-i18n-docs
5-
// @version 0.0.1
5+
// @version 0.0.2
66
// @updateURL https://raw.githubusercontent.com/xiaoyu2er/nextjs-i18n-docs/refs/heads/dev/apps/tampermonkey/dist/script.iife.js
77
// @downloadURL https://raw.githubusercontent.com/xiaoyu2er/nextjs-i18n-docs/refs/heads/dev/apps/tampermonkey/dist/script.iife.js
88
// @description Adds a translation button to nextjs.org with links to community-maintained translated documentation
@@ -115,22 +115,21 @@
115115
);
116116
function devLog(...args) {
117117
}
118-
function devWarn(...args) {
119-
}
120-
function devError(...args) {
121-
}
122-
function waitForLearnButton(callback, maxAttempts = 30) {
118+
function waitForTargetButton(callback, maxAttempts = 30) {
123119
let attempts = 0;
124120
const check = () => {
125121
try {
126122
const learnButton = document.querySelector('a[href="/learn"]');
127-
if (learnButton) {
123+
const searchButton = document.querySelector('button[aria-label="Search documentation"]');
124+
if (learnButton || searchButton) {
128125
callback();
129-
} else if (attempts < maxAttempts) {
126+
return;
127+
}
128+
if (attempts < maxAttempts) {
130129
attempts++;
131130
setTimeout(check, 200);
132131
} else {
133-
devLog("⚠️ Learn button not found after maximum attempts");
132+
devLog("⚠️ Neither Learn button nor Search button found after maximum attempts");
134133
}
135134
} catch (error) {
136135
}
@@ -298,6 +297,8 @@
298297
return container;
299298
}
300299
function addTranslationButton() {
300+
var _a, _b;
301+
let addedCount = 0;
301302
const learnButtonSelectors = [
302303
'a[href="/learn"]',
303304
'a[href*="/learn"]',
@@ -311,57 +312,89 @@
311312
break;
312313
}
313314
}
314-
if (!learnButton) {
315-
return;
316-
}
317-
try {
318-
const existingButton = document.querySelector(
319-
".next-i18n-translate-container"
320-
);
321-
if (existingButton) {
322-
devLog("✅ Translation button already exists");
323-
return;
315+
if (learnButton) {
316+
const existingLearnButton = (_a = learnButton.parentNode) == null ? void 0 : _a.querySelector(".next-i18n-translate-container");
317+
if (!existingLearnButton) {
318+
try {
319+
const translationDropdown = createTranslationDropdown();
320+
translationDropdown.setAttribute("data-placement", "learn-button");
321+
const parentNode = learnButton.parentNode;
322+
if (parentNode) {
323+
if (learnButton.nextSibling) {
324+
parentNode.insertBefore(translationDropdown, learnButton.nextSibling);
325+
} else {
326+
parentNode.appendChild(translationDropdown);
327+
}
328+
devLog("✅ Translation button added next to Learn button");
329+
addedCount++;
330+
}
331+
} catch (error) {
332+
}
324333
}
325-
const translationDropdown = createTranslationDropdown();
326-
const parentNode = learnButton.parentNode;
327-
if (!parentNode) {
328-
devError("❌ Learn button has no parent node");
329-
return;
334+
}
335+
const searchButtonSelectors = [
336+
'button[aria-label="Search documentation"]',
337+
"button.navbar_search__dZT2b",
338+
'button[data-variant="small"]'
339+
];
340+
let searchButton = null;
341+
for (const selector of searchButtonSelectors) {
342+
try {
343+
searchButton = document.querySelector(selector);
344+
if (searchButton) {
345+
devLog(`🔍 Found Search button with selector: ${selector}`);
346+
break;
347+
}
348+
} catch (error) {
330349
}
331-
if (learnButton.nextSibling) {
332-
parentNode.insertBefore(translationDropdown, learnButton.nextSibling);
333-
} else {
334-
parentNode.appendChild(translationDropdown);
350+
}
351+
if (searchButton) {
352+
const existingSearchButton = (_b = searchButton.parentNode) == null ? void 0 : _b.querySelector(".next-i18n-translate-container");
353+
if (!existingSearchButton) {
354+
try {
355+
const translationDropdown = createTranslationDropdown();
356+
translationDropdown.setAttribute("data-placement", "search-button");
357+
const parentNode = searchButton.parentNode;
358+
if (parentNode) {
359+
if (searchButton.nextSibling) {
360+
parentNode.insertBefore(translationDropdown, searchButton.nextSibling);
361+
} else {
362+
parentNode.appendChild(translationDropdown);
363+
}
364+
devLog("✅ Translation button added next to Search button");
365+
addedCount++;
366+
}
367+
} catch (error) {
368+
}
335369
}
336-
devLog("✅ Translation button added successfully");
370+
}
371+
if (addedCount === 0 && !learnButton && !searchButton) {
372+
return false;
373+
}
374+
if (addedCount > 0) {
337375
setTimeout(() => {
338-
const verifyButton = document.querySelector(
376+
const verifyButtons = document.querySelectorAll(
339377
".next-i18n-translate-container"
340378
);
341-
if (!verifyButton) {
342-
devWarn(
343-
"⚠️ Translation button was removed shortly after adding, React might be re-rendering"
344-
);
379+
if (verifyButtons.length === 0) {
345380
setTimeout(() => {
346-
devLog(
347-
"🔄 Attempting to re-add translation button after React stabilization"
348-
);
349381
addTranslationButton();
350382
}, 1e3);
351383
} else {
352-
devLog("🎉 Translation button is stable and working!");
384+
devLog(`🎉 ${verifyButtons.length} translation button(s) are stable and working!`);
353385
}
354386
}, 500);
355-
} catch (error) {
356387
}
388+
return addedCount > 0;
357389
}
358390
function initializeScript() {
359391
setTimeout(() => {
360392
addTranslationButton();
361393
setTimeout(() => {
362-
if (!document.querySelector(".next-i18n-translate-container")) {
363-
waitForLearnButton(() => {
364-
devLog("🎯 Learn button found, attempting to add translation button");
394+
const existingButtons = document.querySelectorAll(".next-i18n-translate-container");
395+
if (existingButtons.length === 0) {
396+
waitForTargetButton(() => {
397+
devLog("🎯 Target button found, attempting to add translation button");
365398
addTranslationButton();
366399
});
367400
}

0 commit comments

Comments
 (0)