[call-me] - fix translate

This commit is contained in:
Miroslav Pejic
2026-02-10 01:55:44 +01:00
parent 159c263049
commit 8063e51312
15 changed files with 248 additions and 51 deletions
+35 -15
View File
@@ -205,7 +205,8 @@ function translatePage() {
// Translate elements with data-i18n-title attribute (for tooltips)
document.querySelectorAll('[data-i18n-title]').forEach((element) => {
const key = element.getAttribute('data-i18n-title');
element.title = t(key);
const translatedTitle = t(key);
setElementTitle(element, translatedTitle);
});
// Update document title
@@ -215,6 +216,37 @@ function translatePage() {
updateCustomTranslations();
}
/**
* Set element title in a way that works with Bootstrap tooltips.
* Bootstrap may cache the initial title into the Tooltip instance config.
* @param {Element} element
* @param {string} translatedTitle
*/
function setElementTitle(element, translatedTitle) {
if (!element || typeof translatedTitle !== 'string') return;
// Keep regular title attribute in sync
element.setAttribute('title', translatedTitle);
// Bootstrap 5 stores original title here and may remove the title attribute
element.setAttribute('data-bs-original-title', translatedTitle);
// If a Bootstrap Tooltip instance already exists, update its cached config/content
try {
if (typeof bootstrap !== 'undefined' && bootstrap.Tooltip) {
const instance = bootstrap.Tooltip.getInstance ? bootstrap.Tooltip.getInstance(element) : null;
if (instance) {
if (instance._config) instance._config.title = translatedTitle;
if (typeof instance.setContent === 'function') {
instance.setContent({ '.tooltip-inner': translatedTitle });
}
}
}
} catch (err) {
// No-op: translation should still work without tooltip refresh
}
}
/**
* Update custom translations for specific elements
*/
@@ -226,18 +258,6 @@ function updateCustomTranslations() {
// Update app name
const appName = document.getElementById('appName');
if (appName) appName.textContent = t('appName');
// Update settings title for language
const settingsTitles = document.querySelectorAll('.settings-title');
if (settingsTitles.length > 0) {
settingsTitles[0].innerHTML = '<i class="fas fa-globe"></i> ' + t('settings.language');
}
if (settingsTitles.length > 1) {
settingsTitles[1].innerHTML = '<i class="fas fa-video"></i> Media Devices';
}
if (settingsTitles.length > 2) {
settingsTitles[2].innerHTML = '<i class="fas fa-comments"></i> Chat Settings';
}
}
/**
@@ -320,7 +340,7 @@ function translateElement(element) {
// Translate data-i18n-title
if (element.hasAttribute && element.hasAttribute('data-i18n-title')) {
const key = element.getAttribute('data-i18n-title');
element.title = t(key);
setElementTitle(element, t(key));
}
// Recursively translate children
@@ -347,7 +367,7 @@ function translateElement(element) {
element.querySelectorAll('[data-i18n-title]').forEach((child) => {
const key = child.getAttribute('data-i18n-title');
child.title = t(key);
setElementTitle(child, t(key));
});
}
}
+34 -11
View File
@@ -115,6 +115,7 @@
data-toggle="tooltip"
data-placement="top"
title="Share room"
data-i18n-title="controls.shareRoom"
>
<i class="fas fa-share-nodes"></i>
</button>
@@ -125,6 +126,7 @@
data-toggle="tooltip"
data-placement="top"
title="Toggle hide me"
data-i18n-title="controls.toggleHideMe"
>
<i class="fas fa-eye-slash"></i>
</button>
@@ -135,6 +137,7 @@
data-toggle="tooltip"
data-placement="top"
title="Toggle audio"
data-i18n-title="controls.toggleAudio"
>
<i class="fas fa-microphone"></i>
</button>
@@ -145,6 +148,7 @@
data-toggle="tooltip"
data-placement="top"
title="Toggle video"
data-i18n-title="controls.toggleVideo"
>
<i class="fas fa-video"></i>
</button>
@@ -155,6 +159,7 @@
data-toggle="tooltip"
data-placement="top"
title="Swap camera"
data-i18n-title="controls.swapCamera"
>
<i class="fas fa-camera-rotate"></i>
</button>
@@ -165,6 +170,7 @@
data-toggle="tooltip"
data-placement="top"
title="Toggle screen"
data-i18n-title="controls.toggleScreen"
>
<i class="fas fa-desktop"></i>
</button>
@@ -175,6 +181,7 @@
data-toggle="tooltip"
data-placement="top"
title="Toggle users"
data-i18n-title="controls.toggleUsers"
>
<i class="fas fa-users"></i>
</button>
@@ -185,6 +192,7 @@
data-toggle="tooltip"
data-placement="top"
title="Leave"
data-i18n-title="controls.leave"
>
<i class="fas fa-phone-slash red"></i>
</button>
@@ -207,7 +215,12 @@
</button>
</div>
<button id="exitSidebarBtn" class="btn btn-exit-sidebar" title="Close sidebar">
<button
id="exitSidebarBtn"
class="btn btn-exit-sidebar"
title="Close sidebar"
data-i18n-title="room.closeSidebar"
>
<i class="fas fa-times"></i>
</button>
</div>
@@ -256,39 +269,46 @@
<!-- Settings Tab Content -->
<div id="settingsContent" class="tab-content">
<div class="settings-section">
<h3 class="settings-title"><i class="fas fa-globe"></i> Language</h3>
<h3 class="settings-title">
<i class="fas fa-globe"></i> <span data-i18n="settings.language">Language</span>
</h3>
<div class="setting-group">
<label for="languageSelect" class="setting-label">
<i class="fas fa-language"></i> Select Language
<i class="fas fa-language"></i>
<span data-i18n="settings.selectLanguage">Select Language</span>
</label>
<select id="languageSelect" class="setting-select"></select>
</div>
<h3 class="settings-title"><i class="fas fa-video"></i> Media Devices</h3>
<h3 class="settings-title">
<i class="fas fa-video"></i> <span data-i18n="settings.mediaDevicesTitle">Media Devices</span>
</h3>
<div class="setting-group">
<label for="videoSelect" class="setting-label"> <i class="fas fa-camera"></i> Camera </label>
<label for="videoSelect" class="setting-label">
<i class="fas fa-camera"></i> <span data-i18n="settings.videoInput">Camera</span>
</label>
<select id="videoSelect" class="setting-select">
<option value="">Loading cameras...</option>
<option value="" data-i18n="settings.loadingCameras">Loading cameras...</option>
</select>
</div>
<div class="setting-group">
<label for="audioSelect" class="setting-label">
<i class="fas fa-microphone"></i> Microphone
<i class="fas fa-microphone"></i> <span data-i18n="settings.audioInput">Microphone</span>
</label>
<select id="audioSelect" class="setting-select">
<option value="">Loading microphones...</option>
<option value="" data-i18n="settings.loadingMicrophones">Loading microphones...</option>
</select>
</div>
<div class="setting-group">
<label for="audioOutputSelect" class="setting-label">
<i class="fas fa-volume-up"></i> Speaker
<i class="fas fa-volume-up"></i> <span data-i18n="settings.audioOutput">Speaker</span>
</label>
<select id="audioOutputSelect" class="setting-select">
<option value="">Loading speakers...</option>
<option value="" data-i18n="settings.loadingSpeakers">Loading speakers...</option>
</select>
</div>
@@ -301,7 +321,10 @@
</button>
</div>
<h3 class="settings-title"><i class="fas fa-comments"></i> Chat Settings</h3>
<h3 class="settings-title">
<i class="fas fa-comments"></i>
<span data-i18n="settings.chatSettingsTitle">Chat Settings</span>
</h3>
<div class="settings-actions">
<button id="saveChatBtn" class="btn btn-success btn-save-chat">
<i class="fas fa-download"></i> <span data-i18n="settings.saveMessages">Save Messages</span>