Language fixes

This commit is contained in:
Khyretos 2024-01-04 21:58:15 +01:00
parent 932a21647d
commit 0efb495339
11 changed files with 210 additions and 131 deletions

View file

@ -240,7 +240,7 @@ def get_translation():
source=detectedLanguage, target=settings["LANGUAGE"]["TRANSLATE_TO"]
).translate(message)
except Exception as e:
return jsonify({"error": e}), 500
return jsonify({"error": "Could not translate, continuing with next language"}), 500
return jsonify({"translation": translated}), 200

View file

@ -274,7 +274,7 @@ h1 {
.username.sender {
padding: 0px 5px 5px 30px;
margin: 20px 5px 5px 30px;
margin: 20px 5px 5px 25px;
}
.username.user {
@ -505,13 +505,20 @@ h1 {
background-color: var(--main-color1);
}
.emoji-picker {
margin-left: auto;
visibility: hidden;
bottom: 50px;
left: 0px;
.emotes {
position: relative;
cursor: pointer;
}
.dark {
display: none;
position: absolute;
z-index: 1;
top: -400px;
}
.emotes:hover .dark {
display: block;
}
.fi {
@ -539,11 +546,15 @@ h1 {
padding: 0px 0px 0px 0px;
margin: -45px 0px 0px -40px;
top: 30px;
left: 20px;
}
.language-icon {
position: relative;
top: 45px;
left: 20px;
}
.flag-icon {
width: 20px !important;
height: 20px !important;
left: 18px;
}

View file

@ -61,11 +61,6 @@
color: var(--main-color2);
}
.hdp:hover {
position: fixed;
/* filter: brightness(150%); */
}
.menu .items .item-active {
background: -webkit-linear-gradient(left, var(--main-color2) 10%, var(--main-color2), var(--main-color1) 10%, var(--main-color1) 10%);
color: var(--main-color2);
@ -229,60 +224,50 @@
height: 100%;
}
.btn {
background-color: blue;
color: red;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
.pop {
position: relative;
display: inline-block;
cursor: pointer;
}
.pop.up {
.pop-selection {
width: 20px !important;
height: 20px !important;
}
.miniText {
position: absolute;
font-size: 8pt;
color: white;
padding: 3px;
}
.pop-content {
display: none;
position: absolute;
background-color: black;
background-color: var(--main-color3);
z-index: 1;
height: 400px;
width: max-content;
overflow: auto;
display: grid;
grid-template-columns: repeat(3, 1fr);
top: -400px;
color: white;
border: 1px solid #444;
}
pop-content div {
color: white;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.pop-content div:hover {
display: none;
/* background-color: black; */
backdrop-filter: invert(50%);
}
.pop:hover .pop-content {
display: grid;
/* display: none; */
grid-template-columns: repeat(3, 1fr);
/* display: block; */
}
.pop:hover .btn {
background-color: blue;
}
.language-select {
margin: 5px;
padding: 5px;
position: relative;
}
.language-select:hover {
background-color: blue;
}

View file

@ -377,22 +377,17 @@ input[type='lol'] {
.tooltip {
position: absolute;
display: inline-block;
visibility: hidden;
font-size: 12px;
line-height: 20px;
font-size: 12pt;
padding: 5px;
background: var(--main-color3);
border-radius: 5px;
visibility: hidden;
opacity: 1;
box-shadow: -2px 2px 5px rgba(0, 0, 0, 0.2);
transition:
opacity 0.3s,
visibility 0s;
color: var(--main-color2);
font-family: 'xxii_avenmedium';
z-index: 999;
max-width: 200px;
width: max-content;
}
div[type='text']:disabled {

View file

@ -78,24 +78,18 @@ textarea {
0 0 5px #070607,
0 0 5px #070607,
0 0 5px #070607;
/* transition: all 0.15s ease-in-out; */
transition: all 0.15s ease-in-out;
text-align: center;
}
.SmallButton:hover {
/* color: var(--main-color1); */
width: 50px;
color: var(--main-color1);
cursor: pointer;
/* filter: brightness(150%); */
}
.SmallButton:active {
color: var(--main-color1);
transform: translateY(4px);
text-shadow:
0 0 5px #000,
0 0 5px #000,
0 0 5px #000;
}
.AdvancedMenuButton {

View file

@ -44,13 +44,13 @@
<select name="defaultLanguage" class="top-select" id="language"></select>
</div>
<div id="window-controls">
<div class="button" id="min-button" tip="Minimize window" tip-left>
<div class="button" id="min-button" tip="Minimize window">
<i class="fa-solid fa-window-minimize"></i>
</div>
<div class="button" id="max-button" tip="Maximize window" tip-left>
<div class="button" id="max-button" tip="Maximize window">
<i class="fa-solid fa-window-maximize"></i>
</div>
<div class="button" id="close-button" tip="Close application" tip-left>
<div class="button" id="close-button" tip="Close application">
<i class="fa-solid fa-xmark"></i>
</div>
</div>
@ -577,13 +577,21 @@
<div id="chatBox" class="message-window"></div>
<!-- User input box-->
<div id="userInput" class="chat-input">
<div id="emoji-picker" class="emoji-picker">
<div class="emotes">
<button class="SmallButton">
<i class="fa-regular fa-grin fa-2x" id="emojis" aria-hidden="true"></i>
</button>
<emoji-picker class="dark"></emoji-picker>
</div>
<button class="SmallButton">
<i class="fa-regular fa-grin fa-2x" id="emojis" aria-hidden="true"></i>
</button>
<div class="pop">
<div class="pop in">
<div class="miniText">In</div>
<button class="SmallButton">
<i class="fa-solid fa-globe fa-2x" aria-hidden="true"></i>
</button>
<div class="pop-content"></div>
</div>
<div class="pop out">
<div class="miniText">Out</div>
<button class="SmallButton">
<i class="fa-solid fa-globe fa-2x" aria-hidden="true"></i>
</button>
@ -697,7 +705,7 @@
</section>
</div>
</div>
<div id="VIEWERS_PANEL" tip="Hide Viewers" tip-left>
<div id="VIEWERS_PANEL" tip="Hide Viewers">
<div class="circle-right">
<i class="fa fa-eye hide" aria-hidden="true"></i>
</div>

View file

@ -47,6 +47,10 @@ async function getInstalledVoices() {
function setTranslatedMessage(message) {
if (message.language.selectedLanguage.ISO639 !== message.language.detectedLanguage.ISO639) {
const messageBox = document.getElementById(message.messageId).getElementsByClassName('msg-box')[0];
const languageBox = document.getElementById(message.messageId).getElementsByClassName('language-icon flag-icon')[0];
languageBox.classList = `fi fi-${message.language.detectedLanguage.ISO3166} fis language-icon flag-icon`;
languageBox.setAttribute('tip', message.language.detectedLanguage.name);
const translationHeader = document.createElement('div');
translationHeader.className = 'translation-header';
@ -57,7 +61,7 @@ function setTranslatedMessage(message) {
translationIcon.className = 'translation-icon';
const languageElement = document.createElement('span');
const language = getLanguageProperties(settings.LANGUAGE.TRANSLATE_TO);
languageElement.classList = `fi fi-${message.language.selectedLanguage.ISO3166} fis`;
languageElement.classList = `fi fi-${message.language.selectedLanguage.ISO3166} fis flag-icon`;
languageElement.setAttribute('tip', message.language.selectedLanguage.name);
addSingleTooltip(languageElement);
translationIcon.appendChild(languageElement);
@ -80,6 +84,7 @@ function setTranslatedMessage(message) {
language: message.language
});
}
return message.language.detectedLanguage;
}
async function getTranslatedMessage(message) {
@ -90,16 +95,23 @@ async function getTranslatedMessage(message) {
},
body: JSON.stringify({
message: message.message,
remainder: message.remainingDetectedLanguages,
language: message.language.detectedLanguage.IETF
}) // Convert the data to JSON and include it in the request body
};
try {
const response = await fetch(`http://127.0.0.1:${settings.GENERAL.PORT}/translate`, requestOptions);
const responseData = await response.json();
if (response.ok) {
const responseData = await response.json();
console.log('Translated message:', responseData);
if (settings.LANGUAGE.BROADCAST_TRANSLATION) {
twitch.sendMessage(
`[${message.language.detectedLanguage.name} ${message.language.detectedLanguage.ISO639} > ${message.language.selectedLanguage.name} ${message.language.selectedLanguage.ISO639}] @${message.username}: ${responseData.translation}`
);
}
setTranslatedMessage({
originalMessage: message.message,
translation: responseData.translation,
@ -109,38 +121,65 @@ async function getTranslatedMessage(message) {
username: message.username,
logoUrl: message.logoUrl
});
if (settings.LANGUAGE.BROADCAST_TRANSLATION) {
twitch.sendMessage(
`[${message.language.detectedLanguage.name} ${message.language.detectedLanguage.ISO639} > ${message.language.selectedLanguage.name} ${message.language.selectedLanguage.ISO639}] @${message.username}: ${responseData.translation}`
);
}
return message.language.detectedLanguage;
} else {
console.error('Failed to send termination signal to Flask server.');
message.message = 'Error,could not translate message';
message.languaga = 'en-GB';
getTranslatedMessage(message);
console.error(responseData);
if (message.remainingDetectedLanguages.length > 0) {
message.language.detectedLanguage = getLanguageProperties(message.remainingDetectedLanguages[0]);
message.remainingDetectedLanguages.shift();
return getTranslatedMessage(message);
} else {
message.message = 'Error, Could not translate message';
message.language.detectedLanguage = getLanguageProperties('en-GB');
return getTranslatedMessage(message);
}
}
} catch (error) {
console.error('Error sending termination signal:', error);
message.message = 'Error, Could not translate message';
message.language.detectedLanguage = getLanguageProperties('en-GB');
getTranslatedMessage(message);
}
}
function filterLanguage(message) {
async function filterLanguage(message) {
const selectedPrimaryLanguage = getLanguageProperties(settings.LANGUAGE.TRANSLATE_TO);
const selectedPrimaryLanguageIndex =
message.languages.indexOf(selectedPrimaryLanguage.ISO639) === -1 ? 99 : message.languages.indexOf(selectedPrimaryLanguage.ISO639);
const selectedSecondaryLanguage = getLanguageProperties(settings.TTS.SECONDARY_TTS_LANGUAGE);
const selectedSecondaryLanguageIndex =
message.languages.indexOf(selectedSecondaryLanguage.ISO639) === -1 ? 99 : message.languages.indexOf(selectedSecondaryLanguage.ISO639);
const detectedLanguage = getLanguageProperties(message.languages[0]);
let detectedLanguage = '';
const remainingDetectedLanguages = [];
const detectedLanguages = message.languages.slice();
for (const [index, language] of detectedLanguages.entries()) {
detectedLanguage = getLanguageProperties(language);
if (detectedLanguage !== 'error') {
detectedLanguages.splice(index, 1);
break;
}
}
for (const [index, language] of detectedLanguages.entries()) {
const remainderLanguage = getLanguageProperties(language);
if (remainderLanguage !== 'error') {
remainingDetectedLanguages.push(remainderLanguage.IETF);
}
}
const language = selectedPrimaryLanguageIndex < selectedSecondaryLanguageIndex ? selectedPrimaryLanguage : detectedLanguage;
if (settings.LANGUAGE.TRANSLATE_TO !== 'none' && selectedPrimaryLanguage.ISO639 !== detectedLanguage.ISO639) {
getTranslatedMessage({
message: message.message,
messageId: message.messageId,
remainingDetectedLanguages,
language: {
selectedLanguage: selectedPrimaryLanguage,
detectedLanguage
detectedLanguage: detectedLanguage
},
username: message.username,
formattedMessage: message.formattedMessage,
@ -160,6 +199,7 @@ function filterLanguage(message) {
logoUrl: message.logoUrl
});
}
return language;
}
@ -182,7 +222,7 @@ async function getDetectedLanguage(message) {
const responseData = await response.json();
console.log('Detected Languages:', responseData);
return filterLanguage({
return await filterLanguage({
languages: responseData.languages,
message: message.message,
messageId: message.messageId,

View file

@ -21,8 +21,8 @@ const languages = {
amharic: { IETF: 'am-ET', ISO639: 'am', ISO3166: 'et' },
'antigua and barbuda creole english': { IETF: 'aig-AG', ISO639: 'aig', ISO3166: 'ag' },
arabic: { IETF: 'ar-SA', ISO639: 'ar', ISO3166: 'sa' },
'arabic egyptian': { IETF: 'ar-EG', ISO639: 'ar', ISO3166: 'eg' },
// aragonese: { IETF: 'an-ES', ISO639: 'an', ISO3166: 'es' },
'arabic egyptian': { IETF: 'ar-EG', ISO639: 'arz', ISO3166: 'eg' },
aragonese: { IETF: 'es-ES', ISO639: 'an', ISO3166: 'es' },
armenian: { IETF: 'hy-AM', ISO639: 'hy', ISO3166: 'am' },
assamese: { IETF: 'as-IN', ISO639: 'as', ISO3166: 'in' },
asturian: { IETF: 'ast-ES', ISO639: 'ast', ISO3166: 'es' },

View file

@ -163,8 +163,25 @@ async function getAudioDevices() {
getAudioDevices();
function setLanguagesinSelectx() {
const languageSelect = document.querySelector('.pop-content'); // obtain the html reference of the google voices comboBox
function setSelectedLanguageinSelect(languageSelect, language) {
const button = languageSelect.querySelector('.SmallButton');
const languageElement = document.createElement('span');
languageElement.classList = `fi fi-${language.ISO3166} fis pop-selection`;
languageElement.setAttribute('tip', language.name);
button.innerHTML = '';
button.appendChild(languageElement);
addSingleTooltip(languageElement);
}
function setLanguagesinSelectx(languageSelector, language) {
const languageSelect = document.querySelector(languageSelector); // obtain the html reference of the google voices comboBox
const languageSelectContent = languageSelect.querySelector('.pop-content');
languageSelectContent.addEventListener('click', e => {
console.log(e.target);
language = getLanguageProperties(e.target.getAttribute('value'));
setSelectedLanguageinSelect(languageSelect, language);
});
for (const language in languageObject.languages) {
if (Object.prototype.hasOwnProperty.call(languageObject.languages, language)) {
@ -177,24 +194,27 @@ function setLanguagesinSelectx() {
const languageElement = document.createElement('span');
languageElement.classList = `fi fi-${ISO3166} fis`;
languageElement.style.pointerEvents = 'none';
option.setAttribute('tip', language);
const text = document.createElement('span');
text.style.pointerEvents = 'none';
text.innerHTML = ` - ${ISO639}`;
option.value = IETF;
option.setAttribute('value', IETF);
languageSelect.appendChild(option);
languageSelectContent.appendChild(option);
option.appendChild(languageElement);
option.appendChild(text);
addSingleTooltip(option);
}
}
// languageSelect.selectedIndex = setting;
setSelectedLanguageinSelect(languageSelect, language);
}
setLanguagesinSelectx();
setLanguagesinSelectx('.pop.in', getLanguageProperties(settings.LANGUAGE.SEND_TRANSLATION_IN));
setLanguagesinSelectx('.pop.out', getLanguageProperties(settings.LANGUAGE.SEND_TRANSLATION_OUT));
function setLanguagesinSelect(languageSelector, setting) {
const languageSelect = document.querySelector(languageSelector); // obtain the html reference of the google voices comboBox
@ -232,6 +252,38 @@ function addVoiceService(name) {
addToselect('#secondaryTTSService');
}
function determineTootlTipPosition(element) {
const horizontal = document.body.clientWidth / 2;
const vertical = document.body.clientHeight / 2;
element.tip.style.left = `${element.mouse.x}px`;
element.tip.style.top = `${element.mouse.y}px`;
const tipPosition = element.tip.getBoundingClientRect();
if (element.position.x < horizontal && element.position.y < vertical) {
element.tip.style.top = `${parseInt(element.tip.style.top) + 25}px`;
element.tip.style.left = `${parseInt(element.tip.style.left) + 10}px`;
}
if (element.position.x < horizontal && element.position.y > vertical) {
element.tip.style.top = `${parseInt(element.tip.style.top) - tipPosition.height}px`;
element.tip.style.left = `${parseInt(element.tip.style.left) + 10}px`;
}
if (element.position.x > horizontal && element.position.y < vertical) {
element.tip.style.top = `${parseInt(element.tip.style.top) + 25}px`;
element.tip.style.left = `${parseInt(element.tip.style.left) - tipPosition.width}px`;
}
if (element.position.x > horizontal && element.position.y > vertical) {
element.tip.style.top = `${parseInt(element.tip.style.top) - tipPosition.height}px`;
element.tip.style.left = `${parseInt(element.tip.style.left) - tipPosition.width}px`;
}
element.tip.style.visibility = 'visible';
}
// Small tooltip
function addSingleTooltip(el) {
const tip = document.createElement('div');
@ -244,14 +296,14 @@ function addSingleTooltip(el) {
image.src = el.src;
tip.appendChild(image);
}
tip.style.transform = `translate(${el.hasAttribute('tip-left') ? 'calc(-100% - 5px)' : '15px'}, ${
el.hasAttribute('tip-top') ? '-100%' : '15px'
})`;
body.appendChild(tip);
tip.pointerEvents = 'none';
element.onmousemove = e => {
tip.style.left = `${e.x}px`;
tip.style.top = `${e.y}px`;
tip.style.visibility = 'visible';
determineTootlTipPosition({
position: element.getBoundingClientRect(),
mouse: { x: e.x, y: e.y },
tip
});
};
element.onmouseleave = e => {
tip.style.visibility = 'hidden';
@ -270,7 +322,7 @@ function showChatMessage(article) {
const messages = document.body.querySelectorAll('.msg-container');
const lastMessage = messages[messages.length - 1];
lastMessage.scrollIntoView();
lastMessage.scrollIntoView({ block: 'end', behavior: 'smooth' });
}
function getPostTime() {
@ -338,33 +390,28 @@ if (fs.existsSync(emoteListSavePath)) {
}
function getLanguageProperties(languageToDetect) {
const filteredLanguage = Object.keys(languageObject.languages).reduce(function (accumulator, currentValue) {
if (
languageObject.languages[currentValue].IETF === languageToDetect ||
languageObject.languages[currentValue].ISO639 === languageToDetect ||
languageObject.languages[currentValue].ISO3166 === languageToDetect
) {
accumulator[currentValue] = languageObject.languages[currentValue];
}
return accumulator;
}, {});
try {
const filteredLanguage = Object.keys(languageObject.languages).reduce(function (accumulator, currentValue) {
if (
languageObject.languages[currentValue].IETF === languageToDetect ||
languageObject.languages[currentValue].ISO639 === languageToDetect ||
languageObject.languages[currentValue].ISO3166 === languageToDetect
) {
accumulator[currentValue] = languageObject.languages[currentValue];
}
return accumulator;
}, {});
const language = {
name: Object.getOwnPropertyNames(filteredLanguage)[0],
ISO3166: filteredLanguage[Object.keys(filteredLanguage)[0]].ISO3166,
ISO639: filteredLanguage[Object.keys(filteredLanguage)[0]].ISO639,
IETF: filteredLanguage[Object.keys(filteredLanguage)[0]].IETF
};
const language = {
name: Object.getOwnPropertyNames(filteredLanguage)[0],
ISO3166: filteredLanguage[Object.keys(filteredLanguage)[0]].ISO3166,
ISO639: filteredLanguage[Object.keys(filteredLanguage)[0]].ISO639,
IETF: filteredLanguage[Object.keys(filteredLanguage)[0]].IETF
};
return language;
}
document.body.querySelector('#emojis').addEventListener('click', () => {
emojiPicker.style.visibility === 'visible' ? (emojiPicker.style.visibility = 'hidden') : (emojiPicker.style.visibility = 'visible');
});
document.body.addEventListener('click', e => {
if (e.target.id !== 'emojis' && e.target.nodeName !== 'EMOJI-PICKER' && emojiPicker.style.visibility === 'visible') {
emojiPicker.style.visibility = 'hidden';
return language;
} catch (e) {
// console.error(error);
return 'error';
}
});
}

View file

@ -752,7 +752,7 @@ document.body.querySelector('#ZOOMLEVEL').addEventListener('change', () => {
});
document.body.querySelector('emoji-picker').addEventListener('emoji-click', e => {
console.log(e.detail);
// console.log(e.detail);
const div = document.getElementById('textInput');
if (e.detail.unicode === undefined) {
div.value += e.detail.name + ' ';

View file

@ -133,17 +133,18 @@ async function displayTwitchMessage(logoUrl, username, messageObject, filteredMe
}
});
}
showChatMessage(article);
if (settings.LANGUAGE.USE_DETECTION) {
await backend.getDetectedLanguage({ message: filteredMessage, messageId, username, logoUrl, formattedMessage }).then(language => {
console.log(language);
const languageElement = document.createElement('span');
languageElement.classList = `fi fi-${language.ISO3166} fis language-icon`;
languageElement.classList = `fi fi-${language.ISO3166} fis language-icon flag-icon`;
languageElement.setAttribute('tip', language.name);
article.appendChild(languageElement);
addSingleTooltip(languageElement);
// Appends the message to the main chat box (shows the message)
showChatMessage(article);
if (filteredMessage && !settings.LANGUAGE.OUTPUT_TO_TTS) {
sound.playVoice({
filteredMessage,
@ -154,16 +155,14 @@ async function displayTwitchMessage(logoUrl, username, messageObject, filteredMe
});
}
window.article = article;
// window.article = article;
});
} else {
showChatMessage(article);
if (filteredMessage) {
sound.playVoice({ filteredMessage, logoUrl, username, formattedMessage });
}
window.article = article;
// window.article = article;
}
sound.playNotificationSound();