diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 596785d1f..1fe772fd9 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -151,6 +151,9 @@ dependencies { androidTestImplementation(libs.androidx.espresso.core) androidTestImplementation(platform(libs.androidx.compose.bom)) androidTestImplementation(libs.androidx.ui.test.junit4) + androidTestImplementation(libs.androidx.test.uiautomator) + androidTestImplementation(libs.coil.test) + androidTestImplementation(libs.coil.network.okhttp) screenshotTestImplementation(libs.screenshot.validation.api) screenshotTestImplementation(libs.androidx.ui.tooling) diff --git a/app/src/androidTest/java/org/fdroid/ui/screenshots/CategoryItems.kt b/app/src/androidTest/java/org/fdroid/ui/screenshots/CategoryItems.kt new file mode 100644 index 000000000..1f2383b88 --- /dev/null +++ b/app/src/androidTest/java/org/fdroid/ui/screenshots/CategoryItems.kt @@ -0,0 +1,4453 @@ +package org.fdroid.ui.screenshots + +import androidx.core.os.LocaleListCompat +import org.fdroid.LocaleChooser.getBestLocale +import org.fdroid.ui.categories.CategoryItem + +fun getCategoryItems(localeList: LocaleListCompat) = + listOf( + CategoryItem( + id = "AI Chat", + name = + mapOf( + "ar" to "محادثة ذكاء اصناعي", + "bg" to "Разговори с ИИ", + "ca" to "Xat d'IA", + "cs" to "AI chat", + "da" to "AI-chat", + "de" to "KI-Chat", + "el" to "AI Συνομιλία", + "en-GB" to "AI Chat", + "en-US" to "AI Chat", + "eo" to "Artefarita intelekto", + "es" to "Chat de IA", + "et" to "Vestlus tehisaruga", + "fa" to "گپ هوشی", + "fr" to "Chat IA", + "ga" to "Comhrá AI", + "he" to "צ'אט AI", + "hr" to "UI chat", + "hu" to "MI csevegés", + "id" to "Chat AI", + "is" to "AI-spjall", + "ja" to "AI チャット", + "kn" to "AI ಚಾಟ್", + "ko" to "AI 채팅", + "lv" to "MI tērzēšana", + "my" to "AI နှင့် ပြောဆိုရန်", + "nb" to "KI-chat", + "nl" to "AI-chat", + "nl-BE" to "AI Chat", + "pl" to "Czat AI", + "pt-BR" to "Conversar com IA", + "ro" to "Chat AI", + "ru" to "Чаты с ИИ", + "sl" to "Klepet z UI", + "sq" to "Fjalosje IA", + "sr" to "Ћаскање са вештачким паметњаковићем", + "sv" to "AI-chatt", + "sw" to "AI Chat", + "tr" to "YZ Sohbet", + "uk" to "Чат з ШІ", + "vi" to "Trò chuyện AI", + "zh-CN" to "AI 聊天", + "zh-TW" to "AI 聊天", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "App Manager", + name = + mapOf( + "ar" to "مدير تطبيق", + "bg" to "Управление на проложения", + "ca" to "Gestor d'aplicacions", + "cs" to "Správce aplikací", + "da" to "Apphåndtering", + "de" to "App-Manager", + "el" to "Διαχειριστής Εφαρμογών", + "en-GB" to "App Manager", + "en-US" to "App Manager", + "eo" to "Administriloj de aplikaĵoj", + "es" to "Gestor de aplicaciones", + "et" to "Rakendustehaldur", + "fa" to "مدیر کاره", + "fr" to "Gestionnaire d'applications", + "ga" to "Bainisteoir Aipeanna", + "he" to "מנהל יישומונים", + "hr" to "Upravljač aplikacijama", + "hu" to "Alkalmazáskezelő", + "id" to "Manajer Aplikasi", + "is" to "Forritastýring", + "ja" to "アプリマネージャー", + "kn" to "ಅಪ್ಲಿಕೇಶನ್ ಮ್ಯಾನೇಜರ್", + "ko" to "앱 관리자", + "lv" to "Lietotņu pārvaldnieks", + "my" to "အက်ပ်များစီမံရန်", + "nb" to "App-administrasjon", + "nl" to "Appbeheerder", + "nl-BE" to "App Manager", + "pl" to "Menedżer aplikacji", + "pt-BR" to "Gerenciador de aplicativos", + "ro" to "Manager aplicații", + "ru" to "Менеджер приложений", + "sl" to "Upravitelj orodij", + "sq" to "Përgjegjës Aplikacionesh", + "sr" to "Управник програма", + "sv" to "Apphanteraren", + "sw" to "Msimamizi wa Programu", + "tr" to "Uygulama Yöneticisi", + "uk" to "Менеджер застосунків", + "vi" to "Quản lý ứng dụng", + "zh-CN" to "应用管理", + "zh-TW" to "應用程式管理", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "App Store & Updater", + name = + mapOf( + "ar" to "متجر التطبيقات والمُحدِّث", + "bg" to "Магазин за приложения и обновяване", + "ca" to "Botiga d'aplicacions i actualitzador", + "ckb" to "ئاپستۆر و نوێکەرەوەکان", + "cs" to "Obchod s aplikacemi a aktualizátor", + "da" to "Appbutik og -opdatering", + "de" to "App-Store / Updater", + "el" to "Κατάστημα Εφαρμογών & Ενημερωτής", + "en-GB" to "App Store & Updater", + "en-US" to "App Store & Updater", + "eo" to "Deponejoj kaj ĝisdatigiloj de aplikaĵoj", + "es" to "Tienda de aplicaciones y actualizadores", + "es-AR" to "Tienda de aplicaciones y actualizadores", + "es-MX" to "Tienda de Aplicaciones y Actualizador", + "et" to "Rakendustepoed ja uuendused", + "fa" to "فروشگاه کاره و به‌روز رسان", + "fi" to "Sovelluskauppa & päivitysohjelma", + "fr" to "Boutique d'applications & programme de mise à jour", + "ga" to "App Store & Nuashonraitheoir", + "gl" to "Tenda de aplicacións e actualizador", + "he" to "חנות יישומונים ומעדכן", + "hr" to "Trgovina aplikacija i ažuriranje", + "hu" to "Alkalmazásbolt és -frissítő", + "id" to "Toko Aplikasi & Aplikasi Pembaruan", + "is" to "Forritasafn og uppfærslur", + "it" to "App Store & Aggiornamenti", + "ja" to "アプリストア&アップデータ", + "kn" to "ಆಪ್ ಸ್ಟೋರ್", + "ko" to "앱 스토어 및 업데이터", + "lt" to "Programėlių parduotuvė ir atnaujintuvas", + "lv" to "Lietotņu veikals un atjauninātājs", + "my" to "အက်ပ်စတိုး နှင့် အဆင့်မြှင့်တင်မှုများ", + "nb" to "App-butikker & Oppdatere", + "nl" to "Appwinkel & updater", + "nl-BE" to "App Store en Updater", + "pl" to "Sklep z aplikacjami i aktualizator", + "pt" to "Loja de apps e atualizador", + "pt-BR" to "Loja de apps e atualizador", + "pt-PT" to "Loja de apps e atualizador", + "ro" to "Magazin aplicații & Actualizări", + "ru" to "Приложения и обновления", + "sc" to "Butega de aplicatziones e atualizadore", + "sl" to "App trgovina in posodobitve", + "sq" to "Shitore & Përditësues Aplikacionesh", + "sr" to "Складиште и надграђивач програма", + "sv" to "App Store och uppdateringsprogram", + "sw" to "Ghala la Programu", + "ta" to "ஆப் கடை & அப்டேட்டர்", + "tr" to "Uygulama Deposu ve Güncelleyici", + "ug" to "ئەپ دۇكىنى ۋە يېڭىلىغۇچ", + "uk" to "App Store та оновлення", + "vi" to "Cửa hàng ứng dụng & Trình cập nhật", + "zh-CN" to "应用商店和更新工具", + "zh-TW" to "應用程式商店與更新程式", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Bookmark", + name = + mapOf( + "ar" to "علامة", + "bg" to "Отметки", + "ca" to "Adreça d'interès", + "cs" to "Záložka", + "da" to "Bogmærke", + "de" to "Lesezeichen", + "el" to "Σελιδοδείκτης", + "en-GB" to "Bookmark", + "en-US" to "Bookmark", + "eo" to "Administriloj de legosignoj", + "es" to "Marcadores", + "es-AR" to "Marcadores", + "es-MX" to "Marcador", + "et" to "Järjehoidjad", + "fa" to "نشانک", + "fi" to "Kirjanmerkki", + "fr" to "Signet", + "ga" to "Leabharmharc", + "gl" to "Marcadores", + "he" to "סימנייה", + "hr" to "Zabilješka", + "hu" to "Könyvjelző", + "id" to "Markah", + "is" to "Bókamerki", + "it" to "Segnalibri", + "ja" to "ブックマーク", + "kn" to "ಬುಕ್ಮಾರ್ಕ್", + "ko" to "북마크", + "lb" to "Lieszeechen", + "lt" to "Žymė", + "lv" to "Grāmatzīme", + "my" to "မှတ်သားချက်", + "nb" to "Bokmerke", + "nl" to "Bladwijzer", + "nl-BE" to "Bladwijzer", + "pl" to "Zakładka", + "pt" to "Marcador", + "pt-BR" to "Marcador", + "pt-PT" to "Marcador", + "ro" to "Semn de carte", + "ru" to "Закладки", + "sc" to "Sinnalibru", + "sl" to "Zaznamek", + "sq" to "Faqerojtës", + "sr" to "Забелешка", + "sv" to "Bokmärke", + "sw" to "Alamisho", + "ta" to "புத்தககுறி", + "tr" to "Yer imi", + "ug" to "خەتكۈچ", + "uk" to "Закладка", + "vi" to "Dấu trang", + "zh-CN" to "书签", + "zh-TW" to "書籤", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Browser", + name = + mapOf( + "ar" to "المتصفح", + "bg" to "Мрежов четец", + "br" to "Merdeer", + "ca" to "Navegador", + "cs" to "Prohlížeč", + "da" to "Browser", + "de" to "Browser", + "el" to "Περιηγητής", + "en-GB" to "Browser", + "en-US" to "Browser", + "eo" to "Retfoliumiloj", + "es" to "Navegador", + "es-AR" to "Navegador", + "es-MX" to "Navegador", + "et" to "Veebibrauserid", + "fa" to "مرورگر", + "fi" to "Selain", + "fr" to "Navigateur", + "ga" to "Brabhsálaí", + "gl" to "Navegador", + "he" to "דפדפן", + "hr" to "Preglednik", + "hu" to "Böngésző", + "id" to "Peramban", + "is" to "Vafri", + "it" to "Browser", + "ja" to "ブラウザ", + "kn" to "ಬ್ರೌಸರ್", + "ko" to "브라우저", + "lb" to "Browser", + "lt" to "Naršyklė", + "lv" to "Pārlūks", + "my" to "Browser", + "nb" to "Nettleser", + "nl" to "Browser", + "nl-BE" to "Browser", + "pl" to "Przeglądarka", + "pt" to "Navegador", + "pt-BR" to "Navegador", + "pt-PT" to "Navegador", + "ro" to "Navigator web", + "ru" to "Браузеры", + "sc" to "Navigadore", + "sl" to "Brskalnik", + "sq" to "Shfletues", + "sr" to "Прегледник", + "sv" to "Webbläsare", + "sw" to "Kivinjari", + "ta" to "உலாவி", + "tr" to "Tarayıcı", + "ug" to "توركۆرگۈ", + "uk" to "Браузер", + "vi" to "Trình duyệt", + "zh-CN" to "浏览器", + "zh-TW" to "瀏覽器", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Calculator", + name = + mapOf( + "ar" to "حاسبة", + "bg" to "Калкулатор", + "ca" to "Calculadora", + "cs" to "Kalkulačka", + "da" to "Lommeregner", + "de" to "Rechner", + "el" to "Αριθμομηχανή", + "en-GB" to "Calculator", + "en-US" to "Calculator", + "eo" to "Kalkuliloj", + "es" to "Calculadora", + "es-AR" to "Calculadora", + "es-MX" to "Calculadora", + "et" to "Kalkulaatorid", + "fa" to "ماشین حساب", + "fi" to "Laskin", + "fr" to "Calculatrice", + "ga" to "Áireamhán", + "gl" to "Calculadora", + "he" to "מחשבון", + "hr" to "Kalkulator", + "hu" to "Számológép", + "id" to "Kalkulator", + "is" to "Reiknivél", + "it" to "Calcolatrice", + "ja" to "計算機", + "kn" to "ಕ್ಯಾಲ್ಕುಲೇಟರ್", + "ko" to "계산기", + "lt" to "Skaičiuotuvas", + "lv" to "Skaitļotājs", + "my" to "ဂဏန်းပေါင်းစက်", + "nb" to "Kalkulator", + "nl" to "Rekenmachine", + "nl-BE" to "Rekenmachine", + "pl" to "Kalkulator", + "pt" to "Calculador", + "pt-BR" to "Calculadora", + "pt-PT" to "Calculador", + "ro" to "Calculator", + "ru" to "Калькуляторы", + "sc" to "Carculadora", + "sl" to "Kalkulator", + "sq" to "Llogaritës", + "sr" to "Рачунар", + "sv" to "Kalkylator", + "sw" to "Kikokotoo", + "ta" to "கணிப்பான்", + "tr" to "Hesap Makinesi", + "ug" to "ھېسابلىغۇچ", + "uk" to "Калькулятор", + "vi" to "Máy tính bỏ túi", + "zh-CN" to "计算器", + "zh-TW" to "計算機", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Calendar & Agenda", + name = + mapOf( + "ar" to "التقويم والأجندة", + "bg" to "Календар и график", + "ca" to "Calendaris i Agendes", + "cs" to "Kalendář a agenda", + "da" to "Kalender og dagsorden", + "de" to "Kalender / Terminplaner", + "el" to "Ημερολόγιο & Ατζέντα", + "en-GB" to "Calendar & Agenda", + "en-US" to "Calendar & Agenda", + "eo" to "Kalendaroj kaj tempplanoj", + "es" to "Calendarios y agendas", + "es-AR" to "Calendarios y agendas", + "es-MX" to "Calendario y Agenda", + "et" to "Kalender ja päevakava", + "fa" to "تقویم و دستور کار", + "fi" to "Kalenteri & esityslista", + "fr" to "Calendrier & Agenda", + "ga" to "Féilire agus Clár Oibre", + "gl" to "Calendario e axenda", + "he" to "לוח שנה וסדר יום", + "hr" to "Kalendar i planiranje termina", + "hu" to "Naptár és napirend", + "id" to "Kalender & Agenda", + "is" to "Dagatal og dagskrá", + "it" to "Calendario & Agenda", + "ja" to "カレンダー&アジェンダ", + "kn" to "ಕ್ಯಾಲೆಂಡರ್", + "ko" to "캘린더 및 일정", + "lt" to "Kalendorius ir darbotvarkė", + "lv" to "Kalendārs un dienaskārtība", + "my" to "ပြက္ခဒိန်နှင့် လုပ်ငန်းစဉ်များ", + "nb" to "Kalender & Agenda", + "nl" to "Kalender & agenda", + "nl-BE" to "Kalender & Agenda", + "pl" to "Kalendarz i harmonogram", + "pt" to "Calendário e agenda", + "pt-BR" to "Calendário e agenda", + "pt-PT" to "Calendário e agenda", + "ro" to "Calendar & Agenda", + "ru" to "Ежедневники", + "sc" to "Calendàriu e agenda", + "sl" to "Koledar in urnik", + "sq" to "Kalendar & Plane", + "sr" to "Календар и роковник", + "sv" to "Kalender och agenda", + "sw" to "Kalenda na Ajenda", + "ta" to "காலண்டர் மற்றும் நிகழ்ச்சி நிரல்", + "tr" to "Takvim ve Ajanda", + "ug" to "يىلنامە ۋە كۈنتەرتىپ", + "uk" to "Календар і порядок денний", + "vi" to "Lịch & Nhật trình", + "zh-CN" to "日历和日程", + "zh-TW" to "行事曆與日程", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Clock", + name = + mapOf( + "ar" to "ساعة", + "br" to "Horolaj", + "ca" to "Rellotge", + "cs" to "Hodiny", + "da" to "Ur", + "de" to "Uhr", + "el" to "Ρολόι", + "en-GB" to "Clock", + "en-US" to "Clock", + "eo" to "Horloĝoj", + "es" to "Reloj", + "et" to "Kellad", + "fa" to "ساعت", + "fr" to "Horloge", + "ga" to "Clog", + "he" to "שעון", + "hr" to "Sat", + "hu" to "Óra", + "id" to "Jam", + "is" to "Klukka", + "ja" to "時計", + "kn" to "ಗಡಿಯಾರ", + "ko" to "시계", + "lv" to "Pulkstenis", + "my" to "နာရီ", + "nb" to "Klokke", + "nl" to "Klok", + "nl-BE" to "Klok", + "pl" to "Zegar", + "pt-BR" to "Relógio", + "ro" to "Ceas", + "ru" to "Часы", + "sl" to "Ura", + "sq" to "Sahat", + "sr" to "Часовник", + "sv" to "Klocka", + "sw" to "Saa", + "tr" to "Saat", + "uk" to "Годинник", + "vi" to "Đồng hồ", + "zh-CN" to "时钟", + "zh-TW" to "時鐘", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Cloud Storage & File Sync", + name = + mapOf( + "ar" to "التخزين السحابي ومزامنة الملفات", + "bg" to "Облачно хранилище и синхронизиране", + "ca" to "Emmagatzematge al núvol i sincronització d'arxius", + "cs" to "Cloudové úložiště a synchronizace souborů", + "da" to "Cloudlager og filsynkronisering", + "de" to "Cloud-Speicher / Dateisynchronisierung", + "el" to "Cloud Αποθηκευτικός Χώρος & Συγχρονισμός Αρχείων", + "en-GB" to "Cloud Storage & File Sync", + "en-US" to "Cloud Storage & File Sync", + "eo" to "Nuba konservado kaj dosiera samtempigo", + "es" to "Subir y sincronizar archivos", + "es-AR" to "Subir y sincronizar archivos", + "et" to "Pilveruum ja sünkroonimine", + "fa" to "فضای ابری و همگام سازی پرونده", + "fi" to "Pilvitallennus ja tiedostojen synkronointi", + "fr" to "Stockage dans le cloud & Synchronisation de fichiers", + "ga" to "Stóráil Néil & Sioncrónú Comhad", + "gl" to "Almacenamento na nube e sincronización", + "he" to "אחסון בענן וסנכרון קבצים", + "hr" to "Spremanje u oblaku i sinkronizacija datoteka", + "hu" to "Felhős tárolás és fájlszinkronizálás", + "id" to "Penyimpanan Awan & Sinkronisasi Berkas", + "is" to "Geymsla á tölvuskýi og samstilling skráa", + "it" to "Archiviazione Cloud & Sincornizzazione dei File", + "ja" to "クラウド・ストレージ&ファイル同期", + "ko" to "클라우드 저장소 및 파일 동기화", + "lt" to "Saugykla debesyje ir failų sinchronizavimas", + "lv" to "Mākoņkrātuve un datņu sinhronizēšana", + "my" to "Cloud သိုလှောင်မှုနှင့် ဖိုင်ချိတ်ဆက်ခြင်း", + "nb" to "Skylagring & Filsynkronisering", + "nl" to "Cloudopslag & bestandssynchronisatie", + "nl-BE" to "Cloud opslag & Bestand Synchronisatie", + "pl" to "Przechowywanie w chmurze i synchronizacja plików", + "pt" to "Armazenamento na nuvem e sincronização de ficheiros", + "pt-BR" to "Armazenamento na nuvem e sincronização de arquivos", + "pt-PT" to "Armazenamento na nuvem e sincronização de ficheiros", + "ro" to "Stocare în cloud & Sincronizare fișiere", + "ru" to "Хранение и синхронизация", + "sc" to "Archiviatzione in sa nue e sincronizada de documentos", + "sl" to "Shranjevanje v oblaku in sinhronizacija datotek", + "sq" to "Depozitim Në Re & Njëkohësim Kartelash", + "sr" to "Складиште у облаку и усклађивање датотека", + "sv" to "Molnlagring och filsynkronisering", + "sw" to "Hifadhi ya Wingu na Usawazishaji wa Faili", + "ta" to "முகில் ச்டோரேச் & கோப்பு ஒத்திசைவு", + "tr" to "Bulut Depolama ve Dosya Eşitleme", + "ug" to "بۇلۇت ساقلىغۇچ ۋە ھۆججەت قەدەمداش", + "uk" to "Хмарне сховище та синхронізація файлів", + "vi" to "Lưu trữ trên mây & Đồng bộ tệp", + "zh-CN" to "云存储和文件同步", + "zh-TW" to "雲端儲存與檔案同步", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Connectivity", + name = + mapOf( + "af" to "Konnektiwiteit", + "ar" to "الاتصال", + "ast" to "Conectividá", + "ba" to "Бәйләнеш", + "be" to "Сувязь", + "bg" to "Свързаност", + "bn" to "যোগাযোগ", + "bn-BD" to "যোগাযোগ", + "bo" to "མཐུད་མཚམས།", + "br" to "Kevreadusted", + "ca" to "Connectivitat", + "ckb" to "پەیوەندی", + "cs" to "Spojení", + "cy" to "Cysylltedd", + "da" to "Forbindelse", + "de" to "Konnektivität", + "el" to "Συνδεσιμότητα", + "en-GB" to "Connectivity", + "en-US" to "Connectivity", + "eo" to "Konekteco", + "es" to "Conectividad", + "es-AR" to "Conectividad", + "es-MX" to "Conectividad", + "et" to "Ühenduvus", + "eu" to "Sareak", + "fa" to "اتّصال", + "fi" to "Yhteydet", + "fil" to "Konektibidad", + "fr" to "Connectivité", + "fy" to "Ferbiningen", + "ga" to "Nascacht", + "gd" to "Comas-ceangail", + "gl" to "Conectividade", + "he" to "קישוריות", + "hi" to "कनैक्टिविटी", + "hr" to "Povezivanje", + "hu" to "Kapcsolódás", + "hy" to "Կապ", + "id" to "Konektivitas", + "is" to "Tengingar", + "it" to "Connettività", + "ja" to "通信", + "kab" to "Tuqqniwt", + "kmr" to "Girêdanî", + "kn" to "ಸಂಪರ್ಕ", + "ko" to "접속성", + "lb" to "Connectioun", + "lt" to "Ryšiai ir tinklas", + "lv" to "Savienojamība", + "mk" to "Поврзаност", + "ml" to "സമ്പർക്കനില", + "mn" to "Холболт", + "mr" to "संपर्क", + "my" to "ကွန်ရက်ဆက်သွယ်မှု", + "nb" to "Tilkobling", + "nl" to "Verbinden", + "nl-BE" to "Connectiviteit", + "nn" to "Samband", + "pa" to "ਕਨੈਕਟਵਿਟੀ", + "pl" to "Łączność", + "pt" to "Conectividade", + "pt-BR" to "Conectividade", + "pt-PT" to "Conectividade", + "ro" to "Conectivitate", + "ru" to "Связь", + "sc" to "Connetividade", + "sk" to "Pripojiteľnosť", + "sl" to "Povezljivost", + "sn" to "Mahakiro", + "so" to "Ku", + "sq" to "Aftësi lidhjeje", + "sr" to "Повезивање", + "sv" to "Anslutbarhet", + "sw" to "Muunganisho", + "ta" to "இணைப்பு", + "te" to "kalavaDika", + "th" to "การสื่อสาร", + "tr" to "Bağlanabilirlik", + "tzm" to "Azday", + "ug" to "ئۇلىنىشچانلىق", + "uk" to "Зв'язок", + "ur" to "کنیکٹیویٹی", + "vi" to "Kết nối", + "yue" to "網絡", + "zh-CN" to "连接", + "zh-HK" to "網絡", + "zh-TW" to "連線", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Contact", + name = + mapOf( + "ar" to "التواصل", + "ca" to "Contacte", + "cs" to "Kontakt", + "da" to "Kontakt", + "de" to "Kontakt", + "el" to "Επικοινωνία", + "en-GB" to "Contact", + "en-US" to "Contact", + "eo" to "Listoj de kontaktoj", + "es" to "Contactos", + "et" to "Kontaktihaldus", + "fa" to "آشنا", + "fr" to "Contact", + "ga" to "Teagmháil", + "he" to "פרטי קשר", + "hr" to "Kontakt", + "hu" to "Névjegy", + "id" to "Kontak", + "is" to "Tengiliðir", + "ja" to "連絡", + "kn" to "ಸಂಪರ್ಕಿಸಿ", + "ko" to "연락처", + "my" to "ဆက်သွယ်ရန်", + "nb" to "Kontakt", + "nl" to "Contact", + "nl-BE" to "Contact", + "pl" to "Kontakt", + "pt-BR" to "Contato", + "ro" to "Contact", + "ru" to "Контакты", + "sl" to "Stiki", + "sq" to "Kontakt", + "sr" to "Додир", + "sv" to "Kontakt", + "sw" to "Mawasiliano", + "tr" to "İletişim", + "uk" to "Контакти", + "vi" to "Danh bạ", + "zh-CN" to "联络", + "zh-TW" to "聯絡", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Development", + name = + mapOf( + "af" to "Ontwikkeling", + "ar" to "التطوير", + "ast" to "Desendolcu", + "ba" to "Эшләү", + "be" to "Распрацоўка", + "ber" to "ⵜⵉⴳⵎⵉ", + "bg" to "Разработка", + "bn" to "ডেভেলপমেন্ট", + "bn-BD" to "ডেভেলপমেন্ট", + "bo" to "ཡར་རྒྱས།", + "br" to "Diorren", + "ca" to "Desenvolupament", + "ckb" to "گەشەپێدان", + "cs" to "Vývoj", + "cy" to "Datblygiad", + "da" to "Udvikling", + "de" to "Entwicklung", + "el" to "Προγραμματισμός", + "en-GB" to "Development", + "en-US" to "Development", + "eo" to "Programado", + "es" to "Desarrollo", + "es-AR" to "Desarrollo", + "es-MX" to "Desarrollo", + "et" to "Arendus", + "eu" to "Garapena", + "fa" to "توسعه", + "fi" to "Kehittäminen", + "fil" to "Pagde-develop", + "fr" to "Développement", + "fy" to "Ûntwikkeling", + "ga" to "Forbairt", + "gd" to "Leasachadh", + "gl" to "Desenvolvemento", + "he" to "פיתוח", + "hi" to "विकास", + "hr" to "Razvoj", + "hu" to "Fejlesztés", + "hy" to "Ծրագրավորում", + "id" to "Pengembangan", + "is" to "Þróun", + "it" to "Sviluppo", + "ja" to "開発", + "kab" to "Taneflit", + "kmr" to "Pêşdebirin", + "kn" to "ಅಭಿವೃದ್ಧಿ", + "ko" to "개발", + "lb" to "Entwécklung", + "lt" to "Plėtojimas", + "lv" to "Izstrāde", + "mk" to "Развој", + "ml" to "ആപ്പ് നിർമാണം", + "mn" to "Хөгжил", + "my" to "ဆော့ဝဲလ်ရေးသားခြင်း", + "nb" to "Utvikling", + "ne" to "विकास", + "nl" to "Ontwikkeling", + "nl-BE" to "Ontwikkeling", + "nn" to "Utvikling", + "pa" to "ਡਿਵੈਲਪਮੈਂਟ", + "pl" to "Rozwój", + "ps" to "پرمختيا", + "pt" to "Desenvolvimento", + "pt-BR" to "Desenvolvimento", + "pt-PT" to "Desenvolvimento", + "ro" to "Dezvoltare programe", + "ru" to "Разработка", + "sc" to "Isvilupu", + "sk" to "Vývoj", + "sl" to "Razvijanje", + "sn" to "Tsvitsa", + "so" to "Hormarka", + "sq" to "Zhvillim", + "sr" to "Развој", + "sv" to "Utveckling", + "sw" to "Maendeleo", + "ta" to "உருவாக்கம்", + "te" to "అభివృద్ధి", + "th" to "การพัฒนา", + "tr" to "Geliştirme", + "tzm" to "asbuɣlu", + "ug" to "تەرەققىيات", + "uk" to "Розробка", + "ur" to "ترقی", + "vi" to "Lập trình", + "yue" to "開發", + "zh-CN" to "开发", + "zh-HK" to "開發", + "zh-TW" to "開發", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "DNS & Hosts", + name = + mapOf( + "ar" to "DNS والمضيفون", + "ba" to "DNS һәм хост", + "bg" to "DNS и хостове", + "ca" to "DNS i Allotjament", + "cs" to "DNS a hostitelé", + "da" to "DNS og værter", + "de" to "DNS / Hosts", + "el" to "DNS & Φιλοξενητές", + "en-GB" to "DNS & Hosts", + "en-US" to "DNS & Hosts", + "eo" to "DNS kaj retgastigo", + "es" to "DNS y bloqueos de red", + "et" to "Nimelahendus ja hostid", + "fa" to "ساناد و میزبان‌ها", + "fr" to "DNS & Hôtes", + "ga" to "DNS & Óstaigh", + "he" to "DNS ומארחים", + "hr" to "DNS i host računala", + "hu" to "DNS és kiszolgálók", + "id" to "DNS & Hos", + "is" to "DNS & Hýsingar", + "it" to "DNS & Hosts", + "ja" to "DNS & ホスト", + "kn" to "DNS", + "ko" to "DNS 및 호스트", + "lt" to "DNS ir serveriai", + "lv" to "DNS un mitinātāji", + "my" to "DNS နှင့် ဟို့စ် (Hosts)", + "nb" to "DNS & Verter", + "nl" to "DNS & hosts", + "nl-BE" to "DNS & Hosts", + "pl" to "DNS i hosty", + "pt" to "DNS & hosts", + "pt-BR" to "DNS e domínios", + "pt-PT" to "DNS & hosts", + "ro" to "DNS & Gazde", + "ru" to "DNS и хосты", + "sc" to "DNS e retzidores (hosts)", + "sl" to "DNS in gostitelji", + "sq" to "DNS & Strehë", + "sr" to "ДНС и домаћини", + "sv" to "DNS och värdar", + "sw" to "DNS & Wapangishi", + "ta" to "டி.என்.எச் & ஓச்ட்கள்", + "tr" to "DNS ve Ana Bilgisayarlar", + "ug" to "DNS ۋە مۇلازىمېتىر", + "uk" to "DNS та хости", + "vi" to "DNS & Máy chủ", + "zh-CN" to "DNS & Hosts", + "zh-TW" to "DNS 與主機", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Draw", + name = + mapOf( + "ar" to "رسم", + "bg" to "Рисуване", + "ca" to "Dibuix", + "cs" to "Kreslení", + "da" to "Tegning", + "de" to "Zeichnen", + "el" to "Ζωγραφική", + "en-GB" to "Draw", + "en-US" to "Draw", + "eo" to "Desegnado", + "es" to "Dibujo", + "et" to "Joonistamine", + "fa" to "رسم", + "fi" to "Piirtäminen", + "fr" to "Dessiner", + "ga" to "Tarraing", + "gl" to "Debuxo", + "he" to "ציור", + "hr" to "Crtanje", + "hu" to "Rajzolás", + "id" to "Gambar", + "is" to "Teikna", + "it" to "Disegna", + "ja" to "お絵描き", + "kn" to "ಎಳೆಯಿರಿ", + "ko" to "그리기", + "lt" to "Piešimas", + "lv" to "Zīmēšana", + "my" to "ဆွဲပါ", + "nb" to "Tegning", + "nl" to "Tekenen", + "nl-BE" to "Teken", + "pl" to "Szkicownik", + "pt" to "Desenhar", + "pt-BR" to "Desenhar", + "pt-PT" to "Desenhar", + "ro" to "Desen", + "ru" to "Рисование", + "sc" to "Disinnu", + "sl" to "Riši", + "sq" to "Vizatim", + "sr" to "Цртање", + "sv" to "Rita", + "sw" to "Kuchora", + "ta" to "டிரா", + "tr" to "Çizim", + "ug" to "سىزمىچىلىق", + "uk" to "Нічия", + "vi" to "Vẽ", + "zh-CN" to "绘图", + "zh-TW" to "繪圖", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Ebook Reader", + name = + mapOf( + "ar" to "قارئ الكتب الإلكترونية", + "bg" to "Четене на електронни книги", + "ca" to "Lector de llibres electrònics", + "cs" to "Čtečka e-knih", + "da" to "E-bogslæser", + "de" to "E-Book-Reader", + "el" to "Αναγνώστης ηλεκτρονικών βιβλίων", + "en-GB" to "Ebook Reader", + "en-US" to "Ebook Reader", + "eo" to "Legiloj de bitlibroj", + "es" to "Lector de libros electrónicos", + "et" to "E-raamatute lugemine", + "fa" to "کتابخوان", + "fi" to "E-kirjan lukija", + "fr" to "Liseuse électronique", + "ga" to "Léitheoir Ríomhleabhar", + "gl" to "Lector de libros electrónicos", + "he" to "מציג Ebook", + "hr" to "Čitač e-knjiga", + "hu" to "E-könyv olvasó", + "id" to "Pembaca Buku Elektronik", + "is" to "Rafbókalesari", + "it" to "Lettore di Ebook", + "ja" to "電子書籍リーダー", + "kn" to "ಇಬುಕ್ ರೀಡರ್", + "ko" to "전자책 리더", + "lt" to "El. knygų skaityklė", + "lv" to "E-grāmatu lasītājs", + "my" to "စာအုပ်ဖတ်ရန်", + "nb" to "E-bok-leser", + "nl" to "E-boeklezer", + "nl-BE" to "Ebook lezer", + "pl" to "Czytnik e-booków", + "pt" to "Leitor de e-book", + "pt-BR" to "Leitor de e-book", + "pt-PT" to "Leitor de e-book", + "ro" to "Carte electronică", + "ru" to "Читалки", + "sc" to "Leghidore de libros eletrònicos", + "sl" to "Bralnik e-knjig", + "sq" to "Lexues Elibrash", + "sr" to "Читач е-књига", + "sv" to "E-boksläsare", + "sw" to "Kisomaji Ebook", + "ta" to "மின்புத்தக வாசகர்", + "tr" to "E-Kitap Okuyucu", + "ug" to "ئېلكىتاب ئوقۇغۇچ", + "uk" to "Зчитувач електронних книг", + "vi" to "Trình đọc ebook", + "zh-CN" to "电子书阅读器", + "zh-TW" to "電子書閱讀器", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Email", + name = + mapOf( + "ar" to "البريد الإلكتروني", + "ba" to "Email", + "bg" to "Електронна поща", + "br" to "Postel", + "ca" to "Correu electrònic", + "cs" to "E-mail", + "da" to "E-mail", + "de" to "E-Mail", + "el" to "Email", + "en-GB" to "Email", + "en-US" to "Email", + "eo" to "Retpoŝto", + "es" to "Correo electrónico", + "es-MX" to "Email", + "et" to "E-post", + "fa" to "رایانامه", + "fi" to "Sähköposti", + "fr" to "E-mail", + "ga" to "Ríomhphost", + "gl" to "Correo electrónico", + "he" to "דוא״ל", + "hr" to "E-mail", + "hu" to "E-mail", + "id" to "Surel", + "is" to "Tölvupóstur", + "it" to "Email", + "ja" to "Eメール", + "kn" to "ಇಮೇಲ್", + "ko" to "이메일", + "lb" to "E-Mail", + "lt" to "Elektroninis paštas", + "lv" to "E-pasts", + "my" to "အီးမေးလ်", + "nb" to "E-post", + "nl" to "E-mail", + "nl-BE" to "E-mail", + "pl" to "E-mail", + "pt" to "E-mail", + "pt-BR" to "E-mail", + "pt-PT" to "E-mail", + "ro" to "E-mail", + "ru" to "Электронная почта", + "sc" to "Posta eletrònica", + "sl" to "E-pošta", + "sq" to "Email", + "sr" to "Е-пошта", + "sv" to "Mejl", + "sw" to "Barua pepe", + "ta" to "மின்னஞ்சல்", + "tr" to "E-posta", + "ug" to "تورخەت", + "uk" to "Електронна пошта", + "vi" to "Email", + "zh-CN" to "电子邮件", + "zh-TW" to "電子郵件", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "File Encryption & Vault", + name = + mapOf( + "ar" to "تعمية الملفات والخزنة", + "ba" to "Файлдарҙы шифрлау һәм Һаҡлағыс", + "bg" to "Шифроване на файлове и хранилище", + "ca" to "Xifratge de fitxers i caixa forta", + "cs" to "Šifrování souborů a trezor", + "da" to "Filkryptering og boks", + "de" to "Dateiverschlüsselung / Tresor", + "el" to "Κρυπτογράφηση Αρχείων & Ασφαλής Φάκελος", + "en-GB" to "File Encryption & Vault", + "en-US" to "File Encryption & Vault", + "eo" to "Dosiera ĉifrado", + "es" to "Cifrado de archivos y bóvedas", + "et" to "Krüptimine ja andmehoidlad", + "fa" to "رمزنگاری پرونده", + "fi" to "Tiedoston salaus & holvi", + "fr" to "Chiffrement de fichiers & Coffre-fort", + "ga" to "Criptiú Comhad & Cruinneachán", + "he" to "הצפנת קבצים וכספת", + "hr" to "Šifriranje datoteka i trezor", + "hu" to "Fájltitkosítás és széfek", + "id" to "Enkripsi Berkas & Brankas", + "is" to "Dulritun skráa og lykilorðageymsla", + "it" to "Criptatore di File & Archivio Nascosto", + "ja" to "ファイル暗号化&保管", + "ko" to "파일 암호화 및 보관", + "lt" to "Failų šifravimas ir saugykla", + "lv" to "Datņu šifrēšana un glabātava", + "my" to "ဖိုင်လုံခြုံရေး နှင့် သိုလှောင်ခန်း", + "nb" to "Filkryptering & Hvelv", + "nl" to "Bestandsversleuteling & kluis", + "nl-BE" to "Bestanden versleuteling en kluis", + "pl" to "Szyfrowanie plików i sejf", + "pt" to "Criptografia de ficheiros e cofre", + "pt-BR" to "Criptografia de arquivos e cofres", + "pt-PT" to "Criptografia de ficheiros e cofre", + "ro" to "Criptare fișiere și seif", + "ru" to "Шифрование файлов", + "sc" to "Tzifradura de documentos e cassaforte", + "sl" to "Šifriranje datotek in trezor", + "sq" to "Fshehtëzim & Kasafortë Kartelash", + "sr" to "Шифровање и складиштење датотека", + "sv" to "Filkryptering och valv", + "sw" to "Usimbaji wa Faili & Vault", + "ta" to "கோப்பு குறியாக்கம் & பெட்டக", + "tr" to "Dosya Şifreleme & Güvenli Kasa", + "ug" to "ھۆججەت شىفىرلاش ۋە ساقلىغۇچ", + "uk" to "Шифрування файлів та сховище", + "vi" to "Mã hóa và lưu trữ tệp", + "zh-CN" to "文件加密和保险库", + "zh-TW" to "檔案加密與保險庫", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "File Transfer", + name = + mapOf( + "ar" to "نقل الملفات", + "ba" to "Файлдарҙы тапшырыу", + "bg" to "Прехвърляне на файлове", + "ca" to "Transferències de fitxers", + "cs" to "Přenos souborů", + "da" to "Filoverførsel", + "de" to "Dateiübertragung", + "el" to "Μεταφορά Αρχείων", + "en-GB" to "File Transfer", + "en-US" to "File Transfer", + "eo" to "Dosiera kunhavigo", + "es" to "Transferencia de archivos", + "et" to "Failide edastamine", + "fa" to "انتقال پرونده", + "fi" to "Tiedostonsiirto", + "fr" to "Transfert de fichiers", + "ga" to "Aistriú Comhad", + "he" to "העברת קבצים", + "hr" to "Prijenos datoteka", + "hu" to "Fájlátvitel", + "id" to "Transfer Berkas", + "is" to "Skráaflutningur", + "it" to "File Transfer", + "ja" to "ファイル転送", + "kn" to "ಫೈಲ್ ವರ್ಗಾವಣೆ", + "ko" to "파일 전송", + "lt" to "Failų perkėlimas", + "lv" to "Datņu pārsūtīšana", + "my" to "ဖိုင်ပေးပို့ခြင်း", + "nb" to "Filoverføring", + "nl" to "Bestandsoverdracht", + "nl-BE" to "Bestandsoverdracht", + "pl" to "Przesyłanie plików", + "pt" to "Transferência de ficheiros", + "pt-BR" to "Transferência de arquivos", + "pt-PT" to "Transferência de ficheiros", + "ro" to "Transfer fișiere", + "ru" to "Передача файлов", + "sc" to "Tràmuda de documentos", + "sl" to "Posredovanje datotek", + "sq" to "Shpërngulje Kartelash", + "sr" to "Пренос датотека", + "sv" to "Filöverföring", + "sw" to "Uhamisho wa faili", + "ta" to "கோப்பு பரிமாற்றம்", + "tr" to "Dosya Aktarımı", + "ug" to "ھۆججەت يوللاش", + "uk" to "Передавання файлів", + "vi" to "Gửi tệp", + "zh-CN" to "文件传输", + "zh-TW" to "檔案傳輸", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Finance Manager", + name = + mapOf( + "ar" to "مدير مالي", + "bg" to "Управление на файлове", + "ca" to "Gestor de finances", + "cs" to "Správce financí", + "da" to "Økonomihåndtering", + "de" to "Finanzmanager", + "el" to "Διαχειριστής Οικονομικών", + "en-GB" to "Finance Manager", + "en-US" to "Finance Manager", + "eo" to "Financ-administriloj", + "es" to "Contabilidad y finanzas", + "et" to "Rahahaldus", + "fa" to "مدیر مالی", + "fr" to "Gestionnaire de finances", + "ga" to "Bainisteoir Airgeadais", + "he" to "ניהול כספים", + "hr" to "Upravljač financijama", + "hu" to "Pénzügykezelő", + "id" to "Pengelola Keuangan", + "is" to "Fjármálaumsýsla", + "it" to "Finanza", + "ja" to "ファイナンスマネージャー", + "kn" to "ಹಣಕಾಸು ವ್ಯವಸ್ಥಾಪಕ", + "ko" to "재무 관리자", + "lt" to "Finansų valdyklė", + "lv" to "Naudas līdzekļu pārvaldnieks", + "my" to "ဘဏ္ဍာရေးစီမံမှု", + "nb" to "Finans", + "nl" to "Financiën beheren", + "nl-BE" to "Financieel manager", + "pl" to "Zarządzanie finansami", + "pt" to "Gestor de finanças", + "pt-BR" to "Gerenciador de finanças", + "pt-PT" to "Gestor de finanças", + "ro" to "Manager financiar", + "ru" to "Финансовый менеджер", + "sc" to "Gestore de finàntzias", + "sl" to "Upravitelj financ", + "sq" to "Përgjegjës Financash", + "sr" to "Управник новцем", + "sw" to "Meneja wa Fedha", + "ta" to "பொருள் மேலாளர்", + "tr" to "Finans Yöneticisi", + "ug" to "مالىيە باشقۇرغۇچ", + "uk" to "Фінансовий менеджер", + "vi" to "Quản lý tài chính", + "zh-CN" to "财务管理工具", + "zh-TW" to "財務管理", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Firewall", + name = + mapOf( + "ar" to "جدار حماية", + "ca" to "Tallafoc", + "cs" to "Firewall", + "da" to "Firewall", + "de" to "Firewall", + "el" to "Τοίχος Προστασίας", + "en-GB" to "Firewall", + "en-US" to "Firewall", + "eo" to "Farjoŝirmiloj", + "es" to "Cortafuegos", + "et" to "Tulemüürid", + "fa" to "دیوار آتش", + "fr" to "Pare-feu", + "ga" to "Balla dóiteáin", + "he" to "חומת אש", + "hr" to "Vatrozid", + "hu" to "Tűzfal", + "id" to "Firewall", + "is" to "Eldveggur", + "ja" to "ファイアウォール", + "kn" to "ಫೈರ್ವಾಲ್", + "ko" to "방화벽", + "lv" to "Ugunsmūris", + "my" to "ကွန်ရက် အကာအကွယ်", + "nb" to "Brannmur", + "nl" to "Firewall", + "nl-BE" to "Firewall", + "pl" to "Zapora", + "pt-BR" to "Firewall", + "ro" to "Firewall", + "ru" to "Брандмауэр", + "sl" to "Požarni zid", + "sq" to "Firewall", + "sv" to "Brandvägg", + "sw" to "Firewall", + "tr" to "Güvenlik Duvarı", + "uk" to "Брандмауер", + "vi" to "Tường lửa", + "zh-CN" to "防火墙", + "zh-TW" to "防火牆", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Forum", + name = + mapOf( + "ar" to "المنتدى", + "bg" to "Форум", + "br" to "Forom", + "ca" to "Fòrum", + "cs" to "Fórum", + "da" to "Forum", + "de" to "Forum", + "el" to "Φόρουμ", + "en-GB" to "Forum", + "en-US" to "Forum", + "eo" to "Diskutejoj", + "es" to "Foros", + "et" to "Foorumid", + "fa" to "انجمن", + "fr" to "Forum", + "ga" to "Fóram", + "he" to "פורום", + "hr" to "Forum", + "hu" to "Fórum", + "id" to "Forum", + "is" to "Spjallsvæði", + "it" to "Forum", + "ja" to "フォーラム", + "kn" to "ವೇದಿಕೆ", + "ko" to "포럼", + "lb" to "Forum", + "lt" to "Forumas", + "lv" to "Forums", + "my" to "ဖိုရမ်", + "nb" to "Forum", + "nl" to "Forum", + "nl-BE" to "Forum", + "pl" to "Forum", + "pt" to "Fórum", + "pt-BR" to "Fórum", + "pt-PT" to "Fórum", + "ro" to "Forum", + "ru" to "Форум", + "sl" to "Klepetalnica", + "sq" to "Forum", + "sv" to "Forum", + "sw" to "Jukwaa la majadiliano", + "ta" to "மன்றம்", + "tr" to "Forum", + "uk" to "Форум", + "vi" to "Diễn đàn", + "zh-CN" to "论坛", + "zh-TW" to "論壇", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Gallery", + name = + mapOf( + "ar" to "معرض", + "bg" to "Галерия", + "ca" to "Galeria", + "cs" to "Galerie", + "da" to "Galleri", + "de" to "Galerie", + "el" to "Συλλογή", + "en-GB" to "Gallery", + "en-US" to "Gallery", + "eo" to "Bild-foliumiloj", + "es" to "Galería", + "et" to "Galeriid", + "fa" to "نگارخانه", + "fi" to "Galleria", + "fr" to "Galerie", + "ga" to "Gailearaí", + "he" to "גלריה", + "hr" to "Galerija", + "hu" to "Galéria", + "id" to "Galeri", + "is" to "Myndasafn", + "it" to "Galleria", + "ja" to "ギャラリー", + "kn" to "ಗ್ಯಾಲರಿ", + "ko" to "갤러리", + "lb" to "Galerie", + "lt" to "Galerija", + "lv" to "Galerija", + "my" to "ပြခန်း", + "nb" to "Galleri", + "nl" to "Galerij", + "nl-BE" to "Galerij", + "pl" to "Galeria", + "pt" to "Galeria", + "pt-BR" to "Galeria", + "pt-PT" to "Galeria", + "ro" to "Galerie", + "ru" to "Галерея", + "sc" to "Galleria", + "sl" to "Galerija", + "sq" to "Galeri", + "sr" to "Излог слика", + "sv" to "Galleri", + "sw" to "Matunzio", + "ta" to "கேலரி", + "tr" to "Galeri", + "ug" to "سۈرەتدان", + "uk" to "Галерея", + "vi" to "Thư viện ảnh", + "zh-CN" to "相册", + "zh-TW" to "圖庫", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Games", + name = + mapOf( + "af" to "Speletjies", + "ar" to "الألعاب", + "ast" to "Xuegos", + "ba" to "Уйындар", + "be" to "Гульні", + "ber" to "ⵓⵔⴰⵔⵏ", + "bg" to "Игри", + "bn" to "গেমস", + "bn-BD" to "গেমস", + "bo" to "རྩེད་རིགས།", + "br" to "C'hoarioù", + "ca" to "Jocs", + "ckb" to "یاری", + "cs" to "Hry", + "cy" to "Gemau", + "da" to "Spil", + "de" to "Spiele", + "el" to "Παιχνίδια", + "en-GB" to "Games", + "en-US" to "Games", + "eo" to "Ludoj", + "es" to "Juegos", + "es-AR" to "Juegos", + "es-MX" to "Juegos", + "et" to "Mängud", + "eu" to "Jolasak", + "fa" to "بازی", + "fi" to "Pelit", + "fil" to "Laro", + "fr" to "Jeux", + "fy" to "Spultsjes", + "ga" to "Cluichí", + "gd" to "Geamannan", + "gl" to "Xogos", + "he" to "משחקים", + "hi" to "गेम्स", + "hr" to "Igre", + "hu" to "Játékok", + "hy" to "Խաղեր", + "id" to "Permainan", + "is" to "Leikir", + "it" to "Giochi", + "ja" to "ゲーム", + "kab" to "Uraren", + "kmr" to "Lîsk", + "kn" to "ಆಟಗಳು", + "ko" to "게임", + "lb" to "Spiller", + "lt" to "Žaidimai", + "lv" to "Spēles", + "mk" to "Игри", + "ml" to "കളികൾ", + "mn" to "Тоглоомууд", + "mr" to "खेळ", + "my" to "ဂိမ်းများ", + "nb" to "Spill", + "ne" to "खेलहरू", + "nl" to "Spellen", + "nl-BE" to "Spellen", + "nn" to "Spel", + "pa" to "ਖੇਡਾਂ", + "pl" to "Gry", + "ps" to "لوبې", + "pt" to "Jogos", + "pt-BR" to "Jogos", + "pt-PT" to "Jogos", + "ro" to "Jocuri", + "ru" to "Игры", + "sc" to "Giogos", + "si" to "ක්‍රීඩා", + "sk" to "Hry", + "sl" to "Igre", + "sn" to "Mitambo", + "so" to "Geemamka", + "sq" to "Lojëra", + "sr" to "Игре", + "sv" to "Spel", + "sw" to "Michezo", + "ta" to "விளையாட்டுகள்", + "te" to "ఆట", + "th" to "เกม", + "tr" to "Oyunlar", + "tzm" to "uraren", + "ug" to "ئويۇنلار", + "uk" to "Ігри", + "ur" to "گیمس", + "vi" to "Trò chơi", + "yue" to "遊戲", + "zh-CN" to "游戏", + "zh-HK" to "遊戲", + "zh-TW" to "遊戲", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Graphics", + name = + mapOf( + "af" to "Grafika", + "ar" to "الرسومات", + "ast" to "Graphics", + "ba" to "Графика", + "be" to "Графіка", + "bg" to "Графика", + "bn" to "গ্রাফিক্স", + "bn-BD" to "গ্রাফিক্স", + "bo" to "བརྐོས་རིས།", + "br" to "Graferezh", + "ca" to "Gràfics", + "ckb" to "نیگارەیی", + "cs" to "Grafika", + "cy" to "Graffigau", + "da" to "Grafik", + "de" to "Grafik", + "el" to "Γραφικά", + "en-GB" to "Graphics", + "en-US" to "Graphics", + "eo" to "Grafiko", + "es" to "Gráficos", + "es-AR" to "Gráficos", + "es-MX" to "Gráficos", + "et" to "Graafika", + "eu" to "Grafikoak", + "fa" to "گرافیک", + "fi" to "Grafiikka", + "fil" to "Grapiks", + "fr" to "Graphisme", + "fy" to "Grafysk", + "ga" to "Grafaicí", + "gd" to "Grafaigeachd", + "gl" to "Gráficas", + "he" to "גרפיקה", + "hi" to "ग्राफिक्स", + "hr" to "Grafika", + "hu" to "Grafika", + "hy" to "Գրաֆիկա", + "id" to "Grafis", + "is" to "Myndefni", + "it" to "Grafica", + "ja" to "グラフィック", + "kab" to "Tiẓrudlifin", + "kmr" to "Grafîk", + "kn" to "ಗ್ರಾಫಿಕ್ಸ್", + "ko" to "그래픽", + "lb" to "Grafik", + "lt" to "Grafika", + "lv" to "Grafika", + "mk" to "Графика", + "ml" to "Graphics", + "mn" to "График", + "mr" to "ग्राफिक्स", + "my" to "ဂရပ်ဖစ်များ", + "nb" to "Grafikk", + "ne" to "ग्राफिक्स", + "nl" to "Grafisch", + "nl-BE" to "Grafisch", + "nn" to "Bilete", + "pa" to "ਗਰਾਫਿਕਸ", + "pl" to "Grafika", + "ps" to "كښنيزونه", + "pt" to "Gráficos", + "pt-BR" to "Gráficos", + "pt-PT" to "Gráficos", + "ro" to "Grafică", + "ru" to "Графика", + "sc" to "Gràfica", + "sk" to "Grafika", + "sl" to "Grafika", + "sn" to "Magraphics", + "so" to "Farshaxa", + "sq" to "Grafika", + "sr" to "Графика", + "sv" to "Grafik", + "sw" to "Michoro", + "ta" to "க்ராஃபிக்ஸ்", + "te" to "గ్రాఫిక్స్", + "th" to "กราฟิก", + "tr" to "Çizim", + "tzm" to "Tiwwunɣa", + "ug" to "رەسىملەر", + "uk" to "Графіка", + "ur" to "گرافیکس", + "vi" to "Đồ hoạ", + "yue" to "圖像", + "zh-CN" to "图像", + "zh-HK" to "繪圖", + "zh-TW" to "圖形", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Habit Tracker", + name = + mapOf( + "ar" to "متتبع العادات", + "bg" to "Проследяване на навици", + "ca" to "Registre d'hàbits", + "cs" to "Sledování návyků", + "de" to "Gewohnheitstracker", + "el" to "Ιχνηλάτης Συνηθειών", + "en-GB" to "Habit Tracker", + "en-US" to "Habit Tracker", + "eo" to "Spuriloj de kutimoj", + "es" to "Seguimiento de hábitos", + "et" to "Elustiil", + "fa" to "ردیاب عادت", + "fr" to "Suivi des habitudes", + "ga" to "Rianaitheoir Nósanna", + "he" to "מעקב הרגלים", + "hr" to "Praćenje navika", + "hu" to "Szokáskövető", + "id" to "Pelacak Perilaku", + "is" to "Venjuskráning", + "it" to "Monitor Abitudini", + "ja" to "ハビットトラッカー", + "kn" to "ಅಭ್ಯಾಸ ಟ್ರ್ಯಾಕರ್", + "ko" to "습관 추적기", + "lt" to "Įpročių sekiklis", + "lv" to "Ieradumu izsekotājs", + "my" to "အလေ့အထ မှတ်တမ်း", + "nb" to "Vanesporer", + "nl" to "Gewoontes bijhouden", + "nl-BE" to "Gewoonte tracker", + "pl" to "Śledzenie nawyków", + "pt" to "Rastejador de hábitos", + "pt-BR" to "Rastreador de hábitos", + "pt-PT" to "Rastejador de hábitos", + "ro" to "Jurnal de obiceiuri", + "ru" to "Трекер привычек", + "sl" to "Sledilnik navad", + "sq" to "Ndjekës Zakonesh", + "sv" to "Vanespårare", + "sw" to "Kifuatilia Tabia", + "ta" to "பழக்கமான டிராக்கர்", + "tr" to "Alışkanlık İzleyici", + "uk" to "Трекер звичок", + "vi" to "Theo dõi thói quen", + "zh-CN" to "习惯追踪程序", + "zh-TW" to "習慣追蹤器", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Icon Pack", + name = + mapOf( + "ar" to "حزمة الأيقونات", + "bg" to "Пакет с пиктограми", + "ca" to "Pack d'icones", + "cs" to "Balíček ikon", + "da" to "Ikonpakke", + "de" to "Symbol-Paket", + "el" to "Πακέτο Εικονιδίων", + "en-GB" to "Icon Pack", + "en-US" to "Icon Pack", + "eo" to "Bildsimbol-pakaĵoj", + "es" to "Paquete de iconos", + "et" to "Ikoonipakid", + "fa" to "بستهٔ نقشک", + "fi" to "Kuvakepaketti", + "fr" to "Pack d'icônes", + "ga" to "Pacáiste Deilbhíní", + "he" to "חבילת סמלים", + "hr" to "Paket ikona", + "hu" to "Ikoncsomag", + "id" to "Paket Ikon", + "is" to "Táknmyndapakki", + "it" to "Pacchetto di icone", + "ja" to "アイコンパック", + "kn" to "ಐಕಾನ್ ಪ್ಯಾಕ್", + "ko" to "아이콘 팩", + "lt" to "Piktogramų pakas", + "lv" to "Ikonu paka", + "my" to "အိုင်ကွန်အစုအဝေး", + "nb" to "Ikonpakke", + "nl" to "Pictogrammenpakket", + "nl-BE" to "Pictogrammenpakket", + "pl" to "Pakiet ikon", + "pt" to "Pacote de ícones", + "pt-BR" to "Pacote de ícones", + "pt-PT" to "Pacote de ícones", + "ro" to "Pachet iconițe", + "ru" to "Наборы значков", + "sc" to "Pachete de iconas", + "sl" to "Zbirka ikon", + "sq" to "Paketë Ikonash", + "sr" to "Омот сличица", + "sv" to "Ikonpaket", + "sw" to "Kifurushi cha ikoni", + "ta" to "படவுரு பேக்", + "tr" to "Simge Paketi", + "ug" to "سىنبەلگە بوغچىسى", + "uk" to "Набір значків", + "vi" to "Gói biểu tượng", + "zh-CN" to "图标包", + "zh-TW" to "圖示套件", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Internet", + name = + mapOf( + "af" to "Internet", + "ar" to "الإنترنت", + "ast" to "Internet", + "ba" to "Интернет", + "be" to "Інтэрнэт", + "ber" to "ⴰⵏⵜⵉⵔⵏⵉⵜ", + "bg" to "Интернет", + "bn" to "ইন্টারনেট", + "bn-BD" to "ইন্টারনেট", + "bo" to "དྲྭ་རྒྱ།", + "br" to "Internet", + "ca" to "Internet", + "ckb" to "ئینتەرنێت", + "cs" to "Internet", + "cy" to "Rhyngrwyd", + "da" to "Internet", + "de" to "Internet", + "el" to "Διαδίκτυο", + "en-GB" to "Internet", + "en-US" to "Internet", + "eo" to "Interreto", + "es" to "Internet", + "es-AR" to "Internet", + "es-MX" to "Internet", + "et" to "Internet", + "eu" to "Internet", + "fa" to "اینترنت", + "fi" to "Internet", + "fil" to "Internet", + "fr" to "Internet", + "fy" to "Internet", + "ga" to "Idirlíon", + "gd" to "Eadar-lìon", + "gl" to "Internet", + "he" to "אינטרנט", + "hi" to "इंटरनेट", + "hr" to "Internet", + "hu" to "Internet", + "hy" to "Ցանց", + "id" to "Internet", + "is" to "Internetið", + "it" to "Internet", + "ja" to "インターネット", + "kab" to "Internet", + "kmr" to "Înternet", + "kn" to "ಇಂಟರ್ನೆಟ್", + "ko" to "인터넷", + "lb" to "Internet", + "lt" to "Internetas", + "lv" to "Internets", + "mk" to "Интернет", + "ml" to "Internet", + "mn" to "Интернет", + "mr" to "इंटरनेट", + "my" to "အင်တာနက်", + "nb" to "Internett", + "ne" to "इन्टरनेट", + "nl" to "Internet", + "nl-BE" to "Internet", + "nn" to "Internett", + "pa" to "ਇੰਟਰਨੈੱਟ", + "pl" to "Internet", + "ps" to "نړیجال", + "pt" to "Internet", + "pt-BR" to "Internet", + "pt-PT" to "Internet", + "ro" to "Internet", + "ru" to "Интернет", + "sc" to "Ìnternet", + "si" to "අන්තර්ජාලය", + "sk" to "Internet", + "sl" to "Internet", + "sn" to "Dandemutande", + "so" to "Khadka", + "sq" to "Internet", + "sr" to "Интернет", + "sv" to "Internet", + "sw" to "Mtandao", + "ta" to "இணையம்", + "te" to "అంతర్జాలం", + "th" to "อินเทอร์เน็ต", + "tr" to "İnternet", + "tzm" to "antirnit", + "ug" to "تور", + "uk" to "Інтернет", + "ur" to "انٹرنیٹ", + "vi" to "Internet", + "yue" to "互聯網", + "zh-CN" to "网络", + "zh-HK" to "互聯網", + "zh-TW" to "網際網路", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Inventory", + name = + mapOf( + "ar" to "جرد", + "ca" to "Inventari", + "cs" to "Inventář", + "da" to "Inventar", + "de" to "Inventar", + "el" to "Απόθεμα", + "en-GB" to "Inventory", + "en-US" to "Inventory", + "eo" to "Administriloj de posedaĵoj", + "es" to "Inventario", + "et" to "Varahaldus", + "fa" to "موجودی", + "fr" to "Inventaire", + "ga" to "Fardal", + "he" to "מלאי", + "hr" to "Inventar", + "hu" to "Leltár", + "id" to "Inventaris", + "is" to "Birgðaskráning", + "ja" to "在庫", + "kn" to "ದಾಸ್ತಾನು", + "ko" to "인벤토리", + "lv" to "Lietu uzskaite", + "my" to "ပစ္စည်းစာရင်း", + "nb" to "Inventar", + "nl" to "Inventarisatie", + "nl-BE" to "Voorraad", + "pl" to "Zasoby", + "pt-BR" to "Inventário", + "ro" to "Inventar", + "sl" to "Popis imetja", + "sq" to "Inventar", + "sv" to "Inventarie", + "sw" to "Orodha ya Bidhaa", + "tr" to "Envanter", + "uk" to "Інвентар", + "vi" to "Quản lý kho", + "zh-CN" to "物品清单", + "zh-TW" to "庫存", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Keyboard & IME", + name = + mapOf( + "ar" to "لوحة المفاتيح وIME", + "bg" to "Клавиатура и въвеждане", + "ca" to "Teclat i IME", + "cs" to "Klávesnice a IME", + "da" to "Tastatur og IME", + "de" to "Tastatur / IME", + "el" to "Πληκτρολόγιο & IME", + "en-GB" to "Keyboard & IME", + "en-US" to "Keyboard & IME", + "eo" to "Klavaroj", + "es" to "Teclado y métodos de entrada (IME)", + "et" to "Klahvistik ja sisendmeetodid", + "fa" to "صفحه‌کلید و ورودی متن", + "fi" to "Näppäimistö ja tekstinsyöttö", + "fr" to "Clavier & IME", + "ga" to "Méarchlár & IME", + "he" to "מקלדת ושיטות קלט", + "hr" to "Tipkovnica i IME uređivač", + "hu" to "Billentyűzet és bevitelszerkesztő", + "id" to "Papan Tik & IME", + "is" to "Lyklaborð og innsláttur", + "it" to "Tastiera e Metodi di Inserimento", + "ja" to "キーボード&IME", + "kn" to "ಕೀಬೋರ್ಡ್", + "ko" to "키보드 및 IME", + "lt" to "Klaviatūra ir įvesties metodai (IME)", + "lv" to "Tastatūra un ievades veidu redaktors", + "my" to "ကီးဘုတ်နှင့် စာရိုက်စနစ်", + "nb" to "Tastatur & Inndatametoder", + "nl" to "Toetsenbord & invoer", + "nl-BE" to "Toetsenbord en IME", + "pl" to "Klawiatura i IME", + "pt" to "Teclado e métodos de entrada", + "pt-BR" to "Teclado e métodos de entrada", + "pt-PT" to "Teclado e MDE (IME)", + "ro" to "Tastatură & IME", + "ru" to "Клавиатуры и ввод", + "sc" to "Tecladu e mètodos de intrada (IME)", + "sl" to "Tipkovnica in urejevalec vnosa IME", + "sq" to "Tastierë & IME", + "sr" to "Тастатура и начин уноса", + "sv" to "Tangentbord och IME", + "sw" to "Kibodi na IME", + "ta" to "விசைப்பலகை & ime", + "tr" to "Klavye ve Giriş Yöntemi Düzenleyici", + "ug" to "ھەرپتاختا ۋە كىرگۈزگۈچ", + "uk" to "Клавіатура та ввід", + "vi" to "Bàn phím & IME", + "zh-CN" to "键盘和输入法", + "zh-TW" to "鍵盤與輸入法", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Launcher", + name = + mapOf( + "ar" to "مُطلِق", + "bg" to "Начален екран", + "ca" to "Llançador", + "cs" to "Launcher", + "da" to "Launcher", + "de" to "Launcher", + "el" to "Εκκινητής", + "en-GB" to "Launcher", + "en-US" to "Launcher", + "eo" to "Aplikaĵlanĉiloj", + "es" to "Lanzador de aplicaciones", + "et" to "Käivitajad", + "fa" to "اجراگر", + "fi" to "Käynnistin", + "fr" to "Lanceur", + "ga" to "Lainseálaí", + "he" to "משגר", + "hr" to "Pokretač", + "hu" to "Indító", + "id" to "Peluncur", + "is" to "Ræsir", + "it" to "Launcher", + "ja" to "ランチャー", + "kn" to "ಲಾಂಚರ್", + "ko" to "런처", + "lt" to "Paleidimo programa", + "lv" to "Palaidējs", + "my" to "ပင်မစာမျက်နှာပြင်စနစ်", + "nb" to "Launcher", + "nl" to "Launcher", + "nl-BE" to "Launcher", + "pl" to "Launcher", + "pt" to "Lançador", + "pt-BR" to "Tela inicial", + "pt-PT" to "Lançador", + "ro" to "Lansator", + "ru" to "Лаунчер", + "sc" to "Aviadores de aplicatziones", + "sl" to "Zaganjalnik", + "sq" to "Nisës", + "sr" to "Покретач", + "sv" to "Startare", + "sw" to "Kizindua", + "ta" to "துவக்கி", + "tr" to "Başlatıcı", + "ug" to "قوزغاتقۇچ", + "uk" to "Запускач", + "vi" to "Trình launcher", + "zh-CN" to "启动器", + "zh-TW" to "啟動器", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Local Media Player", + name = + mapOf( + "ar" to "مشغل الوسائط المحلي", + "bg" to "Местно изпълняване на медия", + "ca" to "Reproductor local de mitjans", + "cs" to "Přehrávač lokálních médií", + "da" to "Lokal medieafspiller", + "de" to "Lokaler Mediaplayer", + "el" to "Τοπικός Αναπαραγωγέας Πολυμέσων", + "en-GB" to "Local Media Player", + "en-US" to "Local Media Player", + "eo" to "Ludiloj de lokaj aŭdvidaĵoj", + "es" to "Reproductor local", + "et" to "Meediaesitus nutiseadmest", + "fa" to "پخش کنندهٔ آهنگ محلی", + "fi" to "Paikallisen median soitin", + "fr" to "Lecteur multimédia local", + "ga" to "Seinnteoir Meán Áitiúil", + "he" to "נגן מדיה מקומית", + "hr" to "Lokalni player medija", + "hu" to "Helyi médialejátszó", + "id" to "Pemutar Media Lokal", + "is" to "Margmiðlunarspilari á tæki", + "it" to "Lettore Media Locali", + "ja" to "ローカル・メディアプレイヤー", + "kn" to "ಸ್ಥಳೀಯ ಮೀಡಿಯಾ ಪ್ಲೇಯರ್", + "ko" to "로컬 미디어 플레이어", + "lt" to "Vietinės medijos leistuvė", + "lv" to "Vietējo informācijas nesēju atskaņotājs", + "my" to "စက်တွင်း မီဒီယာဖွင့်စနစ်", + "nb" to "Lokal mediaspiller", + "nl" to "Lokale mediaspeler", + "nl-BE" to "Lokale mediaspeler", + "pl" to "Lokalny odtwarzacz multimediów", + "pt" to "Reprodutor de média local", + "pt-BR" to "Reprodutor de mídia local", + "pt-PT" to "Reprodutor de média local", + "ro" to "Vizualizator media local", + "ru" to "Медиаплееры", + "sc" to "Leghidore multimediale locale", + "sl" to "Lokalni predvajalnik glasbe", + "sq" to "Lojtës Mediash Vendore", + "sr" to "Местни извођач садржаја", + "sv" to "Lokal mediaspelare", + "sw" to "Kicheza Midia ya Kifaa", + "ta" to "உள்ளக மீடியா பிளேயர்", + "tr" to "Yerel Medya Oynatıcı", + "ug" to "يەرلىك ۋاسىتە قويغۇچ", + "uk" to "Локальний медіапрогравач", + "vi" to "Trình phát phương tiện offline", + "zh-CN" to "本地媒体播放器", + "zh-TW" to "本機媒體播放器", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Location Tracker & Sharer", + name = + mapOf( + "ar" to "متتبع ومشارك الموقع", + "bg" to "Публикуване и споделяне на местоположение", + "ca" to "Seguiment i compartició d'ubicació", + "cs" to "Sledování a sdílení polohy", + "de" to "Standort-Tracker / -Teiler", + "el" to "Ιχνηλάτης & Διαμοιραστής Τοποθεσίας", + "en-GB" to "Location Tracker & Sharer", + "en-US" to "Location Tracker & Sharer", + "eo" to "Spuriloj (kaj kunhavigiloj) de pozicio", + "es" to "Seguir y compartir mi ubicación", + "et" to "Asukoha logimine ja jagamine", + "fa" to "ردیابی و هم‌رسانی مکان", + "fr" to "Suivi & partage de localisation", + "ga" to "Rianaitheoir Suímh & Roinnteoir", + "he" to "מעקב ושיתוף מיקום", + "hr" to "Praćenje i dijeljenje lokacije", + "hu" to "Helykövető és -megosztó", + "id" to "Pelacak & Pembagi Lokasi", + "is" to "Staðsetningarrakning og deiling", + "it" to "Localizzatore & Condivisione", + "ja" to "場所の記録&共有", + "ko" to "위치 추적 및 공유기", + "lt" to "Vietovės sekimo ir bendrinimo įrankis", + "lv" to "Atrašanās vietas izsekotājs un kopīgotājs", + "my" to "တည်နေရာ ခြေရာခံနှင့် မျှဝေမှုစနစ်", + "nb" to "Lokasjonssporer og -deling", + "nl" to "Locatie bijhouden en delen", + "nl-BE" to "Locatietracker en -deler", + "pl" to "Śledzenie i udostępnianie lokalizacji", + "pt-BR" to "Rastreador e compartilhador de localização", + "ro" to "Localizare și partajare locație", + "ru" to "Отслеживание и публикация местоположения", + "sl" to "Sledilnik in delilnik položaja", + "sq" to "Gjurmues & Dhënës Vendndodhjesh", + "sv" to "Platsspårare och delare", + "sw" to "Kifuatilia Mahali & Mshiriki", + "tr" to "Konum İzleyici ve Paylaşıcı", + "uk" to "Відстеження та поширення розташування", + "vi" to "Định vị và chia sẻ vị trí", + "zh-CN" to "位置跟踪 & 分享", + "zh-TW" to "位置追蹤器與分享器", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Messaging", + name = + mapOf( + "ar" to "مراسلة", + "ba" to "Мессенджер", + "bg" to "Обмяна на съобщения", + "ca" to "Missatges", + "cs" to "Posílání zpráv", + "da" to "Beskeder", + "de" to "Messaging", + "el" to "Μηνύματα", + "en-GB" to "Messaging", + "en-US" to "Messaging", + "eo" to "Komunikiloj", + "es" to "Mensajería", + "et" to "Sõnumirakendused", + "fa" to "پیام رسانی", + "fi" to "Viestit", + "fr" to "Messagerie", + "ga" to "Teachtaireachtaí", + "he" to "התכתבות", + "hr" to "Razmjena poruka", + "hu" to "Üzenetküldés", + "id" to "Perpesanan", + "is" to "Skilaboð", + "it" to "Messaggi", + "ja" to "メッセージング", + "kn" to "ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆ", + "ko" to "메시지", + "lt" to "Susirašinėjimas", + "lv" to "Ziņapmaiņa", + "my" to "စာပေးပို့ခြင်း", + "nb" to "Meldinger", + "nl" to "Berichten", + "nl-BE" to "Berichten", + "pl" to "Komunikacja", + "pt" to "Mensageiros", + "pt-BR" to "Mensageiros", + "pt-PT" to "Mensageiros", + "ro" to "Mesagerie", + "ru" to "Сообщения", + "sc" to "Messagìstica", + "sl" to "Sporočila", + "sq" to "Shkëmbim Mesazhesh", + "sr" to "Поруке", + "sv" to "Meddelanden", + "sw" to "Ujumbe", + "ta" to "செய்தியிடல்", + "tr" to "Mesajlaşma", + "ug" to "ئۇچۇرلىشىش", + "uk" to "Повідомлення", + "vi" to "Nhắn tin", + "zh-CN" to "消息收发", + "zh-TW" to "訊息傳遞", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Money", + name = + mapOf( + "af" to "Geld", + "ar" to "المالية", + "ast" to "Dineru", + "ba" to "Финанстар", + "be" to "Фінансы", + "ber" to "ⴰⵥⵕⴼ", + "bg" to "Финанси", + "bn" to "অর্থ", + "bn-BD" to "অর্থ", + "bo" to "དངུལ།", + "br" to "Arc'hant", + "ca" to "Diners", + "ckb" to "پارە", + "cs" to "Peníze", + "cy" to "Arian", + "da" to "Penge", + "de" to "Geld", + "el" to "Οικονομικά", + "en-GB" to "Money", + "en-US" to "Money", + "eo" to "Financoj", + "es" to "Dinero", + "es-AR" to "Dinero", + "es-MX" to "Dinero", + "et" to "Raha", + "eu" to "Dirua", + "fa" to "مالی", + "fi" to "Raha", + "fil" to "Pananalapi", + "fr" to "Finances", + "fy" to "Jild", + "ga" to "Airgead", + "gd" to "Airgead", + "gl" to "Diñeiro", + "he" to "כלכלה", + "hi" to "धन", + "hr" to "Novac", + "hu" to "Pénzügyek", + "hy" to "Փող", + "id" to "Finansial", + "is" to "Fjármál", + "it" to "Finanze", + "ja" to "金融", + "kab" to "Tadrimt", + "kmr" to "Diravî", + "kn" to "ಹಣ", + "ko" to "금융", + "lb" to "Suen", + "lt" to "Pinigai", + "lv" to "Nauda", + "mk" to "Пари", + "ml" to "സാമ്പത്തികം", + "mn" to "Мөнгө", + "my" to "ငွေကြေး", + "nb" to "Penger", + "ne" to "पैसा", + "nl" to "Geld", + "nl-BE" to "Geld", + "nn" to "Økonomi", + "pa" to "ਪੈਸੇ", + "pl" to "Finanse", + "pt" to "Finanças", + "pt-BR" to "Dinheiro", + "pt-PT" to "Finanças", + "ro" to "Finanțe", + "ru" to "Финансы", + "sc" to "Dinare", + "sk" to "Financie", + "sl" to "Denar", + "sn" to "Mari", + "so" to "Lacag", + "sq" to "Para", + "sr" to "Финансије", + "sv" to "Pengar", + "sw" to "Pesa", + "ta" to "பணம்", + "te" to "డబ్బు", + "th" to "การเงิน", + "tr" to "Finans", + "tzm" to "aẓeṛf", + "ug" to "پۇل", + "uk" to "Фінанси", + "ur" to "رقم", + "vi" to "Tài chính", + "yue" to "理財", + "zh-CN" to "理财", + "zh-HK" to "財經", + "zh-TW" to "理財", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Multimedia", + name = + mapOf( + "af" to "Multimedia", + "ar" to "الوسائط المتعددة", + "ast" to "Multimedia", + "ba" to "Мультимедиа", + "be" to "Мультымедыя", + "bg" to "Мултимедия", + "bn" to "মাল্টিমিডিয়া", + "bn-BD" to "মাল্টিমিডিয়া", + "bo" to "བརྒྱུད་ལམ་སྣ་ཚོགས།", + "br" to "Liesvedia", + "ca" to "Multimèdia", + "ckb" to "ڕەنگاڵە", + "cs" to "Multimédia", + "cy" to "Aml-gyfrwng", + "da" to "Multimedier", + "de" to "Multimedia", + "el" to "Πολυμέσα", + "en-GB" to "Multimedia", + "en-US" to "Multimedia", + "eo" to "Sono kaj video", + "es" to "Multimedia", + "es-AR" to "Multimedia", + "es-MX" to "Multimedia", + "et" to "Multimeedia", + "eu" to "Multimedia", + "fa" to "چندرسانه‌ای", + "fi" to "Multimedia", + "fil" to "Multimedia", + "fr" to "Multimédia", + "fy" to "Multimedia", + "ga" to "Ilmheáin", + "gd" to "Meadhanan", + "gl" to "Multimedia", + "he" to "מולטימדיה", + "hi" to "मल्टीमीडिया", + "hr" to "Multimedija", + "hu" to "Multimédia", + "hy" to "Մուլտիմեդիա", + "id" to "Multimedia", + "is" to "Margmiðlun", + "it" to "Multimedia", + "ja" to "マルチメディア", + "kab" to "Agetmedia", + "kn" to "ಮಲ್ಟಿಮೀಡಿಯಾ", + "ko" to "멀티미디어", + "lb" to "Multimedia", + "lt" to "Multimedija", + "lv" to "Multivide", + "mk" to "Мултимедија", + "ml" to "Multimedia", + "mn" to "Мультимедиа", + "mr" to "मल्टीमीडिया", + "my" to "မီဒီယာ", + "nb" to "Multimedia", + "ne" to "मल्टिमेडिया", + "nl" to "Multimedia", + "nl-BE" to "Multimedia", + "nn" to "Multimedia", + "pa" to "ਮਲਟੀ-ਮੀਡਿਆ", + "pl" to "Multimedia", + "ps" to "ګڼرسنۍ", + "pt" to "Multimédia", + "pt-BR" to "Multimídia", + "pt-PT" to "Multimédia", + "ro" to "Multimedia", + "ru" to "Мультимедиа", + "sc" to "Multimèdia", + "sk" to "Multimédiá", + "sl" to "Multimedija", + "sn" to "Midhiya yakasiyana", + "so" to "Lagu", + "sq" to "Multimedia", + "sr" to "Мултимедија", + "sv" to "Multimedia", + "sw" to "Multimedia", + "ta" to "பல்லூடகம்", + "te" to "మల్టీమీడియా", + "th" to "สื่อผสม", + "tr" to "Çoklu ortam", + "ug" to "كۆپ ۋاسىتە", + "uk" to "Мультимедіа", + "ur" to "ملٹیمیڈیا", + "vi" to "Đa phương tiện", + "yue" to "多媒體", + "zh-CN" to "多媒体", + "zh-HK" to "多媒體", + "zh-TW" to "多媒體", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Music Practice Tool", + name = + mapOf( + "bg" to "Инструмент за музикална практика", + "ca" to "Eina de pràctica musical", + "cs" to "Nástroj pro cvičení hudby", + "de" to "Musikübungstool", + "el" to "Εργαλείο Εξάσκησης Μουσικής", + "en-GB" to "Music Practice Tool", + "en-US" to "Music Practice Tool", + "eo" to "Muzik-ekzerciloj", + "es" to "Práctica musical", + "et" to "Muusikatarvikud", + "fa" to "ابزار تمرین آهنگ", + "fr" to "Outil de pratique musicale", + "ga" to "Uirlis Cleachtaidh Ceoil", + "he" to "כלי תרגול מוזיקה", + "hr" to "Alat za vježbanje glazbe", + "hu" to "Zenei gyakorló eszközök", + "id" to "Alat Latihan Musik", + "is" to "Tónlistaræfingatól", + "it" to "Strumento per la Pratica Musicale", + "ja" to "音楽練習ツール", + "kn" to "ಸಂಗೀತ ಅಭ್ಯಾಸ ಸಾಧನ", + "ko" to "음악 연습용 도구", + "lt" to "Muzikinės praktikos įrankis", + "lv" to "Mūzikas vingrināšanās rīks", + "my" to "ဂီတလေ့ကျင့်ရေး ကိရိယာ", + "nb" to "Musikkøvingsverktøy", + "nl" to "Hulpmiddelen voor muzikanten", + "nl-BE" to "Muziek oefentool", + "pl" to "Narzędzie do ćwiczeń muzycznych", + "pt" to "Ferramenta de prática musical", + "pt-BR" to "Ferramenta de prática musical", + "pt-PT" to "Ferramenta de prática musical", + "ro" to "Instrumentul de practică muzicală", + "ru" to "Инструмент для музыкальной практики", + "sl" to "Orodje za vadbo glasbe", + "sq" to "Mjet Praktimi Muzike", + "sv" to "Muskikövningsapp", + "sw" to "Zana ya Mazoezi ya Muziki", + "ta" to "இசை பயிற்சி கருவி", + "tr" to "Müzik Çalışma Aracı", + "uk" to "Інструмент для музичної практики", + "vi" to "Công cụ luyện tập nhạc", + "zh-CN" to "音乐练习工具", + "zh-TW" to "音樂練習工具", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Navigation", + name = + mapOf( + "af" to "Navigasie", + "ar" to "التصفح", + "ast" to "Navegación", + "ba" to "Навигация", + "be" to "Навігацыя", + "bg" to "Местоположение", + "bn" to "দিক নির্ণয়", + "bn-BD" to "দিক নির্ণয়", + "bo" to "ཕྱོགས་ཁྲིད།", + "br" to "Merdeiñ", + "ca" to "Navegació", + "ckb" to "ڕێدۆز", + "cs" to "Navigace", + "cy" to "Llywio", + "da" to "Navigation", + "de" to "Navigation", + "el" to "Πλοήγηση", + "en-GB" to "Navigation", + "en-US" to "Navigation", + "eo" to "Navigado", + "es" to "Navegación", + "es-AR" to "Navegación", + "es-MX" to "Navegación", + "et" to "Tee juhatamine", + "eu" to "Orientazioa", + "fa" to "ناوبری", + "fi" to "Navigointi", + "fil" to "Nabigasyon", + "fr" to "Navigation", + "fy" to "Navigaasje", + "ga" to "Loingseoireacht", + "gd" to "Seòladaireachd", + "gl" to "Navigación", + "he" to "ניווט", + "hi" to "नेविगेशन", + "hr" to "Navigacija", + "hu" to "Navigáció", + "hy" to "Կողմնորոշում", + "id" to "Navigasi", + "is" to "Yfirsýn", + "it" to "Navigazione", + "ja" to "地図とナビ", + "kab" to "Asnirem", + "kn" to "ಸಂಚರಣೆ", + "ko" to "네비게이션", + "lb" to "Navigatioun", + "lt" to "Navigacija", + "lv" to "Kartes un pārvietošanās norādes", + "mk" to "Навигација", + "ml" to "Navigation", + "mn" to "Чиглүүлэлт", + "mr" to "मार्गक्रम", + "my" to "လမ်းညွှန်", + "nb" to "Navigasjon", + "ne" to "नेभिगेसन", + "nl" to "Navigatie", + "nl-BE" to "Navigatie", + "nn" to "Navigasjon", + "pa" to "ਨੇਵੀਗੇਸ਼ਨ", + "pl" to "Nawigacja", + "ps" to "چلونه", + "pt" to "Navegação", + "pt-BR" to "Navegação", + "pt-PT" to "Navegação", + "ro" to "Navigație", + "ru" to "Навигация", + "sc" to "Nàvigu", + "sk" to "Navigácia", + "sl" to "Navigacija", + "sn" to "Mafambiro", + "so" to "Dhex", + "sq" to "Lëvizje", + "sr" to "Навигација", + "sv" to "Navigation", + "sw" to "Urambazaji", + "ta" to "வழிகாட்டல்", + "te" to "నౌకాయానం", + "th" to "การนำทาง", + "tr" to "Navigasyon", + "ug" to "يول باشلاش", + "uk" to "Навігація", + "ur" to "سمت شناسی", + "vi" to "Điều hướng", + "yue" to "導航", + "zh-CN" to "导航", + "zh-HK" to "導航", + "zh-TW" to "導航", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Network Analyzer", + name = + mapOf( + "ar" to "مُحلِّل شبكة", + "ca" to "Analitzador de xarxa", + "cs" to "Analýza sítě", + "de" to "Netzwerkanalyse", + "el" to "Αναλυτής Δικτύου", + "en-GB" to "Network Analyser", + "en-US" to "Network Analyzer", + "eo" to "Analiziloj de retkonektoj", + "es" to "Diagnósticos de red", + "et" to "Võrguanalüüs", + "fa" to "تحلیلگر شبکه", + "fr" to "Analyseur de réseau", + "ga" to "Anailíseoir Líonra", + "he" to "מאבחן רשת", + "hr" to "Analizator mreže", + "hu" to "Hálózatelemző", + "id" to "Penganalisis Jaringan", + "is" to "Greining netkerfa", + "ja" to "ネットワークアナライザ", + "kn" to "ನೆಟ್‌ವರ್ಕ್ ವಿಶ್ಲೇಷಕ", + "ko" to "네트워크 분석기", + "lv" to "Tīkla analizētājs", + "my" to "ကွန်ရက် စစ်ဆေးခွဲခြမ်းမှုစနစ်", + "nb" to "Nettverksanalyse", + "nl" to "Netwerkanalyse", + "nl-BE" to "Netwerk analysetool", + "pl" to "Analizator sieci", + "pt-BR" to "Analisador de rede", + "ro" to "Analiză rețea", + "ru" to "Сетевой анализатор", + "sl" to "Pregledovalnik omrežja", + "sq" to "Analizues Rrjeti", + "sw" to "Kichanganuzi cha Mtandao", + "tr" to "Ağ İnceleyici", + "uk" to "Аналізатор мережі", + "vi" to "Chẩn đoán mạng", + "zh-CN" to "网络分析工具", + "zh-TW" to "網路分析工具", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "News", + name = + mapOf( + "ar" to "أخبار", + "bg" to "Новини", + "br" to "Keleier", + "ca" to "Notícies", + "cs" to "Zprávy", + "da" to "Nyheder", + "de" to "Nachrichten", + "el" to "Νέα", + "en-GB" to "News", + "en-US" to "News", + "eo" to "Legiloj de novaĵoj", + "es" to "Noticias", + "et" to "Uudised", + "fa" to "اخبار", + "fi" to "Uutiset", + "fr" to "Nouvelles", + "ga" to "Nuacht", + "he" to "חדשות", + "hr" to "Vijesti", + "hu" to "Hírek", + "id" to "Berita", + "is" to "Fréttir", + "it" to "Notizie", + "ja" to "ニュース", + "kn" to "ಸುದ್ದಿ", + "ko" to "뉴스", + "lb" to "Noriichten", + "lt" to "Naujienos", + "lv" to "Ziņas", + "my" to "သတင်းများ", + "nb" to "Nyheter", + "nl" to "Nieuws", + "nl-BE" to "Nieuws", + "pl" to "Wiadomości", + "pt" to "Notícias", + "pt-BR" to "Notícias", + "pt-PT" to "Notícias", + "ro" to "Știri", + "ru" to "Новости", + "sc" to "Novas", + "sl" to "Novice", + "sq" to "Lajme", + "sr" to "Вести", + "sv" to "Nyheter", + "sw" to "Habari", + "ta" to "செய்தி", + "tr" to "Haberler", + "ug" to "خەۋەر", + "uk" to "Новини", + "vi" to "Tin tức", + "zh-CN" to "新闻", + "zh-TW" to "新聞", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Note", + name = + mapOf( + "ar" to "ملاحظة", + "bg" to "Бележки", + "ca" to "Notes", + "cs" to "Poznámka", + "da" to "Note", + "de" to "Notiz", + "el" to "Σημειώσεις", + "en-GB" to "Note", + "en-US" to "Note", + "eo" to "Notlibroj", + "es" to "Notas", + "et" to "Märkmikud", + "fa" to "یادداشت", + "fr" to "Note", + "ga" to "Nóta", + "he" to "הערה", + "hr" to "Bilješka", + "hu" to "Jegyzet", + "id" to "Catatan", + "is" to "Minnispunktur", + "it" to "Appunti", + "ja" to "ノート", + "kn" to "ಗಮನಿಸಿ", + "ko" to "메모", + "lb" to "Notiz", + "lt" to "Pastaba", + "lv" to "Piezīme", + "my" to "မှတ်စု", + "nb" to "Notater", + "nl" to "Notities", + "nl-BE" to "Notitie", + "pl" to "Notatka", + "pt" to "Nota", + "pt-BR" to "Nota", + "pt-PT" to "Nota", + "ro" to "Notițe", + "ru" to "Заметки", + "sc" to "Nota", + "sl" to "Beležka", + "sq" to "Shënim", + "sr" to "Белешка", + "sv" to "Notera", + "sw" to "Dokezo", + "ta" to "குறிப்பு", + "tr" to "Not", + "ug" to "خاتىرە", + "uk" to "Примітка", + "vi" to "Ghi chú", + "zh-CN" to "笔记", + "zh-TW" to "記事", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Online Media Player", + name = + mapOf( + "ar" to "مشغل الوسائط عبر الإنترنت", + "bg" to "Отдалечено изпълняване на медия", + "ca" to "Reproductor de mitjans en línia", + "cs" to "Přehrávač online médií", + "da" to "Online medieafspiller", + "de" to "Online-Mediaplayer", + "el" to "Διαδικτυακός Αναπαραγωγέας Πολυμέσων", + "en-GB" to "Online Media Player", + "en-US" to "Online Media Player", + "eo" to "Ludiloj de foraj aŭdvidaĵoj", + "es" to "Reproductor en línea", + "et" to "Meediaesitus võrgust", + "fa" to "پخش کنندهٔ رسانهٔ برخط", + "fi" to "Verkkomediasoitin", + "fr" to "Lecteur multimédia en ligne", + "ga" to "Seinnteoir Meán Ar Líne", + "he" to "נגן מדיה מקוונת", + "hr" to "Online player medija", + "hu" to "Online médialejátszó", + "id" to "Pemutar Media Daring", + "is" to "Margmiðlunarspilari á neti", + "it" to "Lettore Media Online", + "ja" to "オンライン・メディアプレイヤー", + "kn" to "ಆನ್‌ಲೈನ್ ಮೀಡಿಯಾ ಪ್ಲೇಯರ್", + "ko" to "온라인 미디어 플레이어", + "lt" to "Internetinė medijos leistuvė", + "lv" to "Tiešsaistes informācijas nesēju atskaņotājs", + "my" to "အွန်လိုင်း မီဒီယာဖွင့်စနစ်", + "nb" to "Nettmediaspiller", + "nl" to "Online mediaspeler", + "pl" to "Odtwarzacz multimediów online", + "pt" to "Reprodutor de média on-line", + "pt-BR" to "Reprodutor de mídia on-line", + "pt-PT" to "Reprodutor de média on-line", + "ro" to "Vizualizator media pe Internet", + "ru" to "Онлайн-медиаплееры", + "sc" to "Leghidore multimediale in lìnia", + "sl" to "Predvajalnik spletnih vsebin", + "sq" to "Lojtës Mediash Në Internet", + "sr" to "Мрежни извођач садржаја", + "sv" to "Online mediaspelare", + "sw" to "Kicheza Midia Mtandaoni", + "ta" to "நிகழ்நிலை மீடியா பிளேயர்", + "tr" to "Çevrim içi Ortam Oynatıcı", + "ug" to "توردا ۋاسىتە قويغۇچ", + "uk" to "Онлайн-медіаплеєр", + "vi" to "Trình phát phương tiện online", + "zh-CN" to "在线媒体播放器", + "zh-TW" to "線上媒體播放器", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Pass Wallet", + name = + mapOf( + "ar" to "محفظة المرور", + "bg" to "Портмоне за пропуски", + "ca" to "Cartera de paraules de pas", + "cs" to "Peněženka na lístky", + "de" to "Passcode-Wallet", + "el" to "Πορτοφόλι Πάσου", + "en-GB" to "Pass Wallet", + "en-US" to "Pass Wallet", + "eo" to "Biletujoj (por lojalec-kartoj)", + "es" to "Billetes de transporte y entradas", + "et" to "Raha- ja kaarditaskud", + "fa" to "کیف پول رمز", + "fr" to "Portefeuille de pass", + "ga" to "Sparán Pas", + "he" to "ארנק סודות", + "hr" to "Novčanik za propusnice i kartice", + "hu" to "Jegytárca", + "id" to "Dompet Sandi", + "is" to "Lykilorðaveski", + "it" to "Portafogli Pass", + "ja" to "パスウォレット", + "kn" to "ಪಾಸ್ ವಾಲೆಟ್", + "ko" to "패스 지갑", + "lt" to "Bilietų piniginė", + "lv" to "Caurlaižu maks", + "my" to "လက်မှတ် သိမ်းဆည်းရာ", + "nb" to "Lommebøker & Kort", + "nl" to "Pasjesportemonnee", + "nl-BE" to "Kaarten portemonnee", + "pl" to "Portfel haseł", + "pt" to "Carteira de passe", + "pt-BR" to "Carteira de passe", + "pt-PT" to "Carteira de passe", + "ro" to "Portofel tichete", + "ru" to "Кошелек", + "sc" to "Portafòlliu de cartas e billetes", + "sl" to "Denarnica kartic", + "sq" to "Kuletë Fjalëkalimesh", + "sr" to "Новчаник лозинки", + "sv" to "Passplånbok", + "ta" to "பணப்பையை கடந்து செல்லுங்கள்", + "tr" to "Şifre Cüzdanı", + "ug" to "ئىم ھەميانى", + "uk" to "Гаманець Pass", + "vi" to "Ví giấy tờ", + "zh-CN" to "卡包", + "zh-TW" to "票證錢包", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Password & 2FA", + name = + mapOf( + "ar" to "كلمات السر والاستيثاق الثنائي", + "ba" to "Пароль һәм 2FA", + "bg" to "Парола и двустепенно удостоверяване", + "ca" to "Paraules de pas i autenticació de dos factors", + "cs" to "Heslo a 2FA", + "da" to "Adgangskode og 2FA", + "de" to "Passwort / 2FA", + "el" to "Κωδικοί Πρόσβασης & 2FA", + "en-GB" to "Password & 2FA", + "en-US" to "Password & 2FA", + "eo" to "Pasvort-administriloj kaj dupaŝaj aŭtentigiloj", + "es" to "Contraseñas y segundo factor de autenticación", + "et" to "Salasõnad ja 2FA", + "fa" to "گذرواژه و دوعاملی", + "fi" to "Salasana ja kaksivaiheinen todennus", + "fr" to "Mot de passe & A2F", + "ga" to "Pasfhocal agus 2FA", + "he" to "סיסמה ואימות דו־שלבי", + "hr" to "Lozinka i dvofaktorska autentifikacija", + "hu" to "Jelszavak és 2FA", + "id" to "Kata Sandi & 2FA", + "is" to "Lykilorð og 2FA", + "it" to "Password & Autenticazione a 2 Fattori", + "ja" to "パスワード&2要素認証", + "kn" to "ಪಾಸ್ವರ್ಡ್", + "ko" to "비밀번호 및 2단계 인증", + "lt" to "Slaptažodžiai ir 2 fakt. autentif.", + "lv" to "Paroles un divpakāpju autentificēšana", + "my" to "စကားဝှက်နှင့် အဆင့်ဆင့်လုံခြုံရေး", + "nb" to "Passord & 2FA", + "nl" to "Wachtwoorden & 2FA", + "nl-BE" to "Wachtwoord en 2FA", + "pl" to "Hasło i uwierzytelnianie dwuskładnikowe (2FA)", + "pt" to "Palavras-passe e dois fatores", + "pt-BR" to "Senhas e dois fatores", + "pt-PT" to "Palavras-passe e dois fatores", + "ro" to "Parole & 2FA", + "ru" to "Пароли и авторизация", + "sc" to "Crae de intrada e autenticatzione a duos fatores", + "sl" to "Gesla in dvostopenjsko preverjanje pristnosti", + "sq" to "Fjalëkalime & 2FA", + "sr" to "Лозинке и двострука пријава", + "sv" to "Lösenord och 2FA", + "ta" to "கடவுச்சொல் & 2FA", + "tr" to "Şifre & 2FA", + "ug" to "ئىم ۋە ئىككى ئامىللىق دەلىللەش", + "uk" to "Пароль і двофакторна автентифікація", + "vi" to "Mật khẩu & 2FA", + "zh-CN" to "密码和双因素认证", + "zh-TW" to "密碼與兩步驟驗證", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Phone & SMS", + name = + mapOf( + "af" to "Telefoon & SMS", + "ar" to "الهاتف و الرسائل القصيرة", + "ast" to "Telefonía y SMS", + "ba" to "Телефон һәм SMS", + "be" to "Тэлефон і SMS", + "bg" to "Телефон и съобщения", + "bn" to "ফোন ও এসএমএস", + "bn-BD" to "ফোন ও এসএমএস", + "bo" to "ཁ་པར་དང་འཕྲིན་ཐུང་།", + "br" to "Pellgomz hag SMS", + "ca" to "Mòbil i missatgeria", + "ckb" to "تەلەفۆن و کورتەنامە", + "cs" to "Telefon a SMS", + "cy" to "Ffôn ac SMS", + "da" to "Telefon & SMS", + "de" to "Telefon / SMS", + "el" to "Τηλέφωνο & SMS", + "en-GB" to "Phone & SMS", + "en-US" to "Phone & SMS", + "eo" to "Telefonado kaj SMS", + "es" to "Llamadas de teléfono y SMS", + "es-AR" to "Teléfono y SMS", + "es-MX" to "Teléfono & SMS", + "et" to "Telefon & SMS", + "eu" to "Telefonoa eta SMS", + "fa" to "تلفن و پیامک", + "fi" to "Puhelin ja tekstiviestit", + "fil" to "Tawag & Text", + "fr" to "Téléphone et SMS", + "fy" to "Telefoan & SMS", + "ga" to "Fón & SMS", + "gd" to "Fòn ⁊ SMS", + "gl" to "Teléfono móbil e SMS", + "he" to "טלפון ומסרונים", + "hi" to "फ़ोन तथा SMS", + "hr" to "Mobitel i SMS", + "hu" to "Telefon és SMS", + "hy" to "Հեռախոս և կարճ հաղորդագրություն", + "id" to "Telepon & SMS", + "is" to "Símar og SMS", + "it" to "Telefono e SMS", + "ja" to "電話とSMS", + "kab" to "Tiliɣri d SMS", + "kmr" to "Telefon & SMS", + "kn" to "ಫೋನ್ ಮತ್ತು SMS", + "ko" to "전화 및 문자", + "lb" to "Telefon & SMS", + "lt" to "Telefonas ir SMS", + "lv" to "Tālrunis un īsziņas", + "mk" to "Телефон и СМС", + "ml" to "ഫോണും എസ എം എസും", + "mn" to "Утас ба SMS", + "mr" to "फोन आणि एस एम", + "my" to "ဖုန်းနှင့်စာတို", + "nb" to "Telefon og SMS", + "ne" to "फोन र एसएमएस", + "nl" to "Telefoon & SMS", + "nl-BE" to "Telefoon & SMS", + "nn" to "Telefon og SMS", + "pa" to "ਫ਼ੋਨ ਤੇ SMS", + "pl" to "Telefon i SMS", + "ps" to "لرغږون او استوزې", + "pt" to "Telefone e SMS", + "pt-BR" to "Telefone & SMS", + "pt-PT" to "Telefone e SMS", + "ro" to "Telefon & SMS", + "ru" to "Телефон и SMS", + "sc" to "Telèfono & SMS", + "sk" to "Telefón a SMS", + "sl" to "Telefon & SMS", + "sn" to "Nhare neTsamba pfupi", + "so" to "Taleefanka &", + "sq" to "Telefon & SMS", + "sr" to "Телефон и SMS", + "sv" to "Telefon & SMS", + "sw" to "Simu na Huduma ya Ujumbe Fupi", + "ta" to "தொலைபேசி & குறுஞ்செய்தி", + "te" to "ఫోన్ & ఎస్ఎంఎస్", + "th" to "โทรศัพท์และ SMS", + "tr" to "Telefon ve SMS", + "ug" to "فون & قىسقا ئۇچۇر", + "uk" to "Телефон і SMS", + "ur" to "پھون اور ایس ایم ایس", + "vi" to "Gọi điện & SMS", + "yue" to "電話同短訊", + "zh-CN" to "通话与短信", + "zh-HK" to "通話與短訊", + "zh-TW" to "通話與簡訊", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Podcast", + name = + mapOf( + "ar" to "بودكاست", + "bg" to "Подкасти", + "br" to "Podskign", + "ca" to "Podcast", + "cs" to "Podcast", + "da" to "Podcast", + "de" to "Podcast", + "el" to "Podcast", + "en-GB" to "Podcast", + "en-US" to "Podcast", + "eo" to "Ludiloj de aboneblaj sondosieroj (podkastoj)", + "es" to "Pódcast", + "et" to "Taskuhääling", + "fa" to "پادپخش", + "fi" to "Podcast", + "fr" to "Podcast", + "ga" to "Podchraoladh", + "he" to "הסכת", + "hr" to "Podcast", + "hu" to "Podcast", + "id" to "Siniar", + "is" to "Hlaðvarp", + "it" to "Podcast", + "ja" to "ポッドキャスト", + "kn" to "ಪಾಡ್ಕ್ಯಾಸ್ಟ್", + "ko" to "팟캐스트", + "lb" to "Podcast", + "lt" to "Tinklalaidė", + "lv" to "Raidieraksts", + "my" to "အသံလွှင့်မှု", + "nb" to "Podcast", + "nl" to "Podcast", + "nl-BE" to "Podcast", + "pl" to "Podcast", + "pt" to "Podcast", + "pt-BR" to "Podcast", + "pt-PT" to "Podcast", + "ro" to "Podcast", + "ru" to "Подкасты", + "sc" to "Podcast", + "sl" to "Podkast", + "sq" to "Podkast", + "sr" to "Довод", + "sv" to "Pod", + "sw" to "Podikasti", + "ta" to "போட்காச்ட்", + "tr" to "Podcast", + "ug" to "تارقاتقۇ", + "uk" to "Подкаст", + "vi" to "Podcast", + "zh-CN" to "播客", + "zh-TW" to "播客", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Public Transport", + name = + mapOf( + "ar" to "خريطة ومواعيد النقل العام", + "bg" to "Обществен транспорт", + "ca" to "Mapa de transport públic i horaris", + "cs" to "Veřejná doprava", + "da" to "Offentlig transport", + "de" to "Öffentlicher Verkehr / Netz- und Fahrpläne", + "el" to "Δημόσια Συγκοινωνία", + "en-GB" to "Public Transport", + "en-US" to "Public Transport", + "eo" to "Publika transporto", + "es" to "Transporte público", + "et" to "Ühistransport ja sõiduplaanid", + "fa" to "حمل‌ونقل عمومی", + "fi" to "Joukkoliikenteen kartta ja aikataulu", + "fr" to "Transports en commun", + "ga" to "Léarscáil & Amchlár Iompair Phoiblí", + "he" to "מפה ולו״ז תחבורה ציבורית", + "hr" to "Javni prijevoz", + "hu" to "Tömegközlekedés", + "id" to "Peta & Jadwal Transportasi Umum", + "is" to "Almenningssamgöngur", + "it" to "Trasporti Pubblici", + "ja" to "公共交通機関の地図&時刻表", + "kn" to "ಸಾರ್ವಜನಿಕ ಸಾರಿಗೆ", + "ko" to "대중교통 지도 및 시간표", + "lb" to "Ëffentlechen Transport", + "lt" to "Vieš. transp. žemėlapis ir tvarkaraštis", + "lv" to "Sabiedriskais transports", + "my" to "အများသုံး သယ်ယူပို့ဆောင်ရေး", + "nb" to "Offentlig transport", + "nl" to "Openbaar vervoer", + "nl-BE" to "Openbaar vervoer", + "pl" to "Mapa transportu publicznego i rozkład jazdy", + "pt" to "Mapa de transporte público e horários", + "pt-BR" to "Mapa de transporte público e horários", + "pt-PT" to "Mapa de transporte público e horários", + "ro" to "Transport public & Orar", + "ru" to "Транспорт и расписания", + "sc" to "Oràrios e mapas de sos trasportos pùblicos", + "sl" to "Javni prevoz", + "sq" to "Transport Publik", + "sr" to "Карта и ред вожње јавног превоза", + "sv" to "Kollektivtrafik", + "sw" to "Usafiri wa Umma", + "ta" to "பொது போக்குவரத்து வரைபடம் & கால அட்டவணை", + "tr" to "Toplu Taşıma Haritası ve Zaman Çizelgesi", + "ug" to "ئاممىۋى قاتناش خەرىتىسى ۋە ۋاقىت جەدۋىلى", + "uk" to "Карта та розклад руху громадського транспорту", + "vi" to "Phương tiện giao thông", + "zh-CN" to "公共交通地图和时间表", + "zh-TW" to "大眾運輸", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Reading", + name = + mapOf( + "af" to "Lees", + "ar" to "القراءة", + "ast" to "Llectura", + "ba" to "Уҡыу", + "be" to "Чытанне", + "ber" to "ⵜⵉⵖⵓⵔⵉ", + "bg" to "Четене", + "bn" to "পড়া", + "bn-BD" to "পড়া", + "bo" to "ཀློག་བཞིན་པ།", + "br" to "Lenn", + "ca" to "Lectura", + "ckb" to "خوێندنەوە", + "cs" to "Čtení", + "cy" to "Darllen", + "da" to "Læsning", + "de" to "Lesen", + "el" to "Ανάγνωση", + "en-GB" to "Reading", + "en-US" to "Reading", + "eo" to "Legado", + "es" to "Lectura", + "es-AR" to "Lectura", + "es-MX" to "Leyendo", + "et" to "Lugemine", + "eu" to "Irakurketa", + "fa" to "خواندن", + "fi" to "Lukeminen", + "fil" to "Pagbabasa", + "fr" to "Lecture", + "fy" to "Lêze", + "ga" to "Léamh", + "gd" to "Leughadh", + "gl" to "Lectura", + "he" to "קריאה", + "hi" to "पठन", + "hr" to "Čitanje", + "hu" to "Olvasás", + "hy" to "Ընթերցում", + "id" to "Membaca", + "is" to "Lestur", + "it" to "Lettura", + "ja" to "読書", + "kab" to "Taɣuṛi", + "kmr" to "Xwendin", + "kn" to "ಓದುವಿಕೆ", + "ko" to "독서", + "lb" to "Liesen", + "lt" to "Skaitymas", + "lv" to "Lasīšana", + "mk" to "Читање", + "ml" to "Reading", + "mn" to "Унших", + "mr" to "वाचन", + "my" to "ဖတ်ရှုခြင်း", + "nb" to "Lesing", + "ne" to "पढ्दै", + "nl" to "Lezen", + "nl-BE" to "Lezen", + "nn" to "Lesing", + "pa" to "ਪੜ੍ਹਨ", + "pl" to "Czytanie", + "ps" to "لوستنه", + "pt" to "Leitura", + "pt-BR" to "Leitura", + "pt-PT" to "Leitura", + "ro" to "Citit", + "ru" to "Чтение", + "sc" to "Letura", + "sk" to "Čítanie", + "sl" to "Branje", + "sn" to "Kuverenga", + "so" to "Akhriska", + "sq" to "Lexim", + "sr" to "Читање", + "sv" to "Läsning", + "sw" to "Kusoma", + "ta" to "படித்தல்", + "te" to "చదవటం", + "th" to "การอ่าน", + "tr" to "Okuma", + "tzm" to "tiɣuri", + "ug" to "ئوقۇشلۇق", + "uk" to "Читання", + "ur" to "پڈھنا", + "vi" to "Đọc", + "yue" to "開卷", + "zh-CN" to "阅读", + "zh-HK" to "閱讀", + "zh-TW" to "閱讀", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Recipe Manager", + name = + mapOf( + "ar" to "مدير الوصفات", + "bg" to "Управление на рецепти", + "ca" to "Gestor de receptes", + "cs" to "Správce receptů", + "de" to "Rezeptmanager", + "el" to "Διαχείριση συνταγών", + "en-GB" to "Recipe Manager", + "en-US" to "Recipe Manager", + "eo" to "Administriloj de kuir-receptoj", + "es" to "Recetas de cocina", + "et" to "Retseptihaldus", + "fa" to "مدیر دستور پخت", + "fi" to "Reseptien hallinta", + "fr" to "Gestionnaire de recettes", + "ga" to "Bainisteoir Oidis", + "he" to "ניהול מתכונים", + "hr" to "Upravljač receptima", + "hu" to "Receptkezelő", + "id" to "Pengelola Resep", + "is" to "Uppskriftasafn", + "it" to "Gestore Ricette", + "ja" to "レシピマネージャー", + "kn" to "ರೆಸಿಪಿ ಮ್ಯಾನೇಜರ್", + "ko" to "레시피 관리자", + "lt" to "Receptų tvarkyklė", + "lv" to "Recepšu pārvaldnieks", + "my" to "ဟင်းချက်နည်းစီမံခန့်ခွဲမှုစနစ်", + "nb" to "Oppskrifter", + "nl" to "Receptenboek", + "nl-BE" to "Receptenbeheerder", + "pl" to "Menedżer przepisów", + "pt" to "Gestor de receitas", + "pt-BR" to "Gerenciador de receitas", + "pt-PT" to "Gestor de receitas", + "ro" to "Manager rețete", + "ru" to "Рецепты", + "sc" to "Manigiadore de retzetas", + "sl" to "Upravitelj receptov", + "sq" to "Përgjegjës Recetash Gatimi", + "sr" to "Управник упутства", + "sv" to "Recepthanterare", + "ta" to "செய்முறை மேலாளர்", + "tr" to "Tarif Yöneticisi", + "ug" to "رىسالە باشقۇرغۇچ", + "uk" to "Менеджер рецептів", + "vi" to "Quản lý công thức", + "zh-CN" to "菜谱管理工具", + "zh-TW" to "食譜管理", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Religion", + name = + mapOf( + "ar" to "دين", + "bg" to "Религия", + "ca" to "Religió", + "cs" to "Náboženství", + "de" to "Religion", + "el" to "Θρησκεία", + "en-GB" to "Religion", + "en-US" to "Religion", + "eo" to "Religio", + "es" to "Religión", + "et" to "Usk ja religioon", + "fa" to "مذهبی", + "fr" to "Religion", + "ga" to "Reiligiún", + "he" to "דת", + "hr" to "Vjera", + "hu" to "Vallás", + "id" to "Agama", + "is" to "Trúarbrögð", + "ja" to "宗教", + "kn" to "ಧರ್ಮ", + "ko" to "종교", + "lv" to "Ticība", + "my" to "ဘာသာရေး", + "nb" to "Religion", + "nl" to "Godsdienst", + "nl-BE" to "Religie", + "pl" to "Religia", + "pt-BR" to "Religião", + "ro" to "Religie", + "ru" to "Религия", + "sl" to "Vera", + "sq" to "Fe", + "sv" to "Religion", + "sw" to "Dini", + "tr" to "Din", + "uk" to "Релігія", + "vi" to "Tôn giáo", + "zh-CN" to "宗教", + "zh-TW" to "宗教", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Science & Education", + name = + mapOf( + "af" to "Wetenskap en onderwys", + "ar" to "العلوم و التعليم", + "ast" to "Ciencia y educación", + "ba" to "Фән һәм Мәғариф", + "be" to "Навука і адукацыя", + "ber" to "ⵜⴰⵎⴰⵙⵙⴰⵏⵜ ⴷ ⵓⵙⴳⵎⵉ", + "bg" to "Наука и образование", + "bn" to "বিজ্ঞান ও শিক্ষা", + "bn-BD" to "বিজ্ঞান ও শিক্ষা", + "bo" to "ཚན་རིག་དང་ཤེས་ཡོན།", + "br" to "Skiantoù ha deskadurezh", + "ca" to "Ciència i educació", + "ckb" to "زانست و فێرکردن", + "cs" to "Věda a vzdělání", + "cy" to "Gwyddoniaeth ac Addysg", + "da" to "Videnskab & Uddannelse", + "de" to "Wissenschaft / Bildung", + "el" to "Επιστήμη & Εκπαίδευση", + "en-GB" to "Science & Education", + "en-US" to "Science & Education", + "eo" to "Scienco kaj edukado", + "es" to "Ciencia y Educación", + "es-AR" to "Ciencias y Educación", + "es-MX" to "Ciencia y Educación", + "et" to "Teadus & haridus", + "eu" to "Zientzia eta hezkuntza", + "fa" to "علم و آموزش", + "fi" to "Tiede ja koulutus", + "fil" to "Agham & Edukasyon", + "fr" to "Science et éducation", + "fy" to "Wittenskip & Edukaasje", + "ga" to "Eolaíocht & Oideachas", + "gd" to "Saidheans ⁊ foghlam", + "gl" to "Ciencia e educación", + "he" to "מדע וחינוך", + "hi" to "विज्ञान और शिक्षा", + "hr" to "Znanost i obrazovanje", + "hu" to "Tudomány és oktatás", + "hy" to "Կրթություն և գիտություն", + "id" to "Sains & Edukasi", + "is" to "Menntun og vísindi", + "it" to "Scienza ed educazione", + "ja" to "科学と教育", + "kab" to "Tussna & Usegmi", + "kmr" to "Zanist & perwerde", + "kn" to "ವಿಜ್ಞಾನ ಮತ್ತು ಶಿಕ್ಷಣ", + "ko" to "과학 및 교육", + "lb" to "Wëssenschaft & Bildung", + "lt" to "Mokslas ir švietimas", + "lv" to "Zinātne un izglītība", + "mk" to "Наука и Образование", + "ml" to "ശാസ്ത്രവും വിദ്യാഭ്യാസവും", + "mn" to "Шинжлэх ухаан ба боловсрол", + "mr" to "विज्ञान आणि शिक्षण", + "my" to "သိပ္ပံနှင့်ပညာရေး", + "nb" to "Vitenskap & utdanning", + "ne" to "विज्ञान र शिक्षा", + "nl" to "Wetenschap & onderwijs", + "nl-BE" to "Onderwijs & wetenschap", + "nn" to "Vitskap og utdanning", + "pa" to "ਵਿਗਿਆਨ ਤੇ ਸਿੱਖਿਆ", + "pl" to "Nauka i edukacja", + "ps" to "پوهه او زده کړه", + "pt" to "Ciência e educação", + "pt-BR" to "Ciência & Educação", + "pt-PT" to "Ciência e educação", + "ro" to "Știință & educație", + "ru" to "Наука и образование", + "sc" to "Iscièntzia e educatzione", + "sk" to "Veda a výuka", + "sl" to "Znanost & Izobrazba", + "sn" to "zveScience neFundo", + "so" to "Sayniska & Waxbarashada", + "sq" to "Shkencë & Arsim", + "sr" to "Наука и образовање", + "sv" to "Vetenskap & Utbildning", + "sw" to "Sayansi na Elimu", + "ta" to "அறிவியலும் கல்வியும்", + "te" to "విజ్ఞానం & విద్య", + "th" to "วิทยาศาสตร์และการศึกษา", + "tr" to "Bilim ve Eğitim", + "tzm" to "Tamassant d usegmi", + "ug" to "پەن & مائارىپ", + "uk" to "Освіта й наука", + "ur" to "سائنس اور تعلیم", + "vi" to "Khoa học & Giáo dục", + "yue" to "科學與教育", + "zh-CN" to "科学与教育", + "zh-HK" to "科學與教育", + "zh-TW" to "科學與教育", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Security", + name = + mapOf( + "af" to "Sekuriteit", + "ar" to "الأمان", + "ast" to "Seguranza", + "ba" to "Хәүефһеҙлек", + "be" to "Бяспека", + "ber" to "ⵙⵙⵍⴰⵎⵜ", + "bg" to "Сигурност", + "bn" to "নিরাপত্তা", + "bn-BD" to "নিরাপত্তা", + "bo" to "སྲུང་སྐྱོབ།", + "br" to "Diogelroez", + "ca" to "Seguretat", + "ckb" to "پاراستن", + "cs" to "Zabezpečení", + "cy" to "Diogelwch", + "da" to "Sikkerhed", + "de" to "Sicherheit", + "el" to "Ασφάλεια", + "en-GB" to "Security", + "en-US" to "Security", + "eo" to "Sekureco", + "es" to "Seguridad", + "es-AR" to "Seguridad", + "es-MX" to "Seguridad", + "et" to "Turvalisus", + "eu" to "Segurtasuna", + "fa" to "امنیت", + "fi" to "Tietoturva", + "fil" to "Seguridad", + "fr" to "Sécurité", + "fy" to "Befeiliging", + "ga" to "Slándáil", + "gd" to "Tèarainteachd", + "gl" to "Seguranza", + "he" to "אבטחה", + "hi" to "सुरक्षा", + "hr" to "Sigurnost", + "hu" to "Biztonság", + "hy" to "Անվտանգություն", + "id" to "Keamanan", + "is" to "Öryggi", + "it" to "Sicurezza", + "ja" to "セキュリティ", + "kab" to "Taɣellist", + "kmr" to "Ewlehî", + "kn" to "ಭದ್ರತೆ", + "ko" to "보안", + "lb" to "Sécherheet", + "lt" to "Saugumas", + "lv" to "Drošība", + "mk" to "Безбедност", + "ml" to "സുരക്ഷാ സംബന്ധം", + "mn" to "Аюулгүй байдал", + "mr" to "सुरक्षा", + "my" to "လုံခြံရေး", + "nb" to "Sikkerhet", + "ne" to "सुरक्षा", + "nl" to "Beveiliging", + "nl-BE" to "Beveiliging", + "nn" to "Tryggleik", + "pa" to "ਸੁਰੱਖਿਆ", + "pl" to "Bezpieczeństwo", + "ps" to "خونديينه", + "pt" to "Segurança", + "pt-BR" to "Segurança", + "pt-PT" to "Segurança", + "ro" to "Securitate", + "ru" to "Безопасность", + "sc" to "Seguràntzia", + "sk" to "Bezpečnosť", + "sl" to "Varnost", + "sn" to "Zvekukwdekwera", + "so" to "Amniga", + "sq" to "Siguri", + "sr" to "Безбедност", + "sv" to "Säkerhet", + "sw" to "Usalama", + "ta" to "பாதுகாப்பு", + "te" to "రక్షణ", + "th" to "ความมั่นคง", + "tr" to "Güvenlik", + "ug" to "بىخەتەرلىك", + "uk" to "Безпека", + "ur" to "سیکوریٹی", + "vi" to "Bảo mật", + "yue" to "保密", + "zh-CN" to "安全", + "zh-HK" to "安全與保安", + "zh-TW" to "安全性", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Shopping List", + name = + mapOf( + "ar" to "قائمة التسوق", + "bg" to "Списък за пазаруване", + "ca" to "Llista de la compra", + "cs" to "Nákupní seznam", + "da" to "Indkøbsliste", + "de" to "Einkaufsliste", + "el" to "Λίστες για ψώνια", + "en-GB" to "Shopping List", + "en-US" to "Shopping List", + "eo" to "Listoj de aĉetoj", + "es" to "Lista de la compra", + "et" to "Ostunimekirjad", + "fa" to "سیاههٔ خرید", + "fi" to "Ostoslista", + "fr" to "Liste de courses", + "ga" to "Liosta Siopadóireachta", + "he" to "רשימת קניות", + "hr" to "Popis za kupovinu", + "hu" to "Bevásárlólista", + "id" to "Daftar Belanja", + "is" to "Innkaupalisti", + "it" to "Lista della spesa", + "ja" to "買い物リスト", + "kn" to "ಶಾಪಿಂಗ್ ಪಟ್ಟಿ", + "ko" to "쇼핑 목록", + "lt" to "Pirkinių sąrašas", + "lv" to "Iepirkumu saraksts", + "my" to "ဈေးဝယ်စာရင်း", + "nb" to "Handleliste", + "nl" to "Boodschappenlijst", + "nl-BE" to "Boodschappenlijst", + "pl" to "Lista zakupów", + "pt" to "Lista de compras", + "pt-BR" to "Lista de compra", + "pt-PT" to "Lista de compras", + "ro" to "Listă cumpărături", + "ru" to "Список покупок", + "sc" to "Lista de còmporas", + "sl" to "Nakupovalni seznam", + "sq" to "Listë Blerjesh", + "sr" to "Списак за куповину", + "sv" to "Inköpslista", + "sw" to "Orodha ya Manunuzi", + "ta" to "சாப்பிங் பட்டியல்", + "tr" to "Alışveriş Listesi", + "ug" to "مال سېتىۋېلىش تىزىمى", + "uk" to "Список покупок", + "vi" to "Danh sách mua sắm", + "zh-CN" to "购物清单", + "zh-TW" to "購物清單", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Social Network", + name = + mapOf( + "ar" to "شبكة اجتماعية", + "ba" to "Социаль селтәр", + "bg" to "Социална мрежа", + "ca" to "Xarxes socials", + "cs" to "Sociální síť", + "de" to "Soziales Netzwerk", + "el" to "Μέσα κοινωνικής δικτύωσης", + "en-GB" to "Social Network", + "en-US" to "Social Network", + "eo" to "Sociaj komunikiloj", + "es" to "Redes sociales", + "et" to "Sotsiaalvõrgustik", + "fa" to "شبکهٔ اجتماعی", + "fi" to "Sosiaalinen verkosto", + "fr" to "Réseau social", + "ga" to "Líonra Sóisialta", + "he" to "רשתות חברתיות", + "hr" to "Dreuštvena mreža", + "hu" to "Közösségi hálózat", + "id" to "Jaringan Sosial", + "is" to "Samfélagsnet", + "it" to "Social Network", + "ja" to "ソーシャルネットワーク", + "kn" to "ಸಾಮಾಜಿಕ ನೆಟ್ವರ್ಕ್", + "ko" to "소셜 네트워크", + "lt" to "Socialinis tinklas", + "lv" to "Sabiedriskais tīkls", + "my" to "လှုမှုကွန်ယက်", + "nb" to "Sosialt nettverk", + "nl" to "Sociaal netwerk", + "nl-BE" to "Sociaalnetwerk", + "pl" to "Sieć społecznościowa", + "pt" to "Rede social", + "pt-BR" to "Redes sociais", + "pt-PT" to "Rede social", + "ro" to "Rețea socială", + "ru" to "Соцсети", + "sc" to "Retes sotziales", + "sl" to "Družabna omrežja", + "sq" to "Rrjet Shoqëror", + "sr" to "Друштвена мрежа", + "sv" to "Socialt nätverk", + "ta" to "சமூக வலைப்பின்னல்", + "tr" to "Sosyal Ağ", + "ug" to "ئىجتىمائىي تور", + "uk" to "Соціальна мережа", + "vi" to "Mạng xã hội", + "zh-CN" to "社交网络", + "zh-TW" to "社群網路", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Sports & Health", + name = + mapOf( + "af" to "Sport en gesondheid", + "ar" to "الرياضة و الصحة", + "ast" to "Deporte y salú", + "ba" to "Спорт һәм Һаулыҡ", + "be" to "Спорт і здароўе", + "bg" to "Спорт и здраве", + "bn" to "খেলাধুলা ও স্বাস্থ্য", + "bn-BD" to "খেলাধুলা ও স্বাস্থ্য", + "bo" to "རྩེད་རིགས་དང་འཕྲོད་བསྟེན།", + "br" to "Sportoù ha yec'hed", + "ca" to "Esports i Salut", + "ckb" to "تەندرووستی و وەرزش", + "cs" to "Sport a zdraví", + "cy" to "Chwaraeon a Iechyd", + "da" to "Sport & Sundhed", + "de" to "Sport / Gesundheit", + "el" to "Αθλητισμός & Υγεία", + "en-GB" to "Sports & Health", + "en-US" to "Sports & Health", + "eo" to "Sporto kaj sano", + "es" to "Deportes y Salud", + "es-AR" to "Deportes y Salud", + "es-MX" to "Deportes & Salud", + "et" to "Sport & tervis", + "eu" to "Kirola eta osasuna", + "fa" to "ورزش و سلامت", + "fi" to "Urheilu ja terveys", + "fil" to "Palakasan & Kalusugan", + "fr" to "Sport et santé", + "fy" to "Sport & Sûnens", + "ga" to "Spóirt & Sláinte", + "gd" to "Spòrs ⁊ slàinte", + "gl" to "Deportes e saúde", + "he" to "בריאות וספורט", + "hi" to "खेल-कूद एवं स्वास्थ्य", + "hr" to "Sport i zdravlje", + "hu" to "Sport és egészség", + "hy" to "Սպորտ և առողջություն", + "id" to "Olahraga & Kesehatan", + "is" to "Íþróttir og heilsa", + "it" to "Sport e salute", + "ja" to "運動と健康", + "kab" to "Addal & Tazmert", + "kmr" to "Werzişî & tenduristî", + "kn" to "ಕ್ರೀಡೆ ಮತ್ತು ಆರೋಗ್ಯ", + "ko" to "스포츠 및 건강", + "lb" to "Sport & Gesondheet", + "lt" to "Sportas ir sveikata", + "lv" to "Sports un veselība", + "mk" to "Спорт и Здравје", + "ml" to "കായികവും ആരോഗ്യവും", + "mn" to "Спорт ба эрүүл мэнд", + "mr" to "खेळ आणि", + "my" to "အားကစားနှင့်ကျန်းမာရေး", + "nb" to "Idrett og helse", + "nl" to "Sport & gezondheid", + "nl-BE" to "Sport & Gezondheid", + "nn" to "Idrett og helse", + "pa" to "ਖੇਡਾਂ ਅਤੇ ਸਿਹਤ", + "pl" to "Sport i zdrowie", + "ps" to "کړاو او روغتيا", + "pt" to "Desporto e saúde", + "pt-BR" to "Esportes & Saúde", + "pt-PT" to "Desporto e saúde", + "ro" to "Sport & sănătate", + "ru" to "Спорт и здоровье", + "sc" to "Isport e Salude", + "sk" to "Šport & Zdravie", + "sl" to "Šport & zdravje", + "sn" to "Nhabvu neUtano", + "so" to "Ciyaaraha & Caafimaadka", + "sq" to "Sporte & Shëndet", + "sr" to "Спорт и здравље", + "sv" to "Sport & Hälsa", + "sw" to "Michezo na Afya", + "ta" to "விளையாட்டும் உடல்நலமும்", + "te" to "క్రీడలు & ఆరోగ్యం", + "th" to "กีฬาและสุขภาพ", + "tr" to "Spor ve Sağlık", + "ug" to "تەنتەربىيە & ساغلاملىق", + "uk" to "Спорт і здоров'я", + "ur" to "کھیل اور صحت", + "vi" to "Thể thao & sức khoẻ", + "yue" to "運動與健康", + "zh-CN" to "运动与健康", + "zh-HK" to "體育與健康", + "zh-TW" to "運動與健康", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "System", + name = + mapOf( + "af" to "Stelsel", + "ar" to "النظام", + "ast" to "Sistema", + "ba" to "Система", + "be" to "Сістэма", + "bg" to "Системни", + "bn" to "ব্যবস্থা", + "bn-BD" to "ব্যবস্থা", + "bo" to "མ་ལག", + "br" to "Reizhiad", + "ca" to "Sistema", + "ckb" to "سیستەم", + "cs" to "Systém", + "cy" to "System", + "da" to "System", + "de" to "System", + "el" to "Σύστημα", + "en-GB" to "System", + "en-US" to "System", + "eo" to "Operaciumaj iloj", + "es" to "Sistema", + "es-AR" to "Sistema", + "es-MX" to "Sistema", + "et" to "Süsteem", + "eu" to "Sistema", + "fa" to "سامانه", + "fi" to "Järjestelmä", + "fil" to "Sistema", + "fr" to "Système", + "fy" to "Systeem", + "ga" to "Córas", + "gd" to "An siostam", + "gl" to "Sistema", + "he" to "מערכת", + "hi" to "सिस्टम", + "hr" to "Sustav", + "hu" to "Rendszer", + "hy" to "Համակարգ", + "id" to "Sistem", + "is" to "Kerfið", + "it" to "Sistema", + "ja" to "システム", + "kab" to "Anagraw", + "kmr" to "Pergal", + "kn" to "ಸಿಸ್ಟಮ್", + "ko" to "시스템", + "lb" to "System", + "lt" to "Sistema", + "lv" to "Sistēma", + "mk" to "Систем", + "ml" to "ഉപകരണ സംബന്ധം", + "mn" to "Систем", + "mr" to "यंत्रणा", + "my" to "စနစ်", + "nb" to "System", + "nl" to "Systeem", + "nl-BE" to "Systeem", + "nn" to "System", + "pa" to "ਸਿਸਟਮ", + "pl" to "System", + "ps" to "غونډال", + "pt" to "Sistema", + "pt-BR" to "Sistema", + "pt-PT" to "Sistema", + "ro" to "Sistem", + "ru" to "Системные", + "sc" to "Sistema", + "sk" to "Systém", + "sl" to "Sistem", + "sn" to "Sistemu", + "so" to "Aalada", + "sq" to "Sistem", + "sr" to "Систем", + "sv" to "System", + "sw" to "Mfumo", + "ta" to "அமைப்பு", + "te" to "వ్యవస్థ", + "th" to "เครื่องมือระบบ", + "tr" to "Sistem", + "tzm" to "Anegraw", + "ug" to "سىستېما", + "uk" to "Система", + "ur" to "نظام", + "vi" to "Hệ thống", + "yue" to "系統", + "zh-CN" to "系统", + "zh-HK" to "系統", + "zh-TW" to "系統", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Task", + name = + mapOf( + "ar" to "مهمة", + "bg" to "Задача", + "ca" to "Tasques", + "cs" to "Úkol", + "da" to "Opgave", + "de" to "Aufgaben", + "el" to "Εργασία", + "en-GB" to "Task", + "en-US" to "Task", + "eo" to "Planiloj", + "es" to "Tareas", + "et" to "Ülesanded", + "fa" to "کارها", + "fi" to "Tehtävä", + "fr" to "Tâche", + "ga" to "Tasc", + "he" to "משימות", + "hr" to "Zadatak", + "hu" to "Feladat", + "id" to "Tugas", + "is" to "Verkefni", + "it" to "Task", + "ja" to "タスク", + "kn" to "ಕಾರ್ಯ", + "ko" to "작업", + "lt" to "Užduotis", + "lv" to "Uzdevums", + "my" to "အလုပ်", + "nb" to "Oppgaver", + "nl" to "Taken", + "nl-BE" to "Taak", + "pl" to "Zadanie", + "pt" to "Tarefa", + "pt-BR" to "Tarefa", + "pt-PT" to "Tarefa", + "ro" to "Activitate", + "ru" to "Задачи", + "sc" to "Faina", + "sl" to "Opravila", + "sq" to "Punë", + "sr" to "Задатак", + "sv" to "Uppgift", + "sw" to "Kazi", + "ta" to "பணி", + "tr" to "Görev", + "ug" to "ۋەزىپە", + "uk" to "Завдання", + "vi" to "Công việc", + "zh-CN" to "任务", + "zh-TW" to "任務", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Text Editor", + name = + mapOf( + "ar" to "محرِّر نصوص", + "bg" to "Текстов редактор", + "ca" to "Editor de text", + "cs" to "Textový editor", + "da" to "Tekstredigering", + "de" to "Texteditor", + "el" to "Επεξεργαστής Κειμένου", + "en-GB" to "Text Editor", + "en-US" to "Text Editor", + "eo" to "Tekst-redaktiloj", + "es" to "Editor de textos", + "et" to "Tekstitoimetid", + "fa" to "ویرایشگر متن", + "fi" to "Tekstimuokkain", + "fr" to "Éditeur de texte", + "ga" to "Eagarthóir Téacs", + "he" to "עריכת טקסט", + "hr" to "Uređivač teksta", + "hu" to "Szövegszerkesztő", + "id" to "Penyunting Teks", + "is" to "Textaritill", + "it" to "Editor di Testo", + "ja" to "テキストエディタ", + "kn" to "ಪಠ್ಯ ಸಂಪಾದಕ", + "ko" to "텍스트 편집기", + "lt" to "Tekstų redaktorius", + "lv" to "Teksta redaktors", + "my" to "စာသား ပြင်ဆင်ရန်", + "nb" to "Tekstredigering", + "nl" to "Tekstverwerker", + "nl-BE" to "Teksteditor", + "pl" to "Edytor tekstu", + "pt" to "Editor de textos", + "pt-BR" to "Editor de texto", + "pt-PT" to "Editor de textos", + "ro" to "Editor text", + "ru" to "Текстовые редакторы", + "sc" to "Editore de testu", + "sl" to "Urejevalnik besedila", + "sq" to "Përpunues Tekstesh", + "sr" to "Управник писања", + "sv" to "Textredigerare", + "ta" to "உரை ஆசிரியர்", + "tr" to "Metin Düzenleyici", + "ug" to "تېكىست تەھرىرلىگۈچ", + "uk" to "Текстовий редактор", + "vi" to "Trình soạn thảo", + "zh-CN" to "文本编辑器", + "zh-TW" to "文字編輯器", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Theming", + name = + mapOf( + "af" to "Thema\'s", + "ar" to "السمات", + "ast" to "Aspeutu", + "ba" to "Тема", + "be" to "Тэмы", + "bg" to "Теми", + "bn" to "থিমিং", + "bn-BD" to "থিমিং", + "bo" to "བརྗོད་གཞི་གླེང་བཞིན་པ།", + "br" to "Neuz", + "ca" to "Temes", + "ckb" to "وتار", + "cs" to "Vzhledy", + "cy" to "Themáu", + "da" to "Temaer", + "de" to "Aussehen", + "el" to "Προσωποποίηση", + "en-GB" to "Theming", + "en-US" to "Theming", + "eo" to "Haŭtoj (etosoj)", + "es" to "Colores e interfaz", + "es-AR" to "Personalización", + "es-MX" to "Personalización", + "et" to "Kujundused", + "eu" to "Itxura", + "fa" to "شخصی‌سازی", + "fi" to "Teemat", + "fil" to "Pagtetema", + "fr" to "Personnalisation", + "ga" to "Téamaí", + "gd" to "Ùrlaran", + "gl" to "Aparencia", + "he" to "עיצוב", + "hi" to "विषय", + "hr" to "Teme", + "hu" to "Stílus", + "hy" to "Ոճ", + "id" to "Personalisasi", + "is" to "Þemu", + "it" to "Personalizzazione", + "ja" to "テーマ", + "kab" to "Aggan", + "kn" to "ಥೀಮ್", + "ko" to "꾸미기", + "lt" to "Apipavidalinimas", + "lv" to "Izskats", + "mk" to "Теми", + "ml" to "ഭാവഭേദം", + "mn" to "Дулаан", + "mr" to "धर्तीवर", + "my" to "အပြင်အဆင်", + "nb" to "Tilpasning", + "nl" to "Thema's", + "nl-BE" to "Thema’s", + "nn" to "Tema", + "pa" to "ਥੀਮਿੰਗ", + "pl" to "Motywy", + "pt" to "Temas", + "pt-BR" to "Temas", + "pt-PT" to "Temas", + "ro" to "Teme", + "ru" to "Темы", + "sc" to "Temas", + "sk" to "Témy", + "sl" to "Izgled", + "sn" to "Kudingindira", + "sq" to "Ndryshim teme grafike", + "sr" to "Теме", + "sv" to "Temasättning", + "sw" to "Mandhari", + "ta" to "தீமிங்", + "th" to "ธีมต่างๆ", + "tr" to "Tema", + "ug" to "ئاساسىي ئۇسلۇب", + "uk" to "Тематика", + "ur" to "تھیمنگ", + "vi" to "Giao diện", + "yue" to "佈景主題", + "zh-CN" to "主题", + "zh-HK" to "主題", + "zh-TW" to "主題", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Time", + name = + mapOf( + "af" to "Tyd", + "ar" to "الوقت", + "ast" to "Time", + "ba" to "Сәғәт", + "be" to "Час", + "ber" to "ⴰⴳⵓⵔ", + "bg" to "Управление на времето", + "bn" to "সময়", + "bn-BD" to "সময়", + "bo" to "དུས་ཚོད།", + "br" to "Eur", + "ca" to "Temps", + "ckb" to "کات", + "cs" to "Čas", + "cy" to "Amser", + "da" to "Tid", + "de" to "Zeit", + "el" to "Χρόνος", + "en-GB" to "Time", + "en-US" to "Time", + "eo" to "Tempo", + "es" to "Hora, gestión del tiempo", + "es-AR" to "Tiempo", + "es-MX" to "Hora", + "et" to "Aeg", + "eu" to "Denbora", + "fa" to "زمان", + "fi" to "Aika", + "fil" to "Oras", + "fr" to "Temps", + "fy" to "Tiid", + "ga" to "Am", + "gd" to "Àm", + "gl" to "Tempo", + "he" to "זמן", + "hi" to "समय", + "hr" to "Vrijeme", + "hu" to "Idő", + "hy" to "Ժամանակ", + "id" to "Waktu", + "is" to "Tími", + "it" to "Tempo", + "ja" to "日付と時刻", + "kab" to "Akud", + "kmr" to "Dem", + "kn" to "ಸಮಯ", + "ko" to "시간", + "lb" to "Zäit", + "lt" to "Laikas", + "lv" to "Laiks", + "mk" to "Време", + "ml" to "സമയം", + "mn" to "Цаг хугацаа", + "mr" to "वेळ", + "my" to "အချိန်", + "nb" to "Tid", + "ne" to "समय", + "nl" to "Tijd", + "nl-BE" to "Tijd", + "nn" to "Tid", + "pa" to "ਸਮਾਂ", + "pl" to "Czas", + "ps" to "مهال", + "pt" to "Tempo", + "pt-BR" to "Tempo", + "pt-PT" to "Tempo", + "ro" to "Timp", + "ru" to "Часы", + "sc" to "Tempus", + "sk" to "Čas", + "sl" to "Čas", + "sn" to "Nguva", + "so" to "Wakhtiga", + "sq" to "Kohë", + "sr" to "Време", + "sv" to "Tid", + "sw" to "Saa", + "ta" to "நேரம்", + "te" to "సమయం", + "th" to "เวลา", + "tr" to "Zaman", + "tzm" to "Akud", + "ug" to "ۋاقىت", + "uk" to "Час", + "ur" to "وقت", + "vi" to "Thời gian", + "yue" to "時間", + "zh-CN" to "时间", + "zh-HK" to "時間", + "zh-TW" to "時間", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Translation & Dictionary", + name = + mapOf( + "ar" to "ترجمة وقواميس", + "bg" to "Превод и речник", + "ca" to "Traducció i diccionari", + "cs" to "Překlad a slovník", + "da" to "Oversættelse og ordbog", + "de" to "Übersetzung / Wörterbuch", + "el" to "Μετάφραση & Λεξικό", + "en-GB" to "Translation & Dictionary", + "en-US" to "Translation & Dictionary", + "eo" to "Tradukiloj kaj vortaroj", + "es" to "Traducción y diccionarios", + "et" to "Tõlkimine ja sõnastikud", + "fa" to "ترجمه و واژه‌نامه", + "fi" to "Käännös ja sanakirja", + "fr" to "Traduction & dictionnaire", + "ga" to "Aistriúchán & Foclóir", + "he" to "תרגום ומילונים", + "hr" to "Prijevod i riječnik", + "hu" to "Fordítás és szótár", + "id" to "Penerjemahan & Kamus", + "is" to "Þýðingar og orðasafn", + "it" to "Traduzione & Dizionario", + "ja" to "翻訳&辞書", + "kn" to "ಅನುವಾದ", + "ko" to "번역 및 사전", + "lt" to "Vertimas ir žodynas", + "lv" to "Tulkošana un vārdnīca", + "my" to "ဘာသာပြန်နှင့် အဘိဓာန်", + "nb" to "Oversettelse & Ordbok", + "nl" to "Vertalen & woordenboek", + "pl" to "Tłumaczenie i słownik", + "pt" to "Tradução e dicionário", + "pt-BR" to "Tradução e dicionário", + "pt-PT" to "Tradução e dicionário", + "ro" to "Traducere & dicționar", + "ru" to "Перевод и словари", + "sc" to "Tradutzione e ditzionàriu", + "sl" to "Prevajalec in slovar", + "sq" to "Përkthim & Fjalor", + "sr" to "Превод и речник", + "sv" to "Översättning och ordbok", + "sw" to "Tafsiri na Kamusi", + "ta" to "மொழிபெயர்ப்பு மற்றும் அகராதி", + "tr" to "Çeviri ve Sözlük", + "ug" to "تەرجىمە ۋە لۇغەت", + "uk" to "Переклад і словник", + "vi" to "Dịch & Từ điển", + "zh-CN" to "翻译和词典", + "zh-TW" to "翻譯與辭典", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Unit Convertor", + name = + mapOf( + "ar" to "محول الوحدات", + "bg" to "Превръщане на мерни единици", + "ca" to "Convertidor d'unitats", + "cs" to "Převodník jednotek", + "de" to "Einheitenumrechner", + "el" to "Μετατροπέας Μονάδων Μέτρησης", + "en-GB" to "Unit Convertor", + "en-US" to "Unit Convertor", + "eo" to "Konvertiloj de unuoj", + "es" to "Conversión de unidades", + "et" to "Ühikute teisendajad", + "fa" to "تبدیلگر یکا", + "fi" to "Yksikkömuunnin", + "fr" to "Convertisseur d'unités", + "ga" to "Tiontaire Aonaid", + "he" to "המרת יחידות מידה", + "hr" to "Konverter jedinica", + "hu" to "Mértékegység-átváltó", + "id" to "Pengubah Satuan", + "is" to "Einingaumbreytir", + "it" to "Convertitore di unità", + "ja" to "単位変換", + "kn" to "ಘಟಕ ಪರಿವರ್ತಕ", + "ko" to "단위 변환기", + "lt" to "Vienetų keitiklis", + "lv" to "Vienību pārveidotājs", + "my" to "ယူနစ် ပြောင်းလဲမှု", + "nb" to "Enhetskonvertering", + "nl" to "Eenheden omrekenen", + "pl" to "Konwerter jednostek", + "pt" to "Conversor de unidades", + "pt-BR" to "Conversor de unidades", + "pt-PT" to "Conversor de unidades", + "ro" to "Convertor unități", + "ru" to "Перевод единиц", + "sc" to "Cunvertidore de unidades", + "sl" to "Pretvornik enot", + "sq" to "Shndërrues Njësish", + "sr" to "Претварач јединца", + "sv" to "Enhetskonverterare", + "sw" to "Kigeuzi cha Vipimo", + "ta" to "ஒன்றுபட்டது மாற்றி", + "tr" to "Birim Dönüştürücü", + "ug" to "ئولچەم ئالماشتۇرغۇچ", + "uk" to "Конвертер одиниць", + "vi" to "Chuyển đổi đơn vị", + "zh-CN" to "单位转换工具", + "zh-TW" to "單位換算", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Voice & Video Chat", + name = + mapOf( + "ar" to "المحادثة الصوتية والمرئية", + "bg" to "Аудио и видео разговори", + "ca" to "Xat de veu i vídeo", + "cs" to "Hlasový a video chat", + "da" to "Stemme- og videochat", + "de" to "Sprach-/Video-Chat", + "el" to "Φωνή & Βιντεοκλήσεις", + "en-GB" to "Voice & Video Chat", + "en-US" to "Voice & Video Chat", + "eo" to "Sonaj/videaj komunikiloj", + "es" to "Chat de vídeo y voz", + "et" to "Hääl- ja videovestlused", + "fa" to "گپ صوتی و تصویری", + "fi" to "Ääni- ja videokeskustelu", + "fr" to "Chat vocal & vidéo", + "ga" to "Comhrá Gutha & Físeáin", + "he" to "שיחות שמע ווידאו", + "hr" to "Glasovni i video chat", + "hu" to "Hang- és videócsevegés", + "id" to "Percakapan Suara & Video", + "is" to "Tal- og myndspjall", + "it" to "Chat Vocale & Video", + "ja" to "音声&ビデオチャット", + "ko" to "음성 및 영상 채팅", + "lt" to "Balso ir garso pokalbiai", + "lv" to "Balss un video tērzēšana", + "my" to "အသံနှင့် ဗီဒီယိုဖြင့် ပြောဆိုခြင်း", + "nb" to "Stemme- & Video-chat", + "nl" to "Bellen & videobellen", + "pl" to "Czat głosowy i wideo", + "pt" to "Chat de voz e vídeo", + "pt-BR" to "Ligação de voz e vídeo", + "pt-PT" to "Chat de voz e vídeo", + "ro" to "Apeluri audio & Video", + "ru" to "Голосовые и видеочаты", + "sc" to "Tzarrada de boghe e vìdeu", + "sl" to "Glasovni in slikovni klepet", + "sq" to "Fjalosje Me Zë & Video", + "sr" to "Ћаскање гласом и видеом", + "sv" to "Röst- och videochatt", + "sw" to "Mazungumzo ya Sauti na Video", + "ta" to "குரல் & வீடியோ அரட்டை", + "tr" to "Sesli ve Görüntülü Görüşme", + "ug" to "ئۈن ۋە سىن سۆھبەت", + "uk" to "Голосовий та відеочат", + "vi" to "Trò chuyện thoại và video", + "zh-CN" to "音视频聊天", + "zh-TW" to "語音與視像聊天", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "VPN & Proxy", + name = + mapOf( + "ar" to "وسيط وVPN", + "ba" to "VPN һәм прокси", + "bg" to "ВЧМ и прокси", + "ca" to "VPN i Proxy", + "cs" to "VPN a proxy", + "da" to "VPN og proxy", + "de" to "VPN / Proxy", + "el" to "VPN & Διακομιστές μεσολάβησης", + "en-GB" to "VPN & Proxy", + "en-US" to "VPN & Proxy", + "eo" to "VPN kaj retperiloj", + "es" to "Redes privadas (VPN) y proxies", + "es-MX" to "VPN & Proxy", + "et" to "VPN ja proksiteenused", + "fa" to "پیشکار و وی‌پی‌ان", + "fi" to "VPN ja välityspalvelin", + "fr" to "VPN & proxy", + "ga" to "VPN & Seachfhreastalaí", + "he" to "VPN ותיווך", + "hr" to "VPN i proxy", + "hu" to "VPN és proxy", + "id" to "VPN & Proksi", + "is" to "VPN og milliþjónn", + "it" to "VPN & Proxy", + "ja" to "VPN & プロキシ", + "kn" to "VPN", + "ko" to "VPN 및 프록시", + "lt" to "VPN ir įgaliotieji serveriai", + "lv" to "VPN un starpniekserveris", + "my" to "VPN နှင့် Proxy", + "nb" to "VPN & Mellomserver", + "nl" to "VPN & proxy", + "pl" to "VPN i proxy", + "pt" to "VPN e proxy", + "pt-BR" to "VPN e proxy", + "pt-PT" to "VPN e proxy", + "ro" to "VPN & Proxy", + "ru" to "VPN и прокси", + "sc" to "VPN e serbidores intermediàrios", + "sl" to "VPN in posredniški strežniki (proxy)", + "sq" to "VPN & Ndërmjetës", + "sr" to "Нестварна лична мрежа и посредник", + "sv" to "VPN och proxy", + "ta" to "VPN & பதிலாள்", + "tr" to "VPN ve Proxy", + "ug" to "مەۋھۇم شەخسىي تور ۋە ۋاكالەتچى مۇلازىمېتىر", + "uk" to "VPN та проксі", + "vi" to "VPN & Proxy", + "zh-CN" to "VPN 和代理", + "zh-TW" to "VPN 與代理伺服器", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Wallet", + name = + mapOf( + "ar" to "المحفظة", + "bg" to "Портмоне", + "ca" to "Cartera", + "cs" to "Peněženka", + "da" to "Pung", + "de" to "Wallet", + "el" to "Πορτοφόλι", + "en-GB" to "Wallet", + "en-US" to "Wallet", + "eo" to "Monujoj", + "es" to "Cartera", + "et" to "Dokumendi- ja rahataskud", + "fa" to "کیف پول", + "fi" to "Lompakko", + "fr" to "Portefeuille", + "ga" to "Sparán", + "he" to "ארנקים", + "hr" to "Novčanik", + "hu" to "Pénztárca", + "id" to "Dompet", + "is" to "Veski", + "it" to "Portafoglio", + "ja" to "ウォレット", + "kn" to "ವಾಲೆಟ್", + "ko" to "지갑", + "lt" to "Piniginė", + "lv" to "Maks", + "my" to "ပိုက်ဆံအိတ်", + "nb" to "Lommebok", + "nl" to "Portemonnee", + "pl" to "Portfel", + "pt" to "Carteira", + "pt-BR" to "Carteira", + "pt-PT" to "Carteira", + "ro" to "Portofel", + "ru" to "Кошельки", + "sc" to "Taschinu", + "sl" to "Denarnica", + "sq" to "Kuletë", + "sr" to "Новчаник", + "sv" to "Plånbok", + "sw" to "Mkoba", + "ta" to "பணப்பையை", + "tr" to "Cüzdan", + "ug" to "ھەميان", + "uk" to "Гаманець", + "vi" to "Ví", + "zh-CN" to "钱包", + "zh-TW" to "錢包", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Wallpaper", + name = + mapOf( + "ar" to "خلفية الشاشة", + "bg" to "Тапет", + "ca" to "Fons de pantalla", + "cs" to "Tapeta", + "da" to "Baggrund", + "de" to "Hintergrundbild", + "el" to "Ταπετσαρία", + "en-GB" to "Wallpaper", + "en-US" to "Wallpaper", + "eo" to "Ekranfonoj", + "es" to "Fondos de pantalla", + "et" to "Taustapildid", + "fa" to "کاغذدیواری", + "fi" to "Taustakuva", + "fr" to "Fonds d'écran", + "ga" to "Páipéar balla", + "he" to "תמונות רקע", + "hr" to "Slika pozadine", + "hu" to "Háttérkép", + "id" to "Latar Belakang", + "is" to "Bakgrunnsmynd", + "it" to "Sfondo", + "ja" to "壁紙", + "kn" to "ವಾಲ್ಪೇಪರ್", + "ko" to "배경화면", + "lt" to "Užsklanda", + "lv" to "Ekrāntapete", + "my" to "နောက်ခံပုံ", + "nb" to "Bakgrunn", + "nl" to "Achtergrond", + "pl" to "Tapeta", + "pt" to "Papel de parede", + "pt-BR" to "Plano de fundo", + "pt-PT" to "Papel de parede", + "ro" to "Fundal", + "ru" to "Обои", + "sc" to "Isfundu", + "sl" to "Ozadja", + "sq" to "Sfond", + "sr" to "Позадинска слика", + "sv" to "Tapet", + "sw" to "Picha ya Mandharinyuma", + "ta" to "வால்பேப்பர்", + "tr" to "Duvar kağıdı", + "ug" to "تام قەغەز", + "uk" to "Шпалери", + "vi" to "Hình nền", + "zh-CN" to "壁纸", + "zh-TW" to "背景圖片", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Weather", + name = + mapOf( + "ar" to "الطقس", + "bg" to "Времето", + "br" to "Amzer", + "ca" to "Clima", + "cs" to "Počasí", + "da" to "Vejr", + "de" to "Wetter", + "el" to "Καιρός", + "en-GB" to "Weather", + "en-US" to "Weather", + "eo" to "Veterprognozo", + "es" to "El tiempo y previsiones", + "et" to "Ilmaennustus", + "fa" to "آب و هوا", + "fi" to "Sää", + "fr" to "Météo", + "ga" to "Aimsir", + "he" to "מזג אוויר", + "hr" to "Vrijeme", + "hu" to "Időjárás", + "id" to "Cuaca", + "is" to "Veður", + "it" to "Meteo", + "ja" to "天気", + "kn" to "ಹವಾಮಾನ", + "ko" to "날씨", + "lt" to "Orai", + "lv" to "Laikapstākļi", + "my" to "ရာသီဥတု", + "nb" to "Vær", + "nl" to "Weer", + "pl" to "Pogoda", + "pt" to "Clima", + "pt-BR" to "Clima", + "pt-PT" to "Clima", + "ro" to "Meteo", + "ru" to "Погода", + "sc" to "Mèteu", + "sl" to "Vreme", + "sq" to "Mot", + "sr" to "Временске прилике", + "sv" to "Väder", + "ta" to "வானிலை", + "tr" to "Hava Durumu", + "ug" to "ھاۋا رايى", + "uk" to "Погода", + "vi" to "Thời tiết", + "zh-CN" to "天气", + "zh-TW" to "天氣", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Workout", + name = + mapOf( + "ar" to "تمرين", + "bg" to "Упражнения", + "ca" to "Entrenament", + "cs" to "Cvičení", + "da" to "Træning", + "de" to "Workout", + "el" to "Γυμναστική", + "en-GB" to "Workout", + "en-US" to "Workout", + "eo" to "Trejnado", + "es" to "Ejercicio físico", + "et" to "Treening", + "fa" to "ورزش", + "fi" to "Harjoitus", + "fr" to "Entraînement", + "ga" to "Babhta traenála", + "he" to "כושר", + "hr" to "Trening", + "hu" to "Edzés", + "id" to "Olahraga", + "is" to "Líkamsrækt", + "it" to "Allenamento", + "ja" to "ワークアウト", + "kn" to "ತಾಲೀಮು", + "ko" to "운동", + "lt" to "Treniruotė", + "lv" to "Trenēšanās", + "my" to "လေ့ကျင့်ခန်း", + "nb" to "Trening", + "nl" to "Trainen & work-out", + "pl" to "Trening", + "pt" to "Exercício físico", + "pt-BR" to "Exercício físico", + "pt-PT" to "Exercício físico", + "ro" to "Antrenament", + "ru" to "Тренировки", + "sc" to "Allenamentu", + "sl" to "Telovadba", + "sq" to "Stërvitje", + "sr" to "Вежбање", + "sv" to "Träningspass", + "ta" to "பயிற்சி", + "tr" to "Antrenman", + "ug" to "چېنىقىش", + "uk" to "Тренування", + "vi" to "Sức khỏe", + "zh-CN" to "锻炼", + "zh-TW" to "健身", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + CategoryItem( + id = "Writing", + name = + mapOf( + "af" to "Skryf", + "ar" to "الكتابة", + "ast" to "Escritura", + "ba" to "Яҙмалар", + "be" to "Напісанне", + "ber" to "ⵜⵉⵔⵔⴰ", + "bg" to "Писане", + "bn" to "লেখা", + "bn-BD" to "লেখা", + "bo" to "འབྲི་བཞིན་པ།", + "br" to "Skrivañ", + "ca" to "Escriptura", + "ckb" to "نووسین", + "cs" to "Psaní", + "cy" to "Ysgrifennu", + "da" to "Skrivning", + "de" to "Schreiben", + "el" to "Γραφή", + "en-GB" to "Writing", + "en-US" to "Writing", + "eo" to "Skribado", + "es" to "Escritura", + "es-AR" to "Escritura", + "es-MX" to "Escribiendo", + "et" to "Kirjutamine", + "eu" to "Idazketa", + "fa" to "نوشتن", + "fi" to "Kirjoittaminen", + "fil" to "Pagsusulat", + "fr" to "Écriture", + "fy" to "Skrieuwe", + "ga" to "Ag scríobh", + "gd" to "Sgrìobhadh", + "gl" to "Escrita", + "he" to "כתיבה", + "hi" to "लेखन", + "hr" to "Pisanje", + "hu" to "Írás", + "hy" to "Տեքստ", + "id" to "Menulis", + "is" to "Skrifa", + "it" to "Scrittura", + "ja" to "執筆", + "kab" to "Tira", + "kmr" to "Nivîsandin", + "kn" to "ಬರೆಯುವುದು", + "ko" to "작성", + "lb" to "Schreiwen", + "lt" to "Rašymas", + "lv" to "Rakstīšana", + "mk" to "Пишување", + "ml" to "രചന", + "mn" to "Бичих", + "mr" to "लिखाण", + "my" to "ရေးသားခြင်း", + "nb" to "Skriving", + "ne" to "लेखन", + "nl" to "Schrijven", + "nl-BE" to "Schrijven", + "nn" to "Skriving", + "pa" to "ਲਿਖਣ", + "pl" to "Pisanie", + "ps" to "ليکنه", + "pt" to "Escrita", + "pt-BR" to "Escrita", + "pt-PT" to "Escrita", + "ro" to "Scris", + "ru" to "Офис", + "sc" to "Iscritura", + "sk" to "Písanie", + "sl" to "Pisanje", + "sn" to "Kunyora", + "so" to "Qorista", + "sq" to "Shkrim", + "sr" to "Писање", + "sv" to "Skrivande", + "sw" to "Kuandika", + "ta" to "எழுதுதல்", + "te" to "వ్రాయటం", + "th" to "การเขียน", + "tr" to "Yazım", + "tzm" to "Tirra", + "ug" to "يېزىقچىلىق", + "uk" to "Написання", + "ur" to "لکهائی", + "vi" to "Soạn thảo", + "yue" to "寫作", + "zh-CN" to "记录", + "zh-HK" to "文書", + "zh-TW" to "書寫", + ) + .getBestLocale(localeList) ?: "Unknown Category", + ), + ) diff --git a/app/src/androidTest/java/org/fdroid/ui/screenshots/DetailsItem.kt b/app/src/androidTest/java/org/fdroid/ui/screenshots/DetailsItem.kt new file mode 100644 index 000000000..2a0434836 --- /dev/null +++ b/app/src/androidTest/java/org/fdroid/ui/screenshots/DetailsItem.kt @@ -0,0 +1,180 @@ +package org.fdroid.ui.screenshots + +import org.fdroid.database.AppMetadata + +val appMetadata = + AppMetadata( + repoId = 1L, + packageName = "org.fdroid.basic", + added = 1680776466000L, + lastUpdated = 1772364577000L, + name = + mapOf( + "en-GB" to "F-Droid Basic", + "es" to "F-Droid Basic", + "pl" to "F-Droid Podstawowy", + "pt" to "F-Droid Básico", + "pt-PT" to "F-Droid Básico", + "ru" to "F-Droid Basic", + "ar" to "F-Droid Basic", + "ca" to "F-Droid bàsic", + "cs" to "F-Droid Basic", + "de" to "F-Droid Basic", + "en-US" to "F-Droid Basic", + "eo" to "F-Droid Baza", + "et" to "F-Droid Basic", + "fa-IR" to "اف‌دروید پایه‌ای", + "fr" to "F-Droid Basic", + "ga" to "F-Droid Bunúsach", + "he" to "F-Droid בסיסי", + "hu-HU" to "Alap F-Droid", + "is-IS" to "Grunnútgáfa F-Droid", + "ja" to "F-Droid Basic", + "pt-BR" to "F-Droid Básico", + "ro" to "F-Droid Basic", + "sr" to "Основни F-Droid", + "sv-SE" to "F-Droid Basic", + "ta-IN" to "எஃப்-டிராய்டு அடிப்படை", + "tr" to "F-Droid Temel", + "uk" to "F-Droid Basic", + "zh-CN" to "F-Droid Basic", + "zh-TW" to "F-Droid Basic", + ), + summary = + mapOf( + "en-GB" to "The minimal client app for the app store that respects freedom and privacy", + "es" to "Aplicación para la tienda de aplicaciones; respeta la libertad y la privacidad", + "pl" to "Minimalistyczna apka kliencka dla sklepu z apkami szanująca wolność i prywatność", + "pt" to "App cliente mínima para a loja de apps que respeita a liberdade e a privacidade", + "pt-PT" to + "App cliente mínima para a loja de apps que respeita a liberdade e a privacidade", + "ru" to "Минималистичный магазин приложений, уважающий свободу и приватность", + "ar" to "تطبيق عميل خفيف لمتجر التطبيقات والذي يحترم الحرية والخصوصية", + "ca" to "El client mínim del centre d'aplicacions que respecta la llibertat i privadesa", + "cs" to "Minimální klient pro obchod s aplikacemi, který respektuje svobodu a soukromí", + "de" to "Der minimale Client für den App-Store, der Freiheit und Privatsphäre respektiert", + "en-US" to "The minimal client app for the app store that respects freedom and privacy", + "eo" to "Minimuma kliento por la aplikaĵa vendejo respektanta liberecon kaj privatecon", + "et" to "Lihtsustatud variant F-Droidi rakendustepoe kliendist", + "fa-IR" to "کارخواه کمینه برای فروشگاه کاره‌ای که به آزادی و محرمانگی احترام می‌گذارد", + "fr" to "L’application minimale pour le magasin d’applis respectueux de la vie privée", + "ga" to "Aip íosta cliant don siopa a léiríonn meas ar shaoirse agus ar phríobháideachas", + "he" to "יישומון הלקוח המזערי לחנות יישומונים שמכבד חופש ופרטיות", + "hu-HU" to "Az alap app a tárolóban, amely tiszteli a szabadságot és a magánéletet", + "is-IS" to + "Lágmarksviðmót forritsins fyrir hugbúnaðarsafnið sem virðir frelsi og gagnaleynd", + "ja" to "自由とプライバシーを尊重するアプリストアの簡略版クライアント", + "pt-BR" to + "App cliente mínimo para a loja de apps que respeita a liberdade e a privacidade", + "ro" to "Client minim pentru magazinul de aplicații ce respectă libertatea și intimitatea", + "sr" to "Клијент апликација за продавницу апликација која поштује слободу и приватност", + "sv-SE" to "Den minimala klient-appen för app-butiken som respekterar frihet och privatliv", + "sw" to "An app cliant íosta don siopa app a urramaíonn saoirse agus príobháideachta", + "ta-IN" to + "விடுதலை மற்றும் தனியுரிமையை மதிக்கும் பயன்பாட்டு கடைக்கான குறைந்தபட்ச வாங்கி பயன", + "tr" to "Özgürlük ve gizliliğe saygılı uygulama mağazası için sade bir istemci uygulaması", + "uk" to "Мінімалістичний клієнтський застосунок, який поважає свободу й приватність", + "zh-CN" to "尊重自由和隐私的应用商店的极简客户端应用", + "zh-TW" to "尊重自由和隱私的應用商店最小客戶端應用程序", + ), + description = + mapOf( + "en-GB" to + "NOTE: The Basic version of F-Droid Client has a reduced feature set (e.g. no nearby share and no panic feature). It targets Android 13 and can do unattended updates without privileged extension or root.\n\nF-Droid is an installable catalogue of libre softw", + "es" to + "NOTA: La versión básica de F-Droid Client tiene un conjunto de características reducidas (por ejemplo, no hay recursos compartidos cercanos y no hay función de pánico). Está dirigido a Android 13 y puede hacer actualizaciones desatendidas sin extensión pri", + "pl" to + "UWAGA: Podstawowa wersja klienta F-Droid ma ograniczony zestaw funkcji (np. brak pobliskiego udziału i funkcji paniki). Jest przeznaczona dla systemu Android 13 i może wykonywać nienadzorowane aktualizacje bez uprzywilejowanego rozszerzenia lub roota.\n\nF", + "pt" to + "AVISO: A versão básica do cliente F-Droid tem menos funções (por exemplo, não tem o \"Por perto\" ou a função de pânico). Está preparado para o Android 13 e pode fazer atualizações sem intervenção do utilizador, sem precisar da extensão privilegiada ou de ", + "pt-PT" to + "AVISO: A versão básica do cliente F-Droid tem menos funções (por exemplo, não tem o \"Por perto\" ou a função de pânico). Está preparado para o Android 13 e pode fazer atualizações sem intervenção do utilizador, sem precisar da extensão privilegiada ou de ", + "ru" to + "ПРИМЕЧАНИЕ: Basic-версия клиента F-Droid имеет урезанный набор функций (например, нет общего доступа к близлежащим ресурсам и функции паники). Она нацелена на Android 13 и может выполнять обновления без участия пользователя и без особого расширения или roo", + "ar" to + "ملاحظة: الإصدار الأساسي من عميل F-Droid يحتوي على مجموعة ميزات مخفضة (على سبيل المثال، لا توجد مشاركة قريبة ولا توجد ميزة الذعر). وهو يستهدف Android 13 ويمكنه إجراء تحديثات غير مراقبة بدون امتداد أو جذر مميز.\n\nF-Droid عبارة عن كتالوج قابل للتثبيت لتطبيقا", + "ca" to + "NOTA: La versió bàsica del client de l'F-Droid té un conjunt de funcionalitats reduït (p. ex. no hi ha compartició propera i funció del pànic). Està orientada a l'Android 13 i pot fer actualitzacions desateses sense extensions de privilegis ni permisos d'a", + "cs" to + "UPOZORNĚNÍ: Základní (Basic) verze klienta F-Droid má omezenou sadu funkcí (např. žádné sdílení nablízku nebo funkci paniky). Cílí na systém Android 13 a dokáže provádět automatické aktualizace bez privilegovaného rozšíření nebo rootu.\n\nF-Droid je katalo", + "de" to + "HINWEIS: Die Basisversion von F-Droid Client hat einen eingeschränkten Funktionsumfang (z. B. keine Freigabe in der Nähe und keine Panikfunktion). Sie zielt auf Android 13 ab und kann unbeaufsichtigte Updates ohne privilegierte Erweiterung oder Root durchf", + "en-US" to + "NOTE: The Basic version of F-Droid Client has a reduced feature set (e.g. no nearby share and no panic feature). It targets Android 13 and can do unattended updates without privileged extension or root.\n\nF-Droid is an installable catalogue of libre softw", + "eo" to + "RIMARKO: la baza versio de kliento F-Droid estas senigita de kelkaj ebloj (kiel proksima interŝanĝo kaj panika butono). Ĝi celas Android 13 kaj povas ĝisdatigi aplikaĵojn fone sen uzi ĉefuzantan permeson aŭ la privilegian aldonaĵon.\n\nF-Droid estas instal", + "et" to + "NB! F-Droid Basic on piiratud funktsionaalsusega klient (nt. puuduvad naabritega jagamine ja paanikarežiimi keelamine). Ta on mõeldud Android 13-le ja saab paigaldada uuendusi iseseisvalt, priviligeeritud laienduse või juurkasutajata.\n\nF-Droid on paigald", + "fa-IR" to + "نکته: نگارش پایه‌ای کارخواه اف دروید مجموعه ویز؛ی‌های کم‌تری دارد (برای نمونه هم‌رسانی نزدیک و دکمهٔ هراس). اندروید ۱۳ را هدف قرار داده و می‌تواند به‌روز رسانی‌های پس‌زمینه را بدون ریشه یا افزونهٔ ممتاز انجام دهد.\n\nاف‌دروید کالانمایی قابل نصب از کاره‌های", + "fr" to + "REMARQUE : la version Basic du client F-Droid a un jeu de fonctionnalités réduit (par ex. pas de partage de proximité et aucune fonction \"no panic\"). Elle est destinée à la plateforme Android 13 et peut faire des mises à jour sans extension privilégiée o", + "ga" to + "NÓTA: Tá sraith gnéithe laghdaithe ag an leagan Bunúsach de Chliant F-Droid (e.g. gan aon chomhroinnt in aice láimhe agus gan aon ghné scaoill). Díríonn sé ar Android 13 agus is féidir leis nuashonruithe gan duine a dhéanamh gan síneadh pribhléideach ná fr", + "he" to + "הערה: לגרסה הבסיסית של לקוח F-Droid יש מערכת תכונה מופחתת (לדוגמה, אין שיתוף סמוך ואין תכונה פאניקה). הוא מכוון לאנדרואיד 13 ויכול לעשות עדכונים ללא הרחבה מועדפת או root.\n\nF-Droid הוא קטלוג של יישומי תוכנה חופשית עבור אנדרואיד. יישומון לקוח F-Droid מקל ל", + "hu-HU" to + "MEGJEGYZÉS: Az alap F-Droid verzió csökkentett funkciókészlettel rendelkezik (pl. nincs közeli megosztás és nincs pánik funkció). Az android 13-as rendszert célozza meg, és képes felügyelet nélküli frissítéseket végezni jogosultsági kiterjesztés vagy root ", + "is-IS" to + "ATHUGAÐU: Grunnútgáfa (Basic) F-Droid forritsins er með færri eiginleika (t.d. ekki deilingu til tækja í nágrenninu og enga neyðaraðgerð). Hún miðast við Android 13 og getur séð um uppfærslur án afskipta notandans án forgangsviðbótarinnar eða rótaraðgangs.", + "ja" to + "注意:F-DroidクライアントのBasic版は、機能が制限されています(例えば、近くへ共有やパニック機能がありません)。Android 13がターゲットで、特権の拡張やroot無しで更新出来ます。\n\nF-DroidはAndroidのための自由かつインストール可能なソフトウェアアプリの目録です。F-Droidクライアントアプリは、あなたのデバイス上での閲覧、インストール、更新の追跡を簡単にします。\n\nF-Droidは互換性のあるリポジトリへ接続します。標準のリポジトリはf-droid.orgでホスト", + "pt-BR" to + "AVISO: A versão básica do cliente F-Droid tem um número reduzido de funções (por exemplo, não tem o \"Por perto\" ou a função de Pánico). Ela \"atinge\" o Android 13 e pode fazer atualizações sem intervenção do usuário, sem precisar da extensão privilegiad", + "ro" to + "NOTĂ: Versiunea de client F-Droid Basic are un set redus de funcții (de exemplu, fără partajare în apropiere și fără funcție de panică). Aceasta vizează Android 13 și poate face actualizări nesupravegheate fără extensia privilegiată sau root.\n\nF-Droid es", + "sr" to + "Напомена: Основна верзија клијента F-Droid има ограничен сет функција (нпр. нема опцију за дељење у близини и нема функцију за хитне случајеве). Она је намењена за Android 13 и може да обавља ажурирања без повишених привилегија или рута.\n\nF-Droid је ката", + "sv-SE" to + "OBS: Basic-versionen av F-Droid Client har en reducerad funktionsuppsättning (t.ex. ingen när-delning och ingen panikfunktion). Den riktar sig till Android 13 och kan göra obevakade uppdateringar utan privilegierad förlängning eller root.\n\nF-Droid är en ", + "ta-IN" to + "குறிப்பு: எஃப்-டிராய்டு கிளையண்டின் அடிப்படை பதிப்பு குறைக்கப்பட்ட அம்சத் தொகுப்பைக் கொண்டுள்ளது (எ.கா. அருகிலுள்ள பங்கு இல்லை மற்றும் அச்சம் நற்பொருத்தம் இல்லை). இது ஆண்ட்ராய்டு 13 ஐ குறிவைக்கிறது மற்றும் சலுகை பெற்ற நீட்டிப்பு அல்லது வேர் இல்லாமல் கவனிக்", + "tr" to + "NOT: F-Droid İstemcisinin Temel sürümünün düşürülmüş özellikleri mevcuttur (mesela nearby share ve panik özelliği yok). Android 13'ü hedef alır ve özel eklenti veya root gerektirmeden gözetimsiz güncellemeler yapabilir.\nF-Droid, Android için özgür yazılım", + "uk" to + "ПРИМІТКА. Базова версія F-Droid Client має скорочений набір функцій (наприклад, немає функції спільного доступу поблизу та функції паніки). Він націлений на Android 13 і може виконувати автоматичні оновлення без привілейованого розширення або root-права. ", + "zh-CN" to + "注意:F-Droid 客户端基础版本的功能不全 (如没有“附近”分享和应急功能)。它针对 Android 13 ,可以在没有特权扩展或 root 的情况下执行无人值守更新。.\n\nF-Droid 是 Android 系统自由软件应用的可安装目录。 F-Droid 客户端应用使得浏览、安装和跟踪设备上的应用更新变得轻而易举。\n\n它可以连接到任何兼容 F-Droid 的存储库。默认存储库托管在 f-droid.org 上,其中只包含真正的自由软件。\n\nAndroid 本身是开放的,意思是你可以从任何地", + "zh-TW" to + "注意:F-Droid 用戶端基本版的功能集較少(例如,沒有附近共享和恐慌功能)。它以 Android 13 為目標,無需特權擴充或 root 即可進行無人值守更新。\n\nF-Droid 是適用於 Android 的自由軟體應用程式的可安裝目錄。 F-Droid 用戶端應用程式可以輕鬆瀏覽、安裝和追蹤裝置上的更新。\n\n它可以連接到任何與 F-Droid 相容的儲存庫。預設 repo 託管在 f-droid.org,其中僅包含真正的自由軟體。\n\nAndroid 本身是開放的,這意味著您可以自由地從任何", + ), + webSite = "https://f-droid.org", + changelog = "https://gitlab.com/fdroid/fdroidclient/-/blob/HEAD/CHANGELOG.md", + license = "GPL-3.0-or-later", + sourceCode = "https://gitlab.com/fdroid/fdroidclient", + issueTracker = "https://gitlab.com/fdroid/fdroidclient/issues", + translation = "https://hosted.weblate.org/projects/f-droid/f-droid", + preferredSigner = "ef7f822b7653e2011cb8c5a7fc99e8d2ade1717e539ca56d6456295e3bc07312", + authorName = "F-Droid", + authorEmail = "team@f-droid.org", + authorWebSite = null, + authorPhone = null, + donate = listOf("https://f-droid.org/donate"), + liberapayID = null, + liberapay = "F-Droid-Data", + openCollective = "F-Droid-Euro", + bitcoin = "bc1qd8few44yaxc3wv5ceeedhdszl238qkvu50rj4v", + litecoin = null, + flattrID = null, + categories = listOf("App Store & Updater", "System"), + isCompatible = true, + ) + +val appDetailsIcon = + "https://f-droid.org/repo/org.fdroid.basic/en-US/icon_CPdcoTY7kZ3ERIZkij9504KbM1eEY05XaLvVQwHkqHI=.png" +val appDetailsFeatureGraphic = + "https://f-droid.org/repo/org.fdroid.basic/en-US/featureGraphic_8rt-tl-zn9ff1UC0HIBnEBxxqodp18-Ok8l1_gu3EtQ=.jpg" +val appDetailsScreenshots = + mapOf( + "en-US" to + listOf( + "https://f-droid.org/repo/org.fdroid.basic/en-US/phoneScreenshots/01-latest.png", + "https://f-droid.org/repo/org.fdroid.basic/en-US/phoneScreenshots/02-categories.png", + "https://f-droid.org/repo/org.fdroid.basic/en-US/phoneScreenshots/03-updates.png", + "https://f-droid.org/repo/org.fdroid.basic/en-US/phoneScreenshots/04-settings.png", + "https://f-droid.org/repo/org.fdroid.basic/en-US/phoneScreenshots/10-search.png", + "https://f-droid.org/repo/org.fdroid.basic/en-US/phoneScreenshots/11-app-details.png", + "https://f-droid.org/repo/org.fdroid.basic/en-US/phoneScreenshots/20-repos.png", + "https://f-droid.org/repo/org.fdroid.basic/en-US/phoneScreenshots/21-repo-details.png", + ) + ) diff --git a/app/src/androidTest/java/org/fdroid/ui/screenshots/DetailsScreenshotTest.kt b/app/src/androidTest/java/org/fdroid/ui/screenshots/DetailsScreenshotTest.kt new file mode 100644 index 000000000..d890c0748 --- /dev/null +++ b/app/src/androidTest/java/org/fdroid/ui/screenshots/DetailsScreenshotTest.kt @@ -0,0 +1,57 @@ +package org.fdroid.ui.screenshots + +import androidx.compose.ui.platform.LocalLocaleList +import androidx.core.os.LocaleListCompat +import org.fdroid.LocaleChooser.getBestLocale +import org.fdroid.download.NetworkState +import org.fdroid.install.InstallState +import org.fdroid.ui.details.AppDetails +import org.fdroid.ui.details.AppDetailsItem +import org.fdroid.ui.details.VersionItem +import org.fdroid.ui.utils.getAppDetailsActions +import org.fdroid.ui.utils.testVersion1 +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.Parameterized + +@RunWith(Parameterized::class) +class DetailsScreenshotTest(localeName: String) : LocalizedScreenshotTest(localeName) { + + companion object { + @JvmStatic @Parameterized.Parameters(name = "{0}") fun locales() = locales + } + + @Test + fun appDetails() = + screenshotTest("3_Details", showBottomBar = false) { + val localeList = + LocaleListCompat.forLanguageTags( + LocalLocaleList.current.localeList.map { it.toLanguageTag() }.joinToString(",") + ) + val item = + AppDetailsItem( + app = appMetadata, + actions = getAppDetailsActions(), + installState = InstallState.Unknown, + networkState = NetworkState(isOnline = true, isMetered = false), + name = appMetadata.name.getBestLocale(localeList) ?: "Unknown name", + summary = appMetadata.summary.getBestLocale(localeList), + description = appMetadata.description.getBestLocale(localeList), + icon = appDetailsIcon, + featureGraphic = appDetailsFeatureGraphic, + phoneScreenshots = appDetailsScreenshots.getBestLocale(localeList) ?: emptyList(), + versions = + listOf( + VersionItem( + testVersion1, + isInstalled = false, + isSuggested = true, + isCompatible = true, + isSignerCompatible = true, + showInstallButton = true, + ) + ), + ) + AppDetails(item = item, onNav = {}, onBackNav = {}) + } +} diff --git a/app/src/androidTest/java/org/fdroid/ui/screenshots/DiscoverItems.kt b/app/src/androidTest/java/org/fdroid/ui/screenshots/DiscoverItems.kt new file mode 100644 index 000000000..ac9c91d11 --- /dev/null +++ b/app/src/androidTest/java/org/fdroid/ui/screenshots/DiscoverItems.kt @@ -0,0 +1,401 @@ +package org.fdroid.ui.screenshots + +import androidx.core.os.LocaleListCompat +import org.fdroid.LocaleChooser.getBestLocale +import org.fdroid.ui.discover.AppDiscoverItem + +fun getNewApps(localeList: LocaleListCompat) = + listOf( + AppDiscoverItem( + packageName = "jp.nonbili.noutube", + name = mapOf("en-US" to "NouTube").getBestLocale(localeList) ?: "Unknown App", + isInstalled = true, + imageModel = + "https://f-droid.org/repo/jp.nonbili.noutube/en-US/icon_A1nC0BkAzsvNhws7y1thjfhF8LJJReXVUORApHsstDE=.png", + ), + AppDiscoverItem( + packageName = "net.thunderbird.android", + name = + mapOf( + "ar" to "ثَندَربِرْد: حرّر صندوق بريدك", + "be" to "Thunderbird: Вольная Пошта", + "bg" to "Thunderbird: Освободете пощата", + "br" to "Thunderbird: Dieubit hor boest degemer", + "ca" to "Thunderbird: allibereu la vostra safata d'entrada", + "co" to "Thunderbird : Messaghjeria libera", + "cs-CZ" to "Thunderbird: Svobodná pošta", + "cy" to "Thunderbird: Rhyddhau'r Blwch Derbyn", + "de-DE" to "Thunderbird: Befreie deinen Posteingang", + "el-GR" to "Thunderbird: Ελεύθερα email", + "en-GB" to "Thunderbird: Free Your Inbox", + "en-US" to "Thunderbird: Free Your Inbox", + "eo" to "Thunderbird: Libera retpoŝtilo", + "es-ES" to "Thunderbird; libera tu correo", + "et" to "Thunderbird: e-post sinu jaoks", + "eu-ES" to "Androiderako Thunderbird", + "fa-IR" to "تاندربرد: آزادی صندوق ورودی", + "fi-FI" to "Thunderbird: Vapauta postilaatikkosi", + "fr-FR" to "Thunderbird : Courriel libre", + "fy" to "Thunderbird: Befrij jo Postfek", + "ga" to "Thunderbird: Saor Do Phost", + "gd" to "Thunderbird: Saorsa dhan phost agad", + "hi-IN" to "थंडरबर्ड - इन्बॉक्स मुक्त करें", + "hr" to "Thunderbird: Oslobodite svoju poštu", + "hu-HU" to "Thunderbird: Szabad levelezés", + "id" to "Thunderbird: Kosongkan Kotak Masuk Anda", + "is-IS" to "Thunderbird: Frjáls póstur", + "it-IT" to "Thunderbird: libera la tua casella di posta", + "iw-IL" to "ת'אנדרבירד: שחרר את תיבת הדואר שלך", + "ja-JP" to "Thunderbird: 受信トレイをもっと自由に", + "lt" to "Thunderbird: lais. savo gaut.", + "mnw" to "ဂစေံလလဳ: သၠးကဠာလိက်မၞး", + "nl-NL" to "Thunderbird: Bevrijd uw e-mail", + "nn" to "Thunderbird: Frigjer innboksen", + "no-NO" to "Thunderbird: Frigjør innboksen", + "pl-PL" to "Thunderbird: Uwolnij pocztę", + "pt-BR" to "Thunderbird: Liberte seu email", + "pt-PT" to "Thunderbird: Liberte o seu email", + "ro" to "Thunderbird: poștă liberă", + "ru-RU" to "Thunderbird: свободная почта", + "sk" to "Thunderbird: Slobodná Schránka", + "sl" to "Thunderbird: sprostite svoj nabiralnik!", + "sq" to "Thunderbird: Free Your Inbox", + "sr" to "Thunderbird: Ослободите своје сандуче", + "sv-SE" to "Thunderbird: Frigör din inkorg", + "ta-IN" to "இடிபறவை: உங்கள் உள்பெட்டி விடுவி", + "tr-TR" to "Thunderbird: Özgür E-posta", + "uk" to "Thunderbird: Вільна е-пошта", + "vi" to "Thunderbird: Giải phóng hộp thư của bạn", + "zh-CN" to "Thunderbird:解放收件箱", + "zh-TW" to "Thunderbird: 釋放你的收件匣", + ) + .getBestLocale(localeList) ?: "Unknown App", + isInstalled = true, + imageModel = + "https://f-droid.org/repo/net.thunderbird.android/en-US/icon_llBuXRxsJFITCCuDze-ENOPa1J_HFZLudN5K3gU-xiU=.png", + ), + AppDiscoverItem( + packageName = "io.element.android.x", + name = + mapOf("en-US" to "Element X - Secure Chat & Call").getBestLocale(localeList) + ?: "Unknown App", + isInstalled = false, + imageModel = + "https://f-droid.org/repo/io.element.android.x/en-US/icon_YBz4_OnMHd7E2Bd_oEza9ImLSlHTpL_C-ovHcKljeFA=.png", + ), + AppDiscoverItem( + packageName = "org.breezyweather", + name = mapOf("en-US" to "Breezy Weather").getBestLocale(localeList) ?: "Unknown App", + isInstalled = true, + imageModel = + "https://f-droid.org/repo/org.breezyweather/en-US/icon_e18rWq0tKc__3173BVXmiiasM_F7yrUbs6kh7lQffto=.png", + ), + AppDiscoverItem( + packageName = "helium314.keyboard", + name = + mapOf( + "ar" to "HeliBoard", + "bg" to "HeliBoard", + "bn" to "হেলিবোর্ড", + "ca" to "HeliBoard", + "cs-CZ" to "HeliBoard", + "de-DE" to "HeliBoard", + "en-US" to "HeliBoard", + "es-ES" to "HeliBoard", + "et" to "HeliBoard", + "fi-FI" to "HeliBoard", + "fr-FR" to "HeliBoard", + "gl-ES" to "HeliBoard", + "hu-HU" to "HeliBoard", + "id" to "HeliBoard", + "is-IS" to "HeliBoard", + "it-IT" to "HeliBoard", + "iw-IL" to "הליבורד HeliBoard", + "lv" to "HeliBoard", + "nl-NL" to "HeliBoard", + "pa-PK" to "ہیلی‌بورڈ", + "pl-PL" to "HeliBoard", + "pt" to "HeliBoard", + "pt-BR" to "HeliBoard", + "ru-RU" to "HeliBoard", + "ta-IN" to "எலிபோர்டு", + "tr-TR" to "HeliBoard", + "uk" to "HeliBoard", + "zh-CN" to "HeliBoard", + ) + .getBestLocale(localeList) ?: "Unknown App", + isInstalled = true, + imageModel = + "https://f-droid.org/repo/helium314.keyboard/en-US/icon_-nkf9NO4Zp7Y0YX1AOcQdZMf32R_bPt8AZC2Ycn2v1I=.png", + ), + AppDiscoverItem( + packageName = "dev.imranr.obtainium.fdroid", + name = + mapOf("de" to "Obtainium", "en-US" to "Obtainium", "ru-RU" to "Obtainium") + .getBestLocale(localeList) ?: "Unknown App", + isInstalled = false, + imageModel = + "https://f-droid.org/repo/dev.imranr.obtainium.fdroid/en-US/icon_8o6Dm3kPEr-C-8U1QdRd9B6DrkXPqLJQ7or0KN7ut_4=.png", + ), + ) + +fun getRecentlyUpdatedApps(localeList: LocaleListCompat) = + listOf( + AppDiscoverItem( + packageName = "com.fsck.k9", + name = + mapOf( + "ar" to "K-9 Mail", + "be" to "Пошта K-9", + "bg" to "K-9 Поща", + "ca" to "K-9 Mail", + "co" to "K-9 Mail", + "cs-CZ" to "K-9 Mail", + "cy" to "K-9 Mail", + "de" to "K-9 Mail", + "el-GR" to "K-9 Mail", + "en-GB" to "K-9 Mail", + "en-US" to "K-9 Mail", + "eo" to "K-9 Retpoŝtilo", + "es" to "K-9 Mail", + "et" to "K-9 Mail", + "eu-ES" to "K-9 Mail", + "fa-IR" to "نامهٔ کی۹", + "fr" to "Courriel K-9 Mail", + "fy" to "K-9 Mail", + "ga" to "K-9 Mail", + "gd" to "Post K-9", + "he" to "K-9 דוא\"ל", + "hi-IN" to "K-9 Mail", + "hr" to "K-9 Mail", + "hu-HU" to "K-9 Mail", + "id" to "Surel K-9", + "is-IS" to "K-9 - Póstur", + "it" to "K-9 Mail", + "ja" to "K-9 Mail", + "kk" to "K-9 Пошта", + "ko-KR" to "K-9 메일", + "lt" to "K-9 paštas", + "mnw" to "တိုက်လိက် K-၉", + "nb" to "K-9 E-post", + "nl-NL" to "K-9 Mail", + "nn" to "K-9 Mail", + "pl" to "K-9 Mail", + "pt-BR" to "K-9 Mail", + "pt-PT" to "K-9 Mail", + "ro" to "K-9 Mail", + "ru" to "Почта K-9", + "sk" to "K-9 Mail", + "sl" to "Pošta K-9", + "sq" to "K-9 Mail", + "sr" to "K-9 Mail", + "sv-SE" to "K-9 Mail", + "ta-IN" to "கே-9 அஞ்சல்", + "tr" to "K-9 Posta", + "uk" to "K-9 Mail", + "vi" to "K-9 Mail", + "zh-CN" to "K-9 Mail", + "zh-TW" to "K-9 Mail", + ) + .getBestLocale(localeList) ?: "Unknown App", + isInstalled = false, + imageModel = + "https://f-droid.org/repo/com.fsck.k9/en-US/icon_-2bZW0ZnkKqPVher2SxQK8hXGGSjgaBHoa8x6vW0v8w=.png", + ), + AppDiscoverItem( + packageName = "com.github.andreyasadchy.xtra", + name = mapOf("en-US" to "Xtra").getBestLocale(localeList) ?: "Unknown App", + isInstalled = false, + imageModel = + "https://f-droid.org/repo/com.github.andreyasadchy.xtra/en-US/icon_yfnxF0cNrXwFX2a93BUclISVaIQzoRmbOuxtGDAwz28=.png", + ), + AppDiscoverItem( + packageName = "com.github.libretube", + name = mapOf("en-US" to "LibreTube").getBestLocale(localeList) ?: "Unknown App", + isInstalled = false, + imageModel = + "https://f-droid.org/repo/com.github.libretube/en-US/icon_p6_cfoYk-2IlerJpH4rKIQmkI76zXtS3R9-RZp-3Ggk=.png", + ), + AppDiscoverItem( + packageName = "com.inspiredandroid.linuxcommandbibliotheca", + name = mapOf("en-US" to "Linux Command Library").getBestLocale(localeList) ?: "Unknown App", + isInstalled = false, + imageModel = + "https://f-droid.org/repo/com.inspiredandroid.linuxcommandbibliotheca/en-US/icon_DrA_e_52nvGa_kTMSapBw4MCqKpccl8WZqrG5enB7rI=.png", + ), + AppDiscoverItem( + packageName = "com.junkfood.seal", + name = + mapOf( + "ar-SA" to "Seal", + "bn" to "সিল", + "de-DE" to "Seal", + "en-US" to "Seal", + "es" to "Seal", + "fr-FR" to "Seal", + "hi" to "सील", + "hr" to "Seal", + "id" to "Seal", + "it" to "Seal", + "ja" to "Seal", + "ml" to "സീൽ", + "nb-NO" to "Seal", + "nl-NL" to "Zeehond", + "pt-BR" to "Seal", + "ru" to "Seal", + "th" to "Seal", + "uk" to "Тюлень", + "vi" to "Hải Cẩu", + "zh-CN" to "Seal", + "zh-TW" to "Seal", + ) + .getBestLocale(localeList) ?: "Unknown App", + isInstalled = false, + imageModel = + "https://f-droid.org/repo/com.junkfood.seal/en-US/icon_j8mCLA_OX-sJn7TRAdvoaUMW1f6djRv6RMzAnNdaG4I=.png", + ), + AppDiscoverItem( + packageName = "com.kunzisoft.keepass.libre", + name = + mapOf( + "ar" to "KeePassDX Passkey Vault", + "cs-CZ" to "Trezor pro klíče KeePassDX", + "de-DE" to "KeePassDX Passkey-Tresor", + "en-US" to "KeePassDX Passkey Vault", + "es-ES" to "KeePassDX Passkey Vault", + "et" to "KeePassDX salasõnahoidla", + "fr-FR" to "KeePassDX - Passkey local", + "hr" to "KeePassDX Passkey Vault", + "hu-HU" to "KeePassDX jelszótároló", + "id" to "KeePassDX Passkey Vault", + "it-IT" to "Cassaforte passkey KeePassDX", + "ja-JP" to "KeePassDX パスワード管理ツール", + "lt" to "KeePassDX slaptažodžių seifas", + "lv" to "KeePassDX: paroļu pārvaldnieks", + "mk-MK" to "KeePassDX Passkey Vault", + "nl-NL" to "KeePassDX Passkey-kluis", + "pl-PL" to "KeePassDX – Bezpieczny sejf", + "ru-RU" to "KeePassDX - менеджер паролей", + "sq" to "Kasafortë Kyçklm. KeePassDX", + "th" to "ตู้นิรภัยพาสคีย์คียพาสดีเอ็กซ์", + "tr-TR" to "KeePassDX Passkey Vault", + "zh-CN" to "KeePassDX 密码库", + "zh-TW" to "KeePassDX 密碼(金鑰/單字)保險庫", + ) + .getBestLocale(localeList) ?: "Unknown App", + isInstalled = false, + imageModel = + "https://f-droid.org/repo/com.kunzisoft.keepass.libre/en-US/icon_eLwXEQD9l2URrUS3t8esDXnsKGBaH02E-ddEYhV_i7Q=.png", + ), + ) + +fun getMostDownloadedApps(localeList: LocaleListCompat) = + listOf( + AppDiscoverItem( + packageName = "app.organicmaps", + name = + mapOf( + "vi" to "Organic Maps: bản đồ dẫn đường", + "km-KH" to "Organic Maps・ផែនទីក្រៅបណ្ដាញ", + "pt-PT" to "Organic Maps - Mapas offline", + "zh-CN" to "Organic Maps・离线地图与导航 & GPS", + "iw-IL" to "Organic Maps・מפת אופליין ו-GPS", + "lv" to "Organic Maps・Kartes・Navigācija", + "kk" to "Organic Maps: Карталар", + "hr" to "Organic Maps: offline karte", + "th" to "Organic Maps: แผนที่gps", + "si-LK" to "Organic Maps・ඔෆ්ලයින් සිතියම්", + "sl" to "Organic Maps・Offline Karte", + "ru-RU" to "Organic Maps: GPS карты офлайн", + "ne-NP" to "Organic Map・अफलाइन नक्सा & GPS", + "fr-FR" to "Organic Maps: gps hors ligne", + "es-ES" to "Organic Maps: mapas offline", + "mk-MK" to "Organic Maps・Мапи и навигација", + "be" to "Organic Maps: GPS карты офлайн", + "lt" to "Organic Maps・žemėlapis & GPS", + "ms" to "Organic Maps: Peta & Navigasi", + "en-US" to "Organic Maps・Offline Map & GPS", + "tr-TR" to "Organic Maps: Haritalar ve GPS", + "ro" to "Organic Maps: hărți offline", + "hi-IN" to "Organic Maps・ऑफ़लाइन मैप", + "mr-IN" to "Organic Maps ऑफलाईन नकाशे", + "bn-BD" to "Organic Maps・मैप्स और नेविगेशन", + "ca" to "Organic Map・Mapa Offline i GPS", + "it-IT" to "Organic Maps: Mappe Offline", + "uk" to "Organic Maps: GPS карти офлайн", + "zh-TW" to "Organic Maps・離線地圖與導航 GPS", + "zh-HK" to "Organic Maps: 地圖與導航", + "gl-ES" to "Organic Maps・Mapa fóra de liña", + "bg" to "Organic Maps: офлайн GPS карти", + "cs-CZ" to "Organic Maps・mapy offline, GPS", + "ml-IN" to "Organic Maps・ഓഫ്‌ലൈൻ മാപ്പ്", + "nl-NL" to "Organic Maps: offline kaarten", + "de-DE" to "Organic Maps Offline Karten", + "ja-JP" to "Organic Maps: マップ & ナビゲーション", + "da-DK" to "Organic Maps: Offline Kort", + "fa" to "Organic Maps・نقشه آفلاین و GPS", + "ur" to "Organic Maps・Offline Map & GPS", + "ko-KR" to "Organic Maps・GPS 지도 길찾기 앱 & 地图", + "id" to "Organic Maps: pemetaan offline", + "sr" to "Organic Maps・Mape i navigacija", + "el-GR" to "Organic Maps: Χάρτες & GPS", + "eu-ES" to "Organic Maps・Offline Map & GPS", + "hu-HU" to "Organic Maps offline navigáció", + "lo-LA" to "Organic Maps・ແຜນທີ່ອອບໄລນ໌", + "no-NO" to "Organic Maps・kart & navigasjon", + "sv-SE" to "Organic Maps: kartor & GPS", + "et" to "Organic Maps: gps offline", + "pl-PL" to "Organic Map・mapy i GPS offline", + "kn-IN" to "Organic Maps・ಆಫ್‌ಲೈನ್ ಮ್ಯಾಪ್", + "pt-BR" to "Organic Maps - Mapas offline", + "ar" to "Organic Maps・خرائط بدون إنترنت", + "ka-GE" to "Organic Map: ნავიგაცია, რუკები", + "sk" to "Organic Map・Offline Mapy & GPS", + "gu" to "Organic Maps・ઓફલાઇન નકશો", + "az-AZ" to "Organic Maps – Xəritə və GPS", + "fi-FI" to "Organic Maps: offline kartat", + ) + .getBestLocale(localeList) ?: "Unknown App", + isInstalled = false, + imageModel = + "https://f-droid.org/repo/app.organicmaps/en-US/icon_dE7f4P95-uKZwu7cI89Q0xSi_-gvU4DD-XnLoDG9RLg=.png", + ), + AppDiscoverItem( + packageName = "at.bitfire.davdroid", + name = mapOf("ca" to "DAVx⁵", "en-US" to "DAVx⁵").getBestLocale(localeList) ?: "Unknown App", + isInstalled = false, + imageModel = + "https://f-droid.org/repo/at.bitfire.davdroid/en-US/icon_NexNou7vmaD45rbdc8kjLj0Rv7FW128Mde9OQpHFXPE=.png", + ), + AppDiscoverItem( + packageName = "ch.protonvpn.android", + name = + mapOf("en-US" to "ProtonVPN - Secure and Free VPN").getBestLocale(localeList) + ?: "Unknown App", + isInstalled = false, + imageModel = + "https://f-droid.org/repo/ch.protonvpn.android/en-US/icon_xAphlcwMgx7oE7sxB15sxUFIO8geUokWkG01K1fubas=.png", + ), + AppDiscoverItem( + packageName = "com.aurora.store", + name = mapOf("en-US" to "Aurora Store").getBestLocale(localeList) ?: "Unknown App", + isInstalled = false, + imageModel = + "https://f-droid.org/repo/com.aurora.store/en-US/icon_tbAhwq51NNd0liZcTg0cQNNvazxrWlj7bPCe_1TkCV8=.png", + ), + AppDiscoverItem( + packageName = "com.duckduckgo.mobile.android", + name = + mapOf("en-US" to "DuckDuckGo Privacy Browser").getBestLocale(localeList) ?: "Unknown App", + isInstalled = false, + imageModel = + "https://f-droid.org/repo/com.duckduckgo.mobile.android/en-US/icon_QyKhnj_C0Pek3xtJAfPFTvywRXDutsVh7r-9t-doP9E=.png", + ), + AppDiscoverItem( + packageName = "com.foobnix.pro.pdf.reader", + name = mapOf("en-US" to "Librera Reader").getBestLocale(localeList) ?: "Unknown App", + isInstalled = false, + imageModel = + "https://f-droid.org/repo/com.foobnix.pro.pdf.reader/en-US/icon_y15Jxhzp6YrmjLC-wtc27B6XLTcArf7yK-2WlpNaoe0=.png", + ), + ) diff --git a/app/src/androidTest/java/org/fdroid/ui/screenshots/DiscoverScreenshotTest.kt b/app/src/androidTest/java/org/fdroid/ui/screenshots/DiscoverScreenshotTest.kt new file mode 100644 index 000000000..8cd10a02a --- /dev/null +++ b/app/src/androidTest/java/org/fdroid/ui/screenshots/DiscoverScreenshotTest.kt @@ -0,0 +1,34 @@ +package org.fdroid.ui.screenshots + +import androidx.compose.foundation.text.input.rememberTextFieldState +import androidx.core.os.LocaleListCompat +import org.fdroid.ui.discover.Discover +import org.fdroid.ui.discover.LoadedDiscoverModel +import org.junit.Ignore +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.Parameterized + +@RunWith(Parameterized::class) +class DiscoverScreenshotTest(localeName: String) : LocalizedScreenshotTest(localeName) { + + companion object { + @JvmStatic @Parameterized.Parameters(name = "{0}") fun locales() = locales + } + + @Test + fun appDetails() = + screenshotTest("1_Discover") { + val localeList = LocaleListCompat.getDefault() + val model = + LoadedDiscoverModel( + newApps = getNewApps(localeList), + recentlyUpdatedApps = getRecentlyUpdatedApps(localeList), + mostDownloadedApps = getMostDownloadedApps(localeList), + categories = getCategoryItems(localeList).groupBy { it.group }, + searchTextFieldState = rememberTextFieldState(), + hasRepoIssues = false, + ) + Discover(discoverModel = model, onListTap = {}, onAppTap = {}, onNav = {}) + } +} diff --git a/app/src/androidTest/java/org/fdroid/ui/screenshots/IdlingEventListener.kt b/app/src/androidTest/java/org/fdroid/ui/screenshots/IdlingEventListener.kt new file mode 100644 index 000000000..aded9657f --- /dev/null +++ b/app/src/androidTest/java/org/fdroid/ui/screenshots/IdlingEventListener.kt @@ -0,0 +1,29 @@ +package org.fdroid.ui.screenshots + +import androidx.compose.ui.test.IdlingResource +import coil3.EventListener +import coil3.request.ErrorResult +import coil3.request.ImageRequest +import coil3.request.SuccessResult + +class IdlingEventListener : IdlingResource, EventListener() { + private val requests: MutableSet = java.util.concurrent.ConcurrentHashMap.newKeySet() + override val isIdleNow: Boolean + get() = requests.isEmpty() + + override fun onStart(request: ImageRequest) { + requests.add(request.data.toString()) + } + + override fun onSuccess(request: ImageRequest, result: SuccessResult) { + requests.remove(request.data.toString()) + } + + override fun onError(request: ImageRequest, result: ErrorResult) { + requests.remove(request.data.toString()) + } + + override fun onCancel(request: ImageRequest) { + requests.remove(request.data.toString()) + } +} diff --git a/app/src/androidTest/java/org/fdroid/ui/screenshots/LocalizedScreenshotTest.kt b/app/src/androidTest/java/org/fdroid/ui/screenshots/LocalizedScreenshotTest.kt new file mode 100644 index 000000000..7d1150d42 --- /dev/null +++ b/app/src/androidTest/java/org/fdroid/ui/screenshots/LocalizedScreenshotTest.kt @@ -0,0 +1,87 @@ +package org.fdroid.ui.screenshots + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.test.DeviceConfigurationOverride +import androidx.compose.ui.test.Locales +import androidx.compose.ui.test.junit4.v2.createComposeRule +import androidx.compose.ui.text.intl.LocaleList +import androidx.navigation3.runtime.NavKey +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import coil3.SingletonImageLoader +import coil3.annotation.DelicateCoilApi +import java.io.File +import kotlin.test.assertTrue +import kotlin.test.fail +import org.fdroid.BuildConfig.FLAVOR_variant +import org.fdroid.ui.MainContent +import org.fdroid.ui.navigation.NavigationKey +import org.junit.Assume.assumeTrue +import org.junit.Before +import org.junit.Rule + +private const val ENABLED = false + +@OptIn(DelicateCoilApi::class) +abstract class LocalizedScreenshotTest(val localeName: String) { + @get:Rule val composeRule = createComposeRule() + + companion object { + val locales = listOf("en-US", "de-DE", "ar-SA", "he", "zh-CN") + } + + private val context = InstrumentationRegistry.getInstrumentation().targetContext + private val idlingEventListener = IdlingEventListener() + private val uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + init { + val imageLoader = + SingletonImageLoader.get(context).newBuilder().eventListener(idlingEventListener).build() + SingletonImageLoader.setUnsafe(imageLoader) + composeRule.registerIdlingResource(idlingEventListener) + } + + @Before + fun before() { + assumeTrue(ENABLED) + } + + protected fun screenshotTest( + screenName: String, + showBottomBar: Boolean = true, + currentNavKey: NavKey = NavigationKey.Discover, + numUpdates: Int = 3, + hasAppIssues: Boolean = true, + content: @Composable (Modifier) -> Unit, + ) { + val localeList = LocaleList(localeName) + composeRule.setContent { + DeviceConfigurationOverride( + override = DeviceConfigurationOverride.Locales(locales = localeList) + ) { + MainContent( + isBigScreen = false, + dynamicColors = false, + showBottomBar = showBottomBar, + currentNavKey = currentNavKey, + numUpdates = numUpdates, + hasAppIssues = hasAppIssues, + onNav = {}, + content = content, + ) + } + } + composeRule.waitForIdle() + + val dir = context.getExternalFilesDir("screenshots") ?: fail("Could not create screenshots dir") + assertTrue(dir.isDirectory) + val subDir = + File(dir, "${FLAVOR_variant}/fastlane/metadata/$localeName/images/phoneScreenshots") + subDir.mkdirs() + assertTrue(subDir.isDirectory) + + val file = File(subDir, "${screenName}.png") + uiDevice.takeScreenshot(file) + } +} diff --git a/app/src/androidTest/java/org/fdroid/ui/screenshots/MyAppsItems.kt b/app/src/androidTest/java/org/fdroid/ui/screenshots/MyAppsItems.kt new file mode 100644 index 000000000..7ecdf198f --- /dev/null +++ b/app/src/androidTest/java/org/fdroid/ui/screenshots/MyAppsItems.kt @@ -0,0 +1,304 @@ +package org.fdroid.ui.screenshots + +import androidx.core.os.LocaleListCompat +import org.fdroid.LocaleChooser.getBestLocale +import org.fdroid.ui.apps.AppUpdateItem +import org.fdroid.ui.apps.InstalledAppItem +import org.fdroid.ui.utils.getPreviewVersion + +fun getUpdates(localeList: LocaleListCompat) = + listOf( + AppUpdateItem( + repoId = 1L, + packageName = "app.organicmaps", + name = + mapOf( + "vi" to "Organic Maps: bản đồ dẫn đường", + "km-KH" to "Organic Maps・ផែនទីក្រៅបណ្ដាញ", + "pt-PT" to "Organic Maps - Mapas offline", + "zh-CN" to "Organic Maps・离线地图与导航 & GPS", + "iw-IL" to "Organic Maps・מפת אופליין ו-GPS", + "lv" to "Organic Maps・Kartes・Navigācija", + "kk" to "Organic Maps: Карталар", + "hr" to "Organic Maps: offline karte", + "th" to "Organic Maps: แผนที่gps", + "si-LK" to "Organic Maps・ඔෆ්ලයින් සිතියම්", + "sl" to "Organic Maps・Offline Karte", + "ru-RU" to "Organic Maps: GPS карты офлайн", + "ne-NP" to "Organic Map・अफलाइन नक्सा & GPS", + "fr-FR" to "Organic Maps: gps hors ligne", + "es-ES" to "Organic Maps: mapas offline", + "mk-MK" to "Organic Maps・Мапи и навигација", + "be" to "Organic Maps: GPS карты офлайн", + "lt" to "Organic Maps・žemėlapis & GPS", + "ms" to "Organic Maps: Peta & Navigasi", + "en-US" to "Organic Maps・Offline Map & GPS", + "tr-TR" to "Organic Maps: Haritalar ve GPS", + "ro" to "Organic Maps: hărți offline", + "hi-IN" to "Organic Maps・ऑफ़लाइन मैप", + "mr-IN" to "Organic Maps ऑफलाईन नकाशे", + "bn-BD" to "Organic Maps・मैप्स और नेविगेशन", + "ca" to "Organic Map・Mapa Offline i GPS", + "it-IT" to "Organic Maps: Mappe Offline", + "uk" to "Organic Maps: GPS карти офлайн", + "zh-TW" to "Organic Maps・離線地圖與導航 GPS", + "zh-HK" to "Organic Maps: 地圖與導航", + "gl-ES" to "Organic Maps・Mapa fóra de liña", + "bg" to "Organic Maps: офлайн GPS карти", + "cs-CZ" to "Organic Maps・mapy offline, GPS", + "ml-IN" to "Organic Maps・ഓഫ്‌ലൈൻ മാപ്പ്", + "nl-NL" to "Organic Maps: offline kaarten", + "de-DE" to "Organic Maps Offline Karten", + "ja-JP" to "Organic Maps: マップ & ナビゲーション", + "da-DK" to "Organic Maps: Offline Kort", + "fa" to "Organic Maps・نقشه آفلاین و GPS", + "ur" to "Organic Maps・Offline Map & GPS", + "ko-KR" to "Organic Maps・GPS 지도 길찾기 앱 & 地图", + "id" to "Organic Maps: pemetaan offline", + "sr" to "Organic Maps・Mape i navigacija", + "el-GR" to "Organic Maps: Χάρτες & GPS", + "eu-ES" to "Organic Maps・Offline Map & GPS", + "hu-HU" to "Organic Maps offline navigáció", + "lo-LA" to "Organic Maps・ແຜນທີ່ອອບໄລນ໌", + "no-NO" to "Organic Maps・kart & navigasjon", + "sv-SE" to "Organic Maps: kartor & GPS", + "et" to "Organic Maps: gps offline", + "pl-PL" to "Organic Map・mapy i GPS offline", + "kn-IN" to "Organic Maps・ಆಫ್‌ಲೈನ್ ಮ್ಯಾಪ್", + "pt-BR" to "Organic Maps - Mapas offline", + "ar" to "Organic Maps・خرائط بدون إنترنت", + "ka-GE" to "Organic Map: ნავიგაცია, რუკები", + "sk" to "Organic Map・Offline Mapy & GPS", + "gu" to "Organic Maps・ઓફલાઇન નકશો", + "az-AZ" to "Organic Maps – Xəritə və GPS", + "fi-FI" to "Organic Maps: offline kartat", + ) + .getBestLocale(localeList) ?: "Unknown App", + installedVersionName = "2026.02.18-4-FDroid", + update = getPreviewVersion(versionName = "2026.02.18-5-FDroid", size = 70355961), + whatsNew = "foo bar", + iconModel = + "https://f-droid.org/repo/app.organicmaps/en-US/icon_dE7f4P95-uKZwu7cI89Q0xSi_-gvU4DD-XnLoDG9RLg=.png", + ), + AppUpdateItem( + repoId = 1L, + packageName = "at.bitfire.davdroid", + name = mapOf("ca" to "DAVx⁵", "en-US" to "DAVx⁵").getBestLocale(localeList) ?: "Unknown App", + installedVersionName = "4.5.8-ose", + update = getPreviewVersion(versionName = "4.5.9-ose", size = 15974669), + whatsNew = null, + iconModel = + "https://f-droid.org/repo/at.bitfire.davdroid/en-US/icon_NexNou7vmaD45rbdc8kjLj0Rv7FW128Mde9OQpHFXPE=.png", + ), + AppUpdateItem( + repoId = 1L, + packageName = "ch.protonvpn.android", + name = + mapOf("en-US" to "ProtonVPN - Secure and Free VPN").getBestLocale(localeList) + ?: "Unknown App", + installedVersionName = "5.16.30.9", + update = getPreviewVersion(versionName = "5.16.31.0", size = 54161941), + whatsNew = "foo bar", + iconModel = + "https://f-droid.org/repo/ch.protonvpn.android/en-US/icon_xAphlcwMgx7oE7sxB15sxUFIO8geUokWkG01K1fubas=.png", + ), + ) + +fun getInstalledApps(localeList: LocaleListCompat) = + listOf( + InstalledAppItem( + packageName = "com.aurora.store", + name = mapOf("en-US" to "Aurora Store").getBestLocale(localeList) ?: "Unknown App", + installedVersionName = "4.8.1", + installedVersionCode = 1, + lastUpdated = 1771544205000L, + iconModel = + "https://f-droid.org/repo/com.aurora.store/en-US/icon_tbAhwq51NNd0liZcTg0cQNNvazxrWlj7bPCe_1TkCV8=.png", + ), + InstalledAppItem( + packageName = "com.duckduckgo.mobile.android", + name = + mapOf("en-US" to "DuckDuckGo Privacy Browser").getBestLocale(localeList) ?: "Unknown App", + installedVersionName = "5.268.1", + installedVersionCode = 1, + lastUpdated = 1772699310000L, + iconModel = + "https://f-droid.org/repo/com.duckduckgo.mobile.android/en-US/icon_QyKhnj_C0Pek3xtJAfPFTvywRXDutsVh7r-9t-doP9E=.png", + ), + InstalledAppItem( + packageName = "com.foobnix.pro.pdf.reader", + name = mapOf("en-US" to "Librera Reader").getBestLocale(localeList) ?: "Unknown App", + installedVersionName = "9.3.63-fdroid", + installedVersionCode = 1, + lastUpdated = 1772574994000L, + iconModel = + "https://f-droid.org/repo/com.foobnix.pro.pdf.reader/en-US/icon_y15Jxhzp6YrmjLC-wtc27B6XLTcArf7yK-2WlpNaoe0=.png", + ), + InstalledAppItem( + packageName = "com.fsck.k9", + name = + mapOf( + "ar" to "K-9 Mail", + "be" to "Пошта K-9", + "bg" to "K-9 Поща", + "ca" to "K-9 Mail", + "co" to "K-9 Mail", + "cs-CZ" to "K-9 Mail", + "cy" to "K-9 Mail", + "de" to "K-9 Mail", + "el-GR" to "K-9 Mail", + "en-GB" to "K-9 Mail", + "en-US" to "K-9 Mail", + "eo" to "K-9 Retpoŝtilo", + "es" to "K-9 Mail", + "et" to "K-9 Mail", + "eu-ES" to "K-9 Mail", + "fa-IR" to "نامهٔ کی۹", + "fr" to "Courriel K-9 Mail", + "fy" to "K-9 Mail", + "ga" to "K-9 Mail", + "gd" to "Post K-9", + "he" to "K-9 דוא\"ל", + "hi-IN" to "K-9 Mail", + "hr" to "K-9 Mail", + "hu-HU" to "K-9 Mail", + "id" to "Surel K-9", + "is-IS" to "K-9 - Póstur", + "it" to "K-9 Mail", + "ja" to "K-9 Mail", + "kk" to "K-9 Пошта", + "ko-KR" to "K-9 메일", + "lt" to "K-9 paštas", + "mnw" to "တိုက်လိက် K-၉", + "nb" to "K-9 E-post", + "nl-NL" to "K-9 Mail", + "nn" to "K-9 Mail", + "pl" to "K-9 Mail", + "pt-BR" to "K-9 Mail", + "pt-PT" to "K-9 Mail", + "ro" to "K-9 Mail", + "ru" to "Почта K-9", + "sk" to "K-9 Mail", + "sl" to "Pošta K-9", + "sq" to "K-9 Mail", + "sr" to "K-9 Mail", + "sv-SE" to "K-9 Mail", + "ta-IN" to "கே-9 அஞ்சல்", + "tr" to "K-9 Posta", + "uk" to "K-9 Mail", + "vi" to "K-9 Mail", + "zh-CN" to "K-9 Mail", + "zh-TW" to "K-9 Mail", + ) + .getBestLocale(localeList) ?: "Unknown App", + installedVersionName = "16.1", + installedVersionCode = 1, + lastUpdated = 1770745842000L, + iconModel = + "https://f-droid.org/repo/com.fsck.k9/en-US/icon_-2bZW0ZnkKqPVher2SxQK8hXGGSjgaBHoa8x6vW0v8w=.png", + ), + InstalledAppItem( + packageName = "com.github.andreyasadchy.xtra", + name = mapOf("en-US" to "Xtra").getBestLocale(localeList) ?: "Unknown App", + installedVersionName = "2.54.3", + installedVersionCode = 1, + lastUpdated = 1772397992000L, + iconModel = + "https://f-droid.org/repo/com.github.andreyasadchy.xtra/en-US/icon_yfnxF0cNrXwFX2a93BUclISVaIQzoRmbOuxtGDAwz28=.png", + ), + InstalledAppItem( + packageName = "com.github.libretube", + name = mapOf("en-US" to "LibreTube").getBestLocale(localeList) ?: "Unknown App", + installedVersionName = "0.30.0", + installedVersionCode = 1, + lastUpdated = 1769702789000L, + iconModel = + "https://f-droid.org/repo/com.github.libretube/en-US/icon_p6_cfoYk-2IlerJpH4rKIQmkI76zXtS3R9-RZp-3Ggk=.png", + ), + InstalledAppItem( + packageName = "com.inspiredandroid.linuxcommandbibliotheca", + name = mapOf("en-US" to "Linux Command Library").getBestLocale(localeList) ?: "Unknown App", + installedVersionName = "3.5.13", + installedVersionCode = 1, + lastUpdated = 1772463524000L, + iconModel = + "https://f-droid.org/repo/com.inspiredandroid.linuxcommandbibliotheca/en-US/icon_DrA_e_52nvGa_kTMSapBw4MCqKpccl8WZqrG5enB7rI=.png", + ), + InstalledAppItem( + packageName = "com.junkfood.seal", + name = + mapOf( + "ar-SA" to "Seal", + "bn" to "সিল", + "de-DE" to "Seal", + "en-US" to "Seal", + "es" to "Seal", + "fr-FR" to "Seal", + "hi" to "सील", + "hr" to "Seal", + "id" to "Seal", + "it" to "Seal", + "ja" to "Seal", + "ml" to "സീൽ", + "nb-NO" to "Seal", + "nl-NL" to "Zeehond", + "pt-BR" to "Seal", + "ru" to "Seal", + "th" to "Seal", + "uk" to "Тюлень", + "vi" to "Hải Cẩu", + "zh-CN" to "Seal", + "zh-TW" to "Seal", + ) + .getBestLocale(localeList) ?: "Unknown App", + installedVersionName = "1.13.1-(F-Droid)", + installedVersionCode = 1, + lastUpdated = 1767740580000L, + iconModel = + "https://f-droid.org/repo/com.junkfood.seal/en-US/icon_j8mCLA_OX-sJn7TRAdvoaUMW1f6djRv6RMzAnNdaG4I=.png", + ), + InstalledAppItem( + packageName = "com.kunzisoft.keepass.libre", + name = + mapOf( + "ar" to "KeePassDX Passkey Vault", + "cs-CZ" to "Trezor pro klíče KeePassDX", + "de-DE" to "KeePassDX Passkey-Tresor", + "en-US" to "KeePassDX Passkey Vault", + "es-ES" to "KeePassDX Passkey Vault", + "et" to "KeePassDX salasõnahoidla", + "fr-FR" to "KeePassDX - Passkey local", + "hr" to "KeePassDX Passkey Vault", + "hu-HU" to "KeePassDX jelszótároló", + "id" to "KeePassDX Passkey Vault", + "it-IT" to "Cassaforte passkey KeePassDX", + "ja-JP" to "KeePassDX パスワード管理ツール", + "lt" to "KeePassDX slaptažodžių seifas", + "lv" to "KeePassDX: paroļu pārvaldnieks", + "mk-MK" to "KeePassDX Passkey Vault", + "nl-NL" to "KeePassDX Passkey-kluis", + "pl-PL" to "KeePassDX – Bezpieczny sejf", + "ru-RU" to "KeePassDX - менеджер паролей", + "sq" to "Kasafortë Kyçklm. KeePassDX", + "th" to "ตู้นิรภัยพาสคีย์คียพาสดีเอ็กซ์", + "tr-TR" to "KeePassDX Passkey Vault", + "zh-CN" to "KeePassDX 密码库", + "zh-TW" to "KeePassDX 密碼(金鑰/單字)保險庫", + ) + .getBestLocale(localeList) ?: "Unknown App", + installedVersionName = "4.3.2", + installedVersionCode = 1, + lastUpdated = 1768680637000L, + iconModel = + "https://f-droid.org/repo/com.kunzisoft.keepass.libre/en-US/icon_eLwXEQD9l2URrUS3t8esDXnsKGBaH02E-ddEYhV_i7Q=.png", + ), + InstalledAppItem( + packageName = "com.looker.droidify", + name = mapOf("en-US" to "Droid-ify").getBestLocale(localeList) ?: "Unknown App", + installedVersionName = "0.7.0", + installedVersionCode = 1, + lastUpdated = 1771667689000L, + iconModel = + "https://f-droid.org/repo/com.looker.droidify/en-US/icon_lApsnfhrMqGkCaW-IdnYwx86CUjdTutncPvXPJythaM=.png", + ), + ) diff --git a/app/src/androidTest/java/org/fdroid/ui/screenshots/MyAppsScreenshotTest.kt b/app/src/androidTest/java/org/fdroid/ui/screenshots/MyAppsScreenshotTest.kt new file mode 100644 index 000000000..14dd20c13 --- /dev/null +++ b/app/src/androidTest/java/org/fdroid/ui/screenshots/MyAppsScreenshotTest.kt @@ -0,0 +1,35 @@ +package org.fdroid.ui.screenshots + +import androidx.core.os.LocaleListCompat +import org.fdroid.download.NetworkState +import org.fdroid.ui.apps.MyApps +import org.fdroid.ui.apps.MyAppsModel +import org.fdroid.ui.utils.getMyAppsInfo +import org.junit.Ignore +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.Parameterized + +@RunWith(Parameterized::class) +class MyAppsScreenshotTest(localeName: String) : LocalizedScreenshotTest(localeName) { + + companion object { + @JvmStatic @Parameterized.Parameters(name = "{0}") fun locales() = locales + } + + @Test + fun myApps() = + screenshotTest("2_My_Apps", numUpdates = getUpdates(LocaleListCompat.getDefault()).size) { + val localeList = LocaleListCompat.getDefault() + val model = + MyAppsModel( + appUpdates = getUpdates(localeList), + installingApps = emptyList(), + installedApps = getInstalledApps(localeList), + showAppIssueHint = false, + networkState = NetworkState(isOnline = true, isMetered = false), + ) + val info = getMyAppsInfo(model) + MyApps(myAppsInfo = info, currentPackageName = null, onAppItemClick = {}, onNav = {}) + } +} diff --git a/app/src/main/kotlin/org/fdroid/ui/details/AppDetailsHeader.kt b/app/src/main/kotlin/org/fdroid/ui/details/AppDetailsHeader.kt index 6d5ff8320..bec37feab 100644 --- a/app/src/main/kotlin/org/fdroid/ui/details/AppDetailsHeader.kt +++ b/app/src/main/kotlin/org/fdroid/ui/details/AppDetailsHeader.kt @@ -106,7 +106,7 @@ fun AppDetailsHeader(item: AppDetailsItem, innerPadding: PaddingValues) { OfflineBar(modifier = Modifier.absoluteOffset(y = (-8).dp)) } // Header - val version = item.suggestedVersion ?: item.versions?.first()?.version + val version = item.suggestedVersion ?: item.versions?.firstOrNull()?.version Row( modifier = Modifier.padding(horizontal = 16.dp), horizontalArrangement = spacedBy(16.dp), diff --git a/app/src/main/kotlin/org/fdroid/ui/details/AppDetailsItem.kt b/app/src/main/kotlin/org/fdroid/ui/details/AppDetailsItem.kt index 6c24bd686..56a23ed8a 100644 --- a/app/src/main/kotlin/org/fdroid/ui/details/AppDetailsItem.kt +++ b/app/src/main/kotlin/org/fdroid/ui/details/AppDetailsItem.kt @@ -62,7 +62,7 @@ data class AppDetailsItem( val antiFeatures: List? = null, val issue: AppIssue? = null, val authorHasMoreThanOneApp: Boolean = false, - val proxy: ProxyConfig?, + val proxy: ProxyConfig? = null, ) { constructor( repository: Repository, diff --git a/app/src/main/kotlin/org/fdroid/ui/utils/PreviewUtils.kt b/app/src/main/kotlin/org/fdroid/ui/utils/PreviewUtils.kt index 45a9ea42d..968605bb6 100644 --- a/app/src/main/kotlin/org/fdroid/ui/utils/PreviewUtils.kt +++ b/app/src/main/kotlin/org/fdroid/ui/utils/PreviewUtils.kt @@ -145,23 +145,7 @@ val testApp = categories = listOf("Internet", "Multimedia"), isCompatible = true, ), - actions = - AppDetailsActions( - installAction = { _, _, _ -> }, - requestUserConfirmation = { _ -> }, - checkUserConfirmation = { _ -> }, - cancelInstall = {}, - onUninstallResult = { _ -> }, - onRepoChanged = {}, - onPreferredRepoChanged = {}, - allowBetaVersions = {}, - ignoreAllUpdates = {}, - ignoreThisUpdate = {}, - shareApk = Intent(), - uninstallIntent = Intent(), - launchIntent = Intent(), - shareIntent = Intent(), - ), + actions = getAppDetailsActions(), installState = InstallState.Unknown, networkState = NetworkState(isOnline = false, isMetered = false), appPrefs = AppPrefs("org.schabi.newpipe"), @@ -246,6 +230,24 @@ val testApp = proxy = null, ) +fun getAppDetailsActions() = + AppDetailsActions( + installAction = { _, _, _ -> }, + requestUserConfirmation = { _ -> }, + checkUserConfirmation = { _ -> }, + cancelInstall = {}, + onUninstallResult = { _ -> }, + onRepoChanged = {}, + onPreferredRepoChanged = {}, + allowBetaVersions = {}, + ignoreAllUpdates = {}, + ignoreThisUpdate = {}, + shareApk = Intent(), + uninstallIntent = Intent(), + launchIntent = Intent(), + shareIntent = Intent(), + ) + fun getPreviewVersion(versionName: String, size: Long? = null) = object : PackageVersion { override val versionCode: Long = 23 diff --git a/gradle.properties b/gradle.properties index f4c9c9eef..ff6ee5956 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,6 +2,7 @@ org.gradle.jvmargs=-Xms2g -Xmx4g android.enableJetifier=false android.useAndroidX=true android.experimental.enableScreenshotTest=true +android.injected.androidTest.leaveApksInstalledAfterRun=true kotlin.code.style=official kotlin.mpp.androidSourceSetLayoutVersion=2 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6a0c3bd59..682d29082 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -140,6 +140,8 @@ glide-compiler = { module = "com.github.bumptech.glide:compiler", version.ref = glide-compose = { module = "com.github.bumptech.glide:compose", version.ref = "glideCompose" } glide-annotations = { module = "com.github.bumptech.glide:annotations", version.ref = "glide" } coil-compose = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coilCompose" } +coil-test = { module = "io.coil-kt.coil3:coil-test", version.ref = "coilCompose" } +coil-network-okhttp = { module = "io.coil-kt.coil3:coil-network-okhttp", version.ref = "coilCompose" } hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt" } hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hilt" } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 31c596ba0..9d10888c6 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2628,6 +2628,21 @@ + + + + + + + + + + + + + + + diff --git a/tools/update-screenshot-data.py b/tools/update-screenshot-data.py new file mode 100755 index 000000000..27865655a --- /dev/null +++ b/tools/update-screenshot-data.py @@ -0,0 +1,317 @@ +#!/usr/bin/env python3 +# +# Update data for screenshot creation + +import os +import re +import subprocess + +import requests + +os.chdir(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + + +def main(): + top_apps = get_top_apps() + index = get_index() + packages = index.get("packages", {}) + + # Extract packages from index that are in top_apps + metadata_tuples = [(pkg_name, packages[pkg_name]) for pkg_name in top_apps if + pkg_name in packages and "icon" in packages[pkg_name].get("metadata", {})] + discover_items(metadata_tuples) + categories(index) + my_apps(metadata_tuples) + package_name = "org.fdroid.basic" + app_details(package_name, packages[package_name]["metadata"]) + + # Format files according to official coding style + subprocess.run(["./gradlew", "ktfmtFormat", "--rerun-tasks"], check=True) + + +def get_top_apps(): + response = requests.get("https://grote.gitlab.io/fdroid-metrics-distilled/top/50.json") + response.raise_for_status() + return response.json() + + +def get_index(): + response = requests.get("https://f-droid.org/repo/index-v2.json") + response.raise_for_status() + return response.json() + + +def discover_items(metadata_tuples): + # Sort by 'added' descending, take top 6 + sorted_by_added = sorted(metadata_tuples, key=lambda x: x[1]["metadata"].get("added", 0), reverse=True) + apps_new = [(package_name, package["metadata"]) for package_name, package in sorted_by_added[:6]] + already_added = {pkg for pkg, _ in apps_new} + + # take top 6 after those as most downloaded + remaining = [(package_name, package["metadata"]) for package_name, package in metadata_tuples if + package_name not in already_added] + apps_most_downloaded = remaining[:6] + for pkg, _ in apps_most_downloaded: + already_added.add(pkg) + + # take top 6 after those as last updated + remaining = [(package_name, package["metadata"]) for package_name, package in metadata_tuples if + package_name not in already_added] + apps_last_updated = remaining[:6] + + with open('app/src/androidTest/java/org/fdroid/ui/screenshots/DiscoverItems.kt', "w") as f: + f.write("""package org.fdroid.ui.screenshots + +import androidx.core.os.LocaleListCompat +import org.fdroid.LocaleChooser.getBestLocale +import org.fdroid.ui.discover.AppDiscoverItem + +""") + f.write(generate_discover_items("getNewApps", apps_new)) + f.write(generate_discover_items("getRecentlyUpdatedApps", apps_last_updated)) + f.write(generate_discover_items("getMostDownloadedApps", apps_most_downloaded)) + + +def generate_discover_items(function_name, pkg_list): + items = [] + for pkg_name, metadata in pkg_list: + name_entries = get_localized_map("name", metadata) + icon_url = get_localized_file("icon", metadata) + is_installed = "false" if (int(metadata["added"]) / 1000) % 2 == 0 else "true" + + item = ( + f' AppDiscoverItem(\n' + f' packageName = "{pkg_name}",\n' + f' name =\n' + f' {name_entries}.getBestLocale(localeList) ?: "Unknown App",\n' + f' isInstalled = {is_installed},\n' + f' imageModel =\n' + f' "{icon_url}",\n' + f' )' + ) + items.append(item) + + joined = ",\n".join(items) + return ( + f"fun {function_name}(localeList: LocaleListCompat) =\n" + " listOf(\n" + f"{joined}\n" + " )\n\n" + ) + + +def categories(index): + with open('app/src/androidTest/java/org/fdroid/ui/screenshots/CategoryItems.kt', "w") as f: + f.write("""package org.fdroid.ui.screenshots + +import androidx.core.os.LocaleListCompat +import org.fdroid.LocaleChooser.getBestLocale +import org.fdroid.ui.categories.CategoryItem + +""") + f.write(generate_categories(index)) + + +def generate_categories(index): + c = index.get("repo", {}).get("categories", {}) + lines = [] + for cat_id, cat_data in c.items(): + name_entries = get_localized_map("name", cat_data) + lines.append( + f'CategoryItem(id = "{cat_id}", name = {name_entries}.getBestLocale(localeList) ?: "Unknown Category")' + ) + joined = ",\n".join(lines) + return ( + f"fun getCategoryItems(localeList: LocaleListCompat) =\n" + " listOf(\n" + f"{joined}\n" + " )\n\n" + ) + + +def my_apps(pkg_list): + with open('app/src/androidTest/java/org/fdroid/ui/screenshots/MyAppsItems.kt', "w") as f: + f.write("""package org.fdroid.ui.screenshots + +import androidx.core.os.LocaleListCompat +import org.fdroid.LocaleChooser.getBestLocale +import org.fdroid.ui.apps.AppUpdateItem +import org.fdroid.ui.apps.InstalledAppItem +import org.fdroid.ui.utils.getPreviewVersion + +fun getUpdates(localeList: LocaleListCompat) = + listOf( +""") + f.write(generate_app_update_items(pkg_list[:3])) + f.write(""") +fun getInstalledApps(localeList: LocaleListCompat) = + listOf(\n""") + f.write(generate_installed_app_items(pkg_list[3:13])) + f.write(")") + + +def generate_app_update_items(pkg_list): + items = [] + for package_name, data in pkg_list: + metadata = data["metadata"] + name_entries = get_localized_map("name", metadata) + icon_url = get_localized_file("icon", metadata) + + versions = data.get("versions", {}) + first_version_key = next(iter(versions)) + version = versions[first_version_key] + version_name = version.get("manifest", {}).get("versionName", "1.0") + size = version.get("file", {}).get("size") + + whats_new_map = version.get("whatsNew", {}) + if whats_new_map: + whats_new = '"foo bar"' + else: + whats_new = "null" + + item = ( + f'AppUpdateItem(\n' + f' repoId = 1L,\n' + f' packageName = "{package_name}",\n' + f' name = {name_entries}.getBestLocale(localeList) ?: "Unknown App",\n' + f' installedVersionName = "{reduce_version(version_name)}",\n' + f' update = getPreviewVersion(\n' + f' versionName = "{version_name}",\n' + f' size = {size},\n' + f' ),\n' + f' whatsNew = {whats_new},\n' + f' iconModel = "{icon_url}",\n' + f'),' + ) + items.append(item) + return "\n\n".join(items) + + +def reduce_version(version: str) -> str: + parts = re.split(r'(\D+)', version) + numeric_indices = [i for i, p in enumerate(parts) if p.isdigit()] + + for i in reversed(numeric_indices): + if int(parts[i]) > 0: + parts[i] = str(int(parts[i]) - 1) + break + else: + parts[i] = "9" + + return "".join(parts) + + +def generate_installed_app_items(pkg_list): + items = [] + for package_name, data in pkg_list: + metadata = data["metadata"] + name_entries = get_localized_map("name", metadata) + icon_url = get_localized_file("icon", metadata) + + versions = data.get("versions", {}) + first_version_key = next(iter(versions)) + version = versions[first_version_key] + version_name = version["manifest"]["versionName"] + last_updated = metadata["lastUpdated"] + + item = ( + f'InstalledAppItem(\n' + f' packageName = "{package_name}",\n' + f' name = {name_entries}.getBestLocale(localeList) ?: "Unknown App",\n' + f' installedVersionName = "{version_name}",\n' + f' installedVersionCode = 1,\n' + f' lastUpdated = {last_updated}L,\n' + f' iconModel = "{icon_url}",\n' + f'),' + ) + items.append(item) + return "\n\n".join(items) + + +def app_details(package_name: str, metadata: dict): + with open('app/src/androidTest/java/org/fdroid/ui/screenshots/DetailsItem.kt', "w") as f: + f.write("""package org.fdroid.ui.screenshots + +import org.fdroid.database.AppMetadata +""") + f.write(generate_app_metadata(package_name, metadata)) + + +def generate_app_metadata(package_name: str, metadata: dict) -> str: + def quoted(key: str) -> str: + val = metadata.get(key) + return f'"{val}"' if val else "null" + + cats = metadata.get("categories") + categories_str = f'listOf({", ".join(f"{chr(34)}{c}{chr(34)}" for c in cats)})' if cats else "null" + + donate = metadata.get("donate") + donate_str = f'listOf({", ".join(f"{chr(34)}{d}{chr(34)}" for d in donate)})' if donate else "null" + + return ( + f'val appMetadata = AppMetadata(\n' + f' repoId = 1L,\n' + f' packageName = "{package_name}",\n' + f' added = {metadata.get("added", 0)}L,\n' + f' lastUpdated = {metadata.get("lastUpdated", 0)}L,\n' + f' name = {get_localized_map("name", metadata)},\n' + f' summary = {get_localized_map("summary", metadata)},\n' + f' description = {get_localized_map("description", metadata)},\n' + f' webSite = {quoted("webSite")},\n' + f' changelog = {quoted("changelog")},\n' + f' license = {quoted("license")},\n' + f' sourceCode = {quoted("sourceCode")},\n' + f' issueTracker = {quoted("issueTracker")},\n' + f' translation = {quoted("translation")},\n' + f' preferredSigner = {quoted("preferredSigner")},\n' + f' authorName = {quoted("authorName")},\n' + f' authorEmail = {quoted("authorEmail")},\n' + f' authorWebSite = {quoted("authorWebSite")},\n' + f' authorPhone = {quoted("authorPhone")},\n' + f' donate = {donate_str},\n' + f' liberapayID = {quoted("liberapayID")},\n' + f' liberapay = {quoted("liberapay")},\n' + f' openCollective = {quoted("openCollective")},\n' + f' bitcoin = {quoted("bitcoin")},\n' + f' litecoin = {quoted("litecoin")},\n' + f' flattrID = {quoted("flattrID")},\n' + f' categories = {categories_str},\n' + f' isCompatible = true,\n' + f')\n\n' + f'val appDetailsIcon = "{get_localized_file("icon", metadata)}"\n' + f'val appDetailsFeatureGraphic = "{get_localized_file("featureGraphic", metadata)}"\n' + f'val appDetailsScreenshots = {get_screenshots(metadata)}\n' + ) + + +def get_localized_map(key: str, data: dict) -> str: + value = data.get(key) + entries = ", ".join( + f'"{locale}" to "{text.replace('"', '\\"').replace(chr(10), "\\n")[:256].rstrip('\\')}"' for locale, text in + value.items()) + return f"mapOf({entries})" + + +def get_localized_file(key, metadata): + icon_data = metadata.get(key, {}) + for locale, file_info in icon_data.items(): + if isinstance(file_info, dict) and "name" in file_info: + return f"https://f-droid.org/repo/{file_info['name'].lstrip('/')}" + return "" + + +def get_screenshots(metadata: dict) -> dict[str, list[str]]: + phone = metadata.get("screenshots", {}).get("phone", {}) + screenshots = { + locale: [f"https://f-droid.org/repo{s['name']}" for s in shots] + for locale, shots in phone.items() + } + entries = ", ".join( + f'"{locale}" to listOf({", ".join(f"{chr(34)}{url}{chr(34)}" for url in urls)})' + for locale, urls in screenshots.items() + ) + return f"mapOf({entries})" + + +if __name__ == "__main__": + main()