UNPKG

ticket-selector

Version:

A professional stadium seat selection widget with multi-language support

156 lines (125 loc) 3.75 kB
import { en, az, tr } from './translations.js'; class I18n { constructor(lang = null) { this.languages = { en: en, az: az, tr: tr, }; this.defaultLanguage = 'az'; this.currentLanguage = this.detectLanguage(lang); this.translations = this.languages[this.currentLanguage] || this.languages[this.defaultLanguage]; } detectLanguage(providedLang) { if (providedLang && this.languages[providedLang]) { return providedLang; } const browserLang = this.getBrowserLanguage(); if (this.languages[browserLang]) { return browserLang; } return this.defaultLanguage; } // Extract base language from locale codes (en-US -> en, tr-TR -> tr, etc.) extractLanguageCode(langString) { if (!langString || typeof langString !== 'string') { return null; } // Handle locale codes like en-US, tr-TR, az-AZ, en_US, etc. return langString.split(/[-_]/)[0].toLowerCase().trim(); } getBrowserLanguage() { // Check HTML lang attribute first (highest priority) if (typeof document !== 'undefined') { const htmlLang = document.documentElement.lang; if (htmlLang) { const baseLang = this.extractLanguageCode(htmlLang); if (baseLang && this.languages[baseLang]) { return baseLang; } } } // Check browser language (fallback) if (typeof navigator !== 'undefined') { const navigatorLang = navigator.language || navigator.userLanguage; if (navigatorLang) { const baseLang = this.extractLanguageCode(navigatorLang); if (baseLang && this.languages[baseLang]) { return baseLang; } } } return this.defaultLanguage; } t(keyPath, params = {}, count = null) { const keys = keyPath.split('.'); let value = this.translations; for (const key of keys) { if (value && typeof value === 'object' && key in value) { value = value[key]; } else { value = this.getFallbackTranslation(keyPath); break; } } if (value && typeof value === 'object' && count !== null) { value = this.getPlural(value, count); } if (typeof value !== 'string') { console.warn(`Translation key not found: ${keyPath}`); return keyPath; } return this.replaceParams(value, params, count); } getFallbackTranslation(keyPath) { const keys = keyPath.split('.'); let value = this.languages[this.defaultLanguage]; for (const key of keys) { if (value && typeof value === 'object' && key in value) { value = value[key]; } else { return keyPath; } } return value; } getPlural(pluralObject, count) { const num = parseInt(count); if (num === 0 && pluralObject.zero) { return pluralObject.zero; } else if (num === 1 && pluralObject.one) { return pluralObject.one; } else if (pluralObject.other) { return pluralObject.other; } return pluralObject.other || pluralObject.one || pluralObject.zero || ''; } replaceParams(text, params, count) { let result = text; if (count !== null) { params.count = count; } Object.keys(params).forEach((key) => { const placeholder = `{${key}}`; result = result.replace(new RegExp(placeholder, 'g'), params[key]); }); return result; } setLanguage(lang) { if (this.languages[lang]) { this.currentLanguage = lang; this.translations = this.languages[lang]; return true; } return false; } getCurrentLanguage() { return this.currentLanguage; } getAvailableLanguages() { return Object.keys(this.languages); } } export default I18n;