mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-01-08 07:32:34 +01:00
Observer to find new elements with i18n attribute
This commit is contained in:
parent
a287ccfca2
commit
be08e62fc1
@ -9,6 +9,28 @@ const langs = await fetch('/locales/lang.json').then(response => response.json()
|
|||||||
// eslint-disable-next-line prefer-const
|
// eslint-disable-next-line prefer-const
|
||||||
var localeData = await getLocaleData(localeFile);
|
var localeData = await getLocaleData(localeFile);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An observer that will check if any new i18n elements are added to the document
|
||||||
|
* @type {MutationObserver}
|
||||||
|
*/
|
||||||
|
const observer = new MutationObserver(mutations => {
|
||||||
|
mutations.forEach(mutation => {
|
||||||
|
mutation.addedNodes.forEach(node => {
|
||||||
|
if (node.nodeType === Node.ELEMENT_NODE && node instanceof Element) {
|
||||||
|
if (node.hasAttribute('data-i18n')) {
|
||||||
|
translateElement(node);
|
||||||
|
}
|
||||||
|
node.querySelectorAll('[data-i18n]').forEach(element => {
|
||||||
|
translateElement(element);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (mutation.attributeName === 'data-i18n' && mutation.target instanceof Element) {
|
||||||
|
translateElement(mutation.target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the locale data for the given language.
|
* Fetches the locale data for the given language.
|
||||||
* @param {string} language Language code
|
* @param {string} language Language code
|
||||||
@ -40,6 +62,29 @@ function findLang(language) {
|
|||||||
return supportedLang;
|
return supportedLang;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translates a given element based on its data-i18n attribute.
|
||||||
|
* @param {Element} element The element to translate
|
||||||
|
*/
|
||||||
|
function translateElement(element) {
|
||||||
|
const keys = element.getAttribute('data-i18n').split(';'); // Multi-key entries are ; delimited
|
||||||
|
for (const key of keys) {
|
||||||
|
const attributeMatch = key.match(/\[(\S+)\](.+)/); // [attribute]key
|
||||||
|
if (attributeMatch) { // attribute-tagged key
|
||||||
|
const localizedValue = localeData?.[attributeMatch[2]];
|
||||||
|
if (localizedValue || localizedValue === '') {
|
||||||
|
element.setAttribute(attributeMatch[1], localizedValue);
|
||||||
|
}
|
||||||
|
} else { // No attribute tag, treat as 'text'
|
||||||
|
const localizedValue = localeData?.[key];
|
||||||
|
if (localizedValue || localizedValue === '') {
|
||||||
|
element.textContent = localizedValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async function getMissingTranslations() {
|
async function getMissingTranslations() {
|
||||||
const missingData = [];
|
const missingData = [];
|
||||||
|
|
||||||
@ -103,22 +148,7 @@ export function applyLocale(root = document) {
|
|||||||
|
|
||||||
//find all the elements with `data-i18n` attribute
|
//find all the elements with `data-i18n` attribute
|
||||||
$root.find('[data-i18n]').each(function () {
|
$root.find('[data-i18n]').each(function () {
|
||||||
//read the translation from the language data
|
translateElement(this);
|
||||||
const keys = $(this).data('i18n').split(';'); // Multi-key entries are ; delimited
|
|
||||||
for (const key of keys) {
|
|
||||||
const attributeMatch = key.match(/\[(\S+)\](.+)/); // [attribute]key
|
|
||||||
if (attributeMatch) { // attribute-tagged key
|
|
||||||
const localizedValue = localeData?.[attributeMatch[2]];
|
|
||||||
if (localizedValue || localizedValue == '') {
|
|
||||||
$(this).attr(attributeMatch[1], localizedValue);
|
|
||||||
}
|
|
||||||
} else { // No attribute tag, treat as 'text'
|
|
||||||
const localizedValue = localeData?.[key];
|
|
||||||
if (localizedValue || localizedValue == '') {
|
|
||||||
$(this).text(localizedValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (root !== document) {
|
if (root !== document) {
|
||||||
@ -126,7 +156,6 @@ export function applyLocale(root = document) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function addLanguagesToDropdown() {
|
function addLanguagesToDropdown() {
|
||||||
const uiLanguageSelects = $('#ui_language_select, #onboarding_ui_language_select');
|
const uiLanguageSelects = $('#ui_language_select, #onboarding_ui_language_select');
|
||||||
for (const langObj of langs) { // Set the value to the language code
|
for (const langObj of langs) { // Set the value to the language code
|
||||||
@ -159,6 +188,13 @@ export function initLocales() {
|
|||||||
location.reload();
|
location.reload();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
observer.observe(document, {
|
||||||
|
childList: true,
|
||||||
|
subtree: true,
|
||||||
|
attributes: true,
|
||||||
|
attributeFilter: ['data-i18n'],
|
||||||
|
});
|
||||||
|
|
||||||
registerDebugFunction('getMissingTranslations', 'Get missing translations', 'Detects missing localization data in the current locale and dumps the data into the browser console. If the current locale is English, searches all other locales.', getMissingTranslations);
|
registerDebugFunction('getMissingTranslations', 'Get missing translations', 'Detects missing localization data in the current locale and dumps the data into the browser console. If the current locale is English, searches all other locales.', getMissingTranslations);
|
||||||
registerDebugFunction('applyLocale', 'Apply locale', 'Reapplies the currently selected locale to the page.', applyLocale);
|
registerDebugFunction('applyLocale', 'Apply locale', 'Reapplies the currently selected locale to the page.', applyLocale);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user