diff --git a/bitchat/Localizable.xcstrings b/bitchat/Localizable.xcstrings index f7002d0c..e498a20e 100644 --- a/bitchat/Localizable.xcstrings +++ b/bitchat/Localizable.xcstrings @@ -13393,6 +13393,1866 @@ } } }, + "image_picker.none_selected" : { + "comment" : "Placeholder shown in the image picker before a selection", + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "لم يتم اختيار أي صورة" + } + }, + "bn" : { + "stringUnit" : { + "state" : "translated", + "value" : "কোনো ছবি নির্বাচন করা হয়নি" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "kein bild ausgewählt" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "no image selected" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "ninguna imagen seleccionada" + } + }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "هیچ تصویری انتخاب نشده" + } + }, + "fil" : { + "stringUnit" : { + "state" : "translated", + "value" : "walang napiling larawan" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "aucune image sélectionnée" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "לא נבחרה תמונה" + } + }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "कोई तस्वीर नहीं चुनी गई" + } + }, + "id" : { + "stringUnit" : { + "state" : "translated", + "value" : "tidak ada gambar yang dipilih" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "nessuna immagine selezionata" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "画像が選択されていません" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "선택된 이미지가 없어요" + } + }, + "ms" : { + "stringUnit" : { + "state" : "translated", + "value" : "tiada imej dipilih" + } + }, + "ne" : { + "stringUnit" : { + "state" : "translated", + "value" : "कुनै तस्बिर चयन गरिएको छैन" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "geen afbeelding geselecteerd" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "nie wybrano obrazu" + } + }, + "pt" : { + "stringUnit" : { + "state" : "translated", + "value" : "nenhuma imagem selecionada" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "nenhuma imagem selecionada" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "изображение не выбрано" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "ingen bild vald" + } + }, + "ta" : { + "stringUnit" : { + "state" : "translated", + "value" : "படம் எதுவும் தேர்ந்தெடுக்கப்படவில்லை" + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "ไม่ได้เลือกรูปภาพ" + } + }, + "tr" : { + "stringUnit" : { + "state" : "translated", + "value" : "görsel seçilmedi" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "зображення не вибрано" + } + }, + "ur" : { + "stringUnit" : { + "state" : "translated", + "value" : "کوئی تصویر منتخب نہیں کی گئی" + } + }, + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "chưa chọn ảnh nào" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "未选择图片" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "未選擇圖片" + } + } + } + }, + "notification.nearby.body_many" : { + "comment" : "Body of the nearby notification; placeholder is the peer count", + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld أشخاص بالجوار" + } + }, + "bn" : { + "stringUnit" : { + "state" : "translated", + "value" : "আশেপাশে %lld জন আছে" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld personen in der nähe" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld people around" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld personas cerca" + } + }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld نفر در اطراف هستند" + } + }, + "fil" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld tao sa paligid" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld personnes dans les parages" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld אנשים בסביבה" + } + }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "आस-पास %lld लोग हैं" + } + }, + "id" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld orang di sekitar" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld persone nei dintorni" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "近くに%lld人います" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "근처에 %lld명이 있어요" + } + }, + "ms" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld orang di sekitar" + } + }, + "ne" : { + "stringUnit" : { + "state" : "translated", + "value" : "वरपर %lld जना छन्" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld mensen in de buurt" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld osób w pobliżu" + } + }, + "pt" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld pessoas por perto" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld pessoas por perto" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "людей рядом: %lld" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld personer i närheten" + } + }, + "ta" : { + "stringUnit" : { + "state" : "translated", + "value" : "அருகில் %lld பேர் இருக்கிறார்கள்" + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "มี %lld คนอยู่แถวนี้" + } + }, + "tr" : { + "stringUnit" : { + "state" : "translated", + "value" : "etrafta %lld kişi var" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "людей поруч: %lld" + } + }, + "ur" : { + "stringUnit" : { + "state" : "translated", + "value" : "آس پاس %lld لوگ ہیں" + } + }, + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "có %lld người ở gần" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "附近有 %lld 个人" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "附近有 %lld 個人" + } + } + } + }, + "notification.nearby.body_one" : { + "comment" : "Body of the nearby notification for exactly one peer", + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "شخص واحد بالجوار" + } + }, + "bn" : { + "stringUnit" : { + "state" : "translated", + "value" : "আশেপাশে 1 জন আছে" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 person in der nähe" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 person around" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 persona cerca" + } + }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 نفر در اطراف است" + } + }, + "fil" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 tao sa paligid" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 personne dans les parages" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "אדם אחד בסביבה" + } + }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "आस-पास 1 व्यक्ति है" + } + }, + "id" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 orang di sekitar" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 persona nei dintorni" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "近くに1人います" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "근처에 1명이 있어요" + } + }, + "ms" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 orang di sekitar" + } + }, + "ne" : { + "stringUnit" : { + "state" : "translated", + "value" : "वरपर 1 जना छ" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 persoon in de buurt" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 osoba w pobliżu" + } + }, + "pt" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 pessoa por perto" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 pessoa por perto" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 человек рядом" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 person i närheten" + } + }, + "ta" : { + "stringUnit" : { + "state" : "translated", + "value" : "அருகில் 1 பேர் இருக்கிறார்" + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "มี 1 คนอยู่แถวนี้" + } + }, + "tr" : { + "stringUnit" : { + "state" : "translated", + "value" : "etrafta 1 kişi var" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 людина поруч" + } + }, + "ur" : { + "stringUnit" : { + "state" : "translated", + "value" : "آس پاس 1 شخص ہے" + } + }, + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "có 1 người ở gần" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "附近有 1 个人" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "附近有 1 個人" + } + } + } + }, + "notification.nearby.title" : { + "comment" : "Title of the local notification when mesh peers come into range", + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 أهل bitchat بالقرب منك!" + } + }, + "bn" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 কাছেই bitchat-এর লোকজন!" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 bitchatter in der nähe!" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 bitchatters nearby!" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 ¡bitchateros cerca!" + } + }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 بیت‌چتی‌ها همین نزدیکی‌اند!" + } + }, + "fil" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 may mga bitchatter sa malapit!" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 des bitchatteurs dans le coin !" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 ביטצ'אטרים בסביבה!" + } + }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 पास में bitchat वाले लोग!" + } + }, + "id" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 ada anak bitchat di sekitar!" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 bitchatter nei paraggi!" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 近くにbitchat仲間がいるよ!" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 근처에 bitchat 친구들이 있어요!" + } + }, + "ms" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 ada geng bitchat berdekatan!" + } + }, + "ne" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 नजिकै bitchat का मान्छेहरू!" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 bitchatters in de buurt!" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 bitchatterzy w pobliżu!" + } + }, + "pt" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 bitchatters por perto!" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 bitchatters por perto!" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 битчаттеры рядом!" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 bitchattare i närheten!" + } + }, + "ta" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 அருகிலேயே bitchat ஆட்கள்!" + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 มีชาว bitchat อยู่ใกล้ๆ!" + } + }, + "tr" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 yakınlarda bitchat'çiler var!" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 бітчатери поруч!" + } + }, + "ur" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 قریب ہی bitchat والے موجود ہیں!" + } + }, + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 có dân bitchat ở gần đây!" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 附近有 bitchat 小伙伴!" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "👥 附近有 bitchat 夥伴!" + } + } + } + }, + "system.screenshot.you" : { + "comment" : "Local system line after your screenshot notice was sent to the DM peer", + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "التقطت لقطة شاشة" + } + }, + "bn" : { + "stringUnit" : { + "state" : "translated", + "value" : "তুমি একটি স্ক্রিনশট নিয়েছ" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "du hast einen screenshot gemacht" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "you took a screenshot" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "hiciste una captura de pantalla" + } + }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "اسکرین‌شات گرفتی" + } + }, + "fil" : { + "stringUnit" : { + "state" : "translated", + "value" : "kumuha ka ng screenshot" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "tu as fait une capture d'écran" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "צילמת את המסך" + } + }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "तुमने स्क्रीनशॉट लिया" + } + }, + "id" : { + "stringUnit" : { + "state" : "translated", + "value" : "kamu mengambil tangkapan layar" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "hai fatto uno screenshot" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "スクリーンショットを撮りました" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "스크린샷을 찍었어요" + } + }, + "ms" : { + "stringUnit" : { + "state" : "translated", + "value" : "anda mengambil tangkapan skrin" + } + }, + "ne" : { + "stringUnit" : { + "state" : "translated", + "value" : "तिमीले स्क्रिनसट लियौ" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "je hebt een screenshot gemaakt" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "zrobiłeś(-aś) zrzut ekranu" + } + }, + "pt" : { + "stringUnit" : { + "state" : "translated", + "value" : "tiraste uma captura de ecrã" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "você tirou uma captura de tela" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "ты сделал(а) скриншот" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "du tog en skärmbild" + } + }, + "ta" : { + "stringUnit" : { + "state" : "translated", + "value" : "நீங்கள் ஸ்கிரீன்ஷாட் எடுத்தீர்கள்" + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "คุณแคปหน้าจอ" + } + }, + "tr" : { + "stringUnit" : { + "state" : "translated", + "value" : "ekran görüntüsü aldın" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "ти зробив(-ла) знімок екрана" + } + }, + "ur" : { + "stringUnit" : { + "state" : "translated", + "value" : "تم نے اسکرین شاٹ لیا" + } + }, + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "bạn vừa chụp màn hình" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "你截屏了" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "你截圖了" + } + } + } + }, + "voice.error.mic_permission" : { + "comment" : "Alert message when the microphone permission is denied", + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "يلزم الوصول إلى الميكروفون لتسجيل الرسائل الصوتية." + } + }, + "bn" : { + "stringUnit" : { + "state" : "translated", + "value" : "ভয়েস নোট রেকর্ড করতে মাইক্রোফোন অ্যাক্সেস প্রয়োজন।" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "mikrofonzugriff wird benötigt, um sprachnotizen aufzunehmen." + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "microphone access is required to record voice notes." + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "se necesita acceso al micrófono para grabar notas de voz." + } + }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "برای ضبط پیام‌های صوتی به دسترسی میکروفون نیاز است." + } + }, + "fil" : { + "stringUnit" : { + "state" : "translated", + "value" : "kailangan ng access sa mikropono para makapag-record ng voice notes." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "l'accès au micro est nécessaire pour enregistrer des notes vocales." + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "נדרשת גישה למיקרופון כדי להקליט הודעות קוליות." + } + }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "वॉइस नोट्स रिकॉर्ड करने के लिए माइक्रोफ़ोन की अनुमति ज़रूरी है।" + } + }, + "id" : { + "stringUnit" : { + "state" : "translated", + "value" : "akses mikrofon diperlukan untuk merekam pesan suara." + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "l'accesso al microfono è necessario per registrare note vocali." + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "ボイスメモを録音するにはマイクへのアクセスが必要です。" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "음성 메모를 녹음하려면 마이크 접근 권한이 필요해요." + } + }, + "ms" : { + "stringUnit" : { + "state" : "translated", + "value" : "akses mikrofon diperlukan untuk merakam nota suara." + } + }, + "ne" : { + "stringUnit" : { + "state" : "translated", + "value" : "भ्वाइस नोट रेकर्ड गर्न माइक्रोफोन पहुँच आवश्यक छ।" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "microfoontoegang is nodig om spraakmemo's op te nemen." + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "dostęp do mikrofonu jest wymagany, aby nagrywać wiadomości głosowe." + } + }, + "pt" : { + "stringUnit" : { + "state" : "translated", + "value" : "é preciso acesso ao microfone para gravar notas de voz." + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "o acesso ao microfone é necessário para gravar notas de voz." + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "для записи голосовых сообщений нужен доступ к микрофону." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "mikrofonåtkomst krävs för att spela in röstmeddelanden." + } + }, + "ta" : { + "stringUnit" : { + "state" : "translated", + "value" : "குரல் குறிப்புகளை பதிவு செய்ய மைக்ரோஃபோன் அணுகல் தேவை." + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "ต้องใช้สิทธิ์เข้าถึงไมโครโฟนเพื่ออัดข้อความเสียง" + } + }, + "tr" : { + "stringUnit" : { + "state" : "translated", + "value" : "sesli not kaydetmek için mikrofon erişimi gerekiyor." + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "для запису голосових повідомлень потрібен доступ до мікрофона." + } + }, + "ur" : { + "stringUnit" : { + "state" : "translated", + "value" : "وائس نوٹس ریکارڈ کرنے کے لیے مائیکروفون تک رسائی درکار ہے۔" + } + }, + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "cần quyền truy cập micro để ghi âm tin nhắn thoại." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "录制语音消息需要麦克风权限。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "錄製語音訊息需要麥克風權限。" + } + } + } + }, + "voice.error.save_failed" : { + "comment" : "Alert message when a finished voice note cannot be saved", + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "تعذّر حفظ التسجيل." + } + }, + "bn" : { + "stringUnit" : { + "state" : "translated", + "value" : "রেকর্ডিং সংরক্ষণ করা যায়নি।" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "aufnahme konnte nicht gespeichert werden." + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "recording failed to save." + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "no se pudo guardar la grabación." + } + }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "ضبط ذخیره نشد." + } + }, + "fil" : { + "stringUnit" : { + "state" : "translated", + "value" : "hindi na-save ang recording." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "l'enregistrement n'a pas pu être sauvegardé." + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "שמירת ההקלטה נכשלה." + } + }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "रिकॉर्डिंग सेव नहीं हो सकी।" + } + }, + "id" : { + "stringUnit" : { + "state" : "translated", + "value" : "rekaman gagal disimpan." + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "impossibile salvare la registrazione." + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "録音を保存できませんでした。" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "녹음을 저장하지 못했어요." + } + }, + "ms" : { + "stringUnit" : { + "state" : "translated", + "value" : "rakaman gagal disimpan." + } + }, + "ne" : { + "stringUnit" : { + "state" : "translated", + "value" : "रेकर्डिङ सेभ गर्न सकिएन।" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "de opname kon niet worden opgeslagen." + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "nie udało się zapisać nagrania." + } + }, + "pt" : { + "stringUnit" : { + "state" : "translated", + "value" : "não foi possível guardar a gravação." + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "não foi possível salvar a gravação." + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "не удалось сохранить запись." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "inspelningen kunde inte sparas." + } + }, + "ta" : { + "stringUnit" : { + "state" : "translated", + "value" : "பதிவை சேமிக்க முடியவில்லை." + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "บันทึกเสียงที่อัดไว้ไม่สำเร็จ" + } + }, + "tr" : { + "stringUnit" : { + "state" : "translated", + "value" : "kayıt kaydedilemedi." + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "не вдалося зберегти запис." + } + }, + "ur" : { + "stringUnit" : { + "state" : "translated", + "value" : "ریکارڈنگ محفوظ نہیں ہو سکی۔" + } + }, + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "không lưu được bản ghi âm." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "录音保存失败。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "錄音儲存失敗。" + } + } + } + }, + "voice.error.start_failed" : { + "comment" : "Alert message when the recorder fails to start", + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "تعذّر بدء التسجيل." + } + }, + "bn" : { + "stringUnit" : { + "state" : "translated", + "value" : "রেকর্ডিং শুরু করা যায়নি।" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "aufnahme konnte nicht gestartet werden." + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "could not start recording." + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "no se pudo iniciar la grabación." + } + }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "ضبط شروع نشد." + } + }, + "fil" : { + "stringUnit" : { + "state" : "translated", + "value" : "hindi masimulan ang pag-record." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "impossible de démarrer l'enregistrement." + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "לא ניתן היה להתחיל את ההקלטה." + } + }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "रिकॉर्डिंग शुरू नहीं हो सकी।" + } + }, + "id" : { + "stringUnit" : { + "state" : "translated", + "value" : "tidak dapat memulai perekaman." + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "impossibile avviare la registrazione." + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "録音を開始できませんでした。" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "녹음을 시작할 수 없어요." + } + }, + "ms" : { + "stringUnit" : { + "state" : "translated", + "value" : "tidak dapat memulakan rakaman." + } + }, + "ne" : { + "stringUnit" : { + "state" : "translated", + "value" : "रेकर्डिङ सुरु गर्न सकिएन।" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "kon de opname niet starten." + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "nie udało się rozpocząć nagrywania." + } + }, + "pt" : { + "stringUnit" : { + "state" : "translated", + "value" : "não foi possível iniciar a gravação." + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "não foi possível iniciar a gravação." + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "не удалось начать запись." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "kunde inte starta inspelningen." + } + }, + "ta" : { + "stringUnit" : { + "state" : "translated", + "value" : "பதிவை தொடங்க முடியவில்லை." + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "เริ่มอัดเสียงไม่ได้" + } + }, + "tr" : { + "stringUnit" : { + "state" : "translated", + "value" : "kayıt başlatılamadı." + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "не вдалося почати запис." + } + }, + "ur" : { + "stringUnit" : { + "state" : "translated", + "value" : "ریکارڈنگ شروع نہیں ہو سکی۔" + } + }, + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "không thể bắt đầu ghi âm." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无法开始录音。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "無法開始錄音。" + } + } + } + }, + "voice.error.title" : { + "comment" : "Title of the voice recording error alert", + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "خطأ في التسجيل" + } + }, + "bn" : { + "stringUnit" : { + "state" : "translated", + "value" : "রেকর্ডিং ত্রুটি" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "aufnahmefehler" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "recording error" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "error de grabación" + } + }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "خطای ضبط" + } + }, + "fil" : { + "stringUnit" : { + "state" : "translated", + "value" : "error sa pag-record" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "erreur d'enregistrement" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "שגיאת הקלטה" + } + }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "रिकॉर्डिंग त्रुटि" + } + }, + "id" : { + "stringUnit" : { + "state" : "translated", + "value" : "kesalahan perekaman" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "errore di registrazione" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "録音エラー" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "녹음 오류" + } + }, + "ms" : { + "stringUnit" : { + "state" : "translated", + "value" : "ralat rakaman" + } + }, + "ne" : { + "stringUnit" : { + "state" : "translated", + "value" : "रेकर्डिङ त्रुटि" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "opnamefout" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "błąd nagrywania" + } + }, + "pt" : { + "stringUnit" : { + "state" : "translated", + "value" : "erro de gravação" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "erro de gravação" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "ошибка записи" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "inspelningsfel" + } + }, + "ta" : { + "stringUnit" : { + "state" : "translated", + "value" : "ஒலிப்பதிவு பிழை" + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "การอัดเสียงผิดพลาด" + } + }, + "tr" : { + "stringUnit" : { + "state" : "translated", + "value" : "kayıt hatası" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "помилка запису" + } + }, + "ur" : { + "stringUnit" : { + "state" : "translated", + "value" : "ریکارڈنگ میں خرابی" + } + }, + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "lỗi ghi âm" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "录音出错" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "錄音錯誤" + } + } + } + }, + "voice.error.too_short" : { + "comment" : "Alert message when a voice note is released too quickly to save", + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "التسجيل قصير جدًا." + } + }, + "bn" : { + "stringUnit" : { + "state" : "translated", + "value" : "রেকর্ডিং খুব ছোট।" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "aufnahme ist zu kurz." + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "recording is too short." + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "la grabación es demasiado corta." + } + }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "ضبط خیلی کوتاه است." + } + }, + "fil" : { + "stringUnit" : { + "state" : "translated", + "value" : "masyadong maikli ang recording." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "l'enregistrement est trop court." + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "ההקלטה קצרה מדי." + } + }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "रिकॉर्डिंग बहुत छोटी है।" + } + }, + "id" : { + "stringUnit" : { + "state" : "translated", + "value" : "rekaman terlalu pendek." + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "la registrazione è troppo corta." + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "録音が短すぎます。" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "녹음이 너무 짧아요." + } + }, + "ms" : { + "stringUnit" : { + "state" : "translated", + "value" : "rakaman terlalu pendek." + } + }, + "ne" : { + "stringUnit" : { + "state" : "translated", + "value" : "रेकर्डिङ धेरै छोटो छ।" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "de opname is te kort." + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "nagranie jest za krótkie." + } + }, + "pt" : { + "stringUnit" : { + "state" : "translated", + "value" : "a gravação é demasiado curta." + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "a gravação é muito curta." + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "запись слишком короткая." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "inspelningen är för kort." + } + }, + "ta" : { + "stringUnit" : { + "state" : "translated", + "value" : "பதிவு மிகவும் குறுகியது." + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "เสียงที่อัดสั้นเกินไป" + } + }, + "tr" : { + "stringUnit" : { + "state" : "translated", + "value" : "kayıt çok kısa." + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "запис надто короткий." + } + }, + "ur" : { + "stringUnit" : { + "state" : "translated", + "value" : "ریکارڈنگ بہت مختصر ہے۔" + } + }, + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "bản ghi âm quá ngắn." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "录音太短了。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "錄音太短了。" + } + } + } + }, "content.delivery.reason.legacy_media_consent_required" : { "comment" : "Failure reason when a legacy private-media send lacks per-send consent", "extractionState" : "manual", diff --git a/bitchat/Services/NotificationService.swift b/bitchat/Services/NotificationService.swift index dc8ef193..e50d4da5 100644 --- a/bitchat/Services/NotificationService.swift +++ b/bitchat/Services/NotificationService.swift @@ -260,8 +260,10 @@ final class NotificationService { } func sendNetworkAvailableNotification(peerCount: Int) { - let title = "👥 bitchatters nearby!" - let body = peerCount == 1 ? "1 person around" : "\(peerCount) people around" + let title = String(localized: "notification.nearby.title", defaultValue: "👥 bitchatters nearby!", comment: "Title of the local notification when mesh peers come into range") + let body = peerCount == 1 + ? String(localized: "notification.nearby.body_one", defaultValue: "1 person around", comment: "Body of the nearby notification for exactly one peer") + : String(format: String(localized: "notification.nearby.body_many", defaultValue: "%lld people around", comment: "Body of the nearby notification; placeholder is the peer count"), locale: .current, peerCount) // Fixed identifier so iOS updates the existing notification instead of creating new ones let identifier = "network-available" diff --git a/bitchat/ViewModels/ChatLifecycleCoordinator.swift b/bitchat/ViewModels/ChatLifecycleCoordinator.swift index d6684e8e..ea90e692 100644 --- a/bitchat/ViewModels/ChatLifecycleCoordinator.swift +++ b/bitchat/ViewModels/ChatLifecycleCoordinator.swift @@ -304,7 +304,7 @@ private extension ChatLifecycleCoordinator { func appendPrivateScreenshotNotice(for peerID: PeerID) { let notice = BitchatMessage( sender: "system", - content: "you took a screenshot", + content: String(localized: "system.screenshot.you", defaultValue: "you took a screenshot", comment: "Local system line after your screenshot notice was sent to the DM peer"), timestamp: Date(), isRelay: false, originalSender: nil, diff --git a/bitchat/ViewModels/ChatMediaTransferCoordinator.swift b/bitchat/ViewModels/ChatMediaTransferCoordinator.swift index fe314f62..548e48b0 100644 --- a/bitchat/ViewModels/ChatMediaTransferCoordinator.swift +++ b/bitchat/ViewModels/ChatMediaTransferCoordinator.swift @@ -551,7 +551,7 @@ final class ChatMediaTransferCoordinator { guard context.canSendMediaInCurrentContext else { SecureLogger.info("Voice note blocked outside mesh/private context", category: .session) try? FileManager.default.removeItem(at: url) - context.addSystemMessage("Voice notes are only available in mesh chats.") + context.addSystemMessage(String(localized: "Voice notes are only available in mesh chats.", comment: "System message when a voice note is attempted outside mesh chats")) return } @@ -694,7 +694,7 @@ final class ChatMediaTransferCoordinator { guard context.canSendMediaInCurrentContext else { SecureLogger.info("Image send blocked outside mesh/private context", category: .session) cleanup?() - context.addSystemMessage("Images are only available in mesh chats.") + context.addSystemMessage(String(localized: "Images are only available in mesh chats.", comment: "System message when an image send is attempted outside mesh chats")) return } diff --git a/bitchat/ViewModels/VoiceRecordingViewModel.swift b/bitchat/ViewModels/VoiceRecordingViewModel.swift index 727fa39a..adb7d92a 100644 --- a/bitchat/ViewModels/VoiceRecordingViewModel.swift +++ b/bitchat/ViewModels/VoiceRecordingViewModel.swift @@ -29,7 +29,7 @@ final class VoiceRecordingViewModel: ObservableObject { var alertMessage: String { switch self { case .error(let message): message - case .permissionDenied: "Microphone access is required to record voice notes." + case .permissionDenied: String(localized: "voice.error.mic_permission", defaultValue: "microphone access is required to record voice notes.", comment: "Alert message when the microphone permission is denied") case .idle, .requestingPermission, .preparing, .recording: "" } } @@ -156,7 +156,7 @@ final class VoiceRecordingViewModel: ObservableObject { } } activeSession = nil - state = .error(message: "Could not start recording.") + state = .error(message: String(localized: "voice.error.start_failed", defaultValue: "could not start recording.", comment: "Alert message when the recorder fails to start")) } } } @@ -202,8 +202,8 @@ final class VoiceRecordingViewModel: ObservableObject { guard state == .idle else { return } state = .error( message: finalDuration < VoiceRecorder.minRecordingDuration - ? "Recording is too short." - : "Recording failed to save." + ? String(localized: "voice.error.too_short", defaultValue: "recording is too short.", comment: "Alert message when a voice note is released too quickly to save") + : String(localized: "voice.error.save_failed", defaultValue: "recording failed to save.", comment: "Alert message when a finished voice note cannot be saved") ) return } @@ -212,8 +212,8 @@ final class VoiceRecordingViewModel: ObservableObject { guard generation == holdGeneration, state == .idle else { return } state = .error( message: finalDuration < VoiceRecorder.minRecordingDuration - ? "Recording is too short." - : "Recording failed to save." + ? String(localized: "voice.error.too_short", defaultValue: "recording is too short.", comment: "Alert message when a voice note is released too quickly to save") + : String(localized: "voice.error.save_failed", defaultValue: "recording failed to save.", comment: "Alert message when a finished voice note cannot be saved") ) } } diff --git a/bitchat/Views/ContentComposerView.swift b/bitchat/Views/ContentComposerView.swift index 356c4141..b7deab21 100644 --- a/bitchat/Views/ContentComposerView.swift +++ b/bitchat/Views/ContentComposerView.swift @@ -238,7 +238,7 @@ private extension ContentComposerView { } Spacer() Button(action: voiceRecordingVM.cancel) { - Label("Cancel", systemImage: "xmark.circle") + Label(String(localized: "common.cancel", comment: "Cancel action in the voice recording HUD"), systemImage: "xmark.circle") .labelStyle(.iconOnly) .font(.bitchatSystem(size: 18)) .foregroundColor(.red) diff --git a/bitchat/Views/ContentSheetViews.swift b/bitchat/Views/ContentSheetViews.swift index cf62debb..88be040f 100644 --- a/bitchat/Views/ContentSheetViews.swift +++ b/bitchat/Views/ContentSheetViews.swift @@ -282,7 +282,7 @@ struct ContentPeopleSheetView: View { } } #endif - .alert("Recording Error", isPresented: voiceAlertBinding, actions: { + .alert(Text(String(localized: "voice.error.title", defaultValue: "recording error", comment: "Title of the voice recording error alert")), isPresented: voiceAlertBinding, actions: { Button("common.ok", role: .cancel) {} if voiceRecordingVM.state == .permissionDenied { Button("location_channels.action.open_settings") { diff --git a/bitchat/Views/ContentView.swift b/bitchat/Views/ContentView.swift index 48d353c3..db7b0712 100644 --- a/bitchat/Views/ContentView.swift +++ b/bitchat/Views/ContentView.swift @@ -397,7 +397,7 @@ struct ContentView: View { ImagePreviewView(url: url) } } - .alert("Recording Error", isPresented: rootVoiceAlertBinding, actions: { + .alert(Text(String(localized: "voice.error.title", defaultValue: "recording error", comment: "Title of the voice recording error alert")), isPresented: rootVoiceAlertBinding, actions: { Button("common.ok", role: .cancel) {} if voiceRecordingVM.state == .permissionDenied { Button("location_channels.action.open_settings") { diff --git a/bitchat/Views/Image Viewers/ImagePickerView.swift b/bitchat/Views/Image Viewers/ImagePickerView.swift index defc81e4..d4aa9cfe 100644 --- a/bitchat/Views/Image Viewers/ImagePickerView.swift +++ b/bitchat/Views/Image Viewers/ImagePickerView.swift @@ -64,7 +64,7 @@ struct ImagePickerView: UIViewControllerRepresentable { .resizable() .scaledToFit() } else { - Text("No image selected") + Text(String(localized: "image_picker.none_selected", defaultValue: "no image selected", comment: "Placeholder shown in the image picker before a selection")) } Button("Show") { isPresented = true } } diff --git a/bitchat/Views/Image Viewers/MacImagePickerView.swift b/bitchat/Views/Image Viewers/MacImagePickerView.swift index 1b88c7f2..2f467d6c 100644 --- a/bitchat/Views/Image Viewers/MacImagePickerView.swift +++ b/bitchat/Views/Image Viewers/MacImagePickerView.swift @@ -63,7 +63,7 @@ struct MacImagePickerView: View { .resizable() .scaledToFit() } else { - Text("No image selected") + Text(String(localized: "image_picker.none_selected", defaultValue: "no image selected", comment: "Placeholder shown in the image picker before a selection")) } Button("Show") { isPresented = true } }