Some checks reported errors
continuous-integration/drone Build encountered an error
184 lines
No EOL
6.3 KiB
JavaScript
184 lines
No EOL
6.3 KiB
JavaScript
// Translation Manager
|
|
class TranslationManager {
|
|
constructor() {
|
|
this.currentLanguage = 'en'; // Will be set during initialization
|
|
this.translations = {};
|
|
this.supportedLanguages = {
|
|
'en': { name: 'English', flag: '🇬🇧' },
|
|
'es': { name: 'Español', flag: '🇪🇸' },
|
|
'sv': { name: 'Svenska', flag: '🇸🇪' },
|
|
'el': { name: 'Ελληνικά', flag: '🇬🇷' }
|
|
};
|
|
|
|
// Country to language mapping
|
|
this.countryToLanguage = {
|
|
// Spanish-speaking countries
|
|
'ES': 'es', 'MX': 'es', 'AR': 'es', 'CO': 'es', 'PE': 'es', 'VE': 'es',
|
|
'CL': 'es', 'EC': 'es', 'BO': 'es', 'PY': 'es', 'UY': 'es', 'CU': 'es',
|
|
'DO': 'es', 'GT': 'es', 'HN': 'es', 'SV': 'es', 'NI': 'es', 'CR': 'es',
|
|
'PA': 'es', 'BZ': 'es', 'EQ': 'es',
|
|
// Swedish-speaking countries
|
|
'SE': 'sv', 'FI': 'sv', 'AX': 'sv',
|
|
// Greek-speaking countries
|
|
'GR': 'el', 'CY': 'el',
|
|
// Default to English for all others
|
|
};
|
|
}
|
|
|
|
// Detect language with geolocation fallback
|
|
async detectLanguageWithGeolocation() {
|
|
// Step 1: Check localStorage for saved preference
|
|
const savedLanguage = localStorage.getItem('preferredLanguage');
|
|
if (savedLanguage && this.supportedLanguages[savedLanguage]) {
|
|
console.log('Using saved language preference:', savedLanguage);
|
|
return savedLanguage;
|
|
}
|
|
|
|
// Step 2: Try browser language detection
|
|
const browserLang = this.detectBrowserLanguage();
|
|
if (browserLang !== 'en') {
|
|
console.log('Using browser language:', browserLang);
|
|
return browserLang;
|
|
}
|
|
|
|
// Step 3: Try geolocation API to get country and map to language
|
|
try {
|
|
const countryCode = await this.getCountryFromGeolocation();
|
|
if (countryCode) {
|
|
const language = this.countryToLanguage[countryCode] || 'en';
|
|
console.log('Using geolocation-based language:', language, 'from country:', countryCode);
|
|
return language;
|
|
}
|
|
} catch (error) {
|
|
console.warn('Geolocation failed, continuing with fallback:', error.message);
|
|
}
|
|
|
|
// Step 4: Fallback to English
|
|
console.log('Falling back to English');
|
|
return 'en';
|
|
}
|
|
|
|
// Detect browser language
|
|
detectBrowserLanguage() {
|
|
const browserLang = navigator.language || navigator.userLanguage;
|
|
const langCode = browserLang.split('-')[0];
|
|
|
|
// Check if the detected language is supported
|
|
if (this.supportedLanguages[langCode]) {
|
|
return langCode;
|
|
}
|
|
|
|
// Return 'en' if not supported (will trigger geolocation)
|
|
return 'en';
|
|
}
|
|
|
|
// Get country code from geolocation API
|
|
async getCountryFromGeolocation() {
|
|
const timeout = 5000; // 5 second timeout
|
|
|
|
try {
|
|
const controller = new AbortController();
|
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
|
|
// Try ip-api.com (free, no auth required)
|
|
const response = await fetch('https://ipapi.co/json/', {
|
|
signal: controller.signal,
|
|
headers: { 'Accept': 'application/json' }
|
|
});
|
|
|
|
clearTimeout(timeoutId);
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`API returned status ${response.status}`);
|
|
}
|
|
|
|
const data = await response.json();
|
|
const countryCode = data.country_code;
|
|
|
|
if (countryCode && typeof countryCode === 'string') {
|
|
console.log('Geolocation API returned country:', countryCode);
|
|
return countryCode;
|
|
}
|
|
|
|
throw new Error('No country code in response');
|
|
} catch (error) {
|
|
if (error.name === 'AbortError') {
|
|
console.warn('Geolocation API request timed out');
|
|
} else {
|
|
console.warn('Geolocation API error:', error.message);
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Load translation file
|
|
async loadTranslation(language) {
|
|
try {
|
|
const response = await fetch(`translations/${language}.json`);
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to load ${language} translation`);
|
|
}
|
|
this.translations[language] = await response.json();
|
|
this.currentLanguage = language;
|
|
localStorage.setItem('preferredLanguage', language);
|
|
return true;
|
|
} catch (error) {
|
|
console.error('Error loading translation:', error);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Get translated string
|
|
t(key) {
|
|
if (this.translations[this.currentLanguage] && this.translations[this.currentLanguage][key]) {
|
|
return this.translations[this.currentLanguage][key];
|
|
}
|
|
// Fallback to English if key not found
|
|
if (this.translations['en'] && this.translations['en'][key]) {
|
|
return this.translations['en'][key];
|
|
}
|
|
// Return key if no translation found
|
|
return key;
|
|
}
|
|
|
|
// Get current language
|
|
getCurrentLanguage() {
|
|
return this.currentLanguage;
|
|
}
|
|
|
|
// Get all supported languages
|
|
getSupportedLanguages() {
|
|
return this.supportedLanguages;
|
|
}
|
|
|
|
// Set language
|
|
setLanguage(language) {
|
|
if (this.supportedLanguages[language]) {
|
|
this.currentLanguage = language;
|
|
localStorage.setItem('preferredLanguage', language);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Initialize translations
|
|
async initialize() {
|
|
// Detect language using geolocation fallback chain
|
|
this.currentLanguage = await this.detectLanguageWithGeolocation();
|
|
|
|
// Load all supported language files
|
|
const loadPromises = Object.keys(this.supportedLanguages).map(lang =>
|
|
this.loadTranslation(lang)
|
|
);
|
|
|
|
await Promise.all(loadPromises);
|
|
|
|
// Ensure current language is set correctly
|
|
if (!this.translations[this.currentLanguage]) {
|
|
this.currentLanguage = 'en';
|
|
}
|
|
}
|
|
}
|
|
|
|
// Create global instance
|
|
const i18n = new TranslationManager(); |