Skip to content

Instantly share code, notes, and snippets.

@fluteds
Created May 14, 2023 20:56
Show Gist options
  • Save fluteds/c33fe720e180137ab06642afd736e76c to your computer and use it in GitHub Desktop.
Save fluteds/c33fe720e180137ab06642afd736e76c to your computer and use it in GitHub Desktop.
Shows English translations when Korean text is hovered over on b.stage via Google Translate.
// ==UserScript==
// @name ATEEZ b.stage Translator
// @version 1.0
// @author Fluteds
// @description Shows English translations when Korean text is hovered over on b.stage via Google Translate.
// @match https://ateez.kqent.com/*
// @icon https://static.musictoday.com/store/bands/6099/images/favicon.ico
// @grant GM_xmlhttpRequest
// ==/UserScript==
// TODO: Target post and OP comment reply chains content only
// Create a tooltip element for displaying translations
const tooltip = document.createElement('div');
tooltip.style.position = 'fixed';
tooltip.style.zIndex = '9999';
tooltip.style.backgroundColor = 'rgba(0, 0, 0, 0.8)';
tooltip.style.padding = '5px';
tooltip.style.borderRadius = '3px';
tooltip.style.color = '#fff';
tooltip.style.fontFamily = 'Arial, sans-serif';
tooltip.style.fontSize = '14px';
tooltip.style.maxWidth = '400px'; // Adjust the maximum width as needed
tooltip.style.wordWrap = 'break-word'; // Enable word wrapping
tooltip.style.display = 'none';
document.body.appendChild(tooltip);
// Function to handle hover event and translation
function handleHover(event) {
const text = event.target.textContent;
const isExcludedClass = isExcludedElement(event.target);
if (isKorean(text) && !isExcludedClass) {
translate(text, event.clientX, event.clientY);
}
}
function isExcludedElement(element) {
const excludedClasses = ["UserInfo_subText__EP_i7", "Reactions_container__WFkfN"];
for (const className of excludedClasses) {
if (element.classList.contains(className)) {
return true;
}
}
return false;
}
// Function to check if text is in Korean
function isKorean(text) {
const koreanPattern = /[ㄱ-ㅎㅏ-ㅣ가-힣]/;
return koreanPattern.test(text);
}
// Function to translate Korean text to English
function translate(text, x, y) {
const encodedText = encodeURIComponent(text);
GM_xmlhttpRequest({
method: 'GET',
url: `https://translate.googleapis.com/translate_a/single?client=gtx&sl=ko&tl=en&dt=t&q=${encodedText}`,
onload: function(response) {
const translations = JSON.parse(response.responseText)[0];
const translation = translations.reduce((acc, cur) => acc + cur[0], '');
const decodedTranslation = decodeEntities(translation);
tooltip.innerHTML = decodedTranslation;
tooltip.style.display = 'block';
tooltip.style.left = getTooltipXPosition(x);
tooltip.style.top = getTooltipYPosition(y);
}
});
}
// Decode HTML entities
function decodeEntities(encodedString) {
const textArea = document.createElement('textarea');
textArea.innerHTML = encodedString;
return textArea.value;
}
// Calculate the X position of the tooltip
function getTooltipXPosition(clientX) {
const tooltipWidth = tooltip.offsetWidth;
const windowWidth = window.innerWidth;
const maxPosition = windowWidth - tooltipWidth - 10; // Leave 10px padding
return Math.min(clientX + 10, maxPosition) + 'px';
}
// Calculate the Y position of the tooltip
function getTooltipYPosition(clientY) {
const tooltipHeight = tooltip.offsetHeight;
const windowHeight = window.innerHeight;
const maxPosition = windowHeight - tooltipHeight - 10; // Leave 10px padding
return Math.min(clientY + 10, maxPosition) + 'px';
}
// Add event listeners to handle hover and hide tooltip
document.addEventListener('mouseover', handleHover);
document.addEventListener('mouseout', function(event) {
if (!tooltip.contains(event.relatedTarget)) {
tooltip.style.display = 'none';
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment