diff --git a/src/App.vue b/src/App.vue index c629bd6..53a0cf7 100644 --- a/src/App.vue +++ b/src/App.vue @@ -22,8 +22,37 @@ const installDismissed = ref(false); const isCoarsePointer = ref(false); const isStandalone = ref(false); const themePreference = ref('system'); +const isLangOpen = ref(false); +const langMenuRef = ref(null); let displayModeMedia = null; let prefersColorSchemeMedia = null; +const languageFlags = { + en: '', + zh: '', + hi: '', + es: '', + fr: '', + ar: '', + bn: '', + ru: '', + pt: '', + ur: '', + pl: '' +}; + +const languages = computed(() => [ + { code: 'en', label: t('language.en') }, + { code: 'zh', label: t('language.zh') }, + { code: 'hi', label: t('language.hi') }, + { code: 'es', label: t('language.es') }, + { code: 'fr', label: t('language.fr') }, + { code: 'ar', label: t('language.ar') }, + { code: 'bn', label: t('language.bn') }, + { code: 'ru', label: t('language.ru') }, + { code: 'pt', label: t('language.pt') }, + { code: 'ur', label: t('language.ur') }, + { code: 'pl', label: t('language.pl') } +]); const installLabel = computed(() => { return isCoarsePointer.value ? t('pwa.installMobile') : t('pwa.installDesktop'); @@ -85,6 +114,18 @@ const handleSystemThemeChange = () => { } }; +const selectLanguage = (value) => { + setLocale(value); + isLangOpen.value = false; +}; + +const handleOutsideClick = (event) => { + if (!langMenuRef.value) return; + if (!langMenuRef.value.contains(event.target)) { + isLangOpen.value = false; + } +}; + onMounted(() => { if (!store.loadState()) { store.initGame(); // Inicjalizacja domyślnej gry jeśli brak zapisu @@ -111,6 +152,7 @@ onMounted(() => { } else if (displayModeMedia?.addListener) { displayModeMedia.addListener(updateStandalone); } + document.addEventListener('click', handleOutsideClick); } }); @@ -128,6 +170,7 @@ onUnmounted(() => { } else if (displayModeMedia?.removeListener) { displayModeMedia.removeListener(updateStandalone); } + document.removeEventListener('click', handleOutsideClick); }); @@ -138,9 +181,29 @@ onUnmounted(() => {

{{ t('app.title') }}

-
- - +
+ +
+ +
{{ t('theme.label') }} @@ -242,35 +305,87 @@ h1 { margin-top: 12px; } -.lang-toggle { +.lang-dropdown { + position: relative; display: inline-flex; - gap: 8px; - padding: 6px 10px; - border-radius: 999px; + align-items: center; +} + +.lang-trigger { background: var(--toggle-bg); border: 1px solid var(--toggle-border); box-shadow: var(--toggle-shadow); -} - -.lang-btn { - background: transparent; - border: 1px solid var(--toggle-btn-border); - color: var(--text-strong); - padding: 4px 10px; border-radius: 999px; - font-size: 0.8rem; - letter-spacing: 1px; + width: 38px; + height: 38px; + display: inline-flex; + align-items: center; + justify-content: center; cursor: pointer; transition: all 0.2s ease; } -.lang-btn.active { +.lang-trigger:hover { + border-color: var(--toggle-hover-border); +} + +.lang-menu { + position: absolute; + top: calc(100% + 8px); + right: 0; + min-width: 170px; + background: var(--toggle-bg); + border: 1px solid var(--toggle-border); + box-shadow: var(--toggle-shadow); + border-radius: 16px; + padding: 8px; + display: flex; + flex-direction: column; + gap: 6px; + z-index: 10; + opacity: 1; +} + +.lang-option { + background: transparent; + border: 1px solid var(--toggle-btn-border); + color: var(--text-strong); + padding: 6px 10px; + border-radius: 12px; + font-size: 0.85rem; + letter-spacing: 0.5px; + display: flex; + align-items: center; + gap: 8px; + cursor: pointer; + transition: all 0.2s ease; + text-align: left; +} + +.lang-option:hover { + border-color: var(--toggle-hover-border); +} + +.lang-option.active { border-color: var(--primary-accent); box-shadow: var(--toggle-active-shadow); } -.lang-btn:hover { - border-color: var(--toggle-hover-border); +.lang-flag { + width: 24px; + height: 16px; + display: inline-flex; +} + +.lang-flag svg { + width: 100%; + height: 100%; + display: block; + border-radius: 2px; +} + +.lang-name { + font-weight: 500; } .theme-toggle { diff --git a/src/components/WinModal.vue b/src/components/WinModal.vue index 9a8c53d..655957e 100644 --- a/src/components/WinModal.vue +++ b/src/components/WinModal.vue @@ -337,6 +337,7 @@ onUnmounted(() => { animation: slideUp 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); position: relative; z-index: 1001; + overflow-wrap: anywhere; } h2 { @@ -344,12 +345,14 @@ h2 { color: var(--primary-accent); margin: 0 0 10px 0; text-shadow: 0 0 20px var(--primary-accent); + overflow-wrap: anywhere; } p { color: var(--text-secondary); font-size: 1.2rem; margin-bottom: 30px; + overflow-wrap: anywhere; } .stats { @@ -380,6 +383,7 @@ p { letter-spacing: 1px; text-transform: uppercase; color: var(--text-muted); + overflow-wrap: anywhere; } .share-buttons { @@ -409,6 +413,13 @@ p { align-self: center; padding: 8px 18px; font-size: 0.85rem; + max-width: 100%; + white-space: normal; +} + +.actions .btn-neon { + max-width: 100%; + white-space: normal; } @keyframes fadeIn { diff --git a/src/composables/useI18n.js b/src/composables/useI18n.js index de0e1d2..bf502ee 100644 --- a/src/composables/useI18n.js +++ b/src/composables/useI18n.js @@ -1,10 +1,12 @@ import { ref, computed } from 'vue'; +const supportedLocales = ['pl', 'en', 'zh', 'hi', 'es', 'fr', 'ar', 'bn', 'ru', 'pt', 'ur']; + const detectLocale = () => { if (typeof navigator === 'undefined') return 'en'; const browserLocale = (navigator.languages && navigator.languages[0]) || navigator.language || 'en'; const short = browserLocale.toLowerCase().split('-')[0]; - return short === 'pl' ? 'pl' : 'en'; + return supportedLocales.includes(short) ? short : 'en'; }; const messages = { @@ -49,6 +51,18 @@ const messages = { 'pwa.installTitle': 'Zainstaluj aplikację i graj offline', 'pwa.installMobile': 'Dodaj do ekranu głównego', 'pwa.installDesktop': 'Zainstaluj na komputerze', + 'language.label': 'Wybór języka', + 'language.pl': 'Polski', + 'language.en': 'Angielski', + 'language.zh': 'Mandaryński', + 'language.hi': 'Hindi', + 'language.es': 'Hiszpański', + 'language.fr': 'Francuski', + 'language.ar': 'Arabski', + 'language.bn': 'Bengalski', + 'language.ru': 'Rosyjski', + 'language.pt': 'Portugalski', + 'language.ur': 'Urdu', 'theme.label': 'Motyw', 'theme.system': 'System', 'theme.light': 'Jasny', @@ -95,10 +109,544 @@ const messages = { 'pwa.installTitle': 'Install the app and play offline', 'pwa.installMobile': 'Add to home screen', 'pwa.installDesktop': 'Install on desktop', + 'language.label': 'Language selection', + 'language.pl': 'Polish', + 'language.en': 'English', + 'language.zh': 'Mandarin', + 'language.hi': 'Hindi', + 'language.es': 'Spanish', + 'language.fr': 'French', + 'language.ar': 'Arabic', + 'language.bn': 'Bengali', + 'language.ru': 'Russian', + 'language.pt': 'Portuguese', + 'language.ur': 'Urdu', 'theme.label': 'Theme', 'theme.system': 'System', 'theme.light': 'Light', 'theme.dark': 'Dark' + }, + zh: { + 'app.title': 'Nonograms', + 'level.easy': '简单 5X5', + 'level.medium': '中等 10X10', + 'level.hard': '困难 15X15', + 'level.custom': '自定义', + 'level.guide': '指南 ❓', + 'actions.reset': '重置', + 'actions.random': '新随机', + 'actions.undo': '撤销', + 'status.time': '时间', + 'status.moves': '步数', + 'status.progress': '进度', + 'fixed.time': '时间:', + 'fixed.progress': '进度:', + 'fixed.hide': '隐藏', + 'fixed.show': '显示', + 'guide.play': '开始', + 'guide.pause': '暂停', + 'guide.step': '步骤', + 'guide.speed': '速度', + 'guide.waiting': '等待...', + 'guide.solved': '已解!', + 'custom.title': '自定义游戏', + 'custom.prompt': '输入网格大小 (5 - 80):', + 'custom.cancel': '取消', + 'custom.start': '开始', + 'custom.sizeError': '尺寸必须在 5 到 80 之间!', + 'win.title': '恭喜!', + 'win.message': '你解开了谜题!', + 'win.time': '时间:', + 'win.playAgain': '再玩一次', + 'win.shareTitle': '分享你的结果', + 'win.shareText': '我在 {time} 内解开了 {size}x{size} 的数织!', + 'win.shareX': 'X', + 'win.shareFacebook': 'Facebook', + 'win.shareWhatsapp': 'WhatsApp', + 'win.shareDownload': '下载截图', + 'pwa.installTitle': '安装应用并离线游玩', + 'pwa.installMobile': '添加到主屏幕', + 'pwa.installDesktop': '安装到桌面', + 'language.label': '语言选择', + 'language.pl': '波兰语', + 'language.en': '英语', + 'language.zh': '中文', + 'language.hi': '印地语', + 'language.es': '西班牙语', + 'language.fr': '法语', + 'language.ar': '阿拉伯语', + 'language.bn': '孟加拉语', + 'language.ru': '俄语', + 'language.pt': '葡萄牙语', + 'language.ur': '乌尔都语', + 'theme.label': '主题', + 'theme.system': '系统', + 'theme.light': '浅色', + 'theme.dark': '深色' + }, + hi: { + 'app.title': 'Nonograms', + 'level.easy': 'आसान 5X5', + 'level.medium': 'मध्यम 10X10', + 'level.hard': 'कठिन 15X15', + 'level.custom': 'कस्टम', + 'level.guide': 'गाइड ❓', + 'actions.reset': 'रीसेट', + 'actions.random': 'नई रैंडम', + 'actions.undo': 'वापस', + 'status.time': 'समय', + 'status.moves': 'चालें', + 'status.progress': 'प्रगति', + 'fixed.time': 'समय:', + 'fixed.progress': 'प्रगति:', + 'fixed.hide': 'छिपाएं', + 'fixed.show': 'दिखाएं', + 'guide.play': 'शुरू', + 'guide.pause': 'रोकें', + 'guide.step': 'कदम', + 'guide.speed': 'गति', + 'guide.waiting': 'प्रतीक्षा...', + 'guide.solved': 'हल हो गया!', + 'custom.title': 'कस्टम गेम', + 'custom.prompt': 'ग्रिड आकार दर्ज करें (5 - 80):', + 'custom.cancel': 'रद्द करें', + 'custom.start': 'शुरू', + 'custom.sizeError': 'आकार 5 और 80 के बीच होना चाहिए!', + 'win.title': 'बधाई!', + 'win.message': 'आपने पहेली हल कर ली!', + 'win.time': 'समय:', + 'win.playAgain': 'फिर से खेलें', + 'win.shareTitle': 'अपना परिणाम साझा करें', + 'win.shareText': 'मैंने {time} में {size}x{size} नॉनोग्राम हल किया!', + 'win.shareX': 'X', + 'win.shareFacebook': 'Facebook', + 'win.shareWhatsapp': 'WhatsApp', + 'win.shareDownload': 'स्क्रीनशॉट डाउनलोड करें', + 'pwa.installTitle': 'ऐप इंस्टॉल करें और ऑफलाइन खेलें', + 'pwa.installMobile': 'होम स्क्रीन पर जोड़ें', + 'pwa.installDesktop': 'डेस्कटॉप पर इंस्टॉल करें', + 'language.label': 'भाषा चयन', + 'language.pl': 'पोलिश', + 'language.en': 'अंग्रेज़ी', + 'language.zh': 'चीनी', + 'language.hi': 'हिंदी', + 'language.es': 'स्पेनिश', + 'language.fr': 'फ़्रेंच', + 'language.ar': 'अरबी', + 'language.bn': 'बंगाली', + 'language.ru': 'रूसी', + 'language.pt': 'पुर्तगाली', + 'language.ur': 'उर्दू', + 'theme.label': 'थीम', + 'theme.system': 'सिस्टम', + 'theme.light': 'हल्का', + 'theme.dark': 'गहरा' + }, + es: { + 'app.title': 'Nonograms', + 'level.easy': 'FÁCIL 5X5', + 'level.medium': 'MEDIO 10X10', + 'level.hard': 'DIFÍCIL 15X15', + 'level.custom': 'PERSONALIZADO', + 'level.guide': 'GUÍA ❓', + 'actions.reset': 'REINICIAR', + 'actions.random': 'NUEVO ALEATORIO', + 'actions.undo': 'DESHACER', + 'status.time': 'TIEMPO', + 'status.moves': 'MOVIMIENTOS', + 'status.progress': 'PROGRESO', + 'fixed.time': 'Tiempo:', + 'fixed.progress': 'Progreso:', + 'fixed.hide': 'Ocultar', + 'fixed.show': 'Mostrar', + 'guide.play': 'INICIAR', + 'guide.pause': 'PAUSA', + 'guide.step': 'PASO', + 'guide.speed': 'VELOCIDAD', + 'guide.waiting': 'Esperando...', + 'guide.solved': '¡Resuelto!', + 'custom.title': 'JUEGO PERSONALIZADO', + 'custom.prompt': 'Introduce el tamaño de la cuadrícula (5 - 80):', + 'custom.cancel': 'Cancelar', + 'custom.start': 'Empezar', + 'custom.sizeError': '¡El tamaño debe estar entre 5 y 80!', + 'win.title': '¡FELICIDADES!', + 'win.message': '¡Has resuelto el rompecabezas!', + 'win.time': 'Tiempo:', + 'win.playAgain': 'Jugar de nuevo', + 'win.shareTitle': 'Comparte tu resultado', + 'win.shareText': '¡Resolví un nonograma de {size}x{size} en {time}!', + 'win.shareX': 'X', + 'win.shareFacebook': 'Facebook', + 'win.shareWhatsapp': 'WhatsApp', + 'win.shareDownload': 'Descargar captura', + 'pwa.installTitle': 'Instala la app y juega sin conexión', + 'pwa.installMobile': 'Agregar a la pantalla de inicio', + 'pwa.installDesktop': 'Instalar en el escritorio', + 'language.label': 'Selección de idioma', + 'language.pl': 'Polaco', + 'language.en': 'Inglés', + 'language.zh': 'Chino', + 'language.hi': 'Hindi', + 'language.es': 'Español', + 'language.fr': 'Francés', + 'language.ar': 'Árabe', + 'language.bn': 'Bengalí', + 'language.ru': 'Ruso', + 'language.pt': 'Portugués', + 'language.ur': 'Urdu', + 'theme.label': 'Tema', + 'theme.system': 'Sistema', + 'theme.light': 'Claro', + 'theme.dark': 'Oscuro' + }, + fr: { + 'app.title': 'Nonograms', + 'level.easy': 'FACILE 5X5', + 'level.medium': 'MOYEN 10X10', + 'level.hard': 'DIFFICILE 15X15', + 'level.custom': 'PERSONNALISÉ', + 'level.guide': 'GUIDE ❓', + 'actions.reset': 'RÉINITIALISER', + 'actions.random': 'NOUVEAU ALÉATOIRE', + 'actions.undo': 'ANNULER', + 'status.time': 'TEMPS', + 'status.moves': 'COUPS', + 'status.progress': 'PROGRÈS', + 'fixed.time': 'Temps:', + 'fixed.progress': 'Progrès:', + 'fixed.hide': 'Masquer', + 'fixed.show': 'Afficher', + 'guide.play': 'LANCER', + 'guide.pause': 'PAUSE', + 'guide.step': 'ÉTAPE', + 'guide.speed': 'VITESSE', + 'guide.waiting': 'En attente...', + 'guide.solved': 'Résolu !', + 'custom.title': 'JEU PERSONNALISÉ', + 'custom.prompt': 'Entrez la taille de la grille (5 - 80) :', + 'custom.cancel': 'Annuler', + 'custom.start': 'Démarrer', + 'custom.sizeError': 'La taille doit être entre 5 et 80 !', + 'win.title': 'FÉLICITATIONS !', + 'win.message': 'Vous avez résolu le puzzle !', + 'win.time': 'Temps:', + 'win.playAgain': 'Rejouer', + 'win.shareTitle': 'Partagez votre résultat', + 'win.shareText': 'J’ai résolu un nonogramme {size}x{size} en {time} !', + 'win.shareX': 'X', + 'win.shareFacebook': 'Facebook', + 'win.shareWhatsapp': 'WhatsApp', + 'win.shareDownload': 'Télécharger la capture', + 'pwa.installTitle': 'Installez l’app et jouez hors ligne', + 'pwa.installMobile': 'Ajouter à l’écran d’accueil', + 'pwa.installDesktop': 'Installer sur le bureau', + 'language.label': 'Choix de la langue', + 'language.pl': 'Polonais', + 'language.en': 'Anglais', + 'language.zh': 'Chinois', + 'language.hi': 'Hindi', + 'language.es': 'Espagnol', + 'language.fr': 'Français', + 'language.ar': 'Arabe', + 'language.bn': 'Bengali', + 'language.ru': 'Russe', + 'language.pt': 'Portugais', + 'language.ur': 'Ourdou', + 'theme.label': 'Thème', + 'theme.system': 'Système', + 'theme.light': 'Clair', + 'theme.dark': 'Sombre' + }, + ar: { + 'app.title': 'Nonograms', + 'level.easy': 'سهل 5X5', + 'level.medium': 'متوسط 10X10', + 'level.hard': 'صعب 15X15', + 'level.custom': 'مخصص', + 'level.guide': 'دليل ❓', + 'actions.reset': 'إعادة ضبط', + 'actions.random': 'عشوائي جديد', + 'actions.undo': 'تراجع', + 'status.time': 'الوقت', + 'status.moves': 'الحركات', + 'status.progress': 'التقدم', + 'fixed.time': 'الوقت:', + 'fixed.progress': 'التقدم:', + 'fixed.hide': 'إخفاء', + 'fixed.show': 'إظهار', + 'guide.play': 'ابدأ', + 'guide.pause': 'إيقاف مؤقت', + 'guide.step': 'خطوة', + 'guide.speed': 'السرعة', + 'guide.waiting': 'جارٍ الانتظار...', + 'guide.solved': 'تم الحل!', + 'custom.title': 'لعبة مخصصة', + 'custom.prompt': 'أدخل حجم الشبكة (5 - 80):', + 'custom.cancel': 'إلغاء', + 'custom.start': 'ابدأ', + 'custom.sizeError': 'يجب أن يكون الحجم بين 5 و80!', + 'win.title': 'تهانينا!', + 'win.message': 'لقد حللت اللغز!', + 'win.time': 'الوقت:', + 'win.playAgain': 'العب مرة أخرى', + 'win.shareTitle': 'شارك نتيجتك', + 'win.shareText': 'حللت نونوغرام {size}x{size} في {time}!', + 'win.shareX': 'X', + 'win.shareFacebook': 'Facebook', + 'win.shareWhatsapp': 'WhatsApp', + 'win.shareDownload': 'تحميل لقطة الشاشة', + 'pwa.installTitle': 'ثبّت التطبيق والعب دون اتصال', + 'pwa.installMobile': 'أضف إلى الشاشة الرئيسية', + 'pwa.installDesktop': 'التثبيت على سطح المكتب', + 'language.label': 'اختيار اللغة', + 'language.pl': 'البولندية', + 'language.en': 'الإنجليزية', + 'language.zh': 'الصينية', + 'language.hi': 'الهندية', + 'language.es': 'الإسبانية', + 'language.fr': 'الفرنسية', + 'language.ar': 'العربية', + 'language.bn': 'البنغالية', + 'language.ru': 'الروسية', + 'language.pt': 'البرتغالية', + 'language.ur': 'الأردية', + 'theme.label': 'السمة', + 'theme.system': 'النظام', + 'theme.light': 'فاتح', + 'theme.dark': 'داكن' + }, + bn: { + 'app.title': 'Nonograms', + 'level.easy': 'সহজ 5X5', + 'level.medium': 'মাঝারি 10X10', + 'level.hard': 'কঠিন 15X15', + 'level.custom': 'কাস্টম', + 'level.guide': 'গাইড ❓', + 'actions.reset': 'রিসেট', + 'actions.random': 'নতুন র‍্যান্ডম', + 'actions.undo': 'পূর্বাবস্থায়', + 'status.time': 'সময়', + 'status.moves': 'চাল', + 'status.progress': 'অগ্রগতি', + 'fixed.time': 'সময়:', + 'fixed.progress': 'অগ্রগতি:', + 'fixed.hide': 'লুকান', + 'fixed.show': 'দেখান', + 'guide.play': 'শুরু', + 'guide.pause': 'বিরতি', + 'guide.step': 'ধাপ', + 'guide.speed': 'গতি', + 'guide.waiting': 'অপেক্ষা...', + 'guide.solved': 'সমাধান হয়েছে!', + 'custom.title': 'কাস্টম গেম', + 'custom.prompt': 'গ্রিডের আকার দিন (5 - 80):', + 'custom.cancel': 'বাতিল', + 'custom.start': 'শুরু', + 'custom.sizeError': 'আকার 5 থেকে 80 এর মধ্যে হতে হবে!', + 'win.title': 'অভিনন্দন!', + 'win.message': 'আপনি ধাঁধা সমাধান করেছেন!', + 'win.time': 'সময়:', + 'win.playAgain': 'আবার খেলুন', + 'win.shareTitle': 'আপনার ফলাফল শেয়ার করুন', + 'win.shareText': 'আমি {time} সময়ে {size}x{size} ননোগ্রাম সমাধান করেছি!', + 'win.shareX': 'X', + 'win.shareFacebook': 'Facebook', + 'win.shareWhatsapp': 'WhatsApp', + 'win.shareDownload': 'স্ক্রিনশট ডাউনলোড করুন', + 'pwa.installTitle': 'অ্যাপটি ইনস্টল করে অফলাইনে খেলুন', + 'pwa.installMobile': 'হোম স্ক্রিনে যোগ করুন', + 'pwa.installDesktop': 'ডেস্কটপে ইনস্টল করুন', + 'language.label': 'ভাষা নির্বাচন', + 'language.pl': 'পোলিশ', + 'language.en': 'ইংরেজি', + 'language.zh': 'চীনা', + 'language.hi': 'হিন্দি', + 'language.es': 'স্প্যানিশ', + 'language.fr': 'ফরাসি', + 'language.ar': 'আরবি', + 'language.bn': 'বাংলা', + 'language.ru': 'রুশ', + 'language.pt': 'পর্তুগিজ', + 'language.ur': 'উর্দু', + 'theme.label': 'থিম', + 'theme.system': 'সিস্টেম', + 'theme.light': 'হালকা', + 'theme.dark': 'গাঢ়' + }, + ru: { + 'app.title': 'Nonograms', + 'level.easy': 'ЛЕГКО 5X5', + 'level.medium': 'СРЕДНЕ 10X10', + 'level.hard': 'ТЯЖЕЛО 15X15', + 'level.custom': 'СВОЯ', + 'level.guide': 'ПОДСКАЗКА ❓', + 'actions.reset': 'СБРОС', + 'actions.random': 'НОВАЯ СЛУЧАЙНАЯ', + 'actions.undo': 'ОТМЕНА', + 'status.time': 'ВРЕМЯ', + 'status.moves': 'ХОДЫ', + 'status.progress': 'ПРОГРЕСС', + 'fixed.time': 'Время:', + 'fixed.progress': 'Прогресс:', + 'fixed.hide': 'Скрыть', + 'fixed.show': 'Показать', + 'guide.play': 'СТАРТ', + 'guide.pause': 'ПАУЗА', + 'guide.step': 'ШАГ', + 'guide.speed': 'СКОРОСТЬ', + 'guide.waiting': 'Ожидание...', + 'guide.solved': 'Решено!', + 'custom.title': 'СВОЯ ИГРА', + 'custom.prompt': 'Введите размер сетки (5 - 80):', + 'custom.cancel': 'Отмена', + 'custom.start': 'Старт', + 'custom.sizeError': 'Размер должен быть от 5 до 80!', + 'win.title': 'ПОЗДРАВЛЯЕМ!', + 'win.message': 'Вы решили головоломку!', + 'win.time': 'Время:', + 'win.playAgain': 'Сыграть снова', + 'win.shareTitle': 'Поделитесь результатом', + 'win.shareText': 'Я решил(а) нонограмму {size}x{size} за {time}!', + 'win.shareX': 'X', + 'win.shareFacebook': 'Facebook', + 'win.shareWhatsapp': 'WhatsApp', + 'win.shareDownload': 'Скачать снимок', + 'pwa.installTitle': 'Установите приложение и играйте офлайн', + 'pwa.installMobile': 'Добавить на главный экран', + 'pwa.installDesktop': 'Установить на компьютер', + 'language.label': 'Выбор языка', + 'language.pl': 'Польский', + 'language.en': 'Английский', + 'language.zh': 'Китайский', + 'language.hi': 'Хинди', + 'language.es': 'Испанский', + 'language.fr': 'Французский', + 'language.ar': 'Арабский', + 'language.bn': 'Бенгальский', + 'language.ru': 'Русский', + 'language.pt': 'Португальский', + 'language.ur': 'Урду', + 'theme.label': 'Тема', + 'theme.system': 'Система', + 'theme.light': 'Светлая', + 'theme.dark': 'Тёмная' + }, + pt: { + 'app.title': 'Nonograms', + 'level.easy': 'FÁCIL 5X5', + 'level.medium': 'MÉDIO 10X10', + 'level.hard': 'DIFÍCIL 15X15', + 'level.custom': 'PERSONALIZADO', + 'level.guide': 'GUIA ❓', + 'actions.reset': 'REINICIAR', + 'actions.random': 'NOVO ALEATÓRIO', + 'actions.undo': 'DESFAZER', + 'status.time': 'TEMPO', + 'status.moves': 'MOVIMENTOS', + 'status.progress': 'PROGRESSO', + 'fixed.time': 'Tempo:', + 'fixed.progress': 'Progresso:', + 'fixed.hide': 'Ocultar', + 'fixed.show': 'Mostrar', + 'guide.play': 'INICIAR', + 'guide.pause': 'PAUSAR', + 'guide.step': 'PASSO', + 'guide.speed': 'VELOCIDADE', + 'guide.waiting': 'Aguardando...', + 'guide.solved': 'Resolvido!', + 'custom.title': 'JOGO PERSONALIZADO', + 'custom.prompt': 'Digite o tamanho da grade (5 - 80):', + 'custom.cancel': 'Cancelar', + 'custom.start': 'Iniciar', + 'custom.sizeError': 'O tamanho deve estar entre 5 e 80!', + 'win.title': 'PARABÉNS!', + 'win.message': 'Você resolveu o puzzle!', + 'win.time': 'Tempo:', + 'win.playAgain': 'Jogar novamente', + 'win.shareTitle': 'Compartilhe seu resultado', + 'win.shareText': 'Resolvi um nonograma {size}x{size} em {time}!', + 'win.shareX': 'X', + 'win.shareFacebook': 'Facebook', + 'win.shareWhatsapp': 'WhatsApp', + 'win.shareDownload': 'Baixar captura', + 'pwa.installTitle': 'Instale o app e jogue offline', + 'pwa.installMobile': 'Adicionar à tela inicial', + 'pwa.installDesktop': 'Instalar no desktop', + 'language.label': 'Seleção de idioma', + 'language.pl': 'Polonês', + 'language.en': 'Inglês', + 'language.zh': 'Chinês', + 'language.hi': 'Hindi', + 'language.es': 'Espanhol', + 'language.fr': 'Francês', + 'language.ar': 'Árabe', + 'language.bn': 'Bengali', + 'language.ru': 'Russo', + 'language.pt': 'Português', + 'language.ur': 'Urdu', + 'theme.label': 'Tema', + 'theme.system': 'Sistema', + 'theme.light': 'Claro', + 'theme.dark': 'Escuro' + }, + ur: { + 'app.title': 'Nonograms', + 'level.easy': 'آسان 5X5', + 'level.medium': 'درمیانہ 10X10', + 'level.hard': 'مشکل 15X15', + 'level.custom': 'حسب ضرورت', + 'level.guide': 'رہنمائی ❓', + 'actions.reset': 'ری سیٹ', + 'actions.random': 'نیا رینڈم', + 'actions.undo': 'واپس', + 'status.time': 'وقت', + 'status.moves': 'چالیں', + 'status.progress': 'پیش رفت', + 'fixed.time': 'وقت:', + 'fixed.progress': 'پیش رفت:', + 'fixed.hide': 'چھپائیں', + 'fixed.show': 'دکھائیں', + 'guide.play': 'شروع', + 'guide.pause': 'توقف', + 'guide.step': 'قدم', + 'guide.speed': 'رفتار', + 'guide.waiting': 'انتظار...', + 'guide.solved': 'حل ہوگیا!', + 'custom.title': 'حسب ضرورت کھیل', + 'custom.prompt': 'گرڈ کا سائز درج کریں (5 - 80):', + 'custom.cancel': 'منسوخ', + 'custom.start': 'شروع', + 'custom.sizeError': 'سائز 5 اور 80 کے درمیان ہونا چاہیے!', + 'win.title': 'مبارک ہو!', + 'win.message': 'آپ نے پہیلی حل کر لی!', + 'win.time': 'وقت:', + 'win.playAgain': 'دوبارہ کھیلیں', + 'win.shareTitle': 'اپنا نتیجہ شیئر کریں', + 'win.shareText': 'میں نے {time} میں {size}x{size} نونوگرام حل کیا!', + 'win.shareX': 'X', + 'win.shareFacebook': 'Facebook', + 'win.shareWhatsapp': 'WhatsApp', + 'win.shareDownload': 'اسکرین شاٹ ڈاؤن لوڈ کریں', + 'pwa.installTitle': 'ایپ انسٹال کریں اور آف لائن کھیلیں', + 'pwa.installMobile': 'ہوم اسکرین پر شامل کریں', + 'pwa.installDesktop': 'ڈیسک ٹاپ پر انسٹال کریں', + 'language.label': 'زبان کا انتخاب', + 'language.pl': 'پولش', + 'language.en': 'انگریزی', + 'language.zh': 'چینی', + 'language.hi': 'ہندی', + 'language.es': 'ہسپانوی', + 'language.fr': 'فرانسیسی', + 'language.ar': 'عربی', + 'language.bn': 'بنگالی', + 'language.ru': 'روسی', + 'language.pt': 'پرتگالی', + 'language.ur': 'اردو', + 'theme.label': 'تھیم', + 'theme.system': 'سسٹم', + 'theme.light': 'ہلکا', + 'theme.dark': 'گہرا' } }; @@ -118,7 +666,7 @@ const t = (key, params) => { }; const setLocale = (value) => { - locale.value = messages[value] ? value : 'en'; + locale.value = supportedLocales.includes(value) ? value : 'en'; if (typeof document !== 'undefined') { document.documentElement.lang = locale.value; document.title = t('app.title');