Add ink integration UI and media playback

This commit is contained in:
2026-05-15 21:23:46 +02:00
parent 44dc64f830
commit f2e786d5bc
89 changed files with 6561 additions and 556 deletions
+52 -28
View File
@@ -13,20 +13,21 @@ class LocalizationModule extends BaseModule {
// Current locale
this.translations = {};
this.defaultLocale = 'en-us';
this.defaultLocale = 'en_US';
this.currentLocale = this.defaultLocale;
this.dependencies = ['persistence-manager'];
// Available translations
this.languageNames = {
'en-us': 'English (US)',
'en-gb': 'English (UK)',
'de-de': 'Deutsch (Deutschland)'
'en_US': 'English (US)',
'de_DE': 'Deutsch (Deutschland)'
};
// Bind methods
this.bindMethods([
'setLocale',
'applyServerLocale',
'normalizeLocale',
'getLocale',
'translate',
'getAvailableLocales',
@@ -44,7 +45,7 @@ class LocalizationModule extends BaseModule {
this.reportProgress(10, "Initializing localization");
// Load default English locale
await this.loadTranslations('en-us');
await this.loadTranslations(this.defaultLocale);
this.reportProgress(50, "Loaded default locale");
// Get stored locale from persistence manager if available
@@ -53,27 +54,26 @@ class LocalizationModule extends BaseModule {
if (persistenceManager) {
const storedLocale = persistenceManager.getPreference('app', 'locale');
if (storedLocale) {
console.log(`Localization: Found stored locale: ${storedLocale}`);
await this.loadTranslations(storedLocale);
this.currentLocale = storedLocale;
this.reportProgress(80, `Loaded stored locale: ${storedLocale}`);
const normalizedLocale = this.normalizeLocale(storedLocale);
console.log(`Localization: Found stored locale: ${normalizedLocale}`);
await this.loadTranslations(normalizedLocale);
this.currentLocale = normalizedLocale;
this.reportProgress(80, `Loaded stored locale: ${normalizedLocale}`);
} else {
// If no stored locale, ensure en-us is the default and persist it
console.log('Localization: No stored locale found, using default en-us');
persistenceManager.updatePreference('app', 'locale', 'en-us');
persistenceManager.updatePreference('tts', 'language', 'en-us');
this.currentLocale = 'en-us';
this.reportProgress(80, "Using default locale: en-us");
console.log(`Localization: No stored locale found, using default ${this.defaultLocale}`);
this.currentLocale = this.defaultLocale;
this.reportProgress(80, `Using default locale: ${this.defaultLocale}`);
}
} else {
console.log('Localization: Persistence manager not available, using default en-us locale');
this.reportProgress(80, "Using default locale: en-us");
console.log(`Localization: Persistence manager not available, using default ${this.defaultLocale} locale`);
this.reportProgress(80, `Using default locale: ${this.defaultLocale}`);
}
// Dispatch event to notify about loaded locale
document.dispatchEvent(new CustomEvent('localization:languageChanged', {
detail: { locale: this.currentLocale }
}));
document.documentElement.lang = this.currentLocale.replace('_', '-');
this.reportProgress(100, "Localization ready");
return true;
@@ -90,14 +90,12 @@ class LocalizationModule extends BaseModule {
* @returns {Promise<void>}
*/
async loadTranslations(locale) {
if (this.translations[locale]) {
const normalizedLocale = this.normalizeLocale(locale);
if (this.translations[normalizedLocale]) {
return; // Already loaded
}
try {
// Normalize locale
const normalizedLocale = locale.toLowerCase();
// Try to load the exact locale
const response = await fetch(`/locales/${normalizedLocale}.json`);
@@ -106,7 +104,7 @@ class LocalizationModule extends BaseModule {
this.translations[normalizedLocale] = translations;
} else {
// If exact locale not found, try to load just the language part
const langPart = normalizedLocale.split('-')[0];
const langPart = normalizedLocale.split('_')[0];
if (langPart !== normalizedLocale) {
const langResponse = await fetch(`/locales/${langPart}.json`);
if (langResponse.ok) {
@@ -128,12 +126,12 @@ class LocalizationModule extends BaseModule {
* @param {string} locale - Locale to set
* @returns {Promise<boolean>} - Success status
*/
async setLocale(locale) {
async setLocale(locale, options = {}) {
if (!locale) return false;
try {
// Normalize locale
const normalizedLocale = locale.toLowerCase();
const normalizedLocale = this.normalizeLocale(locale);
const userInitiated = options.userInitiated !== false;
// Load translations if not already loaded
if (!this.translations[normalizedLocale]) {
@@ -148,12 +146,23 @@ class LocalizationModule extends BaseModule {
if (persistenceManager) {
persistenceManager.updatePreference('app', 'locale', normalizedLocale);
persistenceManager.updatePreference('tts', 'language', normalizedLocale);
if (userInitiated) {
persistenceManager.updatePreference('app', 'localeUserOverride', true);
}
}
document.documentElement.lang = normalizedLocale.replace('_', '-');
// Dispatch locale change event
this.dispatchEvent('locale-changed', {
locale: normalizedLocale
});
document.dispatchEvent(new CustomEvent('locale:changed', {
detail: { locale: normalizedLocale }
}));
document.dispatchEvent(new CustomEvent('localization:languageChanged', {
detail: { locale: normalizedLocale }
}));
return true;
} catch (error) {
@@ -161,6 +170,21 @@ class LocalizationModule extends BaseModule {
return false;
}
}
async applyServerLocale(locale) {
const persistenceManager = this.getModule('persistence-manager');
const userOverride = persistenceManager?.getPreference('app', 'localeUserOverride', false);
if (userOverride) {
return false;
}
return this.setLocale(locale, { userInitiated: false });
}
normalizeLocale(locale) {
const normalized = String(locale || this.defaultLocale).trim().replace('-', '_').toLowerCase();
if (normalized.startsWith('de')) return 'de_DE';
return 'en_US';
}
/**
* Get the current locale
@@ -175,7 +199,7 @@ class LocalizationModule extends BaseModule {
* @returns {string} - Language code
*/
getLanguage() {
return this.currentLocale.split('-')[0];
return this.currentLocale.split('_')[0];
}
/**
@@ -197,7 +221,7 @@ class LocalizationModule extends BaseModule {
if (!locale) return '';
// Normalize locale
const normalizedLocale = locale.toLowerCase();
const normalizedLocale = this.normalizeLocale(locale);
// Try exact match
if (this.languageNames[normalizedLocale]) {
@@ -205,7 +229,7 @@ class LocalizationModule extends BaseModule {
}
// Try language part only
const langPart = normalizedLocale.split('-')[0];
const langPart = normalizedLocale.split('_')[0];
if (this.languageNames[langPart]) {
return this.languageNames[langPart];
}