From 52246b0f35fabe83799d0d67850063092ea2c701 Mon Sep 17 00:00:00 2001 From: gallegonovato Date: Fri, 19 May 2023 11:58:10 +0000 Subject: [PATCH 001/402] Translated using Weblate (Spanish) Currently translated at 100.0% (966 of 966 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/es/ --- src/main/res/values-es/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/res/values-es/strings.xml b/src/main/res/values-es/strings.xml index 8ea82b501..9a58b3b6d 100644 --- a/src/main/res/values-es/strings.xml +++ b/src/main/res/values-es/strings.xml @@ -1019,4 +1019,8 @@ Rechazar Eliminar la cuenta del servidor No se pudo eliminar la cuenta del servidor + Chats en grupo + Buscar un grupo de chats + La búsqueda de canales utiliza un servicio de terceros denominado <a href=https://search.jabber.network>search.jabber.network</a>.<br><br>Si utiliza esta función, tu dirección IP y la búsqueda de términos serán transferidos a este servicio. Para obtener más información, consulta la <a href=https://search.jabber.network/privacy>Política de privacidad</a>. + Guardar como un chat en grupo \ No newline at end of file From c5824e43ac83177a5ed22e985c0ec41d02aaab9f Mon Sep 17 00:00:00 2001 From: ghose Date: Sat, 27 May 2023 08:21:48 +0000 Subject: [PATCH 002/402] Translated using Weblate (Galician) Currently translated at 100.0% (966 of 966 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/gl/ --- src/main/res/values-gl/strings.xml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/res/values-gl/strings.xml b/src/main/res/values-gl/strings.xml index 760d2d5db..bcc2bc11a 100644 --- a/src/main/res/values-gl/strings.xml +++ b/src/main/res/values-gl/strings.xml @@ -35,7 +35,7 @@ enviando… Descifrando a mensaxe. Agarda por favor… - Mensaxe cifrado con OpenPGP + Mensaxe cifrada con OpenPGP O alcume xa está en uso Alcume non válido Admin @@ -98,10 +98,10 @@ Enviar mensaxe a 1%s Enviar mensaxe cifrada con OMEMO Enviar mensaxe cifrada v\\OMEMO - Enviar mensaxe cifrado con OpenPGP + Enviar mensaxe cifrada con OpenPGP Novo alcume en uso Enviar sen cifrar - Fallou o descifrado. Quizais non teñas a chave privada apropiada. + Fallou o desencriptado. Quizais non teñas a chave privada apropiada. OpenKeychain OpenKeychain para cifrar e descifrar as mensaxes e xestionar a túas chaves públicas.

Está baixo licenza GPLv3+ e dispoñible en F-Droid e Google Play.

(Reinicia %1$s após a instalación.)]]>
Reiniciar @@ -176,7 +176,7 @@ Cliente non compatible Erro de fluxo Fallo ao abrir o fluxo - Non cifrado + Sen cifrar OTR OpenPGP OMEMO @@ -669,7 +669,7 @@ Bloquear estraño Bloquear o dominio ao completo En liña neste momento - Volver a intentar o descifrado + Volve intentar o descifrado Fallo na sesión Mecanismo SASL desactualizado O servidor require rexistro no sitio web @@ -705,13 +705,13 @@ Desactivar a encriptación %1$s non pode enviar mensaxes cifradas a %2$s. Podería deberse a que o teu contacto utiliza un servidor sen actualizar ou un cliente que non pode xestionar OMEMO. Non se obtivo a lista de dispositivos - Non se obtiveron as chaves de cifrado + Non se obtiveron as chaves da cifraxe Suxestión: Nalgúns casos, isto pode solucionarse engadíndovos mutuamente as vosas listas de contactos. - Tes a certeza de querer desactivar o cifrado OMEMO para esta conversa\? + Tes a certeza de querer desactivar a cifraxe OMEMO para esta conversa\? \nIsto permitirá á administración do teu servidor ler as túas mensaxes, pero pode ser a única forma de comunicarse con persoas que usan clientes obsoletos. Desactivar agora Borrador: - Cifrado OMEMO + Cifraxe OMEMO OMEMO sempre se utilizará para charlas individuais e privadas en grupo. OMEMO utilizarase por defecto para as novas conversas. OMEMO terá que ser activado explícitamente para novas conversacións. @@ -963,8 +963,8 @@ Esta conversa O teu avatar Avatar para %s - Cifrado con OMEMO - Cifrado con OpenPGP + Cifrada con OMEMO + Cifrada con OpenPGP Sen cifrar Saír Gravar correo de voz From 1258519cfaa24dad8b9b6a607ea416f4a2c83fb8 Mon Sep 17 00:00:00 2001 From: Adeptus2 Date: Fri, 26 May 2023 10:49:24 +0000 Subject: [PATCH 003/402] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (966 of 966 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hant/ --- src/main/res/values-zh-rTW/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/res/values-zh-rTW/strings.xml b/src/main/res/values-zh-rTW/strings.xml index 388ffb1e8..1965f9a15 100644 --- a/src/main/res/values-zh-rTW/strings.xml +++ b/src/main/res/values-zh-rTW/strings.xml @@ -1016,4 +1016,8 @@ 拒絕切換至視訊的要求 從伺服器移除帳戶 無法從伺服器刪除帳戶 + 搜尋群組聊天 + 頻道探索使用一個名為 <a href=https://search.jabber.network>search.jabber.network</a> 的第三方服務,<br><br>使用此功能會將您的 IP 位址和搜尋詞彙傳送至此服務。更多資訊請參見他們的 <a href=https://search.jabber.network/privacy>隱私權政策</a>。 + 群組聊天 + 儲存為群組聊天 \ No newline at end of file From 963f8ccee49f8578c966d6b44121d7e5e0147bd8 Mon Sep 17 00:00:00 2001 From: Adeptus2 Date: Sat, 27 May 2023 10:11:53 +0000 Subject: [PATCH 004/402] Translated using Weblate (Chinese (Traditional)) Currently translated at 10.8% (5 of 46 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/zh_Hant/ --- .../metadata/android/zh-TW/changelogs/397.txt | 3 ++ .../android/zh-TW/changelogs/42047.txt | 1 + .../android/zh-TW/changelogs/42050.txt | 1 + .../android/zh-TW/full_description.txt | 39 +++++++++++++++++++ 4 files changed, 44 insertions(+) create mode 100644 fastlane/metadata/android/zh-TW/changelogs/397.txt create mode 100644 fastlane/metadata/android/zh-TW/changelogs/42047.txt create mode 100644 fastlane/metadata/android/zh-TW/changelogs/42050.txt create mode 100644 fastlane/metadata/android/zh-TW/full_description.txt diff --git a/fastlane/metadata/android/zh-TW/changelogs/397.txt b/fastlane/metadata/android/zh-TW/changelogs/397.txt new file mode 100644 index 000000000..0575a7378 --- /dev/null +++ b/fastlane/metadata/android/zh-TW/changelogs/397.txt @@ -0,0 +1,3 @@ +* 處理 GPX 檔案 +* 改善備份與還原的效能 +* 錯誤修正 diff --git a/fastlane/metadata/android/zh-TW/changelogs/42047.txt b/fastlane/metadata/android/zh-TW/changelogs/42047.txt new file mode 100644 index 000000000..a63fcf276 --- /dev/null +++ b/fastlane/metadata/android/zh-TW/changelogs/42047.txt @@ -0,0 +1 @@ +* 修正 UnifiedPush 散發者當機 diff --git a/fastlane/metadata/android/zh-TW/changelogs/42050.txt b/fastlane/metadata/android/zh-TW/changelogs/42050.txt new file mode 100644 index 000000000..5e10020c6 --- /dev/null +++ b/fastlane/metadata/android/zh-TW/changelogs/42050.txt @@ -0,0 +1 @@ +* 增加設定檔圖片的圓角半徑 diff --git a/fastlane/metadata/android/zh-TW/full_description.txt b/fastlane/metadata/android/zh-TW/full_description.txt new file mode 100644 index 000000000..0e9114c98 --- /dev/null +++ b/fastlane/metadata/android/zh-TW/full_description.txt @@ -0,0 +1,39 @@ +易於使用、可靠、省電,且帶有內建圖像支援、群組聊天和端對端加密的 XMPP 用戶端。 + +設計原則: + +* 在不犧牲安全或隱私權的前提下,盡可能地保持美觀性和易用性 +* 仰賴現存的、已建立的通訊協定 +* 不需要 Google 帳戶或特別的 Google 雲端訊息 (GCM) +* 需要少量可能的權限 + +功能: + +* OMEMOOpenPGP 端對端加密 +* 傳送並接收圖像 +* 加密的音訊和視訊通話 (DTLS-SRTP) +* 依循 Android 設計指南的直覺化 UI +* 為您的聯絡人顯示圖片/ 頭像 +* 與桌面用戶端同步 +* 會議 (書籤支援) +* 通訊錄整合 +* 多個帳戶/整合收件匣 +* 對電池壽命的極低影響 + +Conversations 使在免費的 conversations.im 伺服器上建立一個帳戶變得極為輕易。然而 Conversations 也可在其他 XMPP 伺服器上運作,很多 XMPP 伺服器是由志工驅動的,並且完全免費。 + +XMPP 功能: + +Conversations 可以在所有 XMPP 伺服器上運作。然而,XMPP 是一個可以擴充的通訊協定,這些擴充功能在所謂的 XEP 中也是標準化的。Conversations 支援其中的幾個,已使使用者體驗更佳。有可能您目前的 XMPP 伺服器並不支援這些擴充功能,因此,為了最大限度的發揮 Conversations 的作用,您應該考慮切換到一個支援這些擴充功能的 XMPP 伺服器,或者甚至更好——為您和您的朋友驅動您自己的 XMPP 伺服器。 + +如下 XEP - 截止目前: + +* XEP-0065:SOCKS5 位元資料流 (或 mod_proxy65),將被用於傳輸檔案,如果雙方都在防火牆之後 (NAT)。 +* XEP-0163:用於虛擬化身的私人活動通訊協定 +* XEP-0191:封鎖命令可讓您將濫發垃圾郵件者列入黑名單,或封鎖聯絡人而不把他們從名冊中移除。 +* XEP-0198:串流管理允許 XMPP 在小型網路中斷和基礎 TCP 連線的變更中生存。 +* XEP-0280:訊息副本,自動將您傳送的訊息同步至桌面用戶端,從而允許您在一次會話中從您的行動用戶端無縫切換到您的桌面用戶端。 +* XEP-0237:名冊版本管理,主要是為了節省行動連線不佳時的頻寬。 +* XEP-0313:訊息封存管理將訊息記錄與伺服器同步,隨時掌握離線傳送的訊息。 +* XEP-0352:用戶端狀態指示可讓伺服器知道 Conversations 是否在背景,允許伺服器透過扣留不必要的封裝來節省頻寬。 +* XEP-0363:HTTP 檔案上傳允許您在會議中或與離線聯絡人分享檔案,需要在您的伺服器上有一個額外的元件。 From 6289e048b3d2fdac9095a66cccd7b1b310f1407a Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 5 Jun 2023 10:05:46 +0200 Subject: [PATCH 005/402] catch runtime exception when trying to stop tone manager --- .../siacs/conversations/xmpp/jingle/ToneManager.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/ToneManager.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/ToneManager.java index b64f963d0..2ee307082 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/ToneManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/ToneManager.java @@ -160,8 +160,17 @@ class ToneManager { if (currentTone != null) { currentTone.cancel(true); } - if (toneGenerator != null) { + stopTone(toneGenerator); + } + + private static void stopTone(final ToneGenerator toneGenerator) { + if (toneGenerator == null) { + return; + } + try { toneGenerator.stopTone(); + } catch (final RuntimeException e) { + Log.w(Config.LOGTAG,"tone has already stopped"); } } From 3b26948a9de97c9e735a1c175640fed9e024da2b Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 23 Jun 2023 18:00:58 +0200 Subject: [PATCH 006/402] replace libraries hosted on jcenter --- build.gradle | 11 +++++++---- src/main/AndroidManifest.xml | 2 +- .../java/eu/siacs/conversations/crypto/PgpEngine.java | 4 +++- .../ui/PublishGroupChatProfilePictureActivity.java | 4 ++-- .../ui/PublishProfilePictureActivity.java | 2 +- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/build.gradle b/build.gradle index d1b21e3f5..44e352367 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ apply plugin: 'com.android.application' repositories { google() mavenCentral() - jcenter() + maven { url='https://jitpack.io'} } configurations { @@ -40,8 +40,8 @@ dependencies { } conversationsPlaystoreImplementation("com.android.installreferrer:installreferrer:2.2") quicksyPlaystoreImplementation 'com.google.android.gms:play-services-auth-api-phone:18.0.1' - implementation 'org.sufficientlysecure:openpgp-api:10.0' - implementation 'com.theartofdev.edmodo:android-image-cropper:2.8.0' + implementation 'com.github.open-keychain.open-keychain:openpgp-api:v5.7.1' + implementation("com.github.CanHub:Android-Image-Cropper:2.0.0") implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'androidx.exifinterface:exifinterface:1.3.6' implementation 'androidx.cardview:cardview:1.0.0' @@ -61,7 +61,10 @@ dependencies { implementation 'com.makeramen:roundedimageview:2.3.0' implementation "com.wefika:flowlayout:0.4.1" //noinspection GradleDependency - implementation 'com.otaliastudios:transcoder:0.9.1' + implementation('com.github.natario1:Transcoder:v0.9.1') { + exclude group: 'com.otaliastudios.opengl', module: 'egloo' + } + implementation 'com.github.natario1:Egloo:v0.4.0' implementation 'org.jxmpp:jxmpp-jid:1.0.3' implementation 'org.osmdroid:osmdroid-android:6.1.11' diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index e1fe934af..806232a22 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -298,7 +298,7 @@ android:value="eu.siacs.conversations.ui.SettingsActivity" /> diff --git a/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java b/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java index 9652ad3eb..d3588a995 100644 --- a/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java +++ b/src/main/java/eu/siacs/conversations/crypto/PgpEngine.java @@ -285,7 +285,9 @@ public class PgpEngine { Intent params = new Intent(); params.setAction(OpenPgpApi.ACTION_GET_KEY); params.putExtra(OpenPgpApi.EXTRA_KEY_ID, pgpKeyId); - Intent result = api.executeApi(params, null, null); + final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + final ByteArrayInputStream inputStream = new ByteArrayInputStream(new byte[0]); + Intent result = api.executeApi(params, inputStream, outputStream); return (PendingIntent) result.getParcelableExtra(OpenPgpApi.RESULT_INTENT); } } diff --git a/src/main/java/eu/siacs/conversations/ui/PublishGroupChatProfilePictureActivity.java b/src/main/java/eu/siacs/conversations/ui/PublishGroupChatProfilePictureActivity.java index 81b0ae15c..658567aa6 100644 --- a/src/main/java/eu/siacs/conversations/ui/PublishGroupChatProfilePictureActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/PublishGroupChatProfilePictureActivity.java @@ -40,8 +40,6 @@ import android.widget.Toast; import androidx.annotation.StringRes; import androidx.databinding.DataBindingUtil; -import com.theartofdev.edmodo.cropper.CropImage; - import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.databinding.ActivityPublishProfilePictureBinding; @@ -51,6 +49,8 @@ import eu.siacs.conversations.ui.util.PendingItem; import static eu.siacs.conversations.ui.PublishProfilePictureActivity.REQUEST_CHOOSE_PICTURE; +import com.canhub.cropper.CropImage; + public class PublishGroupChatProfilePictureActivity extends XmppActivity implements OnAvatarPublication { private final PendingItem pendingConversationUuid = new PendingItem<>(); private ActivityPublishProfilePictureBinding binding; diff --git a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java index 16607b81e..b6822b301 100644 --- a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java @@ -19,7 +19,7 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.StringRes; -import com.theartofdev.edmodo.cropper.CropImage; +import com.canhub.cropper.CropImage; import java.util.concurrent.atomic.AtomicBoolean; From 00d7cbf066e733a8cd05579c4034915720c7a2ba Mon Sep 17 00:00:00 2001 From: TheCanine Date: Sat, 10 Jun 2023 12:29:04 +0000 Subject: [PATCH 007/402] Translated using Weblate (Czech) Currently translated at 98.3% (950 of 966 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/cs/ --- src/main/res/values-cs/strings.xml | 101 ++++++++++++++++++++++------- 1 file changed, 77 insertions(+), 24 deletions(-) diff --git a/src/main/res/values-cs/strings.xml b/src/main/res/values-cs/strings.xml index f4e1a083c..1a505ad7f 100644 --- a/src/main/res/values-cs/strings.xml +++ b/src/main/res/values-cs/strings.xml @@ -31,16 +31,9 @@ před %d minutami %d nepřečtená konverzace - - %d nepřečtené konverzace - - %d nepřečtených konverzací - - %d nepřečtených konverzací - odesílám… Dešifrování zprávy. Chvíli strpení… @@ -95,7 +88,9 @@ Smaže historii konverzací Opravdu chcete smazat všechny zprávy v této konverzace?\n\nVarováníToto neovlivní zprávy uložené na jiných zařízeních či serverech. Smazat soubor - Opravdu chcete smazat tento soubor?\n\nVarováníToto neovlivní kopie uložené na jiných zařízeních či serverech. + Opravdu chcete smazat tento soubor\? +\n +\nVarováníToto neovlivní kopie uložené na jiných zařízeních či serverech. Poté zavřít tuto konverzaci Vybrat přístroj Odeslat nešifrovanou zprávu @@ -132,7 +127,7 @@ Zvuk upozornění na nové zprávy Vyzváněcí tón pro příchozí hovory Časová lhůta - Časová lhůta po kterou bude Conversations v tichém režimu při zaznamenání aktivity na jiném přístroji + Časová lhůta po kterou bude Conversations v tichém režimu při zaznamenání aktivity na jiném přístroji. Rozšířené Neodesílat detaily o pádu aplikace Zasíláním detailů o důvodu selhání pomůžete dalšímu vývoji @@ -188,7 +183,7 @@ Skutečně chcete odstranit Váš současný veřejný OpenPGP klíč?\nVaše kontakty Vám nebudou moci nadále posílat zprávy šifrované pomocí OpenPGP. OpenPGP veřejný klíč zveřejněn. Povolit účet - Smazáním Vašeho účtu dojde k vymazání celé Vaší historie konverzací. + Opravdu chcete svůj účet smazat\? Smazáním Vašeho účtu dojde k vymazání celé Vaší historie konverzací Nahrát hlas Adresa XMPP Blokovat XMPP adresu @@ -279,7 +274,9 @@ Povolit Požadováno heslo ke skupinovému chatu Vložit heslo - Nejdříve, prosím, od kontaktu vyžádejte zasílání informací o změně stavu.\n\nTo bude využito k identifikaci aplikace, kterou kontakt používá. + Nejdříve, prosím, od kontaktu vyžádejte zasílání informací o změně stavu. +\n +\nTo bude využito k identifikaci aplikace, kterou kontakt používá. Ihned vyžádat Ignorovat Varování: Odeslání bez povolení vzájemného informování o změně stavu může způsobit nečekané potíže.\n\nJděte do \"Detaily kontaktu\" a ověřte nastavení aktualizace stavu. @@ -318,8 +315,8 @@ Adresa XMPP zkopírována do schránky Chybové hlášení zkopírováno do schránky webová adresa - Skenovat 2D kód - Zobrazit 2D kód + Skenovat QR kód + Zobrazit QR kód Zobrazit seznam blokovaných Detaily účtu Potvrdit @@ -333,7 +330,7 @@ Soubory zálohy byly uloženy do %s Obnovuji zálohu Záloha obnovena - Nezapomeňte povolit účet + Nezapomeňte si účet aktivovat. Vybrat soubor Přijímám %1$s (%2$d%% dokončeno) Stáhnout %s @@ -525,7 +522,9 @@ Pouze pro velké obrázky Povolena optimalizace využití baterie Vaše zařízení používá agresivní optimalizaci výdrže baterie pro %1$s, což může vést k opožděným upozorněním nebo dokonce ke ztrátě některých zpráv.\nDoporučujeme optimalizaci vypnout. - Vaše zařízení používá agresivní optimalizaci výdrže baterie pro %1$s, což může vést k opožděným upozorněním nebo dokonce ke ztrátě některých zpráv.\nNyní budete vyzváni k jejímu vypnutí. + Vaše zařízení používá agresivní optimalizaci výdrže baterie pro %1$s, což může vést k opožděným upozorněním nebo dokonce ke ztrátě některých zpráv. +\n +\nNyní budete vyzváni k jejímu vypnutí. Vypnout Vybraný obsah je příliš dlouhý (Žádné aktivované účty) @@ -534,17 +533,18 @@ Odeslat opravenou zprávu Tento osobní otisk byl již bezpečně ověřen. Ťuknutím na \"Hotovo\" pouze potvrzujete, že %s je členem tohoto skupinového chatu. Tento účet byl vypnut - Bezpečnostní chyba: Neplatný přístup k souboru + Bezpečnostní chyba: Neplatný přístup k souboru! Nebyla nalezena aplikace umožňující sdílení URI Sdílet URI s… Souhlasit a pokračovat - Průvodce je nastaven, aby vytvořil účet na serveru conversations.im.¹\nPokud si vyberete conversations.im jako svého poskytovatele, budete moci komunikovat s uživateli u ostatních poskytovatelů, budou-li mít vaši celou XMPP adresu. + Průvodce je nastaven, aby vytvořil účet na serveru conversations.im. +\nPokud si vyberete conversations.im jako svého poskytovatele, budete moci komunikovat s uživateli u ostatních poskytovatelů, budou-li mít vaši celou XMPP adresu. Vaše celá XMPP adresa: %s Vytvořit účet Použít vlastního provozovatele Zadejte své uživatelské jméno Spravovat viditelnost ručně - Nastavit viditelnost při úpravě statusové zprávy + Nastavit svou viditelnost při úpravě statusové zprávy. Stavová zpráva Volný pro chat Online @@ -601,7 +601,7 @@ Nebylo možné vytvořit dočasný soubor Tento přístroj byl ověřen Kopírovat identifikátor - Oveřil(a) jste všechny OMEMO klíče, které vlastníte. + Oveřil(a) jste všechny OMEMO klíče, které vlastníte Kód neobsahuje otisk pro tuto konverzaci. Ověřené otisky Naskenovat kód kontaktu pomocí fotoaparátu @@ -696,7 +696,7 @@ Přijmout neznámý certifikát? Certifikát není podepsaný žádnou známou certifikační autoritou. Přijmout nesouhlasící jméno serveru? - Server se nemohl prokázat jako \"%s\". Certifikát je platný pouze pro: + Server se nemohl prokázat jako \"%s\". Certifikát je platný pouze pro: Chcete se přesto připojit? Detaily certifikátu: Jednou @@ -716,10 +716,10 @@ OMEMO šifrování OMEMO bude vždy použito k šifrování zpráv v jednotlivých konverzacích i v soukromých skupinách. OMEMO bude použito jako výchozí pro nové konverzace. - OMEMO bude nutné zapnout ručně pro každou každou novou konverzaci. + OMEMO bude nutné zapnout ručně pro každou novou konverzaci. Vytvořit zástupce Velikost písma - Relativní velikost písma v aplikaci + Relativní velikost písma v aplikaci. Zapnuto jako výchozí Vypnuto jako výchozí Malé @@ -875,7 +875,7 @@ Přiložit Najít kanály Prohledat kanály - Možné porušení soukromí + Možné porušení soukromí! Již mám účet Přidat existující účet Vytvořit nový účet @@ -967,4 +967,57 @@ Žádný z aktivních účtů tuto funkci nepodporuje Zálohování zahájeno. Budete upozorněni, jakmile bude záloha hotova. Nelze povolit video. - + + %1$d zmeškaný hovor od %2$s + %1$d zmeškané hovory od %2$s + %1$d zmeškaných hovorů od %2$s + + + %d zmeškaný hovor + %d zmeškané hovory + %d zmeškaných hovorů + + Synchronizovat se záložkami + + %1$d zmeškaný hovor od %2$d kontaktu + %1$d zmeškané hovory od %2$d kontaktů + %1$d zmeškaných hovorů od %2$d kontaktů + + Stahování selhalo: Neplatný soubor + Chystáte se ověřit OMEMO klíče vlastního účtu. To je bezpečné pouze v případě, že jste následovali odkaz z důvěryhodného zdroje a pokud jste ho zveřejnili Vy sami. + Fixovat polohu + Skupinové chaty + Zmeškané hovory + Uložit jako skupinový chat + Tento skupinový chat jste opustili z technických důvodů + Vyhledávání kanálů používá službu třetí strany jménem <a href=https://search.jabber.network>search.jabber.network</a>.<br><br>Používání této služby odešle vaši IP adresu a vyhledávaný termín této službě. Pro více informací konzultujte jejich <a href=https://search.jabber.network/privacy>Zásady ochrany osobních údajů</a>. + Znovu spojuji hovor + Slepě důvěřované klíče OMEMO, které mohou být někdo jiný nebo někým zasaženy. + Příchozí hovor ·(%s) · %s + Nedůvěryhodný řetězec certifikátů + Zprávy se nenačítají kvůli v aplikaci nastavené době uchování. + Vektorová ilustrace + multimediální soubor + Zabránit snímkům obrazovky + Skrýt obsah aplikace v přepínači aplikací a blokovat snímky obrazovky + Nekompatibilní klient + Obnovování připojení + Problém s ověřením + Přepnout na videohovor\? + Odchozí hovor · %s + Přepnout na video + Odmítnout žádosti o přepnutí na video + XEP-0215: External Service Discovery + Pokračovat + e-kniha + Hledat skupinové chaty + Uvolnit polohu + jabber.network + Znovu spojuji videohovor + Odchozí hovor · (%s) · %s + Dokument prostého textu + Registrace účtů nejsou podporovány + Nebyla nalezena žádná XMPP adresa + Smazat avatar + Dočasné selhání autentizace + \ No newline at end of file From ea3087ee51b41ed7fd8a2bc8754955090b94623f Mon Sep 17 00:00:00 2001 From: Jasper Date: Sun, 11 Jun 2023 12:19:24 +0000 Subject: [PATCH 008/402] Translated using Weblate (French) Currently translated at 99.8% (965 of 966 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/fr/ --- src/main/res/values-fr/strings.xml | 86 +++++++++++++++++++++++++----- 1 file changed, 73 insertions(+), 13 deletions(-) diff --git a/src/main/res/values-fr/strings.xml b/src/main/res/values-fr/strings.xml index 67c6e7f1d..c614d08a0 100644 --- a/src/main/res/values-fr/strings.xml +++ b/src/main/res/values-fr/strings.xml @@ -87,7 +87,9 @@ Vider l\'historique de la conversation Êtes-vous sûr de vouloir supprimer tous les messages de cette conversation ?\n\n Avertissement : Cela ne supprimera pas les copies des messages qui sont stockés sur d\'autres appareils ou serveurs. Supprimer le fichier - Êtes-vous sûr de vouloir supprimer ce fichier ?\n\n Avertissement : Cela ne supprimera pas les copies de ce fichier qui sont stockés sur d\'autres appareils ou serveurs. + Êtes-vous sûr de vouloir supprimer ce fichier \? +\n +\nAvertissement : Cela ne supprimera pas les copies de ce fichier qui sont stockées sur d\'autres appareils ou serveurs. Fermez cette conversation après Choisir l\'appareil Envoyer un message en clair @@ -122,12 +124,12 @@ Sonnerie Son des notifications Son de notification pour les nouveaux messages - Sonnerie d\'appel entrant + Sonnerie d\'appels entrants Période sans notification La durée pendant laquelle les notifications sont désactivées après la détection d\'une activité sur l\'un de vos autres appareils. Avancé Ne pas envoyer de rapports d\'erreurs - En envoyant des rapports de crash vous aidez le développement de Conversations + En envoyant des rapports de crash vous aidez le développement Confirmation de lecture Informer vos contacts quand vous avez reçu et lu leurs messages Interdire les captures d’écran @@ -179,9 +181,9 @@ Publier la clé publique OpenPGP Supprimer la clé publique OpenPGP Êtes-vous sûr de vouloir supprimer votre clé publique OpenPGP de votre annonce de présence ?\nVos contacts ne pourront plus vous envoyer de message chiffrés avec OpenPGP. - Clé publique OpenPGP publiée + Clé publique OpenPGP publiée. Activer - Supprimer votre compte effacera l\'historique de vos conversations + Êtes-vous sûr de vouloir supprimer votre compte \? Supprimer votre compte effacera l\'historique de vos conversations Enregistrer un son Adresse XMPP Bloquer l\'adresse XMPP @@ -239,12 +241,14 @@ Détruire le groupe Détruire le canal Voulez-vous vraiment détruire ce groupe ?\n\nAvertissement : le groupe sera complètement supprimé du serveur. - Êtes-vous sûr de vouloir détruire ce canal public\? On Avertissement: le canal sera complètement supprimé du serveur. + Êtes-vous sûr de vouloir détruire ce canal public \? +\n +\nAttention : Le canal sera totalement supprimé du serveur. Impossible de détruire le groupe Impossible de détruire le canal Modifier le sujet du groupe Sujet - Rejoindre le groupe + Rejoindre le groupe… Partir Votre correspondant vous a ajouté dans sa liste de contacts Ajouter en retour @@ -404,7 +408,7 @@ Touche Entrée pour envoyer Utilisez la touche Entrée pour envoyer un message. Vous pourrez toujours utiliser la combinaison Ctrl+Entrée pour envoyer un message, même si cette option est désactivée. Afficher la touche Entrée - Remplacer la touche Émoticônes par une touche Entrée. + Remplacer la touche Émoticônes par la touche Entrée. audio vidéo image @@ -487,7 +491,7 @@ Votre appareil ne supporte pas la sélection de certificats client ! Connexion Connexion via Tor - Rediriger toutes les connexions via le réseau Tor. Nécessite Orbot. + Rediriger toutes les connexions vers le réseau Tor. Nécessite Orbot. Nom d\'hôte Port Adresse du serveur (ou .onion) @@ -526,11 +530,12 @@ Envoyer le message corrigé Vous avez déjà validé l\'empreinte de cette personne pour accorder votre confiance. En sélectionnant « Terminé », vous confirmez simplement que %s fait partie de ce groupe. Vous avez désactivé ce compte - Erreur de sécurité : accès fichier invalide + Erreur de sécurité : accès invalide au fichier ! Aucune application disponible pour partager l\'URI Partager l\'URI avec… Accepter et continuer - Nous vous guiderons tout au long du processus de création d\'un compte sur conversations.im.¹\nLorsque vous sélectionnerez conversations.im en tant que fournisseur, vous pourrez communiquer avec les utilisateurs d\'autres fournisseurs en leur fournissant votre adresse XMPP complète. + Nous vous guiderons tout au long du processus de création d\'un compte sur conversations.im. +\nLorsque vous sélectionnerez conversations.im en tant que fournisseur, vous pourrez communiquer avec les utilisateurs d\'autres fournisseurs en leur fournissant votre adresse XMPP complète. Votre adresse XMPP complète sera : %s Créer un compte Utiliser votre propre fournisseur @@ -704,7 +709,7 @@ Chiffrement OMEMO OMEMO sera toujours utilisé pour des discussions à deux ou les groupes privés. OMEMO sera utilisé par défaut pour les nouvelles discussions. - OMEMO devra être activé manuellement pour chaque nouvelle discussion + OMEMO devra être activé manuellement pour chaque nouvelle discussion. Créer un raccourci Taille de police La taille de police relative utilisée dans l\'application. @@ -789,7 +794,7 @@ %s.]]> Nous vous avons envoyé un autre SMS avec un code à 6 chiffres. Veuillez saisir ci-dessous le code PIN à 6 chiffres. - Renvoyer un SMS. + Renvoyer un SMS Renvoyer SMS (%s) S\'il vous plaît, attendez (%s) retour @@ -966,4 +971,59 @@ Impossible d’activer la vidéo. La création de nouveaux comptes n’est pas prise en charge Aucune adresse XMPP trouvée + + %d appel manqué + %d appels manqués + %d appels manqués + + Empreinte OMEMO (origine du message) + Masquer le contenu de l\'application dans le sélecteur d\'applications et bloquer les captures d\'écran + Client incompatible + Passer en vidéo + La sauvegarde a débuté. Vous serez notifié une fois terminé. + Vous avez quitté ce groupe pour des raisons techniques + Supprimer le compte du serveur + %1$s souhaite obtenir la permission d\'accéder à votre carnet d\'adresses pour le faire correspondre à votre liste de contacts XMPP. +\nCela affichera les noms complets et les avatars de vos contacts. +\n +\n%1$s ne lira que votre carnet d\'adresses et le comparera localement sans rien télécharger sur votre serveur. + ficher multimédia + La découverte des canaux utilise un service tiers appelé <a href=https://search.jabber.network>search.jabber.network</a>.<br><br>L\'utilisation de cette fonction transmet votre adresse IP et votre recherche à ce service. Voir leur <a href=https://search.jabber.network/privacy>Politique de gestion de la vie privée</a> pour plus d\'informations. + Rechercher des groupes + Appel sortant (%s) · %s + Votre système d\'exploitation empêche %1$s d\'accéder à l\'internet lorsqu\'il est en arrière-plan. Pour être notifié de nouveaux messages, vous devez permettre à %1$s d\'accéder à Internet lorsque l\'économiseur de données est activé. +\n%1$s s\'efforcera toujours d\'économiser des données lorsque cela est possible. + Vous êtes sur le point de vérifier les clés OMEMO de votre propre compte. Cette opération n\'est garantie que si vous avez suivi ce lien à partir d\'une source fiable où vous seul pouvez avoir publié ce lien. + Appels manqués + Passer à un appel vidéo \? + Ajouter des traces supplémentaires \? + Compte XMPP + Le compte par lequel les messages push seront reçus. + Serveur Push + Un serveur push choisi par l\'utilisateur pour relayer les messages push via XMPP vers votre appareil. + Aucun (désactivé) + + %1$d appels manqués de %2$d contact + %1$d appels manqués de %2$d contacts + %1$d appels manqués de %2$d contacts + + Discussions de groupe + Enregistrer comme groupe + Synchroniser les favoris + Activer \"Rejoindre automatiquement\" en entrant ou sortant d\'un groupe et réagir aux modifications apportées par d\'autres clients. + graphique vectoriel + Appel entrant (%s) - %s + Appel sortant · %s + + %1$d appel manqué de %2$s + %1$d appels manqués de %2$s + %1$d appels manqués de %2$s + + Les appels sont désactivés lorsque l\'on utilise Tor + Rejeter la demande de passage en vidéo + Décliner + Impossible de supprimer le compte du serveur + Document texte + Échec temporaire de l\'authentification + Supprimer l\'avatar \ No newline at end of file From 3af2d1f79a1929f8dbb9271101b9fca64f94ca3b Mon Sep 17 00:00:00 2001 From: Jasper Date: Sun, 11 Jun 2023 09:33:55 +0000 Subject: [PATCH 009/402] Translated using Weblate (French) Currently translated at 100.0% (13 of 13 strings) Translation: Conversations/Android App (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-conversations/fr/ --- src/conversations/res/values-fr/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/conversations/res/values-fr/strings.xml b/src/conversations/res/values-fr/strings.xml index 47badf219..f0c96726f 100644 --- a/src/conversations/res/values-fr/strings.xml +++ b/src/conversations/res/values-fr/strings.xml @@ -9,8 +9,8 @@ Vous avez été invité à %1$s. Un nom d’utilisateur a déjà été choisi pour vous. Nous allons vous guider à travers le processus de création d’un compte.\nVous pourrez communiquer avec les utilisateurs des autres fournisseurs en leur donnant votre adresse XMPP complète. Votre invitation au serveur Code de provisionnement mal formaté - Appuyez sur le bouton partager pour envoyer à votre contact une invitation pour %1$s - Si vos contacts sont à votre côté, ils peuvent aussi scanner le code ci dessous pour accepter votre invitation + Appuyez sur le bouton partager pour envoyer à votre contact une invitation pour %1$s. + Si vos contacts sont à proximité, ils peuvent aussi scanner le code ci-dessous pour accepter votre invitation. Rejoignez %1$set discutez avec moi : %2$s - Partager une invitation avec ... + Partager une invitation avec … \ No newline at end of file From ec8a574bdcc15f636de9920639b1ad9a70b98305 Mon Sep 17 00:00:00 2001 From: Zash Date: Tue, 13 Jun 2023 21:16:11 +0000 Subject: [PATCH 010/402] Translated using Weblate (Swedish) Currently translated at 98.9% (956 of 966 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/sv/ --- src/main/res/values-sv/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/res/values-sv/strings.xml b/src/main/res/values-sv/strings.xml index fe8138eb5..b6ff153f9 100644 --- a/src/main/res/values-sv/strings.xml +++ b/src/main/res/values-sv/strings.xml @@ -185,7 +185,7 @@ Är du säker på att du vill ta bort din OpenPGP publik nyckel från din tillgänglighetsuppdatering?\nDina kontakter kommer inte längre att kunna skicka dig OpenPGP-krypterade meddelande. OpenPGP-nyckel har publicerats. Aktivera konto - Om du tar bort ditt konto raderas hela din konversationshistorik + Är du säker på att du vill ta bort ditt konto\? Om du tar bort ditt konto raderas hela din konversationshistorik Spela in röst XMPP-adress Blockera XMPP-adress From 3e2035870175d9a56ad67ba256f09367dbd28e0a Mon Sep 17 00:00:00 2001 From: VTCuong Date: Mon, 19 Jun 2023 12:18:27 +0000 Subject: [PATCH 011/402] Translated using Weblate (Vietnamese) Currently translated at 95.8% (926 of 966 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/vi/ --- src/main/res/values-vi/strings.xml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/res/values-vi/strings.xml b/src/main/res/values-vi/strings.xml index 82fd62d39..a1593d57e 100644 --- a/src/main/res/values-vi/strings.xml +++ b/src/main/res/values-vi/strings.xml @@ -31,7 +31,6 @@ %d phút trước %d cuộc hội thoại chưa đọc - đang gửi... Đang giải mã tin nhắn. Xin chờ... @@ -670,7 +669,7 @@ Chấp nhận chứng chỉ không xác định? Chứng chỉ máy chủ này không được một người có quyền chứng chỉ đã biết ký. Chấp nhận tên máy chủ không khớp? - Máy chủ không thể xác thực với tư cách \"%s\". Chứng chỉ chỉ hợp lệ cho: + Máy chủ không thể xác thực với tư cách \"%s\". Chứng chỉ chỉ hợp lệ cho: Bạn có muốn vẫn kết nối không? Chi tiết chứng chỉ: Một lần @@ -945,4 +944,6 @@ Việc sao lưu đã được bắt đầu. Bạn sẽ nhận một thông báo khi việc đó đã hoàn tất. Không thể bật video. Tài liệu văn bản thuần - + Máy khách không tương thích + Trò chuyện nhóm + \ No newline at end of file From ca1ee4a56557d4e452487d466d3b90a89d0fc740 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 25 Jun 2023 19:50:40 +0200 Subject: [PATCH 012/402] process stream features after success when we inlined bind but not sm --- .../siacs/conversations/xmpp/XmppConnection.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 40828ef79..11651397a 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -775,7 +775,6 @@ public class XmppConnection implements Runnable { + ": server sent bound and resumed in SASL2 success"); throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER); } - final boolean processNopStreamFeatures; if (resumed != null && streamId != null) { if (this.boundStreamFeatures != null) { this.streamFeatures = this.boundStreamFeatures; @@ -788,6 +787,8 @@ public class XmppConnection implements Runnable { if (bound != null) { clearIqCallbacks(); this.isBound = true; + processNopStreamFeatures(); + this.boundStreamFeatures = this.streamFeatures; final Element streamManagementEnabled = bound.findChild("enabled", Namespace.STREAM_MANAGEMENT); final Element carbonsEnabled = bound.findChild("enabled", Namespace.CARBONS); @@ -807,9 +808,6 @@ public class XmppConnection implements Runnable { features.carbonsEnabled = true; } sendPostBindInitialization(waitForDisco, carbonsEnabled != null); - processNopStreamFeatures = true; - } else { - processNopStreamFeatures = false; } final HashedToken.Mechanism tokenMechanism; if (SaslMechanism.hashedToken(currentSaslMechanism)) { @@ -831,11 +829,6 @@ public class XmppConnection implements Runnable { + ": no response to our hashed token request " + this.hashTokenRequest); } - // a successful resume will not send stream features - if (processNopStreamFeatures) { - processNopStreamFeatures(); - this.boundStreamFeatures = this.streamFeatures; - } } mXmppConnectionService.databaseBackend.updateAccount(account); this.quickStartInProgress = false; @@ -1551,7 +1544,9 @@ public class XmppConnection implements Runnable { .addChild("device") .setContent(String.format("%s %s", Build.MANUFACTURER, Build.MODEL)); } - if (bind != null) { + // do not include bind if 'inlinestreamManagment' is missing and we have a streamId + final boolean mayAttemptBind = streamId == null || inlineStreamManagement; + if (bind != null && mayAttemptBind) { authenticate.addChild(generateBindRequest(bind)); } if (inlineStreamManagement && streamId != null) { From e3a121121baf0ea810a8616f9da22667b3127297 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 26 Jun 2023 16:08:57 +0200 Subject: [PATCH 013/402] UP: add custom extensions for app<->distributor interaction On registration the app can pass in a 'Messenger' to get a direct response instead of having to somehow wait for the broadcast receiver to fire. The app name can be passed as a pending intent which allows the distributor to validate the sender. --- src/main/AndroidManifest.xml | 2 + .../services/UnifiedPushBroker.java | 73 +++++++++++++++---- .../services/UnifiedPushDistributor.java | 23 +++++- .../services/XmppConnectionService.java | 21 +++++- 4 files changed, 99 insertions(+), 20 deletions(-) diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 806232a22..9b92438eb 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -114,6 +114,8 @@ + + diff --git a/src/main/java/eu/siacs/conversations/services/UnifiedPushBroker.java b/src/main/java/eu/siacs/conversations/services/UnifiedPushBroker.java index 7d2d90dd5..f27bf7fc5 100644 --- a/src/main/java/eu/siacs/conversations/services/UnifiedPushBroker.java +++ b/src/main/java/eu/siacs/conversations/services/UnifiedPushBroker.java @@ -4,6 +4,9 @@ import android.content.ComponentName; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; +import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; import android.preference.PreferenceManager; import android.util.Log; import com.google.common.base.Optional; @@ -62,7 +65,7 @@ public class UnifiedPushBroker { Log.d( Config.LOGTAG, account.getJid().asBareJid() + ": trigger endpoint renewal on bind"); - renewUnifiedEndpoint(transportOptional.get()); + renewUnifiedEndpoint(transportOptional.get(), null); } } } @@ -74,11 +77,15 @@ public class UnifiedPushBroker { } public Optional renewUnifiedPushEndpoints() { + return renewUnifiedPushEndpoints(null); + } + + public Optional renewUnifiedPushEndpoints(final PushTargetMessenger pushTargetMessenger) { final Optional transportOptional = getTransport(); if (transportOptional.isPresent()) { final Transport transport = transportOptional.get(); if (transport.account.isEnabled()) { - renewUnifiedEndpoint(transportOptional.get()); + renewUnifiedEndpoint(transportOptional.get(), pushTargetMessenger); } else { Log.d(Config.LOGTAG, "skipping UnifiedPush endpoint renewal. Account is disabled"); } @@ -88,7 +95,7 @@ public class UnifiedPushBroker { return transportOptional; } - private void renewUnifiedEndpoint(final Transport transport) { + private void renewUnifiedEndpoint(final Transport transport, final PushTargetMessenger pushTargetMessenger) { final Account account = transport.account; final UnifiedPushDatabase unifiedPushDatabase = UnifiedPushDatabase.getInstance(service); final List renewals = @@ -114,16 +121,23 @@ public class UnifiedPushBroker { final Element register = registration.addChild("register", Namespace.UNIFIED_PUSH); register.setAttribute("application", hashedApplication); register.setAttribute("instance", hashedInstance); + final Messenger messenger; + if (pushTargetMessenger != null && renewal.equals(pushTargetMessenger.pushTarget)) { + messenger = pushTargetMessenger.messenger; + } else { + messenger = null; + } this.service.sendIqPacket( account, registration, - (a, response) -> processRegistration(transport, renewal, response)); + (a, response) -> processRegistration(transport, renewal, messenger, response)); } } private void processRegistration( final Transport transport, final UnifiedPushDatabase.PushTarget renewal, + final Messenger messenger, final IqPacket response) { if (response.getType() == IqPacket.TYPE.RESULT) { final Element registered = response.findChild("registered", Namespace.UNIFIED_PUSH); @@ -142,7 +156,7 @@ public class UnifiedPushBroker { Log.d(Config.LOGTAG, "could not parse expiration", e); return; } - renewUnifiedPushEndpoint(transport, renewal, endpoint, expiration); + renewUnifiedPushEndpoint(transport, renewal, messenger, endpoint, expiration); } else { Log.d(Config.LOGTAG, "could not register UP endpoint " + response.getErrorCondition()); } @@ -151,6 +165,7 @@ public class UnifiedPushBroker { private void renewUnifiedPushEndpoint( final Transport transport, final UnifiedPushDatabase.PushTarget renewal, + final Messenger messenger, final String endpoint, final long expiration) { Log.d(Config.LOGTAG, "registered endpoint " + endpoint + " expiration=" + expiration); @@ -171,9 +186,24 @@ public class UnifiedPushBroker { + renewal.instance + " was updated to " + endpoint); - broadcastEndpoint( - renewal.instance, - new UnifiedPushDatabase.ApplicationEndpoint(renewal.application, endpoint)); + final UnifiedPushDatabase.ApplicationEndpoint applicationEndpoint = new UnifiedPushDatabase.ApplicationEndpoint(renewal.application, endpoint); + sendEndpoint(messenger, renewal.instance, applicationEndpoint); + } + } + + private void sendEndpoint(final Messenger messenger, String instance, final UnifiedPushDatabase.ApplicationEndpoint applicationEndpoint) { + if (messenger != null) { + Log.d(Config.LOGTAG,"using messenger instead of broadcast to communicate endpoint to "+applicationEndpoint.application); + final Message message = new Message(); + message.obj = endpointIntent(instance, applicationEndpoint); + try { + messenger.send(message); + } catch (final RemoteException e) { + Log.d(Config.LOGTAG,"messenger failed. falling back to broadcast"); + broadcastEndpoint(instance, applicationEndpoint); + } + } else { + broadcastEndpoint(instance, applicationEndpoint); } } @@ -302,14 +332,19 @@ public class UnifiedPushBroker { private void broadcastEndpoint( final String instance, final UnifiedPushDatabase.ApplicationEndpoint endpoint) { Log.d(Config.LOGTAG, "broadcasting endpoint to " + endpoint.application); - final Intent updateIntent = new Intent(UnifiedPushDistributor.ACTION_NEW_ENDPOINT); - updateIntent.setPackage(endpoint.application); - updateIntent.putExtra("token", instance); - updateIntent.putExtra("endpoint", endpoint.endpoint); + final Intent updateIntent = endpointIntent(instance, endpoint); service.sendBroadcast(updateIntent); } - public void rebroadcastEndpoint(final String instance, final Transport transport) { + private static Intent endpointIntent(final String instance, final UnifiedPushDatabase.ApplicationEndpoint endpoint) { + final Intent intent = new Intent(UnifiedPushDistributor.ACTION_NEW_ENDPOINT); + intent.setPackage(endpoint.application); + intent.putExtra("token", instance); + intent.putExtra("endpoint", endpoint.endpoint); + return intent; + } + + public void rebroadcastEndpoint(final Messenger messenger, final String instance, final Transport transport) { final UnifiedPushDatabase unifiedPushDatabase = UnifiedPushDatabase.getInstance(service); final UnifiedPushDatabase.ApplicationEndpoint endpoint = unifiedPushDatabase.getEndpoint( @@ -317,7 +352,7 @@ public class UnifiedPushBroker { transport.transport.toEscapedString(), instance); if (endpoint != null) { - broadcastEndpoint(instance, endpoint); + sendEndpoint(messenger, instance, endpoint); } } @@ -330,4 +365,14 @@ public class UnifiedPushBroker { this.transport = transport; } } + + public static class PushTargetMessenger { + private final UnifiedPushDatabase.PushTarget pushTarget; + private final Messenger messenger; + + public PushTargetMessenger(UnifiedPushDatabase.PushTarget pushTarget, Messenger messenger) { + this.pushTarget = pushTarget; + this.messenger = messenger; + } + } } diff --git a/src/main/java/eu/siacs/conversations/services/UnifiedPushDistributor.java b/src/main/java/eu/siacs/conversations/services/UnifiedPushDistributor.java index 64c16dbcd..c5402dec6 100644 --- a/src/main/java/eu/siacs/conversations/services/UnifiedPushDistributor.java +++ b/src/main/java/eu/siacs/conversations/services/UnifiedPushDistributor.java @@ -1,10 +1,13 @@ package eu.siacs.conversations.services; +import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.pm.ResolveInfo; import android.net.Uri; +import android.os.Messenger; +import android.os.Parcelable; import android.util.Log; import com.google.common.base.Charsets; @@ -46,12 +49,21 @@ public class UnifiedPushDistributor extends BroadcastReceiver { return; } final String action = intent.getAction(); - final String application = intent.getStringExtra("application"); + final String application; + final Parcelable appByPendingIntent = intent.getParcelableExtra("app"); + if (appByPendingIntent instanceof PendingIntent) { + final PendingIntent pendingIntent = (PendingIntent) appByPendingIntent; + application = pendingIntent.getIntentSender().getCreatorPackage(); + Log.d(Config.LOGTAG,"received application name via pending intent "+ application); + } else { + application = intent.getStringExtra("application"); + } + final Parcelable messenger = intent.getParcelableExtra("messenger"); final String instance = intent.getStringExtra("token"); final List features = intent.getStringArrayListExtra("features"); switch (Strings.nullToEmpty(action)) { case ACTION_REGISTER: - register(context, application, instance, features); + register(context, application, instance, features, messenger); break; case ACTION_UNREGISTER: unregister(context, instance); @@ -69,7 +81,8 @@ public class UnifiedPushDistributor extends BroadcastReceiver { final Context context, final String application, final String instance, - final Collection features) { + final Collection features, + final Parcelable messenger) { if (Strings.isNullOrEmpty(application) || Strings.isNullOrEmpty(instance)) { Log.w(Config.LOGTAG, "ignoring invalid UnifiedPush registration"); return; @@ -92,6 +105,10 @@ public class UnifiedPushDistributor extends BroadcastReceiver { final Intent serviceIntent = new Intent(context, XmppConnectionService.class); serviceIntent.setAction(XmppConnectionService.ACTION_RENEW_UNIFIED_PUSH_ENDPOINTS); serviceIntent.putExtra("instance", instance); + serviceIntent.putExtra("application", application); + if (messenger instanceof Messenger) { + serviceIntent.putExtra("messenger", messenger); + } Compatibility.startService(context, serviceIntent); } else { Log.d(Config.LOGTAG, "not successful. sending error message back to application"); diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index ebbbef4c4..dcb613399 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -32,6 +32,8 @@ import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.IBinder; +import android.os.Messenger; +import android.os.Parcelable; import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.os.SystemClock; @@ -815,9 +817,18 @@ public class XmppConnectionService extends Service { break; case ACTION_RENEW_UNIFIED_PUSH_ENDPOINTS: final String instance = intent.getStringExtra("instance"); - final Optional transport = renewUnifiedPushEndpoints(); + final String application = intent.getStringExtra("application"); + final Messenger messenger = intent.getParcelableExtra("messenger"); + final UnifiedPushBroker.PushTargetMessenger pushTargetMessenger; + if (messenger != null && application != null && instance != null) { + pushTargetMessenger = new UnifiedPushBroker.PushTargetMessenger(new UnifiedPushDatabase.PushTarget(application, instance),messenger); + Log.d(Config.LOGTAG,"found push target messenger"); + } else { + pushTargetMessenger = null; + } + final Optional transport = renewUnifiedPushEndpoints(pushTargetMessenger); if (instance != null && transport.isPresent()) { - unifiedPushBroker.rebroadcastEndpoint(instance, transport.get()); + unifiedPushBroker.rebroadcastEndpoint(messenger, instance, transport.get()); } break; case ACTION_IDLE_PING: @@ -2363,8 +2374,12 @@ public class XmppConnectionService extends Service { return this.unifiedPushBroker.reconfigurePushDistributor(); } + private Optional renewUnifiedPushEndpoints(final UnifiedPushBroker.PushTargetMessenger pushTargetMessenger) { + return this.unifiedPushBroker.renewUnifiedPushEndpoints(pushTargetMessenger); + } + public Optional renewUnifiedPushEndpoints() { - return this.unifiedPushBroker.renewUnifiedPushEndpoints(); + return this.unifiedPushBroker.renewUnifiedPushEndpoints(null); } private void provisionAccount(final String address, final String password) { From 4c38c480fa5747df7ca440048f25fc60b6a1a4d2 Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Tue, 27 Jun 2023 16:30:44 +0200 Subject: [PATCH 014/402] Use libidn for stringprep Which actually validates according to spec instead of just being lazy. --- build.gradle | 1 + .../siacs/conversations/services/XmppConnectionService.java | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 44e352367..ba81efdad 100644 --- a/build.gradle +++ b/build.gradle @@ -67,6 +67,7 @@ dependencies { implementation 'com.github.natario1:Egloo:v0.4.0' implementation 'org.jxmpp:jxmpp-jid:1.0.3' + implementation 'org.jxmpp:jxmpp-stringprep-libidn:1.0.3' implementation 'org.osmdroid:osmdroid-android:6.1.11' implementation 'org.hsluv:hsluv:0.2' implementation 'org.conscrypt:conscrypt-android:2.5.2' diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index dcb613399..d24b22edc 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -33,7 +33,6 @@ import android.os.Bundle; import android.os.Environment; import android.os.IBinder; import android.os.Messenger; -import android.os.Parcelable; import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.os.SystemClock; @@ -60,6 +59,7 @@ import com.google.common.base.Optional; import com.google.common.base.Strings; import org.conscrypt.Conscrypt; +import org.jxmpp.stringprep.libidn.LibIdnXmppStringprep; import org.openintents.openpgp.IOpenPgpService2; import org.openintents.openpgp.util.OpenPgpApi; import org.openintents.openpgp.util.OpenPgpServiceConnection; @@ -68,7 +68,6 @@ import java.io.File; import java.security.Security; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; -import java.text.ParseException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -81,7 +80,6 @@ import java.util.ListIterator; import java.util.Map; import java.util.Set; import java.util.WeakHashMap; -import java.util.concurrent.Callable; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; @@ -131,7 +129,6 @@ import eu.siacs.conversations.ui.UiCallback; import eu.siacs.conversations.ui.interfaces.OnAvatarPublication; import eu.siacs.conversations.ui.interfaces.OnMediaLoaded; import eu.siacs.conversations.ui.interfaces.OnSearchResultsAvailable; -import eu.siacs.conversations.utils.AccountUtils; import eu.siacs.conversations.utils.Compatibility; import eu.siacs.conversations.utils.ConversationsFileObserver; import eu.siacs.conversations.utils.CryptoHelper; @@ -1157,6 +1154,7 @@ public class XmppConnectionService extends Service { @SuppressLint("TrulyRandom") @Override public void onCreate() { + LibIdnXmppStringprep.setup(); if (Compatibility.runsTwentySix()) { mNotificationService.initializeChannels(); } From 0de4939f7f145ba305810d07b8084f5878f1f6f4 Mon Sep 17 00:00:00 2001 From: tuongdai252 Date: Sat, 24 Jun 2023 15:13:07 +0000 Subject: [PATCH 015/402] Translated using Weblate (Vietnamese) Currently translated at 99.8% (965 of 966 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/vi/ --- src/main/res/values-vi/strings.xml | 110 +++++++++++++++++++++-------- 1 file changed, 80 insertions(+), 30 deletions(-) diff --git a/src/main/res/values-vi/strings.xml b/src/main/res/values-vi/strings.xml index a1593d57e..494b689d1 100644 --- a/src/main/res/values-vi/strings.xml +++ b/src/main/res/values-vi/strings.xml @@ -32,8 +32,8 @@ %d cuộc hội thoại chưa đọc - đang gửi... - Đang giải mã tin nhắn. Xin chờ... + đang gửi… + Đang giải mã tin nhắn. Vui lòng chờ… Tin nhắn mã hoá bằng OpenPGP Biệt danh đã được sử dụng Biệt danh không hợp lệ @@ -52,7 +52,7 @@ Bạn có muốn xoá dấu trang %s không? Các cuộc hội thoại với dấu trang này sẽ không bị xoá. Đăng ký tài khoản mới trên máy chủ Đổi mật k trên máy chủ - Chia sẻ với... + Chia sẻ với… Bắt đầu cuộc hội thoại Mời liên hệ Mời @@ -80,12 +80,14 @@ thất bại khi chuyển Đang chuẩn bị sẵn sàng để gửi hình ảnh Đang chuẩn bị sẵn sàng để gửi các hình ảnh - Đang chia sẻ các tập tin. Xin chờ... + Đang chia sẻ các tập tin. Vui lòng chờ… Xoá lịch sử Xoá lịch sử hội thoại Bạn có muốn xoá tất cả tin nhắn trong cuộc hội thoại này không?\n\nCảnh báo: Việc này sẽ không ảnh hưởng đến các tin nhắn được lưu trữ trên các thiết bị hoặc máy chủ khác. Xoá tệp - Bạn có chắc bạn muốn xoá tệp này không?\n\nCảnh báo: Việc này sẽ không xoá các bản sao được lưu trữ trên các thiết bị hoặc máy chủ khác của tệp này. + Bạn có chắc bạn muốn xoá tệp này không\? +\n +\nCảnh báo: Việc này sẽ không xoá các bản sao được lưu trữ trên các thiết bị hoặc máy chủ khác của tệp này. Đóng cuộc hội thoại này sau đó Chọn thiết bị Gửi tin nhắn không mã hoá @@ -102,15 +104,15 @@ Khởi chạy lại Cài đặt Xin cài đặt OpenKeychain - đang đề xuất... - đang chờ... + đang đề xuất… + đang chờ… Không tìm thấy khoá OpenPGP Không thể mã hoá tin nhắn của bạn vì liên hệ của bạn không thông báo mã khoá công khai của họ.\n\nVui lòng yêu cầu liên hệ của bạn thiết lập OpenPGP. Không tìm thấy các khoá OpenPGP Không thể mã hoá tin nhắn của bạn vì các liên hệ của bạn không thông báo mã khoá công khai của họ.\n\nVui lòng yêu cầu họ thiết lập OpenPGP. Tổng quan Chấp thuận các tập tin - Tự động chấp thuận các tập tin nhỏ hơn... + Tự động chấp thuận các tập tin nhỏ hơn… Tập tin đính kèm Thông báo Rung @@ -147,7 +149,9 @@ Không thể chuyển đổi tệp hình ảnh Không tìm thấy tập tin Lỗi I/O tổng quát. Có lẽ đã hết dung lượng lưu trữ? - Ứng dụng mà bạn dùng để chọn hình ảnh này không cung cấp đủ quyền để đọc tệp.\n\nHãy sử dụng trình quản lý tệp khác để chọn hình ảnh + Ứng dụng mà bạn dùng để chọn hình ảnh này không cung cấp đủ quyền để đọc tệp. +\n +\nHãy sử dụng trình quản lý tệp khác để chọn hình ảnh. Ứng dụng bạn dùng để chia sẻ tệp này không cung cấp đủ quyền. Không rõ Tạm thời tắt @@ -180,7 +184,7 @@ Bạn có chắc bạn muốn xoá mã khoá OpenPGP công khai của bạn khỏi sự thông báo có mặt của bạn không?\nCác liên hệ của bạn sẽ không thể gửi các tin nhắn được mã hoá bằng OpenPGP cho bạn nữa. Đã xuất bản mã khoá OpenPGP công khai. Bật tài khoản - Việc xoá tài khoản sẽ xoá toàn bộ lịch sử cuộc hội thoại của bạn + Bạn có chắc chắn muốn xóa tài khoản chứ\? Việc xoá tài khoản sẽ xoá toàn bộ lịch sử cuộc hội thoại của bạn Ghi âm Địa chỉ XMPP Chặn địa chỉ XMPP @@ -219,7 +223,7 @@ v\\Mã vân tay OMEMO (nguồn gốc tin nhắn) Các thiết bị khác Tin tưởng các dấu vân tay OMEMO - Đang nhận khoá... + Đang nhận khoá… Xong Giải mã Tìm kiếm @@ -244,7 +248,7 @@ Không thể phá huỷ kênh Chỉnh sửa chủ đề cuộc trò chuyện nhóm Chủ đề - Đang tham gia cuộc trò chuyện nhóm... + Đang tham gia cuộc trò chuyện nhóm… Rời khỏi Liên hệ đã thêm bạn vào danh bạ Thêm họ vào @@ -254,7 +258,7 @@ Mọi người đã đọc cho đến lúc này Đăng Nhấn ảnh đại diện để chọn ảnh từ thư viện - Đang đăng... + Đang đăng… Máy chủ đã từ chối đăng tải của bạn Không thể chuyển đổi hình ảnh Không thể lưu ảnh đại diện vào ổ đĩa @@ -358,7 +362,7 @@ Có gì đó sai đã xảy ra Đang nhận lịch sử từ máy chủ Không còn lịch sử nào trên máy chủ - Đang cập nhật... + Đang cập nhật… Đã đổi mật khẩu! Không thể đổi mật khẩu Đổi mật khẩu @@ -416,9 +420,9 @@ Đang gửi %s Đang đề xuất %s Ẩn ngoại tuyến - %s đang gõ... + %s đang gõ… %s đã ngừng gõ - %s đang gõ... + %s đang gõ… %s đã ngừng gõ Thông báo đang gõ Để cho các liên hệ của bạn biết khi bạn đang viết tin nhắn cho họ @@ -460,8 +464,8 @@ Máy chủ không chịu trách nhiệm cho miền này Bị hỏng Tính khả dụng - Vắng mặt khi thiết bị bị khoá - Hiện là Vắng mặt khi thiết bị bị khoá + Vắng mặt khi đang khóa máy + Hiện trạng thái Vắng mặt khi đang khóa máy Bận ở chế độ im lặng Hiện là Bận khi thiết bị ở chế độ im lặng Coi chế độ rung như chế độ im lặng @@ -473,7 +477,7 @@ Không thể xử lý chứng chỉ Cài đặt lưu trữ Cài đặt lưu trữ ở phía máy chủ - Đang lấy cài đặt lưu trữ. Vui lòng đợi... + Đang lấy cài đặt lưu trữ. Vui lòng đợi… Không thể lấy cài đặt lưu trữ Yêu cầu CAPTCHA Nhập văn bản trong hình ảnh ở trên @@ -514,7 +518,9 @@ Chỉ các hình ảnh lớn Đã bật tối ưu pin Thiết bị của bạn đang sử dụng tối ưu hoá pin sâu cho %1$s, điều này có thể dẫn đến thông báo bị trì hoãn hay thậm chí là mất tin nhắn.\nChúng tôi khuyên bạn tắt tối ưu hoá pin. - Thiết bị của bạn đang sử dụng tối ưu hoá pin sâu cho %1$s, điều này có thể dẫn đến thông báo bị trì hoãn hay thậm chí là mất tin nhắn.\nBây giờ bạn sẽ được hỏi để tắt tối ưu hoá pin. + Thiết bị của bạn đang sử dụng tối ưu hoá pin sâu cho %1$s, điều này có thể dẫn đến thông báo bị trì hoãn hay thậm chí là mất tin nhắn. +\n +\nBạn sẽ được yêu cầu tắt tối ưu hoá pin ngay bây giờ. Tắt Khu vực chọn quá lớn (Không có tài khoản đã kích hoạt) @@ -525,9 +531,10 @@ Bạn đã tắt tài khoản này Lỗi bảo mật: Truy cập tệp không hợp lệ! Không tìm thấy ứng dụng nào để chia sẻ URI - Chia sẻ URI với... + Chia sẻ URI với… Đồng ý và tiếp tục - Một hướng dẫn đã được thiết lập cho việc tạo tài khoản trên conversations.im.¹\nKhi chọn conversations.im làm nhà cung cấp, bạn sẽ có thể giao tiếp với những người dùng của các nhà cung cấp khác bằng cách đưa cho họ địa chỉ XMPP đầy đủ của bạn. + Một hướng dẫn đã được thiết lập cho việc tạo tài khoản trên conversations.im.¹ +\nKhi chọn conversations.im làm nhà cung cấp, bạn sẽ có thể giao tiếp với những người dùng của các nhà cung cấp khác bằng cách đưa cho họ địa chỉ XMPP đầy đủ của bạn. Địa chỉ XMPP đầy đủ của bạn sẽ là: %s Tạo tài khoản Dùng nhà cung cấp của tôi @@ -545,7 +552,7 @@ Đăng ký thất bại: Hãy thử lại sau Đăng ký thất bại: Mật khẩu quá yếu Chọn các thành viên - Tạo nhóm chat... + Đang tạo nhóm chat… Mời lại Tắt Ngắn @@ -608,7 +615,7 @@ Dọn dẹp bộ nhớ riêng Dọn dẹp bộ nhớ riêng nơi các tệp được giữ (Chúng có thể được tải xuống lại từ máy chủ) Tôi đã đi theo liên kết này từ một nguồn được tin tưởng - Bạn sắp xác minh các mã khoá OMEMO của %1$s sau khi nhấn vào một liên kết. Việc này chỉ là bảo mật nếu bạn đã đi theo liên kết này từ một nguồn được tin tưởng, nơi chỉ có %2$s có thể đã xuất bản liên kết này. + Bạn chuẩn bị xác minh các khóa OMEMO của %1$s sau khi nhấn vào một liên kết. Việc làm này chỉ an toàn nếu bạn đã đến liên kết này từ một nguồn đáng tin tưởng, chỉ có %2$s mới có thể cho ra liên kết này trước đó. Xác minh các mã khoá OMEMO Hiện không hoạt động Ẩn không hoạt động @@ -711,7 +718,7 @@ Hiện vị trí Chia sẻ Không thể bắt đầu ghi lại - Vui lòng đợi... + Vui lòng đợi… Cấp quyền truy cập micro cho %1$s Tìm kiếm tin nhắn GIF @@ -783,8 +790,8 @@ Bạn có chắc bạn muốn huỷ quá trình đăng ký không? Không - Đang xác minh... - Đang yêu cầu SMS... + Đang xác minh… + Đang yêu cầu SMS… Mã PIN bạn đã nhập không chính xác. Mã PIN chúng tôi gửi cho bạn đã hết hạn. Lỗi mạng không xác định. @@ -813,7 +820,7 @@ Kênh này sẽ làm cho địa chỉ XMPP của bạn trở thành công khai sách điện tử Gốc (không nén) - Mở bằng... + Mở bằng… Ảnh hồ sơ Conversations Chọn tài khoản Khôi phục bản sao lưu @@ -833,7 +840,7 @@ Vui lòng cung cấp tên cho kênh Vui lòng cung cấp địa chỉ XMPP Đây là một địa chỉ XMPP. Vui lòng cung cấp một cái tên. - Đang tạo kênh công khai... + Đang tạo kênh công khai… Kênh này đã tồn tại Bạn đã tham gia một kênh đang tồn tại Không thể lưu thiết lập kênh @@ -869,7 +876,7 @@ Tài khoản này đã được thiết lập rồi Vui lòng nhập mật khẩu cho tài khoản này Không thể thực hiện hành động này - Tham gia kênh công khai... + Tham gia kênh công khai… Ứng dụng chia sẻ đã không cấp quyền truy cập tệp này. jabber.network @@ -946,4 +953,47 @@ Tài liệu văn bản thuần Máy khách không tương thích Trò chuyện nhóm + Đồng bộ dấu trang + Đặt cờ \"autojoin\" khi tham gia hoặc rời khỏi nhóm trò chuyện và phản hồi sự điều chỉnh của người dùng khác. + tệp tin đa phương tiện + Tìm kiếm tin nhắn trong nhóm + Tải về thất bại: Tệp tin không hợp lệ + Cuộc gọi nhỡ + Khám phá kênh sử dụng một dịch vụ bên thứ ba gọi là <a href=https://search.jabber.network>search.jabber.network</a>.<br><br>SỬ dụng chức năng này sẽ truyền địa chỉ IP của bạn và tìm kiếm điều khoản đến dịch vụ đó. Hãy đọc <a href=https://search.jabber.network/privacy>Chính sách quyền riêng tư</a> của họ để có thêm thông tin. + Chuyển sang gọi video\? + Đang kết nối lại cuộc gọi + Cuộc gọi đi · %s + + %1$d đã bỏ lỡ cuộc gọi từ danh bạ %2$d + + Đăng ký tài khoản hiện không được hỗ trợ + Cuộc gọi bị vô hiệu hóa khi sử dụng Tor + UnifiedPush Distributor + Tài khoản sẽ nhận được tin nhắn đã đẩy đi. + Tài khoản XMPP + Máy chủ đẩy + Một máy chủ đẩy do người dùng chọn để phát lại tin nhắn đẩy qua XMPP đến thiết bị của bạn. + Không tồn tại (đã vô hiệu hóa) + Từ chối + Lưu thành nhóm trò chuyện + Bạn đã rời khỏi nhóm trò chuyện này vì lý do kỹ thuật + Bạn chuẩn bị xác minh các khoá OMEMO cho tài khoản của chính bạn. Việc làm này chỉ an toàn nếu bạn đã đến liên kết này từ một nguồn đáng tin tưởng, chỉ có bạn mới có thể cho ra liên kết này trước đó. + Tiếp tục + Đang kết nối lại + Đang kết nối lại cuộc gọi video + Cuộc gọi đến (%s) · %s + Cuộc gọi đi (%s) · %s + + %1$d đã bỏ lỡ cuộc gọi từ %2$s + + + %d đã bỏ lỡ cuộc gọi + + Không tìm thấy địa chỉ XMPP + Xác thực tạm thời thất bại + Xóa ảnh đại diện + Chuyển sang video + Từ chối yêu cầu chuyển sang video + Xóa tài khoản khỏi máy chủ + Không thể xóa tài khoản khỏi máy chủ \ No newline at end of file From d9fb88ceda328a73fff36684b2b1e24c744f65b0 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 27 Jun 2023 17:27:36 +0200 Subject: [PATCH 016/402] version bump to 2.12.5 + changelog --- CHANGELOG.md | 5 +++++ build.gradle | 2 +- fastlane/metadata/android/en-US/changelogs/42059.txt | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/42059.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 2baf9330a..21a2eac03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +### Version 2.12.5 + +* Bump Target SDK to 33 again +* Fix issues on servers supporting SASL2 w/o inline Stream Management + ### Version 2.12.4 * Revert Target SDK bump (back to 32) to fix various issues on Android 13 diff --git a/build.gradle b/build.gradle index ba81efdad..271fc7749 100644 --- a/build.gradle +++ b/build.gradle @@ -95,7 +95,7 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 33 - versionCode 42058 + versionCode 42059 versionName "2.12.5" archivesBaseName += "-$versionName" applicationId "eu.siacs.conversations" diff --git a/fastlane/metadata/android/en-US/changelogs/42059.txt b/fastlane/metadata/android/en-US/changelogs/42059.txt new file mode 100644 index 000000000..042b86fcb --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/42059.txt @@ -0,0 +1,2 @@ +* Bump Target SDK to 33 again +* Fix issues on servers supporting SASL2 w/o inline Stream Management From d588e942e6f53437bf463902968992ec18c8ba40 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 29 Jun 2023 09:45:50 +0200 Subject: [PATCH 017/402] =?UTF-8?q?q=20is=20not=20cyrillic=20but=20=D4=9B?= =?UTF-8?q?=20and=20=D1=85=20are?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eu/siacs/conversations/utils/IrregularUnicodeDetector.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/eu/siacs/conversations/utils/IrregularUnicodeDetector.java b/src/main/java/eu/siacs/conversations/utils/IrregularUnicodeDetector.java index d3aade355..3d3c8587b 100644 --- a/src/main/java/eu/siacs/conversations/utils/IrregularUnicodeDetector.java +++ b/src/main/java/eu/siacs/conversations/utils/IrregularUnicodeDetector.java @@ -60,7 +60,7 @@ public class IrregularUnicodeDetector { private static final Map NORMALIZATION_MAP; private static final LruCache CACHE = new LruCache<>(4096); - private static final List AMBIGUOUS_CYRILLIC = Arrays.asList("а","г","е","ѕ","і","q","о","р","с","у"); + private static final List AMBIGUOUS_CYRILLIC = Arrays.asList("а","г","е","ѕ","і","ԛ","о","р","с","у","х"); static { Map temp = new HashMap<>(); From 12b34426fcf1de1fc7cd6ff257d8d48564fa083d Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 29 Jun 2023 09:56:49 +0200 Subject: [PATCH 018/402] =?UTF-8?q?add=20=D1=98=20to=20list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eu/siacs/conversations/utils/IrregularUnicodeDetector.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/eu/siacs/conversations/utils/IrregularUnicodeDetector.java b/src/main/java/eu/siacs/conversations/utils/IrregularUnicodeDetector.java index 3d3c8587b..1c94225b1 100644 --- a/src/main/java/eu/siacs/conversations/utils/IrregularUnicodeDetector.java +++ b/src/main/java/eu/siacs/conversations/utils/IrregularUnicodeDetector.java @@ -60,7 +60,7 @@ public class IrregularUnicodeDetector { private static final Map NORMALIZATION_MAP; private static final LruCache CACHE = new LruCache<>(4096); - private static final List AMBIGUOUS_CYRILLIC = Arrays.asList("а","г","е","ѕ","і","ԛ","о","р","с","у","х"); + private static final List AMBIGUOUS_CYRILLIC = Arrays.asList("а","г","е","ѕ","і","ј","ԛ","о","р","с","у","х"); static { Map temp = new HashMap<>(); From 8d89c33da4a3d95b3bc67c595de402b61c29e827 Mon Sep 17 00:00:00 2001 From: Karma78 <06-outsets.issuer@icloud.com> Date: Sat, 1 Jul 2023 16:32:45 +0000 Subject: [PATCH 019/402] Translated using Weblate (Vietnamese) Currently translated at 99.8% (965 of 966 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/vi/ --- src/main/res/values-vi/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/res/values-vi/strings.xml b/src/main/res/values-vi/strings.xml index 494b689d1..fdac1c310 100644 --- a/src/main/res/values-vi/strings.xml +++ b/src/main/res/values-vi/strings.xml @@ -238,7 +238,7 @@ Tham gia channel@conference.example.com/nick channel@conference.example.com - Lưu thành đánh dấu + Đánh dấu Xoá đánh dấu Phá huỷ cuộc trò chuyện nhóm Phá huỷ kênh @@ -895,7 +895,7 @@ Đang kết thúc cuộc gọi Trả lời Từ chối - Đang khám phá các thiết bị + Đang dò tìm thiết bị Đang đổ chuông Bận Không thể kết nối cuộc gọi @@ -906,7 +906,7 @@ Cúp máy Cuộc gọi đang diễn ra Cuộc gọi video đang diễn ra - Tắt Tor để tạo cuộc gọi + Tắt Tor để gọi Cuộc gọi đến Cuộc gọi nhỡ · %s Cuộc gọi đi From f7d5635c32e7e8bf54388eef49d0081fb84967d2 Mon Sep 17 00:00:00 2001 From: Karma78 <06-outsets.issuer@icloud.com> Date: Sat, 1 Jul 2023 16:12:18 +0000 Subject: [PATCH 020/402] Translated using Weblate (Vietnamese) Currently translated at 100.0% (13 of 13 strings) Translation: Conversations/Android App (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-conversations/vi/ --- src/conversations/res/values-vi/strings.xml | 24 ++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/conversations/res/values-vi/strings.xml b/src/conversations/res/values-vi/strings.xml index f80ceacf8..851ad0927 100644 --- a/src/conversations/res/values-vi/strings.xml +++ b/src/conversations/res/values-vi/strings.xml @@ -1,16 +1,20 @@ Chọn nhà cung cấp XMPP của bạn - Sử dụng conversations.im + Sử dụng “conversations.im” Tạo tài khoản mới - Bạn đã có tài khoản XMPP chưa? Điều này có thể đúng nếu bạn đang dùng một ứng dụng khách cho XMPP khác hoặc đã sử dụng Conversations trước đó. Nếu không, bạn có thể tạo tài khoản XMPP mới ngay bây giờ.\nGợi ý: Một số nhà cung cấp email cũng cung cấp tài khoản XMPP. - XMPP là một mạng nhắn tin ngay lập tức không phụ thuộc vào nhà cung cấp. Bạn có thể sử dụng ứng dụng khách này với bất kỳ máy chủ XMPP nào mà bạn chọn.\nTuy nhiên, vì sự thuận tiện của bạn, chúng tôi đã làm cho việc tạo tài khoản trên conversations.im được dễ dàng; một nhà cung cấp đặc biệt phù hợp với việc sử dụng Conversations. - Bạn đã được mời vào %1$s. Chúng tôi sẽ hướng dẫn bạn trong quá trình tạo tài khoản.\nKhi chọn %1$s là nhà cung cấp, bạn sẽ có thể giao tiếp với những người dùng của các nhà cung cấp khác bằng cách đưa cho họ địa chỉ XMPP đầy đủ của bạn. - Bạn đã được mời vào %1$s. Một tên người dùng đã được chọn sẵn cho bạn. Chúng tôi sẽ hướng dẫn bạn trong quá trình tạo tài khoản.\nBạn sẽ có thể giao tiếp với những người dùng của các nhà cung cấp khác bằng cách đưa cho họ địa chỉ XMPP đầy đủ của bạn. + Bạn đã có sẵn một tài khoản XMPP chưa\? Nếu bạn đang dùng một ứng dụng XMPP khác dành cho máy khách (client) hoặc đã sử dụng Conversations trước đó. Nếu chưa có, bạn có thể tạo tài khoản XMPP mới ngay bây giờ. +\nGợi ý: Một số nhà cung cấp dịch vụ email cũng cung cấp tài khoản XMPP. + XMPP là một dịch vụ mạng tin nhắn không phụ thuộc vào nhà cung cấp nào. Bạn có thể sử dụng ứng dụng máy khách này với bất kỳ máy chủ XMPP nào mà bạn chọn. +\nĐể thuận tiện hơn cho bạn, chúng tôi đã đơn giản hóa khâu tạo tài khoản trên conversations.im – một nhà cung cấp đặc biệt phù hợp cho việc sử dụng Conversations. + Bạn đã được mời vào “ %1$s”. Chúng tôi sẽ hướng dẫn bạn xuyên suốt quá trình tạo tài khoản. +\nKhi chọn “%1$s” làm nhà cung cấp, bạn sẽ có thể liên lạc với những người dùng của các nhà cung cấp khác bằng cách đưa cho họ địa chỉ XMPP đầy đủ của bạn. + Bạn đã được mời vào “%1$s.” Một tên người dùng đã được chọn sẵn cho bạn. Chúng tôi sẽ hướng dẫn bạn xuyên suốt quá trình tạo tài khoản. +\nBạn sẽ có thể với những người dùng của các nhà cung cấp khác bằng cách đưa cho họ địa chỉ XMPP đầy đủ của bạn. Lời mời vào máy chủ của bạn - Mã cung cấp không được định dạng đúng - Nhấn nút chia sẻ để gửi lời mời vào %1$s đến liên hệ của bạn. - Nếu liên hệ của bạn ở gần đây, họ cũng có thể quét mã ở dưới để chấp nhận lời mời của bạn. - Hãy tham gia vào %1$s và trò chuyện với tôi: %2$s - Chia sẻ lời mời với... + Mã cung cấp sai định dạng + Nhấn nút chia sẻ để gửi đến liên hệ của bạn một lời mời vào “%1$s”. + Nếu liên hệ của bạn đang ở gần bên bạn, họ có thể quét mã ở dưới để chấp nhận lời mời của bạn. + Hãy tham gia vào “%1$s” và trò chuyện với tôi: %2$s + Chia sẻ lời mời với… \ No newline at end of file From e9f6280718691e8653fe80bab5ccaf15f3c1b03b Mon Sep 17 00:00:00 2001 From: nautilusx Date: Sun, 2 Jul 2023 17:20:48 +0000 Subject: [PATCH 021/402] Translated using Weblate (German) Currently translated at 100.0% (47 of 47 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/de/ --- fastlane/metadata/android/de-DE/changelogs/42059.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/de-DE/changelogs/42059.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/42059.txt b/fastlane/metadata/android/de-DE/changelogs/42059.txt new file mode 100644 index 000000000..39abfa314 --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/42059.txt @@ -0,0 +1,2 @@ +* Ziel-SDK wieder auf 33 erhöht +* Behebt Probleme auf Servern, die SASL2 ohne Inline Stream Management unterstützen From 5db3ca06b653a7c7c49e6bf5997e6cadb9e019da Mon Sep 17 00:00:00 2001 From: ghose Date: Mon, 3 Jul 2023 17:20:04 +0000 Subject: [PATCH 022/402] Translated using Weblate (Galician) Currently translated at 4.2% (2 of 47 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/gl/ --- .../android/gl-ES/full_description.txt | 40 +++++++++++++++++++ .../android/gl-ES/short_description.txt | 1 + 2 files changed, 41 insertions(+) create mode 100644 fastlane/metadata/android/gl-ES/full_description.txt create mode 100644 fastlane/metadata/android/gl-ES/short_description.txt diff --git a/fastlane/metadata/android/gl-ES/full_description.txt b/fastlane/metadata/android/gl-ES/full_description.txt new file mode 100644 index 000000000..bfc09084c --- /dev/null +++ b/fastlane/metadata/android/gl-ES/full_description.txt @@ -0,0 +1,40 @@ +Fácil de usar, fiable, baixo consumo de batería. Con soporte para imaxes, conversas en grupo e cifraxe e2e. + +Principios do deseño: + +* Ser tan fermosa e doada de usar como sexa posible sen sacrificar a seguridade ou privacidade +* Apoiarse en protocolos existentes e ben establecidos +* Non precisar dunha Conta de Google ou concretamente Google Cloud Messagin (GCM) +* Solicitar os mínimos permisos posibles + +Características: + +* Cifraxe extremo-a-extremo, ben con OMEMO ou con OpenPGP +* Enviar e recibir imaxes +* Chamadas de audio e vídeo cifradas (DTLS-SRTP) +* Interface intuitiva seguindo as recomendacións Android Design +* Imaxes/Avatares para os Contactos +* Sicronizada co cliente de escritorio +* Conferencias (con soporte para marcadores) +* Integración coa Libreta de enderezos +* Varias contas cunha lista de conversas unificada +* Consumo de enerxía moi baixo + +Con Conversations é moi doado crear unha conta no servidor gratuíto conversations.im. Con todo, Conversations funcionará igualmente con calquera outro servidor XMPP. Existen moitos servidores XMPP xestionados por voluntarios e gratuítos. + +Características de XMPP: + +Conversations funciona con calquera sevidor XMPP, mais XMPP é un protocolo extensible. Estas extensións tamén están estadarizadas nos chamados XEP's. +Conversations da soporte a un par delas que axudan a mellorar a experiencia de uso da aplicación. Pode acontecer que o teu servidor XMPP actual non dé soporte para estas extensións. Por tanto para obter o mellor resultado ao usar Conversations debes ter considerar usar un servidor XMPP que si o faga - ou incluso mellor - xestionar o teu propio servidor para as túas amizades. + +Estes XEPs son - neste intre: + +* XEP-0065: SOCKS5 Bytestreams (or mod_proxy65). Usado para a transferencia de ficheiros se as dúas partes están detrás dun cortalumes (NAT). +* XEP-0163: Personal Eventing Protocol para os avatares +* XEP-0191: O bloqueo de ordes permiteche bloquear spammer ou contactos sen eliminalos das túas listaxes. +* XEP-0198: Stream Management permite que XMPP sobreviva a caídas da rede e cambios na conexión TCP. +* XEP-0280: Message Carbons permite sincronizar automáticamente as mensaxes co teu cliente de escritorio e por tanto cambiar dun a outro sen perder mensaxes da conversa. +* XEP-0237: Roster Versioning fundamentalmente para aforrar datos en conexións móbiles +* XEP-0313: Message Archive Management sincroniza o historial de mensaxes co servidor. Para obter as mensaxes recibidas cando Conversations non teña conexión. +* XEP-0352: Client State Indication permítelle ao servidor saber se Conversations está a funcionar en segundo plano. Permítelle ao servidor aforrar ancho de banda retendo paquetes de datos de pouca importancia. +* XEP-0363: HTTP File Upload permíteche compartir ficheiros en salas de conferencia e con contactos que non están conectados. Require un compoñente adicional no teu servidor. diff --git a/fastlane/metadata/android/gl-ES/short_description.txt b/fastlane/metadata/android/gl-ES/short_description.txt new file mode 100644 index 000000000..79c77166e --- /dev/null +++ b/fastlane/metadata/android/gl-ES/short_description.txt @@ -0,0 +1 @@ +Mensaxería instantánea XMPP cifrada e fácil de usar para o teu dispositivo móbil From 836f048bc63411013eb1acac317efd7c65493f04 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 5 Jul 2023 10:51:27 +0200 Subject: [PATCH 023/402] add CI via woodpecker based on docker image provided by Gadgetbridge focus for now is getting something build. we can optimize this later and provide our own image --- .woodpecker.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .woodpecker.yml diff --git a/.woodpecker.yml b/.woodpecker.yml new file mode 100644 index 000000000..2de87b707 --- /dev/null +++ b/.woodpecker.yml @@ -0,0 +1,7 @@ +pipeline: + build: + image: codeberg.org/freeyourgadget/android-fdroid-tools:latest + commands: + - ./gradlew clean + - ./gradlew assembleConversationsFreeDebug + - ./gradlew assembleQuicksyFreeDebug From d1ba36cfdfe2f1532e370c246aa5d866e67e1aa4 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 5 Jul 2023 12:25:41 +0200 Subject: [PATCH 024/402] version bump to 2.12.6 + changelog --- CHANGELOG.md | 4 ++++ build.gradle | 4 ++-- fastlane/metadata/android/en-US/changelogs/42060.txt | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/42060.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 21a2eac03..9ea5fd8dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### Version 2.12.6 + +* Fix 'q' falsely being recognized as cyrillic + ### Version 2.12.5 * Bump Target SDK to 33 again diff --git a/build.gradle b/build.gradle index 271fc7749..1c0a79985 100644 --- a/build.gradle +++ b/build.gradle @@ -95,8 +95,8 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 33 - versionCode 42059 - versionName "2.12.5" + versionCode 42060 + versionName "2.12.6" archivesBaseName += "-$versionName" applicationId "eu.siacs.conversations" resValue "string", "applicationId", applicationId diff --git a/fastlane/metadata/android/en-US/changelogs/42060.txt b/fastlane/metadata/android/en-US/changelogs/42060.txt new file mode 100644 index 000000000..65c918e49 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/42060.txt @@ -0,0 +1 @@ +* Fix 'q' falsely being recognized as cyrillic From fb8b5261080484ffc3f6f8562dde35e0c28772e5 Mon Sep 17 00:00:00 2001 From: ghose Date: Wed, 12 Jul 2023 12:17:12 +0000 Subject: [PATCH 025/402] Translated using Weblate (Galician) Currently translated at 4.2% (2 of 47 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/gl/ --- fastlane/metadata/android/gl-ES/full_description.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fastlane/metadata/android/gl-ES/full_description.txt b/fastlane/metadata/android/gl-ES/full_description.txt index bfc09084c..9bdcf9042 100644 --- a/fastlane/metadata/android/gl-ES/full_description.txt +++ b/fastlane/metadata/android/gl-ES/full_description.txt @@ -4,7 +4,7 @@ Principios do deseño: * Ser tan fermosa e doada de usar como sexa posible sen sacrificar a seguridade ou privacidade * Apoiarse en protocolos existentes e ben establecidos -* Non precisar dunha Conta de Google ou concretamente Google Cloud Messagin (GCM) +* Non precisar dunha Conta de Google ou concretamente Google Cloud Messaging (GCM) * Solicitar os mínimos permisos posibles Características: @@ -29,7 +29,7 @@ Conversations da soporte a un par delas que axudan a mellorar a experiencia de u Estes XEPs son - neste intre: -* XEP-0065: SOCKS5 Bytestreams (or mod_proxy65). Usado para a transferencia de ficheiros se as dúas partes están detrás dun cortalumes (NAT). +* XEP-0065: SOCKS5 Bytestreams (ou mod_proxy65). Usado para a transferencia de ficheiros se as dúas partes están detrás dun cortalumes (NAT). * XEP-0163: Personal Eventing Protocol para os avatares * XEP-0191: O bloqueo de ordes permiteche bloquear spammer ou contactos sen eliminalos das túas listaxes. * XEP-0198: Stream Management permite que XMPP sobreviva a caídas da rede e cambios na conexión TCP. From b4052cb5b62d1d68a3bd40dc151ed102d5607b30 Mon Sep 17 00:00:00 2001 From: nautilusx Date: Thu, 13 Jul 2023 19:23:53 +0000 Subject: [PATCH 026/402] Translated using Weblate (German) Currently translated at 100.0% (48 of 48 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/de/ --- fastlane/metadata/android/de-DE/changelogs/42060.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 fastlane/metadata/android/de-DE/changelogs/42060.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/42060.txt b/fastlane/metadata/android/de-DE/changelogs/42060.txt new file mode 100644 index 000000000..535628636 --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/42060.txt @@ -0,0 +1 @@ +* Fehlerhafte Erkennung von 'q' als kyrillisch behoben From adf96f5f6a477517cfb193052ac71f2450629c3d Mon Sep 17 00:00:00 2001 From: random_r Date: Mon, 24 Jul 2023 09:07:10 +0000 Subject: [PATCH 027/402] Translated using Weblate (Italian) Currently translated at 100.0% (966 of 966 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/it/ --- src/main/res/values-it/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/res/values-it/strings.xml b/src/main/res/values-it/strings.xml index 685c88f56..171fa3e14 100644 --- a/src/main/res/values-it/strings.xml +++ b/src/main/res/values-it/strings.xml @@ -254,7 +254,7 @@ Il contatto ti ha aggiunto alla sua lista contatti Aggiungi anche tu %s ha letto fino a questo punto - %s ha letto fino a questo punto + %s hanno letto fino a questo punto %1$s + altri %2$d hanno letto fino a questo punto Tutti hanno letto fino a questo punto Pubblica From 814216e42f9a528d255c083151d5aad7dcea133d Mon Sep 17 00:00:00 2001 From: 0eoc <0que@proton.me> Date: Wed, 26 Jul 2023 12:41:00 +0000 Subject: [PATCH 028/402] Translated using Weblate (Russian) Currently translated at 100.0% (9 of 9 strings) Translation: Conversations/Android App (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-quicksy/ru/ --- src/quicksy/res/values-ru/strings.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/quicksy/res/values-ru/strings.xml b/src/quicksy/res/values-ru/strings.xml index c4915772b..c24ce3973 100644 --- a/src/quicksy/res/values-ru/strings.xml +++ b/src/quicksy/res/values-ru/strings.xml @@ -1,12 +1,12 @@ - Время, на которое уведомления от Quicksy будут отключены, когда вы пользуетесь аккаунтом на другом устройстве. + Время, на которое уведомления от Quicksy будут отключены после активности с другого устройства Отправляя отчёты об ошибках, вы помогаете в разработке Quicksy Извещать собеседников, когда вы пользуетесь Quicksy Чтобы продолжать получать уведомления, даже если экран выключен, вам необходимо добавить Quicksy в список защищенных приложений. - Аватар для Quicksy - Quicksy не доступно в вашем регионе + Аватар профиля Quicksy + Quicksy недоступен в Вашем регионе. Не удалось подтвердить сервер. Неизвестная ошибка безопасности. Время ожидания подключения к серверу вышло. - + \ No newline at end of file From 7c710e4c5d6c67eab8dcffa929830bc0d86c66ac Mon Sep 17 00:00:00 2001 From: SomeTr Date: Tue, 1 Aug 2023 22:07:31 +0000 Subject: [PATCH 029/402] Translated using Weblate (Ukrainian) Currently translated at 99.7% (964 of 966 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/uk/ --- src/main/res/values-uk/strings.xml | 485 +++++++++++++++++++---------- 1 file changed, 319 insertions(+), 166 deletions(-) diff --git a/src/main/res/values-uk/strings.xml b/src/main/res/values-uk/strings.xml index b7342458c..affb805b9 100644 --- a/src/main/res/values-uk/strings.xml +++ b/src/main/res/values-uk/strings.xml @@ -10,7 +10,7 @@ Додати обліковий запис Редагувати ім\'я Додати до контактів - Вилучити зі списку розмов + Вилучити зі списку контактів Заблокувати контакт Розблокувати контакт Заблокувати домен @@ -38,17 +38,17 @@ Модератор Учасник Гість - Бажаєте вилучити %s з вашого списку розмов? Розмову з цим контактом, не буде вилучено. - Бажаєте заборонити %s надсилати вам повідомлення? - Бажаєте розблокувати %s та дозволити цій особі надсилати вам повідомлення? - Заблокувати усі контакти з %s? - Розблокувати усі контакти з %s? + Бажаєте вилучити %s зі свого списку контактів\? Розмови з цим контактом не буде вилучено. + Бажаєте заборонити %s надсилати Вам повідомлення\? + Бажаєте розблокувати %s та дозволити цій особі надсилати Вам повідомлення\? + Заблокувати всі контакти з %s\? + Розблокувати всі контакти з %s\? Контакт заблоковано Заблоковано - Бажаєте вилучити %s із закладок? Розмову з цією закладкою не буде вилучено. - Зареєструвати новий обліковий запис + Бажаєте вилучити %s із закладок\? Розмови, пов\'язані з цією закладкою, залишаться. + Зареєструвати новий обліковий запис на сервері Змінити пароль - Поділитися + Поділитися… Почати розмову Запросити до групи Запросити @@ -65,42 +65,50 @@ Гаразд Надіслати зараз Ніколи не питати знову - Неможливо з\'єднатися з обліковим записом - Не можу увімкнути режим багатьох облікових записів + Не вдалося з\'єднатися з обліковим записом + Не вдалося з\'єднатися з обліковими записами Перейти для керування обліковими записами Долучити файл - Контакт відсутній у вашому списку розмов. Бажаєте додати його? + Цього контакту немає у Вашому списку. Бажаєте додати його\? Додати контакт - Надсилання не відбулося - Підготовка зображення до передачі - Готовий до надсилання зображень + не вдалося надіслати + Підготовка до передачі зображення + Підготовка до передачі зображень Поширюю файли. Зачекайте, будь ласка… Стерти історію Стерти історію розмов - Дійсно вилучити усі повідомлення цієї розмови?\n\nУвага: Повідомлення, які було раніше надіслано, й далі залишатимуться на інших пристроях або серверах. + Дійсно вилучити всі повідомлення цієї розмови\? +\n +\nУвага: Повідомлення, збережені на інших пристроях або серверах, і надалі залишаться там. Вилучити файл - Ви певні, що бажаєте вилучити цей файл?\n\nУвага: Це не вилучить копії цього файлу, які зберігаються на інших пристроях чи серверах. + Ви впевнені, що хочете вилучити цей файл\? +\n +\nУвага: Це не вилучить копії цього файлу, які зберігаються на інших пристроях чи серверах. Завершити цю розмову пізніше Вибрати пристрій Незашифроване повідомлення Надіслати повідомлення - Повідомлення до %s - Повідомлення зашифроване OMEMO - Повідомлення зашифроване v\\OMEMO + Повідомлення %s + Повідомлення, зашифроване OMEMO + Повідомлення, зашифроване v\\OMEMO Повідомлення зашифроване OpenPGP Ваше прізвисько змінено Надіслати без шифрування - Не вдалося розшифрувати. Можливо, у вас відсутній потрібний приватний ключ. + Не вдалося розшифрувати. Можливо, у Вас відсутній потрібний приватний ключ. OpenKeychain Перезапустити Встановити Будь ласка, встановіть OpenKeychain пропоную… чекаю… - Не знайдено жодного OpenPGP ключа - Не вдалося зашифрувати повідомлення, оскільки контакт не повідомляє власний публічний ключ.\n\nБудь ласка, запропонуйте вашому співрозмовникові встановити OpenPGP. - Не знайдено жодного ключа OpenPGP - Не вдалося розшифрувати повідомлення, оскільки контакт не повідомляє свого публічного ключа.\n\nБудь ласка, попросіть контакт налаштувати OpenPGP. + Не знайдено ключа OpenPGP + Не вдалося зашифрувати повідомлення, оскільки контакт не повідомляє свій публічний ключ. +\n +\nБудь ласка, попросіть співрозмовника налаштувати OpenPGP. + Не знайдено ключів OpenPGP + Не вдалося зашифрувати повідомлення, оскільки контакти не повідомляють свої публічні ключі. +\n +\nБудь ласка, попросіть співрозмовників налаштувати OpenPGP. Загальне Приймати файли Автоматично приймати файли менші за… @@ -114,30 +122,32 @@ Звук сповіщень Звук сповіщень для нових повідомлень Час до блокування - Час надсилання сповіщень не буде враховано у разі активності користувача на іншому пристрої + Час, протягом якого сповіщення вимикнені після виявлення активності на іншому пристрої. Розширені Не надсилати звіти про збої - Надсиланням звітів про відмову ви допомагаєте у розробці + Надсилаючи траси стеку викликів, Ви допомагаєте розробляти застосунок Підтвердження отримання повідомлень - Дайте знати вашим контактам, коли ви отримали й прочитали повідомлення + Повідомляти співрозмовників, що Ви отримали й прочитали їхні повідомлення Інтерфейс користувача Програма OpenKeychain повідомила про помилку. - Неприйнятний ключ для шифрування + Неприйнятний ключ для шифрування. Прийняти Сталася помилка Помилка Ваш обліковий запис - Повідомляти про мою доступність - Отримувати оновлення про доступність - Надіслати запит на оновлення доступності - Зображення + Повідомляти про присутність + Отримувати оновлення присутності + Надіслати запит на оновлення присутності + Обрати зображення Зняти світлину Попередньо давати запит на підписку - Переданий файл не є зображенням - Помилка при конвертації зображення + Обраний файл не є зображенням + Не вдалося конвертувати зображення Файл не знайдено - Загальна помилка вводу-виводу. Можливо, на вашому пристрої закінчилась пам\'ять для збереження? - Застосунок для роботи із зображенням не надав достатніх дозволів.\n\nСкористайтеся іншим файловим менеджером для вибору зображення + Загальна помилка вводу-виводу. Можливо, на пристрої закінчилася вільна пам\'ять\? + Застосунок для роботи із зображенням не надав достатніх дозволів. +\n +\nСкористайтеся іншим файловим менеджером для вибору зображення. Невідомо Тимчасово вимкнено У мережі @@ -165,27 +175,28 @@ Опублікувати піктограму користувача Опублікувати публічний ключ OpenPGP Вилучити публічний ключ OpenPGP - Ви впевнені, що хочете вилучити ваш публічний ключ OpenPGP з вашого оголошення про присутність?\nВаші контакти більше не зможуть надсилати вам повідомлення, зашифровані OpenPGP. + Ви впевнені, що хочете вилучити свій публічний ключ OpenPGP з оголошення про присутність\? +\nВаші контакти більше не зможуть надсилати Вам повідомлення, зашифровані OpenPGP. Публічний ключ OpenPGP опубліковано. Увімкнути обліковий запис - Вилучення облікового запису вилучіть всю історію спілкування + Ви впевнені, що хочете видалити обліковий запис\? Видалення облікового запису знищить усю історію спілкування Записати голос Адреса XMPP Заблокувати адресу XMPP username@example.com Пароль Це недійсна адреса XMPP - Пам\'ять вичерпано. Завелике зображення. + Пам\'ять вичерпано. Завелике зображення Бажаєте додати %s до своєї книги контактів? Інформація про сервер XEP-0313: Керування архівом XEP-0280: Копії повідомлень XEP-0352: Індикація стану клієнта XEP-0191: Команди блокування - XEP-0237: Зміни у списку розмов + XEP-0237: Зміни у списку контактів XEP-0198: Керування потоком XEP-0215: Виявлення зовнішньої служби - XEP-0163: Персональне (піктограми користувачів, OMEMO) + XEP-0163: PEP (піктограми користувачів, OMEMO) XEP-0363: Обмін файлами через HTTP XEP-0357: Push-повідомлення так @@ -224,25 +235,29 @@ Вилучити закладку Вилучити груповий чат Закрити канал - Дійсно вилучити цей груповий чат %s? Груповий чат буде вилучено з сервера. - Дійсно закрити цей публічний канал %s? Канал буде стерто, а дані вилучено з серверу. - Вилучити груповий чат не вдалося + Дійсно вилучити цей груповий чат\? +\n +\nУвага: Груповий чат буде вилучено, а дані стерто з сервера. + Дійсно закрити цей публічний канал\? +\n +\nУвага: Канал буде вилучено, а дані стерто з сервера. + Не вдалося вилучити груповий чат Не вдалося закрити канал Редагувати тему групи Тема Приєднання до групи… Вийти - Контакт додано до вашого списку контактів + Контакт додав Вас до свого списку контактів Також додати %s дочитав(ла) до цього місця - %s прочитав(ла) до цього місця + %s дочитали до цього місця %1$s +%2$d дочитали до цього місця Усі прочитали до цього місця Опублікувати Торкніться піктограми користувача, щоб вибрати зображення з галереї Публікація… - Сервер відхилив вашу публікацію - Щось пішло не так під час перетворення Вашого зображення + Сервер відхилив Вашу публікацію + Не вдалося конвертувати Ваше зображення Неможливо зберегти піктограму користувача на пристрій (Або натисніть і тримайте, щоб скинути до значення за замовчуванням) Ваш сервер не підтримує публікацію піктограм користувачів @@ -258,10 +273,14 @@ Увімкнути Група вимагає пароль Зазначте пароль - Будь ласка, спершу надішліть запит на оновлення пристуності від Вашого контакта.\n\nОновлення буде використано, щоб визначити, яку програму-клієнт (які програми-клієнти) він використовує. + Будь ласка, спершу надішліть запит на оновлення присутності від Вашого контакту. +\n +\nОновлення буде використано, щоб визначити, яку програму-клієнт (які програми-клієнти) він використовує. Надіслати запит зараз Ігнорувати - Попередження: Надсилання без взаємної згоди на оновлення пристуності може спричинити неочікувані проблеми.\n\nПерегляньте деталі контакту та перевірте отримання стану присутности. + Попередження: Надсилання без взаємної згоди на оновлення присутності може спричинити неочікувані проблеми. +\n +\nПерегляньте деталі контакту та перевірте отримання стану присутності. Безпека Дозволити редагування повідомлень Дозволити контактам редагувати свої повідомлення після надсилання @@ -281,10 +300,10 @@ Вас виключили з цієї групи Цю групу закрили Ви більше не берете участі у цій групі - використовується обліковий запис %s + обліковий запис %s розміщений на %s Перевіряю %s на вузлі з HTTP - Ви поза мережею. Спробуйте ще пізніше. + Ви поза мережею. Спробуйте ще раз пізніше Перевірити %s розмір Перевірити %1$s розмір на %2$s Налаштування повідомлення @@ -292,7 +311,7 @@ Вставити як цитату Копіювати оригінальний URL Надіслати знову - URL файла + URL файлу URL скопійовано Адресу XMPP скопійовано Текст повідомлення про помилку скопійовано @@ -312,7 +331,7 @@ Резервні копії збережено до %s Відтворення з резервної копії Відтворено з резервної копії - Не забудьте увімкнути обліковий запис + Не забудьте увімкнути обліковий запис. Файл Отримання %1$s (%2$d%% завершено) Завантажити %s @@ -320,33 +339,35 @@ файл Відкрити %s надсилання (%1$d%% завершено) - Підготовка файлу до передачі + Підготовка до передачі файлу %s запропоновано для завантаження Припинити передачу - передача файла не вдалася + передача файлу не вдалася скасовано передачу файлу Файл вилучено - Не знайдено програми для відкриття файла - Не знайдено застосунку для відкриття посилання - Не знайдено програми, щоб переглянути контакт + Не знайдено застосунку, щоб відкрити файл + Не знайдено застосунку, щоб відкрити посилання + Не знайдено застосунку, щоб переглянути контакт Динамічні позначки - Показувати позначку \"лише для читання\" під контактами - Увікнути сповіщення + Показувати позначку «лише для читання» під контактами + Увімкнути сповіщення Не знайдено сервер групи - Не вдалося створити групу! - Іконка облікового запису + Не вдалося створити групу + Піктограма облікового запису Копіювати цифровий підпис OMEMO Повторно створити ключ OMEMO Стерти пристрої - Ви певні, що хочете стерти всі інші пристрої з OMEMO-оголошення? Наступного разу, коли Ваші пристрої приєднаються, вони знову оголосять про себе, але вони можуть не отримати повідомлення, які можуть бути надіслані тим часом. - Немає ключів, які б можна було використати для цього контакту.\nНе вдалося отримати нові ключі з сервера. Можливо, щось не так з сервером контактів. - Для цього контакту відсутні потрібні ключі.\nПеревірте, що ви обмінялися інформацією про доступність. + Ви впевнені, що хочете стерти всі інші пристрої з OMEMO-оголошення\? Наступного разу, коли Ваші пристрої приєднаються, вони знову оголосять про себе, але вони можуть не отримати повідомлення, надіслані тим часом. + Немає ключів, які б можна було використати для цього контакту. +\nНе вдалося отримати нові ключі з сервера. Можливо, щось не так із сервером контактів\? + Для цього контакту відсутні потрібні ключі. +\nПеревірте, що ви обмінялися інформацією про присутність. Щось пішло не так Отримую історію з сервера Більше немає історії на сервері Оновлюю… Пароль змінено! - Не зміг змінити пароль + Не вдалося змінити пароль Змінити пароль Поточний пароль Новий пароль @@ -361,7 +382,7 @@ Розширений режим Надати право участі Відкликати право участі - Дати права адміністратора + Надати права адміністратора Відкликати права адміністратора Надати права власника Відкликати права власника @@ -376,7 +397,7 @@ Налаштування приватного чату Налаштування публічного каналу Приватно, лише для членів - Зробити XMPP адрес доступним для всіх + Зробити адреси XMPP доступними для всіх Зробити канал модерованим Ви не берете участі Налаштування групи змінено! @@ -388,31 +409,31 @@ Позначити як прочитане Введення Enter для надсилання - Використовувати кнопку Enter для надсилання повідомлень. Якщо цей параметр вимкнено, повідомлення можна надсилати за допомогою комбінації Ctrl-Enter. + Використовувати кнопку Enter для надсилання повідомлень. Якщо цей параметр вимкнено, повідомлення можна надсилати за допомогою комбінації Ctrl+Enter. Показувати кнопку Enter Змінити клавішу емоційок на кнопку Enter аудіо відео зображення PDF документ - програма Android + Програма Android Контакт - Іконку користувача опубліковано! + Піктограму користувача опубліковано! Надсилання %s Пропозиція %s Сховати поза мережею %s пише… %s припинив писати %s пишуть… - %s припинив писати + %s припинили писати Сповіщення про набір - Дайте вашим контактам знати, коли ви пишете їм повідомлення - Розташування + Повідомляти співрозмовників, що Ви пишете їм повідомлення + Надіслати місцезнаходження Показати місцезнаходження - Не знайдено програми, щоб показати місцезнаходження - Розташування + Не знайдено застосунку, щоб показати місцезнаходження + Місцезнаходження Розмову закрито - Полишити приватну групу обміну повідомленнями + Залишити приватну групу Залишити публічний канал Не довіряти системним центрам сертифікації Усі сертифікати мають бути підтверджені вручну @@ -424,8 +445,8 @@ Скасувати %d сертифікат вилучено - %d сертифікати видалено - %d сертифікатів видалено + %d сертифікати вилучено + %d сертифікатів вилучено %d сертифікатів вилучено Замінювати кнопку надсилання швидкими діями @@ -435,7 +456,7 @@ Вибрати швидку дію Шукати в контактах Приватне повідомлення - %1$s залишила групу! + %1$s залишив групу Ім\'я користувача Ім\'я користувача Таке ім\'я користувача не допустиме @@ -443,7 +464,7 @@ Звантаження не вдалося: файл не знайдено Звантаження не вдалося: неможливо з\'єднатися з вузлом Завантаження не вдалося: неможливо записати файл - Мережа ToR не доступна + Мережа Tor недоступна Прив\'язка не спрацювала Сервер не відповідає за цей домен Поламано @@ -453,21 +474,21 @@ Показати налаштування імені вузла та порту при налаштуванні облікового запису xmpp.example.com Вхід із сертифікатом - Не можу розпізнати сертифікат + Не вдалося розпізнати сертифікат Налаштування збереження Налаштування збереження на стороні сервера Отримую налаштування збереженя. Будь ласка, зачекайте… - Не зміг отримати налаштування збереження + Не вдалося отримати налаштування збереження Потрібно розв\'язати головоломку Уведіть текст із зображення вище Ланцюжок сертифікатів не довірений - XMPP адрес не відповідає сертифікату + Адреса XMPP не відповідає сертифікату Оновити сертифікат Помилка отримання ключа OMEMO! Ключ OMEMO звірено з сертифікатом! Ваш пристрій не підтримує вибір сертифікатів клієнта! З\'єднання - З\'єднання через ToR + З\'єднання через Tor Тунелювати всі з\'єднання через мережу Tor. Потребує Orbot Назва вузла Порт @@ -482,34 +503,35 @@ %d повідомлень Завантажити більше повідомлень - Файлом поділилися з %s - Поділитися зображенням з %s - Поділитися зображеннями з %s - Текстом поділилися з %s + Файл надіслано %s + Зображення надіслано %s + Зображення надіслано %s + Текст надіслано %s Синхронізувати контакти Сповіщати про всі повідомлення - Повідомляти, лише якщо згадують + Сповіщати, лише якщо згадують Сповіщення вимкнено Сповіщення призупинено Стиснення зображень - Підказка: Обирайте \"Вибрати файл\" замість \"Вибрати зображення\", щоб надіслати окремі зображення без стиснення в обхід цього налаштування. + Підказка: Обирайте «Вибрати файл» замість «Вибрати зображення», щоб надіслати окремі зображення без стиснення в обхід цього налаштування. Завжди Лише великі зображення - Оптимізацію батареї задіяно + Увімкнено оптимізацію батареї Вимкнути Вибрана ділянка завелика - (Немає активних облікових засобів) + (Немає активних облікових записів) Це обов\'язкове поле Відредагувати Відредаговане повідомлення - Ви вже довіряєте цій особі. Вибираючи \"Готово\", ви лише підтверджуєте, що %s є учасником групи. + Ви вже довіряєте цій особі. Вибираючи «Зроблено», Ви лише підтверджуєте, що %s є учасником групи. Ви вимкнули цей обліковий запис - Помилка з безпекою: Неправильний доступ до файлу! - Не знайдено програми, щоб поділитися URI - Поділитися URI + Помилка безпеки: неправильний доступ до файлу! + Не знайдено застосунку, щоб поділитися URI + Поділитися URI… Погодитися та продовжити - Ми допоможемо вам створити обліковий запис. На наступній сторінці ви зможете змінити автоматично створений пароль.\nПодалі ви зможете спілкуватися з користувачами вашого або будь-якого іншого провайдера, для цього потрібно буде надати користувачеві вашу повну адресу XMPP. - Ваша повна адреса XMPP буде такою: %s + Ми допоможемо Вам створити обліковий запис на conversations.im. +\nВи зможете спілкуватися з користувачами Вашого або будь-якого іншого провайдера, для цього повідомте їм свою повну адресу XMPP. + Ваша повна адреса XMPP: %s Створити обліковий запис Застосувати дані мого власного провайдера Придумайте ім\'я користувача @@ -524,7 +546,7 @@ Створено надійний пароль Ваш пристрій не підтримує вимкнення оптимізації батареї Реєстрація не вдалася: спробуйте ще раз пізніше - Реєстрація не відбулася: пароль занадто слабкий. + Реєстрація не відбулася: пароль занадто слабкий Вибрати учасників Створення групи… Запросити знову @@ -533,7 +555,7 @@ Середній Довгий Показувати останню активність користувача - Дозвольте всім вашим контактам знати, коли ви використовуєте месенджер + Повідомляти співрозмовникам, що Ви користуєтеся Conversations Приватність Тема Виберіть колір теми @@ -542,7 +564,7 @@ Темна Зелене тло Використовувати зелене тло для отриманих повідомлень - Не можу зв\'язатися з OpenKeychain + Не вдалося зв\'язатися з OpenKeychain Цей пристрій більше не використовується Комп\'ютер Мобільний телефон @@ -550,23 +572,23 @@ Браузер Консоль Вимагається оплата - Немає дозволу до користування Інтернет + Надати дозвіл на доступ до Інтернету Я - Контакт просить надавати інформацію про вашу доступність + Контакт просить надавати інформацію про присутність Дозволити Немає дозволу на доступ до %s Віддалений сервер не знайдено Затримка відповіді сервера - Неможливо оновити обліковий запис + Не вдалося оновити обліковий запис Надіслати скаргу про те, що контакт з цим ID розсилає спам. Вилучити ідентифікаційні дані OMEMO - Створити наново ваші ключі OMEMO. Усі ваші контакти будуть змушені підтвердити вас знову. Використовуйте це, лише якщо немає іншого вибору. + Створити наново Ваші ключі OMEMO. Всі Ваші контакти будуть змушені підтвердити Вас знову. Використовуйте це, лише якщо немає іншого вибору. Вилучити вибрані ключі Потрібно підключення, щоб можна було опублікувати піктограму користувача. Показати повідомлення про помилку Повідомлення про помилку - Увімкнено заощадження передачі даних - Неможливо створити тимчасовий файл + Увімкнено заощадження трафіку + Не вдалося створити тимчасовий файл Цей пристрій перевірено Копіювати цифровий підпис QR-код не містить цифрових підписів для цієї розмови. @@ -576,9 +598,9 @@ Поділитися через QR-код Поділитися XMPP URI Поділитися посиланням HTTP - Довіряти новим пристроям - Автоматично довіряти усім новим пристроям співрозмовників, які ще не пройшли перевірки, запитувати підтвердження вручну щоразу, як перевірений контакт додає свій новий пристрій - Ключі OMEMO наосліп прийнято як довірені + Довіряти наосліп до підтвердження + Автоматично довіряти всім новим пристроям співрозмовників, які ще не пройшли перевірки, запитувати підтвердження вручну щоразу, як перевірений контакт додає свій новий пристрій. + Ключі OMEMO, яким Ви довіряєте наосліп, тобто співрозмовник може бути не тим, кому Ви довіряєте. Недовірений Недійсний QR-код Очистити теку з кешем (використовується застосунком Камера) @@ -586,12 +608,13 @@ Очистити приватне сховище Очистити приватне сховище, де зберігаються файли (Їх можна повторно звантажити з сервера) Я перейшов за цим посиланням від довіреного джерела - Ви збираєтеся підтвердити ключі OMEMO для %1$s після переходу за посиланням. Це безпечно, лише якщо ви отримали посилання з довіреного джерела, де лише %2$s міг опублікувати це посилання. - Підтвердити цифрові підписи OMEMO + Ви збираєтеся підтвердити ключі OMEMO для %1$s після переходу за посиланням. Це безпечно, лише якщо Ви отримали посилання з довіреного джерела, де лише %2$s міг опублікувати це посилання. + Підтвердити ключі OMEMO Показувати неактивні Приховати неактивні Не довіряти пристрою - Ви певні, що більше не довіряєте цьому пристрою?\nЦей пристрій і повідомлення з нього будуть позначатися як недовірені. + Ви впевнені, що більше не довіряєте цьому пристрою\? +\nЦей пристрій і повідомлення з нього будуть позначатися як недовірені. %d секунда %d секунди @@ -636,7 +659,7 @@ Відповідні розмови завершено. Контакт заблоковано. Сповіщення від незнайомців - Сповіщувати про повідомлення від незнайомців + Сповіщати про повідомлення і виклики від незнайомців. Отримано повідомлення від незнайомця Заблокувати невідомий контакт Заблокувати весь домен @@ -653,7 +676,7 @@ Учора Перевіряти адресу за допомогою DNSSEC Сертифікати, які містять підтверджену адресу вузла, вважаються перевіреними - Сертифікат не містить XMPP адресу + Сертифікат не містить адреси XMPP частково Записати відео Копіювати @@ -661,11 +684,11 @@ Повідомлення Приватні повідомлення вимкнено Захищені програми - Для отримання сповіщень, навіть коли екран погас, вам потрібно додати застосунок до списку застосунків, до яких не застосовується режим енергозбереження. + Щоб отримувати сповіщення навіть коли екран погас, необхідно додати Conversations до списку захищених програм. Прийняти незнайомий сертифікат? - Сертифікат сервера не підтверджено відомим центром сертифікації + Сертифікат сервера не підтверджено відомим центром сертифікації. Прийняти сервер з невідповідним ім\'ям? - Не вдається перевірити сервер як \"%s\". Сертифікат чинний лише для: + Серверу не вдалося авторизуватися як «%s». Сертифікат чинний лише для: Усе одно бажаєте підключитися? Деталі сертифіката: Один раз @@ -677,41 +700,42 @@ Вимкнути шифрування Неможливо отримати перелік пристроїв Неможливо отримати пакети пристроїв - Підказка: В деяких випадках це можна виправити, якщо додати один до одного у ваших списках контактів. - Дійсно вимкнути шифрування OMEMO?\nПісля цього у адміністратора вашого сервера буде можливість мати доступ до ваших повідомлень. Проте, це може бути єдиним способом спілкуватися з людьми, які використовують застарілі застосунки. + Підказка: В деяких випадках це можна виправити, якщо додати один одного у свої списки контактів. + Дійсно вимкнути шифрування OMEMO\? +\nПісля цього в адміністратора Вашого сервера буде можливість мати доступ до Ваших повідомлень. Проте, це може бути єдиним способом спілкуватися з людьми, які використовують застарілі застосунки. Вимкнути зараз Чернетка: Шифрування OMEMO OMEMO завжди використовуватиметься для приватних розмов та у приватних групах. - Типово для нових розмов використовуватиметься OMEMO - OMEMO потрібно буде активізовувати окремо для кожної нової розмови. + Типово для нових розмов використовуватиметься OMEMO. + OMEMO потрібно буде вмикати окремо для кожної нової розмови. Створити ярлик Розмір шрифту - Розмір шрифту у застосунку + Розмір шрифту в застосунку. Типово ввімкнено Типово вимкнено Малий Середній Великий - Повідомлення не було зашифровано для цього пристрою + Повідомлення не було зашифровано для цього пристрою. Не вдалося розшифрувати повідомлення OMEMO. скасувати Доступ до місцезнаходження вимкнено Закріпити розташування Відкріпити розташування - Скопіювати розташування - Поділитися розташуванням + Скопіювати місцезнаходження + Поділитися місцезнаходженням Шлях - Поділитися розташуванням - Показати розташування + Поділитися місцезнаходженням + Показати місцезнаходження Поділитися - Не можу почати запис - Прошу зачекайте… + Не вдалося почати запис + Будь ласка, зачекайте… Шукати в повідомленнях GIF Переглянути розмову Додаток поширення місцезнаходження - Використовувати додаток поширення місце-знаходження замість вбудованої карти + Використовувати додаток поширення місцезнаходження замість вбудованої карти Копіювати посилання Копіювати адресу XMPP Доступ до файлів через HTTP для S3 @@ -737,8 +761,8 @@ Вхідні виклики Активні виклики Тихі повідомлення - Ця група сповіщень показує сповіщення, які не повинні супроводжуватися звуком. Наприклад, у разі активности на іншому пристрої (період очікування). - Налаштування сповіщень повідомлень + Ця група сповіщень показує сповіщення, які не повинні супроводжуватися звуком. Наприклад, у разі активності на іншому пристрої (період очікування). + Налаштування сповіщень про повідомлення Налаштування сповіщень про вхідні виклики Налаштування пріоритетів, звуку та режиму вібрації для сповіщень Стиснення відео @@ -756,67 +780,67 @@ Недійсний код країни Виберіть країну номер телефону - перевірити номер телефону - Quicksy надішле SMS, щоб перевірити ваш номер телефону. Тарифами Вашого оператора може бути передбачено плату за отримання SMS. Зазначте код вашої країни та номер телефону: -
%s

Чи все гаразд або ви бажаєте зазначити інший номер?]]>
+ Перевірте номер телефону + Quicksy надішле SMS, щоб перевірити Ваш номер телефону. Тарифами Вашого оператора може бути передбачено плату за отримання SMS. Зазначте код Вашої країни та номер телефону: + Ми перевіримо номер телефону

%s

Гаразд чи бажаєте вказати інший номер\?
%s не є дійсним номером телефону. - Будь ласка, введіть ваш номер телефону. + Будь ласка, введіть свій номер телефону. Шукати країну - Підтвердити %s - %s.]]> - Ми направили вам SMS із кодом з 6 цифр + Перевірити %s + Ми направили Вам SMS на %s. + Ми направили Вам SMS із кодом з 6 цифр. Будь ласка, введіть нижче 6 цифр коду. Надіслати нове SMS Надіслати нове SMS (%s) Будь ласка, зачекайте (%s) повернутися - Код, автоматично вставлений з буферу обміну. - Будь ласка, введіть нижче ваш код з 6 цифр. - Ви певні, що хочете припинити процедуру реєстрації? + Код автоматично вставлений з буфера обміну. + Будь ласка, введіть нижче код із 6 цифр. + Ви впевнені, що хочете припинити процедуру реєстрації\? Так Ні - Підтверджую… + Перевірка… Запит SMS… - Код, який ви ввели, не правильний. - Код, який ви ввели, застарів. + Код, який Ви ввели, неправильний. + Код, який Ви ввели, застарів. Невідома помилка мережі. Сервер дав незрозумілу відповідь. Неможливо приєднатися до сервера. Неможливо встановити безпечне з\'єднання. Неможливо знайти сервер. - Щось пішло не так під час обробки вашого запиту. + Щось пішло не так під час обробки Вашого запиту. Користувач зазначив неправильні дані Тимчасово недоступний. Будь ласка, спробуйте знову пізніше. Відсутнє з\'єднання з мережею. Будь ласка, спробуйте ще раз через %s Ви обмежені за рейтингом Забагато спроб - Версія вашого застосунку застаріла + Версія Вашого застосунку застаріла. Оновити Зараз цей номер телефону авторизований на іншому пристрої. - Будь ласка, зазначте ваше ім\'я, щоб надати можливість людям, які не мають вашого контакту, дізналися, хто ви є. + Будь ласка, вкажіть своє ім\'я, щоб надати можливість людям, які не мають Вашого контакту, дізнатися, хто Ви є. Ваше ім\'я - Зазначте ваше ім\'я + Вкажіть своє ім\'я Відредагуйте ім\'я користувача. Відхилити запит Встановити Orbot Запустити Orbot Не знайдено застосунку для пошуку й встановлення нових застосунків. - Цей канал опублікує вашу адресу XMPP + Цей канал опублікує Вашу адресу XMPP Електронна книга Оригінал (не стиснений) - Відкрити - Світлана профілю + Відкрити… + Зображення профілю для Conversations Виберіть обліковий запис Відновити з резервної копії Відновити Зазначте пароль до облікового запису %s, щоб відновити з резервної копії. Не використовуйте відновлення з резервної копії з метою клонування застосунку (запускати одночасно ще один примірник). Відновлення з резервної копії призначене виключно для перенесення даних або на випадок втрати оригінального пристрою. Неможливо відновити з резервної копії. - Неможливл розшифрувати резервну копію. Чи пароль правильний? + Неможливо розшифрувати резервну копію. Чи правильний пароль\? Створити або відновити резервну копію - Ввести адресу XMPP - Створити групу обміну повідомленнями + Введіть адресу XMPP + Створити групу Приєднатися до публічного каналу Створити приватну групу Створити публічний канал @@ -828,7 +852,7 @@ Створення публічного каналу… Цей канал уже існує Ви приєдналися до наявного каналу - Неможливо налаштувати канал + Не вдалося зберегти налаштування каналу Дозволити будь-кому редагувати тему Дозволити будь-кому запрошувати інших Будь-хто може редагувати тему. @@ -838,8 +862,8 @@ Будь-хто може запрошувати інших. Адміністратори бачать адреси XMPP. Будь-хто бачить адреси XMPP. - Цей публічний канал не має учасників. Запросіть ваші контакти або скористайтеся кнопкою поширення, щоб поділитися адресою XMPP. - У цій приватній групі обміну повідомленнями відсутні учасники. + Цей публічний канал не має учасників. Запросіть Ваші контакти або скористайтеся кнопкою поширення, щоб поділитися адресою XMPP. + У цій приватній групі відсутні учасники. Керувати правами Шукати учасників Файл надто великий @@ -866,7 +890,7 @@ jabber.network Локальний сервер - Більшість користувачів вибирають \'jabber.network\' як одну з кращих пропозицій зі всіх публічних середовищ XMPP. + Більшість користувачів вибирають jabber.network як одну з кращих пропозицій з усіх публічних середовищ XMPP. Спосіб пошуку каналів Резервне копіювання Про застосунок @@ -890,10 +914,10 @@ Завершити Активний виклик Активний відеовиклик - Вимкнути ToR для здійснення викликів + Вимкнути Tor для здійснення викликів Вхідний виклик Вихідний виклик - Пропущені виклики + Пропущений виклик Голосовий виклик Відеовиклик Допомога @@ -908,4 +932,133 @@ Перегляд %1$d учасників Перегляд %1$d учасників
- + + %1$d пропущений виклик від %2$d контакту + %1$d пропущених виклики від %2$d контактів + %1$d пропущених викликів від %2$d контактів + %1$d пропущених викликів від %2$d контактів + + Закрити розмову + Збій %1$s + Надсилаючи зі свого облікового запису XMPP траси стеку викликів, Ви допомагаєте розробляти %1$s. + Мелодія для вхідних викликів + Заборонити знімки екрана + Ховати вміст застосунку при перемиканні програм і заборонити знімки екрана + Несумісний клієнт + Домен неможливо перевірити + Обліковий запис для отримання push-повідомлень. + Сервер push + + %1$d пропущений виклик від %2$s + %1$d пропущених виклики від %2$s + %1$d пропущених викликів від %2$s + %1$d пропущених викликів від %2$s + + Звантаження не вдалося: неправильний файл + Встановити статус «Зайнятий», коли пристрій у безшумному режимі + Перемкнути на відеовиклик\? + Надати %1$s доступ до зовнішньої пам\'яті + + %d пропущений виклик + %d пропущених виклики + %d пропущених викликів + %d пропущених викликів + + Трек GPX + Записати голосове повідомлення + + %d непрочитана розмова + %d непрочитаних розмови + %d непрочитаних розмов + %d непрочитаних розмов + + Ця розмова + Додати контакт, створити чи приєднатися до групи або знайти канали + Обліковий запис XMPP + Пошук каналів використовує сторонній сервіс <a href=https://search.jabber.network>search.jabber.network</a>.<br><br>Використання цієї функції передає Вашу IP-адресу та пошукові запити цьому сервісу. Перегляньте їхню <a href=https://search.jabber.network/privacy>Політику конфіденційності</a>, щоб отримати більше інформації. + Вихідний виклик · %s + %1$s використовує <b>OpenKeychain</b> для шифрування повідомлень і керування публічними ключами.<br><br>OpenKeychain поширюється на умовах ліцензії GPLv3+ і доступний для завантаження на F-Droid та Google Play.<br><br><small>(Після встановлення необхідно перезапустити %1$s.)</small> + Додатково + Не вдалося увімкнути відео. + Жоден з активних облікових записів не підтримує цієї функції + Вилучити обліковий запис із сервера + + Не вдалося надіслати повідомлення + Деякі повідомлення не вдалося надіслати + Деякі повідомлення не вдалося надіслати + Деякі повідомлення не вдалося надіслати + + Оберіть сервер для доставки push-повідомлень через XMPP на Ваш пристрій. + Застосунок для передачі зображення не надав достатніх дозволів. + Виклики вимкнені при використанні Tor + %1$s потребує дозволу на доступ до контактів, щоб порівняти їх з Вашими XMPP-контактами. +\nТаким чином можна буде показувати піктограми і повні імена користувачів. +\n +\n%1$s співставлення інформації про контакти відбувається локально, нічого не завантажується на сервер. + Пропущені виклики + Ваша операційна система обмежує для %1$s доступ до Інтернету у фоновому режимі. Щоб отримувати сповіщення про нові повідомлення, Вам потрібно дозволити %1$s необмежений доступ, коли заощадження трафіку увімкнено. +\n%1$s намагатиметься по можливості економити трафік. + Встановлювати прапорець «autojoin» під час приєднання або виходу з групового чату/каналу та реагувати на зміни, зроблені іншими клієнтами. + Ваш пристрій застосовує до %1$s інтенсивний режим енергозбереження, що може спричинити затримку сповіщень чи навіть втрату повідомлень. +\nРекомендуємо вимкнути режим енергозбереження. + Не вдалося відредагувати повідомлення + Цифровий підпис OMEMO (джерело повідомлення) + Цифровий підпис v\\OMEMO (джерело повідомлення) + Продовжити + Групові чати + Зберегти як групу + Синхронізувати закладки + Ви залишили цю групу з технічних причин + векторна графіка + мультимедіа + Шукати групу + «Відійшов» якщо екран заблоковано + Встановити статус «Відійшов», коли пристрій заблоковано + «Зайнятий» у безшумному режимі + Встановити статус «Зайнятий», коли пристрій у віброрежимі + Надати %1$s доступ до камери + Ваш пристрій застосовує до %1$s інтенсивний режим енергозбереження, що може спричинити затримку сповіщень чи навіть втрату повідомлень. +\n +\nЗараз з\'явиться запит на вимкнення режиму енергозбереження. + Ви збираєтеся підтвердити ключі OMEMO для власного облікового запису. Це безпечно, лише якщо Ви перейшли за посиланням з довіреного джерела, де лише Ви могли опублікувати це посилання. + Ви підтвердили всі ключі OMEMO, якими володієте + Ваш пристрій не підтримує вимкнення заощадження трафіку для %1$s. + %1$s не вдалося надіслати зашифроване повідомлення для %2$s. Імовірно, контакт використовує застарілий сервер або програму, яка не підтримує OMEMO. + Надати %1$s доступ до мікрофона + Ненадіслані повідомлення + Показує постійне сповіщення про те, що %1$s працює. + Пропущений виклик · %s + Вхідний виклик (%s) · %s + Вихідний виклик (%s) · %s + Повторне з\'єнання + Повторний виклик + Повторний відеовиклик + Проблема при перевірці + Закріпити + Відкріпити + Усі розмови + Зашифровано за допомогою OMEMO + Зашифровано за допомогою OpenPGP + Не зашифровано + Вийти + Запросити до Conversations + Текстовий документ + Не знайдено адреси XMPP + Немає (вимкнено) + Відхилити + Ваша піктограма + Піктограма для %s + Вилучити піктограму + Не вдалося обробити запрошення + Створення запрошень не підтримується сервером + Реєстрація облікових записів не підтримується + Перемкнути на відео + Відхиляти запит перемкнути на відео + Не вдалося вилучити обліковий запис із сервера + Ненадіслані повідомлення + Створення резервної копії. Ви отримаєте сповіщення щойно резервування завершиться. + Тимчасова помилка авторизації + Відтворити аудіо + Зупинити аудіо + Не знайдено застосунку + \ No newline at end of file From 826ff0cd28c09fa51ab4a4c66c8362a6abfff1b3 Mon Sep 17 00:00:00 2001 From: SomeTr Date: Thu, 3 Aug 2023 05:43:57 +0000 Subject: [PATCH 030/402] Translated using Weblate (Ukrainian) Currently translated at 100.0% (13 of 13 strings) Translation: Conversations/Android App (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-conversations/uk/ --- src/conversations/res/values-uk/strings.xml | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/conversations/res/values-uk/strings.xml b/src/conversations/res/values-uk/strings.xml index 3b855ab5c..400081358 100644 --- a/src/conversations/res/values-uk/strings.xml +++ b/src/conversations/res/values-uk/strings.xml @@ -3,10 +3,18 @@ Виберіть постачальника послуг обміну повідомленнями XMPP Скористатися conversations.im Створити новий обліковий запис - Вже маєте обліковий запис XMPP? Можливо, користуєтеся іншою програмою XMPP або користувалися цією програмою раніше. Якщо ні, можете створити новий обліковий запис XMPP просто зараз.\nЗверніть увагу, що деякі постачальники електронної пошти у той же час надають облікові записи XMPP. - XMPP — це мережа обміну повідомленнями, незалежна від постачальників. Можете використовувати цю програму з будь-яким XMPP сервером, який оберете.\nПроте, для зручності, ми спростили створення облікового запису на conversations.im — у постачальника, який спеціально налаштований на роботу з цією програмою. - Вас запросили до %1$s. Ми проведемо вас крок за кроком, щоб створити обліковий запис.\nОбираючи %1$s в якості свого постачальника, ви зможете спілкуватися з користувачами інших постачальників, для цього повідомте їм свою повну адресу XMPP. - Вас запросили до %1$s. Для вас створено ім\'я користувача. Ми проведемо вас крок за кроком, щоб створити обліковий запис.\nВи зможете спілкуватися з користувачами інших постачальників, для цього повідомите їм свою повну адресу XMPP. + Уже маєте обліковий запис XMPP\? Можливо, користуєтеся іншою програмою XMPP або користувалися Conversations раніше. Якщо ні, можете створити новий обліковий запис XMPP просто зараз. +\nЗверніть увагу, що деякі постачальники електронної пошти у той же час надають облікові записи XMPP. + XMPP — це мережа обміну повідомленнями, незалежна від постачальників. Можете використовувати цю програму з будь-яким XMPP-сервером, який оберете. +\nПроте для зручності ми спростили створення облікового запису на conversations.im — у постачальника, спеціально налаштованого на роботу з Conversations. + Вас запросили до %1$s. Ми проведемо Вас крок за кроком, щоб створити обліковий запис. +\nОбираючи %1$s в якості свого постачальника, Ви зможете спілкуватися з користувачами інших постачальників, для цього повідомте їм свою повну адресу XMPP. + Вас запросили до %1$s. Для Вас створено ім\'я користувача. Ми проведемо Вас крок за кроком, щоб створити обліковий запис. +\nВи зможете спілкуватися з користувачами інших постачальників, для цього повідомте їм свою повну адресу XMPP. Ваше запрошення до сервера Неправильно відформатований код забезпечення - \ No newline at end of file + Якщо контакт поблизу, він також може прийняти запрошення, відсканувавши код нижче. + Приєднуйтеся до %1$s і спілкуйтеся зі мною: %2$s + Запросити… + Натисніть «Поділитися», щоб надіслати Вашому контакту запрошення до %1$s. + \ No newline at end of file From b265a430d23c0697286a83a0f93e15b61fc6755e Mon Sep 17 00:00:00 2001 From: SomeTr Date: Wed, 2 Aug 2023 06:43:53 +0000 Subject: [PATCH 031/402] Translated using Weblate (Ukrainian) Currently translated at 100.0% (9 of 9 strings) Translation: Conversations/Android App (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-quicksy/uk/ --- src/quicksy/res/values-uk/strings.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/quicksy/res/values-uk/strings.xml b/src/quicksy/res/values-uk/strings.xml index e2aa92703..8c678d0a2 100644 --- a/src/quicksy/res/values-uk/strings.xml +++ b/src/quicksy/res/values-uk/strings.xml @@ -1,12 +1,12 @@ - Час, протягом якого застосунок дотримується тиші після активності на іншому пристрої. - Надсилаючи траси стеків виклику, ви допомагаєте розробці цього застосунку. - Дозволити всім вашим контактам знати, коли ви використовуєте цю програму. - Щоб продовжувати отримувати сповіщення, навіть коли екран вимкнуто, потрібно додати цю програму до списку захищених. + Час, протягом якого застосунок дотримується тиші після виявлення активності на іншому пристрої + Надсилаючи траси стеку викликів, Ви допомагаєте розробляти Quicksy + Повідомляти співрозмовникам, що Ви користуєтеся Quicksy + Щоб отримувати сповіщення навіть коли екран погас, необхідно додати Quicksy до списку захищених програм. Зображення профілю для Quicksy - Цей застосунок не доступний у вашій країні. + Цей застосунок не доступний у Вашій країні. Автентичність сервера не підтверджено. Невідома помилка безпеки. Вичерпано час для встановлення з\'єднання із сервером. - + \ No newline at end of file From febaea0131a6c0f5c82c226ceb92aa2f7617baf5 Mon Sep 17 00:00:00 2001 From: SomeTr Date: Fri, 4 Aug 2023 12:21:25 +0000 Subject: [PATCH 032/402] Translated using Weblate (Ukrainian) Currently translated at 4.1% (2 of 48 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/uk/ --- .../metadata/android/uk/full_description.txt | 39 +++++++++++++++++++ .../metadata/android/uk/short_description.txt | 1 + 2 files changed, 40 insertions(+) create mode 100644 fastlane/metadata/android/uk/full_description.txt create mode 100644 fastlane/metadata/android/uk/short_description.txt diff --git a/fastlane/metadata/android/uk/full_description.txt b/fastlane/metadata/android/uk/full_description.txt new file mode 100644 index 000000000..da2b97403 --- /dev/null +++ b/fastlane/metadata/android/uk/full_description.txt @@ -0,0 +1,39 @@ +Надійний, простий у використанні, ощадливо витрачає заряд акумулятора. Має вбудовану підтримку зображень, групових чатів і наскрізного шифрування. + +Принципи проектування: + +* Бути максимально красивим та простим у використанні, не жертвуючи безпекою чи конфіденційністю +* Покладатися на існуючі, добре встановлені протоколи +* Не вимагати облікового запису Google, зокрема Google Cloud Messaging (GCM) +* Вимагати якомога менше дозволів + +Функції: + +* Наскрізне шифрування (від відправника до одержувача) за допомогою OMEMO або OpenPGP +* Надсилання та отримання зображень +* Зашифровані голосові та відеодзвінки (DTLS-SRTP) +* Інтуїтивно зрозумілий інтерфейс користувача, який відповідає вказівкам Android Design +* Зображення / Аватари для Ваших контактів +* Синхронізація з настільним клієнтом +* Конференції (з підтримкою закладок) +* Інтеграція адресної книги +* Кілька облікових записів / єдина папка вхідних +* Дуже низький вплив на термін служби акумулятора + +Conversations дозволяє легко створити обліковий запис на безкоштовному сервері conversations.im. Однак Conversations працюватиме також із будь-яким іншим XMPP-сервером. Чимало серверів XMPP обслуговуються волонтерами і є безкоштовними. + +Функції XMPP: + +Conversations працює з будь-яким сервером XMPP. Проте XMPP — розширюваний протокол. Розширення також стандартизовані в так званих XEP. Conversations підтримує кілька з них, щоб покращити загальний досвід користування. Може виявитися, що Ваш поточний сервер XMPP не підтримує цих розширень. Тому, щоб отримати максимум від Conversations, розгляньте перехід на XMPP-сервер з підтримкою цих розширень або — ще краще — запускайте власний сервер XMPP для себе і своїх друзів. + +На даний час підтримуються такі XEP: + +* XEP-0065: SOCKS5 Bytestreams (або mod_proxy65). Використовується для передачі файлів, якщо обидві сторони знаходяться за брандмауером (NAT). +* XEP-0163: персональний протокол подій для аватарів +* XEP-0191: команда блокування дозволяє Вам заносити спамерів у чорний список або блокувати контакти, не видаляючи їх зі свого списку. +* XEP-0198: керування потоками дозволяє XMPP витримувати невеликі перебої в мережі та зміни основного TCP-з'єднання. +* XEP-0280: Message Carbons, який автоматично синхронізує повідомлення, які Ви надсилаєте, на настільний клієнт і, таким чином, дозволяє плавно переключатися з мобільного клієнта на клієнт для настільного ПК і назад протягом однієї розмови. +* XEP-0237: версія списку в основному для економії пропускної здатності при поганих мобільних з'єднаннях +* XEP-0313: керування архівом повідомлень синхронізує історію повідомлень із сервером. Дізнавайтеся про повідомлення, надіслані, поки Conversations був офлайн. +* XEP-0352: індикація стану клієнта повідомляє серверу, чи працює Conversations у фоновому режимі. Дозволяє серверу заощаджувати пропускну здатність, утримуючи неважливі пакети. +* XEP-0363: завантаження файлів HTTP дозволяє обмінюватися файлами на конференціях і з офлайн-контактами. Потрібен додатковий компонент на Вашому сервері. diff --git a/fastlane/metadata/android/uk/short_description.txt b/fastlane/metadata/android/uk/short_description.txt new file mode 100644 index 000000000..300b89277 --- /dev/null +++ b/fastlane/metadata/android/uk/short_description.txt @@ -0,0 +1 @@ +Простий у використанні XMPP-клієнт з підтримкою шифрування для Вашого телефона From 7a9f18f22332d6ad8c4a520f0b75869d0cdbba29 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 8 Aug 2023 09:04:26 +0200 Subject: [PATCH 033/402] play tones as music when silent only on android 12+ --- .../java/eu/siacs/conversations/xmpp/jingle/ToneManager.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/ToneManager.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/ToneManager.java index 2ee307082..da5b9ab2b 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/ToneManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/ToneManager.java @@ -3,6 +3,7 @@ package eu.siacs.conversations.xmpp.jingle; import android.content.Context; import android.media.AudioManager; import android.media.ToneGenerator; +import android.os.Build; import android.util.Log; import java.util.Arrays; @@ -189,7 +190,8 @@ class ToneManager { private static ToneGenerator getToneGenerator(final boolean ringerModeNormal) { try { - if (ringerModeNormal) { + // when silent and on Android 12+ use STREAM_MUSIC + if (ringerModeNormal || Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { return new ToneGenerator(AudioManager.STREAM_VOICE_CALL,60); } else { return new ToneGenerator(AudioManager.STREAM_MUSIC,100); From b4a07d0093e2086b12519961ade0242ef69ba46e Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 8 Aug 2023 10:39:36 +0200 Subject: [PATCH 034/402] remove channel discovery from Google Play build flavor --- .../services/AbstractQuickConversationsService.java | 5 +++++ .../eu/siacs/conversations/ui/SettingsActivity.java | 1 + .../conversations/ui/StartConversationActivity.java | 10 +++++++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/eu/siacs/conversations/services/AbstractQuickConversationsService.java b/src/main/java/eu/siacs/conversations/services/AbstractQuickConversationsService.java index d05e40ae8..5d6f8eee5 100644 --- a/src/main/java/eu/siacs/conversations/services/AbstractQuickConversationsService.java +++ b/src/main/java/eu/siacs/conversations/services/AbstractQuickConversationsService.java @@ -1,6 +1,7 @@ package eu.siacs.conversations.services; import android.content.Intent; +import android.os.Build; import eu.siacs.conversations.BuildConfig; @@ -25,6 +26,10 @@ public abstract class AbstractQuickConversationsService { return "conversations".equals(BuildConfig.FLAVOR_mode); } + public static boolean isPlayStoreFlavor() { + return "playstore".equals(BuildConfig.FLAVOR_distribution); + } + public abstract void signalAccountStateChange(); public abstract boolean isSynchronizing(); diff --git a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java index 021fc5fad..b9eaf32af 100644 --- a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java @@ -134,6 +134,7 @@ public class SettingsActivity extends XmppActivity implements OnSharedPreference changeOmemoSettingSummary(); if (QuickConversationsService.isQuicksy() + || QuickConversationsService.isPlayStoreFlavor() || Strings.isNullOrEmpty(Config.CHANNEL_DISCOVERY)) { final PreferenceCategory groupChats = (PreferenceCategory) mSettingsFragment.findPreference("group_chats"); diff --git a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java index a2d0b484c..09bc1e839 100644 --- a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java @@ -323,7 +323,11 @@ public class StartConversationActivity extends XmppActivity implements XmppConne } switch (actionItem.getId()) { case R.id.discover_public_channels: - startActivity(new Intent(this, ChannelDiscoveryActivity.class)); + if (QuickConversationsService.isPlayStoreFlavor()) { + throw new IllegalStateException("Channel discovery is not available on Google Play flavor"); + } else { + startActivity(new Intent(this, ChannelDiscoveryActivity.class)); + } break; case R.id.join_public_channel: showJoinConferenceDialog(prefilled); @@ -349,6 +353,9 @@ public class StartConversationActivity extends XmppActivity implements XmppConne final Menu menu = popupMenu.getMenu(); for (int i = 0; i < menu.size(); i++) { final MenuItem menuItem = menu.getItem(i); + if (QuickConversationsService.isPlayStoreFlavor() && menuItem.getItemId() == R.id.discover_public_channels) { + continue; + } final SpeedDialActionItem actionItem = new SpeedDialActionItem.Builder(menuItem.getItemId(), menuItem.getIcon()) .setLabel(menuItem.getTitle() != null ? menuItem.getTitle().toString() : null) .setFabImageTintColor(ContextCompat.getColor(this, R.color.white)) @@ -800,6 +807,7 @@ public class StartConversationActivity extends XmppActivity implements XmppConne @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (grantResults.length > 0) if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { ScanActivity.onRequestPermissionResult(this, requestCode, grantResults); From 0a973b6678f973ac5b841335929167dba25fbc7e Mon Sep 17 00:00:00 2001 From: SomeTr Date: Mon, 7 Aug 2023 05:06:26 +0000 Subject: [PATCH 035/402] Translated using Weblate (Ukrainian) Currently translated at 100.0% (966 of 966 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/uk/ --- src/main/res/values-uk/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/res/values-uk/strings.xml b/src/main/res/values-uk/strings.xml index affb805b9..28d162884 100644 --- a/src/main/res/values-uk/strings.xml +++ b/src/main/res/values-uk/strings.xml @@ -1061,4 +1061,6 @@ Відтворити аудіо Зупинити аудіо Не знайдено застосунку + Дистриб\'ютор UnifiedPush + Додати ще пісні\? \ No newline at end of file From 892b53090f8a34f96e9afb53ebcb3e185990ddd0 Mon Sep 17 00:00:00 2001 From: hamburger1024 Date: Tue, 8 Aug 2023 23:01:39 +0000 Subject: [PATCH 036/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (966 of 966 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index 86038d0c2..399c5d49d 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -72,7 +72,7 @@ 立即发送 不再询问 账户无法连接 - 账户无法连接 + 无法连接到多个账户 点击管理账户 发送文件 该联系人不在您的通讯录中,需要添加吗 ? @@ -146,7 +146,7 @@ 拍摄图片 预先同意订阅请求 您选择的文件不是图像 - 无法转换图片 + 无法转换图片文件 未找到文件 常规I/O错误。可能是存储空间不足? 你用来选择图片的应用没有提供读取文件的足够权限。 @@ -381,7 +381,7 @@ 选择一个操作 没有从属关系 离线 - 已封禁 + 已逐出 成员 高级模式 授予成员权限 From 510f9d801917c4a0d3e9f6d05e596331b141f156 Mon Sep 17 00:00:00 2001 From: 0eoc <0eoc@users.noreply.translate.codeberg.org> Date: Fri, 11 Aug 2023 14:48:56 +0000 Subject: [PATCH 037/402] Translated using Weblate (Russian) Currently translated at 99.5% (962 of 966 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/ru/ --- src/main/res/values-ru/strings.xml | 41 ++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/main/res/values-ru/strings.xml b/src/main/res/values-ru/strings.xml index c099525ad..f6d5bcf1a 100644 --- a/src/main/res/values-ru/strings.xml +++ b/src/main/res/values-ru/strings.xml @@ -183,7 +183,7 @@ Вы действительно хотите удалить ваш OpenPGP публичный ключ из опубликованных?\nВаши собеседники не смогут больше отправлять вам зашифрованные OpenPGP сообщения. Публичный ключ OpenPGP опубликован. Включить аккаунт - Удаление аккаунта также удалит всю историю вашей переписки + Вы уверены, что хотите удалить свой аккаунт\? Это удалит все истории диалогов Запись голоса XMPP-адрес Заблокировать XMPP-адрес @@ -536,7 +536,8 @@ Не найдено приложения для передачи URI Отправить URI… Согласиться и продолжить - Мы поможем Вам создать аккаунт на conversations.im¹.\nВыбрав conversations.im в качестве провайдера, вы сможете общаться с пользователями других провайдеров, сообщив им свой полный XMPP-адрес. + Мы поможем Вам создать аккаунт на conversations.im. +\nВыбрав conversations.im в качестве провайдера, вы сможете общаться с пользователями других провайдеров, сообщив им свой полный XMPP-адрес. Ваш полный XMPP-адрес будет: %s Создать аккаунт Использовать свой провайдер @@ -982,4 +983,40 @@ %d пропущеныыз звонков %d пропущеныыз звонков + Несовместимый клиент + Групповые беседы + медиафайл + Продолжить + Сервер уведомлений + Распределитель UnifiedPush + Пропущенные звонки + Переподключение + Адрес XMPP не найден + Учётная запись XMPP + Вы покинули эту беседу из-за технических причин + Добавить дополнительные треки\? + Переподключение к звонку + Переподключение к видеовызову + Исходящий вызов · %s + Проблема подтверждения + Временная ошибка аутентификации + Удалить аватар + Переключиться на видео + Отклонить запрос смены на видео + Отклонить + Невозможно удалить учётную запись на сервере + Удалить учётную запись на сервере + Сохранить как групповую беседу + Синхронизировать закладки + Устанавливать флаг \"автоприсоединение\" при входе в- и выходе из MUC, и реагировать на изменения от других клиентов. + Поиск по групповым беседам + Загрузка провалена: неверный файл + Перейти на видеовызов\? + Исходящий вызов (%s) · %s + Входящий вызов (%s) · %s + Регистрации учётных записей не поддерживаются + Звонки выключены, пока используется Tor + Учётная запись для получения пуш-уведомлений. + Выбираемый пользователем сервер для перенаправления уведомлений на Ваше устройство. + Обзор каналов использует сторонний сервис <a href=https://search.jabber.network>search.jabber.network</a>.<br><br>Эта функция передаст Ваш IP-адрес и ваш поисковый запрос этому сервису. Ознакомьтесь с их <a href=https://search.jabber.network/privacy>Политикой приватности</a> для получения подробностей. \ No newline at end of file From 6f4ad677d704dde339df10ff94802eb3d79dc6e0 Mon Sep 17 00:00:00 2001 From: SomeTr Date: Fri, 11 Aug 2023 12:53:31 +0000 Subject: [PATCH 038/402] Translated using Weblate (Ukrainian) Currently translated at 56.2% (27 of 48 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/uk/ --- fastlane/metadata/android/uk/changelogs/360.txt | 1 + fastlane/metadata/android/uk/changelogs/362.txt | 1 + fastlane/metadata/android/uk/changelogs/382.txt | 2 ++ fastlane/metadata/android/uk/changelogs/390.txt | 1 + fastlane/metadata/android/uk/changelogs/397.txt | 3 +++ fastlane/metadata/android/uk/changelogs/401.txt | 2 ++ fastlane/metadata/android/uk/changelogs/403.txt | 3 +++ fastlane/metadata/android/uk/changelogs/404.txt | 1 + fastlane/metadata/android/uk/changelogs/405.txt | 1 + fastlane/metadata/android/uk/changelogs/407.txt | 3 +++ fastlane/metadata/android/uk/changelogs/42010.txt | 2 ++ fastlane/metadata/android/uk/changelogs/42013.txt | 1 + fastlane/metadata/android/uk/changelogs/42015.txt | 1 + fastlane/metadata/android/uk/changelogs/42018.txt | 3 +++ fastlane/metadata/android/uk/changelogs/42022.txt | 2 ++ fastlane/metadata/android/uk/changelogs/42023.txt | 2 ++ fastlane/metadata/android/uk/changelogs/42038.txt | 2 ++ fastlane/metadata/android/uk/changelogs/42041.txt | 5 +++++ fastlane/metadata/android/uk/changelogs/42042.txt | 2 ++ fastlane/metadata/android/uk/changelogs/42043.txt | 1 + fastlane/metadata/android/uk/changelogs/42046.txt | 1 + fastlane/metadata/android/uk/changelogs/42047.txt | 1 + fastlane/metadata/android/uk/changelogs/42050.txt | 1 + fastlane/metadata/android/uk/changelogs/42059.txt | 2 ++ fastlane/metadata/android/uk/changelogs/42060.txt | 1 + 25 files changed, 45 insertions(+) create mode 100644 fastlane/metadata/android/uk/changelogs/360.txt create mode 100644 fastlane/metadata/android/uk/changelogs/362.txt create mode 100644 fastlane/metadata/android/uk/changelogs/382.txt create mode 100644 fastlane/metadata/android/uk/changelogs/390.txt create mode 100644 fastlane/metadata/android/uk/changelogs/397.txt create mode 100644 fastlane/metadata/android/uk/changelogs/401.txt create mode 100644 fastlane/metadata/android/uk/changelogs/403.txt create mode 100644 fastlane/metadata/android/uk/changelogs/404.txt create mode 100644 fastlane/metadata/android/uk/changelogs/405.txt create mode 100644 fastlane/metadata/android/uk/changelogs/407.txt create mode 100644 fastlane/metadata/android/uk/changelogs/42010.txt create mode 100644 fastlane/metadata/android/uk/changelogs/42013.txt create mode 100644 fastlane/metadata/android/uk/changelogs/42015.txt create mode 100644 fastlane/metadata/android/uk/changelogs/42018.txt create mode 100644 fastlane/metadata/android/uk/changelogs/42022.txt create mode 100644 fastlane/metadata/android/uk/changelogs/42023.txt create mode 100644 fastlane/metadata/android/uk/changelogs/42038.txt create mode 100644 fastlane/metadata/android/uk/changelogs/42041.txt create mode 100644 fastlane/metadata/android/uk/changelogs/42042.txt create mode 100644 fastlane/metadata/android/uk/changelogs/42043.txt create mode 100644 fastlane/metadata/android/uk/changelogs/42046.txt create mode 100644 fastlane/metadata/android/uk/changelogs/42047.txt create mode 100644 fastlane/metadata/android/uk/changelogs/42050.txt create mode 100644 fastlane/metadata/android/uk/changelogs/42059.txt create mode 100644 fastlane/metadata/android/uk/changelogs/42060.txt diff --git a/fastlane/metadata/android/uk/changelogs/360.txt b/fastlane/metadata/android/uk/changelogs/360.txt new file mode 100644 index 000000000..6685cdb3a --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/360.txt @@ -0,0 +1 @@ +* Підтримка параметрів XMPP URI ?register та ?register;preauth diff --git a/fastlane/metadata/android/uk/changelogs/362.txt b/fastlane/metadata/android/uk/changelogs/362.txt new file mode 100644 index 000000000..742bbaab6 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/362.txt @@ -0,0 +1 @@ +* Підтримка автоматичного перемикання теми на Android 10 diff --git a/fastlane/metadata/android/uk/changelogs/382.txt b/fastlane/metadata/android/uk/changelogs/382.txt new file mode 100644 index 000000000..49a02dfbb --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/382.txt @@ -0,0 +1,2 @@ +* Додано кнопку перемикання камери під час відеовиклику +* Виправлення для голосових дзвінків на планшетах diff --git a/fastlane/metadata/android/uk/changelogs/390.txt b/fastlane/metadata/android/uk/changelogs/390.txt new file mode 100644 index 000000000..f12a56fda --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/390.txt @@ -0,0 +1 @@ +* Можливість записати голосове повідомлення, коли абонент зайнятий diff --git a/fastlane/metadata/android/uk/changelogs/397.txt b/fastlane/metadata/android/uk/changelogs/397.txt new file mode 100644 index 000000000..0c9af0508 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/397.txt @@ -0,0 +1,3 @@ +* Обробляти файли GPX +* Покращення продуктивності при відновленні резервної копії +* Виправлення помилок diff --git a/fastlane/metadata/android/uk/changelogs/401.txt b/fastlane/metadata/android/uk/changelogs/401.txt new file mode 100644 index 000000000..dbce88932 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/401.txt @@ -0,0 +1,2 @@ +* Виправлено пошук на версіях Android до 5-ї включно +* Оптимізація використання пам'яті diff --git a/fastlane/metadata/android/uk/changelogs/403.txt b/fastlane/metadata/android/uk/changelogs/403.txt new file mode 100644 index 000000000..75ec2df34 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/403.txt @@ -0,0 +1,3 @@ +* Виправлено проблеми з підключенням, коли різні облікові записи використовували різні механізми SCRAM +* Додано підтримку SCRAM-SHA-512 +* Дозволено обмін файлами P2P (Jingle) із власним контактом diff --git a/fastlane/metadata/android/uk/changelogs/404.txt b/fastlane/metadata/android/uk/changelogs/404.txt new file mode 100644 index 000000000..130dce1c6 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/404.txt @@ -0,0 +1 @@ +* Незначні покращення стабільності для голосових та відеовикликів diff --git a/fastlane/metadata/android/uk/changelogs/405.txt b/fastlane/metadata/android/uk/changelogs/405.txt new file mode 100644 index 000000000..215a7e262 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/405.txt @@ -0,0 +1 @@ +* Quicksy: Автоматично отримувати SMS підтвердження diff --git a/fastlane/metadata/android/uk/changelogs/407.txt b/fastlane/metadata/android/uk/changelogs/407.txt new file mode 100644 index 000000000..0dcf92020 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/407.txt @@ -0,0 +1,3 @@ +* Показувати кнопку виклику для контактів поза мережею, якщо вони раніше оголосили про підтримку дзвінків +* Кнопка «Назад» більше не завершує виклик під час виклику +* Виправлення помилок diff --git a/fastlane/metadata/android/uk/changelogs/42010.txt b/fastlane/metadata/android/uk/changelogs/42010.txt new file mode 100644 index 000000000..9a3aefa1f --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42010.txt @@ -0,0 +1,2 @@ +* Виправлення різних помилок у підтримці Tor +* Покращення сумісності дзвінків із Dino diff --git a/fastlane/metadata/android/uk/changelogs/42013.txt b/fastlane/metadata/android/uk/changelogs/42013.txt new file mode 100644 index 000000000..6276353cc --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42013.txt @@ -0,0 +1 @@ +* Виправлено проблему з повідомленням про відсутність з'єднання на Android 7.1 diff --git a/fastlane/metadata/android/uk/changelogs/42015.txt b/fastlane/metadata/android/uk/changelogs/42015.txt new file mode 100644 index 000000000..e80184657 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42015.txt @@ -0,0 +1 @@ +* Незначні покращення голосових та відеовикликів diff --git a/fastlane/metadata/android/uk/changelogs/42018.txt b/fastlane/metadata/android/uk/changelogs/42018.txt new file mode 100644 index 000000000..01ffffc78 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42018.txt @@ -0,0 +1,3 @@ +* Показувати чорні смуги, коли віддалене відео не відповідає пропорціям екрана +* Покращення ефективності пошуку +* Додано налаштування для заборони знімків екрана diff --git a/fastlane/metadata/android/uk/changelogs/42022.txt b/fastlane/metadata/android/uk/changelogs/42022.txt new file mode 100644 index 000000000..4a5bfc7bb --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42022.txt @@ -0,0 +1,2 @@ +* Виправлено проблему коли деякі відео не стискалися +* Виправлено рідкісний збій під час відкриття сповіщення diff --git a/fastlane/metadata/android/uk/changelogs/42023.txt b/fastlane/metadata/android/uk/changelogs/42023.txt new file mode 100644 index 000000000..e85b7c0ad --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42023.txt @@ -0,0 +1,2 @@ +* Виправлено збій при відтворенні деяких лапок +* Виправлено збій на екрані привітання diff --git a/fastlane/metadata/android/uk/changelogs/42038.txt b/fastlane/metadata/android/uk/changelogs/42038.txt new file mode 100644 index 000000000..df23d2664 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42038.txt @@ -0,0 +1,2 @@ +* Незначні виправлення помилок +* Відновлено можливість викликів через JMP та інші служби (версія Playstore) diff --git a/fastlane/metadata/android/uk/changelogs/42041.txt b/fastlane/metadata/android/uk/changelogs/42041.txt new file mode 100644 index 000000000..62b971cdf --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42041.txt @@ -0,0 +1,5 @@ +* Реалізація Extensible SASL Profile, Bind 2.0 і Fast для швидшого повторного з'єнання +* Реалізація Channel Binding +* Додано можливість перемикатися з голосового на відеовиклик +* Додано можливість видаляти своє зображення профілю +* Додано сповіщення про пропущені виклики diff --git a/fastlane/metadata/android/uk/changelogs/42042.txt b/fastlane/metadata/android/uk/changelogs/42042.txt new file mode 100644 index 000000000..771ad5b10 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42042.txt @@ -0,0 +1,2 @@ +* Виправлено циклічне повторне надсилання на сервери, які підтримують лише sm:2 +* Показувати «Перемкнути на відео» тільки якщо інша сторона підтримує відео diff --git a/fastlane/metadata/android/uk/changelogs/42043.txt b/fastlane/metadata/android/uk/changelogs/42043.txt new file mode 100644 index 000000000..a92ebf0fc --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42043.txt @@ -0,0 +1 @@ +* Виправлено регресивну помилку в обміні файлами P2P diff --git a/fastlane/metadata/android/uk/changelogs/42046.txt b/fastlane/metadata/android/uk/changelogs/42046.txt new file mode 100644 index 000000000..36f6ac725 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42046.txt @@ -0,0 +1 @@ +* Інтегрований дистриб'ютор UnifiedPush для надсилання push-повідомлень іншим застосункам, які підтримують UnifiedPush, як-от Tusky і Fedilab diff --git a/fastlane/metadata/android/uk/changelogs/42047.txt b/fastlane/metadata/android/uk/changelogs/42047.txt new file mode 100644 index 000000000..5cf6316f1 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42047.txt @@ -0,0 +1 @@ +* Виправлено збій у дистриб'юторі UnifiedPush diff --git a/fastlane/metadata/android/uk/changelogs/42050.txt b/fastlane/metadata/android/uk/changelogs/42050.txt new file mode 100644 index 000000000..cc1ed9ce3 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42050.txt @@ -0,0 +1 @@ +* Збільшено радіус заокруглення кутів зображення профілю diff --git a/fastlane/metadata/android/uk/changelogs/42059.txt b/fastlane/metadata/android/uk/changelogs/42059.txt new file mode 100644 index 000000000..35fffec4c --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42059.txt @@ -0,0 +1,2 @@ +* Target SDK знову підвищено до 33 +* Виправлення проблем із серверами, які підтримують SASL2 без вбудованого керування потоком diff --git a/fastlane/metadata/android/uk/changelogs/42060.txt b/fastlane/metadata/android/uk/changelogs/42060.txt new file mode 100644 index 000000000..20fde53a4 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42060.txt @@ -0,0 +1 @@ +* Виправлено помилкове розпізнавання літери «q» як кириличної From dc83eb9f4246c3ce23c8bfdfc5743c08caa3ff3f Mon Sep 17 00:00:00 2001 From: SomeTr Date: Sat, 12 Aug 2023 19:27:06 +0000 Subject: [PATCH 039/402] Translated using Weblate (Ukrainian) Currently translated at 100.0% (966 of 966 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/uk/ --- src/main/res/values-uk/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/res/values-uk/strings.xml b/src/main/res/values-uk/strings.xml index 28d162884..87f38b56b 100644 --- a/src/main/res/values-uk/strings.xml +++ b/src/main/res/values-uk/strings.xml @@ -1057,7 +1057,7 @@ Не вдалося вилучити обліковий запис із сервера Ненадіслані повідомлення Створення резервної копії. Ви отримаєте сповіщення щойно резервування завершиться. - Тимчасова помилка авторизації + Тимчасова помилка автентифікації Відтворити аудіо Зупинити аудіо Не знайдено застосунку From 76655f05b339766f716635f32ead4e698842aeda Mon Sep 17 00:00:00 2001 From: SomeTr Date: Sat, 12 Aug 2023 15:55:47 +0000 Subject: [PATCH 040/402] Translated using Weblate (Ukrainian) Currently translated at 100.0% (48 of 48 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/uk/ --- fastlane/metadata/android/uk/changelogs/349.txt | 4 ++++ fastlane/metadata/android/uk/changelogs/351.txt | 3 +++ fastlane/metadata/android/uk/changelogs/353.txt | 4 ++++ fastlane/metadata/android/uk/changelogs/364.txt | 2 ++ fastlane/metadata/android/uk/changelogs/367.txt | 2 ++ fastlane/metadata/android/uk/changelogs/379.txt | 1 + fastlane/metadata/android/uk/changelogs/381.txt | 2 ++ fastlane/metadata/android/uk/changelogs/383.txt | 3 +++ fastlane/metadata/android/uk/changelogs/387.txt | 2 ++ fastlane/metadata/android/uk/changelogs/388.txt | 3 +++ fastlane/metadata/android/uk/changelogs/393.txt | 3 +++ fastlane/metadata/android/uk/changelogs/394.txt | 2 ++ fastlane/metadata/android/uk/changelogs/395.txt | 3 +++ fastlane/metadata/android/uk/changelogs/398.txt | 4 ++++ fastlane/metadata/android/uk/changelogs/402.txt | 3 +++ fastlane/metadata/android/uk/changelogs/407.txt | 2 +- fastlane/metadata/android/uk/changelogs/42000.txt | 4 ++++ fastlane/metadata/android/uk/changelogs/42006.txt | 2 ++ fastlane/metadata/android/uk/changelogs/42010.txt | 2 +- fastlane/metadata/android/uk/changelogs/42012.txt | 1 + fastlane/metadata/android/uk/changelogs/42013.txt | 2 +- fastlane/metadata/android/uk/changelogs/42014.txt | 2 ++ fastlane/metadata/android/uk/changelogs/42037.txt | 11 +++++++++++ fastlane/metadata/android/uk/changelogs/42041.txt | 2 +- fastlane/metadata/android/uk/changelogs/42044.txt | 3 +++ fastlane/metadata/android/uk/changelogs/42059.txt | 2 +- 26 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 fastlane/metadata/android/uk/changelogs/349.txt create mode 100644 fastlane/metadata/android/uk/changelogs/351.txt create mode 100644 fastlane/metadata/android/uk/changelogs/353.txt create mode 100644 fastlane/metadata/android/uk/changelogs/364.txt create mode 100644 fastlane/metadata/android/uk/changelogs/367.txt create mode 100644 fastlane/metadata/android/uk/changelogs/379.txt create mode 100644 fastlane/metadata/android/uk/changelogs/381.txt create mode 100644 fastlane/metadata/android/uk/changelogs/383.txt create mode 100644 fastlane/metadata/android/uk/changelogs/387.txt create mode 100644 fastlane/metadata/android/uk/changelogs/388.txt create mode 100644 fastlane/metadata/android/uk/changelogs/393.txt create mode 100644 fastlane/metadata/android/uk/changelogs/394.txt create mode 100644 fastlane/metadata/android/uk/changelogs/395.txt create mode 100644 fastlane/metadata/android/uk/changelogs/398.txt create mode 100644 fastlane/metadata/android/uk/changelogs/402.txt create mode 100644 fastlane/metadata/android/uk/changelogs/42000.txt create mode 100644 fastlane/metadata/android/uk/changelogs/42006.txt create mode 100644 fastlane/metadata/android/uk/changelogs/42012.txt create mode 100644 fastlane/metadata/android/uk/changelogs/42014.txt create mode 100644 fastlane/metadata/android/uk/changelogs/42037.txt create mode 100644 fastlane/metadata/android/uk/changelogs/42044.txt diff --git a/fastlane/metadata/android/uk/changelogs/349.txt b/fastlane/metadata/android/uk/changelogs/349.txt new file mode 100644 index 000000000..03f0b8764 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/349.txt @@ -0,0 +1,4 @@ +* Додано Експертні налаштування для пошуку каналів на локальному сервері замість search.jabber.network +* Позначки про доставку увімкнено за замовчуванням, а налаштування видалено +* «Кнопка надсилання показує стан» увімкнено за замовчуванням, а налаштування видалено +* Налаштування резервного копіювання і процесу на передньому плані перенесено на основний екран diff --git a/fastlane/metadata/android/uk/changelogs/351.txt b/fastlane/metadata/android/uk/changelogs/351.txt new file mode 100644 index 000000000..4b92092b9 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/351.txt @@ -0,0 +1,3 @@ +* Виправлення обміну файлами Jingle IBB +* Повторювані виправлення правопису більше не заповнюють базу даних +* Перехід на Last Message Correction v1.1 diff --git a/fastlane/metadata/android/uk/changelogs/353.txt b/fastlane/metadata/android/uk/changelogs/353.txt new file mode 100644 index 000000000..e0ab4b1da --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/353.txt @@ -0,0 +1,4 @@ +* Користувачі можуть встановлювати своє прізвисько (нікнейм) +* Відновлювати завантаження файлів, зашифрованих OMEMO +* Канали тепер позначаються символом «#» на піктограмі +* Quicksy за замовчуванням використовує «завжди» для шифрування OMEMO (приховує значок замка) diff --git a/fastlane/metadata/android/uk/changelogs/364.txt b/fastlane/metadata/android/uk/changelogs/364.txt new file mode 100644 index 000000000..acf1518ac --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/364.txt @@ -0,0 +1,2 @@ +* Попередній перегляд PDF на Android 5 і новіших +* Використання 12-байтових IV для OMEMO diff --git a/fastlane/metadata/android/uk/changelogs/367.txt b/fastlane/metadata/android/uk/changelogs/367.txt new file mode 100644 index 000000000..4e697be13 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/367.txt @@ -0,0 +1,2 @@ +* Виправлено вибір піктограми користувача на деяких пристроях з Android 10 +* Виправлення обміну файлами для великих файлів diff --git a/fastlane/metadata/android/uk/changelogs/379.txt b/fastlane/metadata/android/uk/changelogs/379.txt new file mode 100644 index 000000000..0143a133a --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/379.txt @@ -0,0 +1 @@ +* Голосові та відеовиклики (необхідна підтримка сервера у вигляді серверів STUN і TURN, доступних для виявлення через XEP-0215) diff --git a/fastlane/metadata/android/uk/changelogs/381.txt b/fastlane/metadata/android/uk/changelogs/381.txt new file mode 100644 index 000000000..c59e5669c --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/381.txt @@ -0,0 +1,2 @@ +* Зворотний зв'язок (звуки «набір номера», «початок дзвінка», «завершення дзвінка») для голосових викликів +* Виправлено проблему з повторною спробою невдалого відеовиклику diff --git a/fastlane/metadata/android/uk/changelogs/383.txt b/fastlane/metadata/android/uk/changelogs/383.txt new file mode 100644 index 000000000..66d879d4b --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/383.txt @@ -0,0 +1,3 @@ +* Значок дзвінка переміщено ліворуч, щоб інші значки панелі інструментів залишалися на відповідних місцях +* Показувати тривалість розмови під час голосових викликів +* Визначення переваги в голосових та відеовикликах (двоє людей телефонують один одному одночасно) diff --git a/fastlane/metadata/android/uk/changelogs/387.txt b/fastlane/metadata/android/uk/changelogs/387.txt new file mode 100644 index 000000000..f82eb6752 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/387.txt @@ -0,0 +1,2 @@ +* Перероблено інтерфейс входу з сертифікатом +* Додано можливість закріплювати чати (додати до обраного) diff --git a/fastlane/metadata/android/uk/changelogs/388.txt b/fastlane/metadata/android/uk/changelogs/388.txt new file mode 100644 index 000000000..6e5f7899a --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/388.txt @@ -0,0 +1,3 @@ +* Зменшено відлуння під час викликів на деяких пристроях +* Виправлено вхід з паролями, що містять спеціальні символи +* Сигнали набору номера та зайнятості відтворюються через динамік під час відеовикликів diff --git a/fastlane/metadata/android/uk/changelogs/393.txt b/fastlane/metadata/android/uk/changelogs/393.txt new file mode 100644 index 000000000..c4bd20e66 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/393.txt @@ -0,0 +1,3 @@ +* Показувати кнопку «Довідка» у випадку невдалого голосового чи відеовиклику +* Виправлено деякі неприємні збої +* Виправлено з'єднання Jingle (обмін файлами + дзвінки) з JID'ами без ресурсу diff --git a/fastlane/metadata/android/uk/changelogs/394.txt b/fastlane/metadata/android/uk/changelogs/394.txt new file mode 100644 index 000000000..374c95fec --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/394.txt @@ -0,0 +1,2 @@ +* Виправлено сповіщення, які не з'являлися за певних умов +* Виправлення проблем сумісності та збоїв, пов’язаних з голосовими та відеовикликами diff --git a/fastlane/metadata/android/uk/changelogs/395.txt b/fastlane/metadata/android/uk/changelogs/395.txt new file mode 100644 index 000000000..890b5c473 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/395.txt @@ -0,0 +1,3 @@ +* Додано «Повернутися до чату» на екрані звукового виклику +* Удосконалено комбінації клавіш +* Виправлення помилок diff --git a/fastlane/metadata/android/uk/changelogs/398.txt b/fastlane/metadata/android/uk/changelogs/398.txt new file mode 100644 index 000000000..837e85eac --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/398.txt @@ -0,0 +1,4 @@ +* Пошук в окремих розмовах +* Сповіщення про невдале надсилання повідомлень +* Імена (нікнейми) користувачів Quicksy зберігаються після перезапуску застосунку +* Додано кнопку для запуску Orbot (Tor) із сповіщення, якщо це необхідно diff --git a/fastlane/metadata/android/uk/changelogs/402.txt b/fastlane/metadata/android/uk/changelogs/402.txt new file mode 100644 index 000000000..1f2ec0fbd --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/402.txt @@ -0,0 +1,3 @@ +* Просте створення запрошень на серверах з підтримкою запрошень +* Перегляд файлів GIF, отриманих з Movim +* Піктограми користувачів зберігаються у кеші diff --git a/fastlane/metadata/android/uk/changelogs/407.txt b/fastlane/metadata/android/uk/changelogs/407.txt index 0dcf92020..abc18bf99 100644 --- a/fastlane/metadata/android/uk/changelogs/407.txt +++ b/fastlane/metadata/android/uk/changelogs/407.txt @@ -1,3 +1,3 @@ * Показувати кнопку виклику для контактів поза мережею, якщо вони раніше оголосили про підтримку дзвінків -* Кнопка «Назад» більше не завершує виклик під час виклику +* Кнопка «Назад» більше не завершує дзвінок під час виклику * Виправлення помилок diff --git a/fastlane/metadata/android/uk/changelogs/42000.txt b/fastlane/metadata/android/uk/changelogs/42000.txt new file mode 100644 index 000000000..7657ede43 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42000.txt @@ -0,0 +1,4 @@ +* Можливість вибирати мелодію для вхідних викликів +* Виправлено виявлення ідентифікатора ключа OpenPGP для OpenKeychain 5.6+ +* Коректна перевірка сертифікатів punycode TLS +* Покращення стабільності встановлення сесії RTP (дзвінки) diff --git a/fastlane/metadata/android/uk/changelogs/42006.txt b/fastlane/metadata/android/uk/changelogs/42006.txt new file mode 100644 index 000000000..6077b0312 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42006.txt @@ -0,0 +1,2 @@ +* Перевіряти голосові та відеовиклики за допомогою вже існуючих сесій OMEMO +* Покращено сумісність із реалізаціями WebRTC без libwebrtc diff --git a/fastlane/metadata/android/uk/changelogs/42010.txt b/fastlane/metadata/android/uk/changelogs/42010.txt index 9a3aefa1f..0c25752b4 100644 --- a/fastlane/metadata/android/uk/changelogs/42010.txt +++ b/fastlane/metadata/android/uk/changelogs/42010.txt @@ -1,2 +1,2 @@ -* Виправлення різних помилок у підтримці Tor +* Виправлення різноманітних помилок у підтримці Tor * Покращення сумісності дзвінків із Dino diff --git a/fastlane/metadata/android/uk/changelogs/42012.txt b/fastlane/metadata/android/uk/changelogs/42012.txt new file mode 100644 index 000000000..654b6af7f --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42012.txt @@ -0,0 +1 @@ +* Виправлено передачу/завантаження через HTTP для користувачів, які не довіряють системним ЦС diff --git a/fastlane/metadata/android/uk/changelogs/42013.txt b/fastlane/metadata/android/uk/changelogs/42013.txt index 6276353cc..f1a182eb3 100644 --- a/fastlane/metadata/android/uk/changelogs/42013.txt +++ b/fastlane/metadata/android/uk/changelogs/42013.txt @@ -1 +1 @@ -* Виправлено проблему з повідомленням про відсутність з'єднання на Android 7.1 +* Виправлено проблеми з повідомленням про відсутність з'єднання на Android 7.1 diff --git a/fastlane/metadata/android/uk/changelogs/42014.txt b/fastlane/metadata/android/uk/changelogs/42014.txt new file mode 100644 index 000000000..39b9354ce --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42014.txt @@ -0,0 +1,2 @@ +* Завжди перевіряти ім'я домену. Без перезапису користувачем +* Підтримка попередньої автентифікації списку контактів diff --git a/fastlane/metadata/android/uk/changelogs/42037.txt b/fastlane/metadata/android/uk/changelogs/42037.txt new file mode 100644 index 000000000..723563a95 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42037.txt @@ -0,0 +1,11 @@ +Версія 2.10.9 +* Запитувати дозволи Bluetooth для голосових та відеовикликів (можна відхилити, якщо не використовуєте гарнітуру Bluetooth) +* Виправлено помилку під час виклику Movim +* Виправлено відображення неправильної піктограми для групових чатів +* Завжди запитувати про вимкнення оптимізації батареї +* Установлено прапорець «лише локально» для сповіщень «x облікових записів у мережі» +* Виправлено взаємодію з плагіном Google Maps Share Location +* Видалено примітку щодо плати за сервер +* Зберігати файли в місці, яке підходить для Android 11 +* Пробувати повторно підключити виклик після перемикання мережі +* Показувати JID абонента та JID облікового запису на екрані вхідного виклику diff --git a/fastlane/metadata/android/uk/changelogs/42041.txt b/fastlane/metadata/android/uk/changelogs/42041.txt index 62b971cdf..8138f1334 100644 --- a/fastlane/metadata/android/uk/changelogs/42041.txt +++ b/fastlane/metadata/android/uk/changelogs/42041.txt @@ -1,5 +1,5 @@ * Реалізація Extensible SASL Profile, Bind 2.0 і Fast для швидшого повторного з'єнання * Реалізація Channel Binding * Додано можливість перемикатися з голосового на відеовиклик -* Додано можливість видаляти своє зображення профілю +* Додано можливість видаляти свою піктограму користувача * Додано сповіщення про пропущені виклики diff --git a/fastlane/metadata/android/uk/changelogs/42044.txt b/fastlane/metadata/android/uk/changelogs/42044.txt new file mode 100644 index 000000000..8facdb3bf --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42044.txt @@ -0,0 +1,3 @@ +* Виправлено повторне надсилання повідомлень при використанні SASL2 +* Виправлення чорного відео між деякими пристроями +* Виправлено збій з порожніми паролями diff --git a/fastlane/metadata/android/uk/changelogs/42059.txt b/fastlane/metadata/android/uk/changelogs/42059.txt index 35fffec4c..06af124bb 100644 --- a/fastlane/metadata/android/uk/changelogs/42059.txt +++ b/fastlane/metadata/android/uk/changelogs/42059.txt @@ -1,2 +1,2 @@ -* Target SDK знову підвищено до 33 +* Цільовий SDK знову підвищено до 33 * Виправлення проблем із серверами, які підтримують SASL2 без вбудованого керування потоком From 0a956bcf9b24e21f66c9188c5a6f27d2c85d48b7 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 8 Aug 2023 11:52:46 +0200 Subject: [PATCH 041/402] version bump to 2.12.7 + changelog --- CHANGELOG.md | 4 ++++ build.gradle | 6 +++--- fastlane/metadata/android/en-US/changelogs/42061.txt | 1 + 3 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/42061.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ea5fd8dd..e1c3d8811 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### Version 2.12.7 + +* Remove channel discovery feature from Google Play version + ### Version 2.12.6 * Fix 'q' falsely being recognized as cyrillic diff --git a/build.gradle b/build.gradle index 1c0a79985..2157efbf1 100644 --- a/build.gradle +++ b/build.gradle @@ -33,7 +33,7 @@ configurations { dependencies { implementation 'androidx.viewpager:viewpager:1.0.0' - playstoreImplementation('com.google.firebase:firebase-messaging:23.1.2') { + playstoreImplementation('com.google.firebase:firebase-messaging:23.2.1') { exclude group: 'com.google.firebase', module: 'firebase-core' exclude group: 'com.google.firebase', module: 'firebase-analytics' exclude group: 'com.google.firebase', module: 'firebase-measurement-connector' @@ -95,8 +95,8 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 33 - versionCode 42060 - versionName "2.12.6" + versionCode 42061 + versionName "2.12.7" archivesBaseName += "-$versionName" applicationId "eu.siacs.conversations" resValue "string", "applicationId", applicationId diff --git a/fastlane/metadata/android/en-US/changelogs/42061.txt b/fastlane/metadata/android/en-US/changelogs/42061.txt new file mode 100644 index 000000000..0475d110d --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/42061.txt @@ -0,0 +1 @@ +* Remove channel discovery feature from Google Play version From 9a662a7e558749abeb48d2a78889accb3d27850a Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 16 Aug 2023 13:59:24 +0200 Subject: [PATCH 042/402] disable opeing ceb files from file manager --- src/conversations/AndroidManifest.xml | 53 +------------------ .../res/layout/dialog_enter_password.xml | 7 +++ src/main/AndroidManifest.xml | 10 ++-- src/main/res/values/strings.xml | 1 + 4 files changed, 16 insertions(+), 55 deletions(-) diff --git a/src/conversations/AndroidManifest.xml b/src/conversations/AndroidManifest.xml index c79e4e265..87c925fe6 100644 --- a/src/conversations/AndroidManifest.xml +++ b/src/conversations/AndroidManifest.xml @@ -24,57 +24,8 @@ android:launchMode="singleTask" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:launchMode="singleTask" /> diff --git a/src/conversations/res/layout/dialog_enter_password.xml b/src/conversations/res/layout/dialog_enter_password.xml index 40f3ba34d..29b50d4ef 100644 --- a/src/conversations/res/layout/dialog_enter_password.xml +++ b/src/conversations/res/layout/dialog_enter_password.xml @@ -22,6 +22,13 @@ android:text="@string/restore_warning" android:textAppearance="@style/TextAppearance.Conversations.Body1"/> + + - + - + @@ -119,7 +119,7 @@
- + @@ -309,7 +309,9 @@ android:label="@string/media_browser" /> - + Restore
Enter your password for the account %s to restore the backup. Do not use the restore backup feature in an attempt to clone (run simultaneously) an installation. Restoring a backup is only meant for migrations or in case you’ve lost the original device. + Do not attempt to restore backups that you have not created yourself! Could not restore backup. Could not decrypt backup. Is the password correct? Backup & Restore From 0677ddc59b5894b4a6e25901a2f2dbe28ca2a948 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 16 Aug 2023 14:10:48 +0200 Subject: [PATCH 043/402] version bump to 2.12.8 + changelog --- CHANGELOG.md | 4 ++++ build.gradle | 4 ++-- fastlane/metadata/android/en-US/changelogs/42062.txt | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/42062.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index e1c3d8811..a78324e55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### Version 2.12.8 + +* Disable opening backup files (.ceb) from file manager + ### Version 2.12.7 * Remove channel discovery feature from Google Play version diff --git a/build.gradle b/build.gradle index 2157efbf1..4ad722ea5 100644 --- a/build.gradle +++ b/build.gradle @@ -95,8 +95,8 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 33 - versionCode 42061 - versionName "2.12.7" + versionCode 42062 + versionName "2.12.8" archivesBaseName += "-$versionName" applicationId "eu.siacs.conversations" resValue "string", "applicationId", applicationId diff --git a/fastlane/metadata/android/en-US/changelogs/42062.txt b/fastlane/metadata/android/en-US/changelogs/42062.txt new file mode 100644 index 000000000..833c320e1 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/42062.txt @@ -0,0 +1 @@ +* Disable opening backup files (.ceb) from file manager From 09f6343ced61a44d87f736889d7c344ce333d6d9 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 17 Aug 2023 09:40:17 +0200 Subject: [PATCH 044/402] Security: Introduce backup file format v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This switches the SQL based backup format to something JSON based. The SQL based format has always been prone to SQL injections that, for example, could delete other messages or preexisting accounts in the app. This hasn’t been a concern this far because why would anyone purposely try to restore a faulty backup? However the argument has been made that a user can be socially engineered to restore an exploited backup file. Before version 2.12.8 a third party app could even trigger the restore process, leaving the backup password entry dialog the only hurdle. On top of that it has been demonstrated that a backup file can be crafted in a way that puts preexisting credentials into a 'pending' message to an attacker ultimately leading to that information being leaked. While destorying information has always been deemed an acceptable risk, leaking information is one step too far. Starting with Conversations 2.12.9 Conversations will no longer be able to read v1 backup files. This means if you are restoring on a new device and you have a v1 backup file you must first install Conversations <= 2.12.8, restore the backup, and then upgrade to Conversations >= 2.12.9. ceb2txt¹ has support for v2 backup files. Conceivably ceb2txt could be extended to convert between v1 and v2 file formats. (ceb2txt already recreates the database from v1 files; It is relatively straight forward to create v2 files from that database. Pull requests welcome.) ¹: https://github.com/iNPUTmice/ceb2txt/ --- .../services/ImportBackupService.java | 273 +++++++++----- .../services/ExportBackupService.java | 341 ++++++++++-------- .../conversations/utils/BackupFileHeader.java | 9 +- 3 files changed, 381 insertions(+), 242 deletions(-) diff --git a/src/conversations/java/eu/siacs/conversations/services/ImportBackupService.java b/src/conversations/java/eu/siacs/conversations/services/ImportBackupService.java index c118d7375..34a2cf6d1 100644 --- a/src/conversations/java/eu/siacs/conversations/services/ImportBackupService.java +++ b/src/conversations/java/eu/siacs/conversations/services/ImportBackupService.java @@ -6,6 +6,7 @@ import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; +import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.database.Cursor; @@ -22,6 +23,8 @@ import androidx.core.app.NotificationManagerCompat; import com.google.common.base.Charsets; import com.google.common.base.Stopwatch; import com.google.common.io.CountingInputStream; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; import org.bouncycastle.crypto.engines.AESEngine; import org.bouncycastle.crypto.io.CipherInputStream; @@ -40,6 +43,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -53,6 +57,10 @@ import javax.crypto.BadPaddingException; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; +import eu.siacs.conversations.crypto.axolotl.SQLiteAxolotlStore; +import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.persistance.DatabaseBackend; import eu.siacs.conversations.persistance.FileBackend; import eu.siacs.conversations.ui.ManageAccountActivity; @@ -65,25 +73,28 @@ public class ImportBackupService extends Service { private static final int NOTIFICATION_ID = 21; private static final AtomicBoolean running = new AtomicBoolean(false); private final ImportBackupServiceBinder binder = new ImportBackupServiceBinder(); - private final SerialSingleThreadExecutor executor = new SerialSingleThreadExecutor(getClass().getSimpleName()); - private final Set mOnBackupProcessedListeners = Collections.newSetFromMap(new WeakHashMap<>()); + private final SerialSingleThreadExecutor executor = + new SerialSingleThreadExecutor(getClass().getSimpleName()); + private final Set mOnBackupProcessedListeners = + Collections.newSetFromMap(new WeakHashMap<>()); private DatabaseBackend mDatabaseBackend; private NotificationManager notificationManager; - private static int count(String input, char c) { - int count = 0; - for (char aChar : input.toCharArray()) { - if (aChar == c) { - ++count; - } - } - return count; - } + private static final Collection TABLE_ALLOW_LIST = + Arrays.asList( + Account.TABLENAME, + Conversation.TABLENAME, + Message.TABLENAME, + SQLiteAxolotlStore.PREKEY_TABLENAME, + SQLiteAxolotlStore.SIGNED_PREKEY_TABLENAME, + SQLiteAxolotlStore.SESSION_TABLENAME, + SQLiteAxolotlStore.IDENTITIES_TABLENAME); @Override public void onCreate() { mDatabaseBackend = DatabaseBackend.getInstance(getBaseContext()); - notificationManager = (android.app.NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager = + (android.app.NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); } @Override @@ -105,16 +116,17 @@ public class ImportBackupService extends Service { return START_NOT_STICKY; } if (running.compareAndSet(false, true)) { - executor.execute(() -> { - startForegroundService(); - final boolean success = importBackup(uri, password); - stopForeground(true); - running.set(false); - if (success) { - notifySuccess(); - } - stopSelf(); - }); + executor.execute( + () -> { + startForegroundService(); + final boolean success = importBackup(uri, password); + stopForeground(true); + running.set(false); + if (success) { + notifySuccess(); + } + stopSelf(); + }); } else { Log.d(Config.LOGTAG, "backup already running"); } @@ -126,42 +138,59 @@ public class ImportBackupService extends Service { } public void loadBackupFiles(final OnBackupFilesLoaded onBackupFilesLoaded) { - executor.execute(() -> { - final List accounts = mDatabaseBackend.getAccountJids(false); - final ArrayList backupFiles = new ArrayList<>(); - final Set apps = new HashSet<>(Arrays.asList("Conversations", "Quicksy", getString(R.string.app_name))); - final List directories = new ArrayList<>(); - for (final String app : apps) { - directories.add(FileBackend.getLegacyBackupDirectory(app)); - } - directories.add(FileBackend.getBackupDirectory(this)); - for (final File directory : directories) { - if (!directory.exists() || !directory.isDirectory()) { - Log.d(Config.LOGTAG, "directory not found: " + directory.getAbsolutePath()); - continue; - } - final File[] files = directory.listFiles(); - if (files == null) { - continue; - } - for (final File file : files) { - if (file.isFile() && file.getName().endsWith(".ceb")) { - try { - final BackupFile backupFile = BackupFile.read(file); - if (accounts.contains(backupFile.getHeader().getJid())) { - Log.d(Config.LOGTAG, "skipping backup for " + backupFile.getHeader().getJid()); - } else { - backupFiles.add(backupFile); + executor.execute( + () -> { + final List accounts = mDatabaseBackend.getAccountJids(false); + final ArrayList backupFiles = new ArrayList<>(); + final Set apps = + new HashSet<>( + Arrays.asList( + "Conversations", + "Quicksy", + getString(R.string.app_name))); + final List directories = new ArrayList<>(); + for (final String app : apps) { + directories.add(FileBackend.getLegacyBackupDirectory(app)); + } + directories.add(FileBackend.getBackupDirectory(this)); + for (final File directory : directories) { + if (!directory.exists() || !directory.isDirectory()) { + Log.d( + Config.LOGTAG, + "directory not found: " + directory.getAbsolutePath()); + continue; + } + final File[] files = directory.listFiles(); + if (files == null) { + continue; + } + for (final File file : files) { + if (file.isFile() && file.getName().endsWith(".ceb")) { + try { + final BackupFile backupFile = BackupFile.read(file); + if (accounts.contains(backupFile.getHeader().getJid())) { + Log.d( + Config.LOGTAG, + "skipping backup for " + + backupFile.getHeader().getJid()); + } else { + backupFiles.add(backupFile); + } + } catch (IOException | IllegalArgumentException e) { + Log.d(Config.LOGTAG, "unable to read backup file ", e); + } } - } catch (IOException | IllegalArgumentException e) { - Log.d(Config.LOGTAG, "unable to read backup file ", e); } } - } - } - Collections.sort(backupFiles, (a, b) -> a.header.getJid().toString().compareTo(b.header.getJid().toString())); - onBackupFilesLoaded.onBackupFilesLoaded(backupFiles); - }); + Collections.sort( + backupFiles, + (a, b) -> + a.header + .getJid() + .toString() + .compareTo(b.header.getJid().toString())); + onBackupFilesLoaded.onBackupFilesLoaded(backupFiles); + }); } private void startForegroundService() { @@ -180,14 +209,16 @@ public class ImportBackupService extends Service { } final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); try { - notificationManager.notify(NOTIFICATION_ID, createImportBackupNotification(max, progress)); + notificationManager.notify( + NOTIFICATION_ID, createImportBackupNotification(max, progress)); } catch (final RuntimeException e) { Log.d(Config.LOGTAG, "unable to make notification", e); } } private Notification createImportBackupNotification(final int max, final int progress) { - NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getBaseContext(), "backup"); + NotificationCompat.Builder mBuilder = + new NotificationCompat.Builder(getBaseContext(), "backup"); mBuilder.setContentTitle(getString(R.string.restoring_backup)) .setSmallIcon(R.drawable.ic_unarchive_white_24dp) .setProgress(max, progress, max == 1 && progress == 0); @@ -212,7 +243,9 @@ public class ImportBackupService extends Service { fileSize = 0; } else { returnCursor.moveToFirst(); - fileSize = returnCursor.getLong(returnCursor.getColumnIndex(OpenableColumns.SIZE)); + fileSize = + returnCursor.getLong( + returnCursor.getColumnIndexOrThrow(OpenableColumns.SIZE)); returnCursor.close(); } inputStream = getContentResolver().openInputStream(uri); @@ -242,40 +275,46 @@ public class ImportBackupService extends Service { final byte[] key = ExportBackupService.getKey(password, backupFileHeader.getSalt()); final AEADBlockCipher cipher = new GCMBlockCipher(new AESEngine()); - cipher.init(false, new AEADParameters(new KeyParameter(key), 128, backupFileHeader.getIv())); - final CipherInputStream cipherInputStream = new CipherInputStream(countingInputStream, cipher); + cipher.init( + false, + new AEADParameters(new KeyParameter(key), 128, backupFileHeader.getIv())); + final CipherInputStream cipherInputStream = + new CipherInputStream(countingInputStream, cipher); final GZIPInputStream gzipInputStream = new GZIPInputStream(cipherInputStream); - final BufferedReader reader = new BufferedReader(new InputStreamReader(gzipInputStream, Charsets.UTF_8)); + final BufferedReader reader = + new BufferedReader(new InputStreamReader(gzipInputStream, Charsets.UTF_8)); + final JsonReader jsonReader = new JsonReader(reader); + if (jsonReader.peek() == JsonToken.BEGIN_ARRAY) { + jsonReader.beginArray(); + } else { + throw new IllegalStateException("Backup file did not begin with array"); + } db.beginTransaction(); - String line; - StringBuilder multiLineQuery = null; - while ((line = reader.readLine()) != null) { - int count = count(line, '\''); - if (multiLineQuery != null) { - multiLineQuery.append('\n'); - multiLineQuery.append(line); - if (count % 2 == 1) { - db.execSQL(multiLineQuery.toString()); - multiLineQuery = null; - updateImportBackupNotification(fileSize, countingInputStream.getCount()); - } - } else { - if (count % 2 == 0) { - db.execSQL(line); - updateImportBackupNotification(fileSize, countingInputStream.getCount()); - } else { - multiLineQuery = new StringBuilder(line); - } + while (jsonReader.hasNext()) { + if (jsonReader.peek() == JsonToken.BEGIN_OBJECT) { + importRow(db, jsonReader, backupFileHeader.getJid(), password); + } else if (jsonReader.peek() == JsonToken.END_ARRAY) { + jsonReader.endArray(); + continue; } + updateImportBackupNotification(fileSize, countingInputStream.getCount()); } db.setTransactionSuccessful(); db.endTransaction(); final Jid jid = backupFileHeader.getJid(); - final Cursor countCursor = db.rawQuery("select count(messages.uuid) from messages join conversations on conversations.uuid=messages.conversationUuid join accounts on conversations.accountUuid=accounts.uuid where accounts.username=? and accounts.server=?", new String[]{jid.getEscapedLocal(), jid.getDomain().toEscapedString()}); + final Cursor countCursor = + db.rawQuery( + "select count(messages.uuid) from messages join conversations on conversations.uuid=messages.conversationUuid join accounts on conversations.accountUuid=accounts.uuid where accounts.username=? and accounts.server=?", + new String[] { + jid.getEscapedLocal(), jid.getDomain().toEscapedString() + }); countCursor.moveToFirst(); final int count = countCursor.getInt(0); - Log.d(Config.LOGTAG, String.format("restored %d messages in %s", count, stopwatch.stop().toString())); + Log.d( + Config.LOGTAG, + String.format( + "restored %d messages in %s", count, stopwatch.stop().toString())); countCursor.close(); stopBackgroundService(); synchronized (mOnBackupProcessedListeners) { @@ -286,7 +325,8 @@ public class ImportBackupService extends Service { return true; } catch (final Exception e) { final Throwable throwable = e.getCause(); - final boolean reasonWasCrypto = throwable instanceof BadPaddingException || e instanceof ZipException; + final boolean reasonWasCrypto = + throwable instanceof BadPaddingException || e instanceof ZipException; synchronized (mOnBackupProcessedListeners) { for (OnBackupProcessed l : mOnBackupProcessedListeners) { if (reasonWasCrypto) { @@ -301,14 +341,71 @@ public class ImportBackupService extends Service { } } + private void importRow( + final SQLiteDatabase db, + final JsonReader jsonReader, + final Jid account, + final String passphrase) + throws IOException { + jsonReader.beginObject(); + final String firstParameter = jsonReader.nextName(); + if (!firstParameter.equals("table")) { + throw new IllegalStateException("Expected key 'table'"); + } + final String table = jsonReader.nextString(); + if (!TABLE_ALLOW_LIST.contains(table)) { + throw new IOException(String.format("%s is not recognized for import", table)); + } + final ContentValues contentValues = new ContentValues(); + final String secondParameter = jsonReader.nextName(); + if (!secondParameter.equals("values")) { + throw new IllegalStateException("Expected key 'values'"); + } + jsonReader.beginObject(); + while (jsonReader.peek() != JsonToken.END_OBJECT) { + final String name = jsonReader.nextName(); + if (jsonReader.peek() == JsonToken.NULL) { + jsonReader.nextNull(); + contentValues.putNull(name); + } else if (jsonReader.peek() == JsonToken.NUMBER) { + contentValues.put(name, jsonReader.nextLong()); + } else { + contentValues.put(name, jsonReader.nextString()); + } + } + jsonReader.endObject(); + jsonReader.endObject(); + if (Account.TABLENAME.equals(table)) { + final Jid jid = + Jid.of( + contentValues.getAsString(Account.USERNAME), + contentValues.getAsString(Account.SERVER), + null); + final String password = contentValues.getAsString(Account.PASSWORD); + if (jid.equals(account) && passphrase.equals(password)) { + Log.d(Config.LOGTAG, "jid and password from backup header had matching row"); + } else { + throw new IOException("jid or password in table did not match backup"); + } + } + db.insert(table, null, contentValues); + } + private void notifySuccess() { - NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getBaseContext(), "backup"); + NotificationCompat.Builder mBuilder = + new NotificationCompat.Builder(getBaseContext(), "backup"); mBuilder.setContentTitle(getString(R.string.notification_restored_backup_title)) .setContentText(getString(R.string.notification_restored_backup_subtitle)) .setAutoCancel(true) - .setContentIntent(PendingIntent.getActivity(this, 145, new Intent(this, ManageAccountActivity.class), s() - ? PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT - : PendingIntent.FLAG_UPDATE_CURRENT)) + .setContentIntent( + PendingIntent.getActivity( + this, + 145, + new Intent(this, ManageAccountActivity.class), + s() + ? PendingIntent.FLAG_IMMUTABLE + | PendingIntent.FLAG_UPDATE_CURRENT + : PendingIntent.FLAG_UPDATE_CURRENT)) .setSmallIcon(R.drawable.ic_unarchive_white_24dp); notificationManager.notify(NOTIFICATION_ID, mBuilder.build()); } @@ -391,4 +488,4 @@ public class ImportBackupService extends Service { return ImportBackupService.this; } } -} \ No newline at end of file +} diff --git a/src/main/java/eu/siacs/conversations/services/ExportBackupService.java b/src/main/java/eu/siacs/conversations/services/ExportBackupService.java index 9826ecbc2..442fc5f4f 100644 --- a/src/main/java/eu/siacs/conversations/services/ExportBackupService.java +++ b/src/main/java/eu/siacs/conversations/services/ExportBackupService.java @@ -19,11 +19,15 @@ import androidx.core.app.NotificationCompat; import com.google.common.base.CharMatcher; import com.google.common.base.Strings; +import com.google.gson.stream.JsonWriter; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.spec.InvalidKeySpecException; @@ -61,16 +65,16 @@ public class ExportBackupService extends Service { public static final String MIME_TYPE = "application/vnd.conversations.backup"; private static final int NOTIFICATION_ID = 19; - private static final int PAGE_SIZE = 20; private static final AtomicBoolean RUNNING = new AtomicBoolean(false); private DatabaseBackend mDatabaseBackend; private List mAccounts; private NotificationManager notificationManager; - private static List getPossibleFileOpenIntents(final Context context, final String path) { + private static List getPossibleFileOpenIntents( + final Context context, final String path) { - //http://www.openintents.org/action/android-intent-action-view/file-directory - //do not use 'vnd.android.document/directory' since this will trigger system file manager + // http://www.openintents.org/action/android-intent-action-view/file-directory + // do not use 'vnd.android.document/directory' since this will trigger system file manager final Intent openIntent = new Intent(Intent.ACTION_VIEW); openIntent.addCategory(Intent.CATEGORY_DEFAULT); if (Compatibility.runsAndTargetsTwentyFour(context)) { @@ -83,134 +87,95 @@ public class ExportBackupService extends Service { final Intent amazeIntent = new Intent(Intent.ACTION_VIEW); amazeIntent.setDataAndType(Uri.parse("com.amaze.filemanager:" + path), "resource/folder"); - //will open a file manager at root and user can navigate themselves + // will open a file manager at root and user can navigate themselves final Intent systemFallBack = new Intent(Intent.ACTION_VIEW); systemFallBack.addCategory(Intent.CATEGORY_DEFAULT); - systemFallBack.setData(Uri.parse("content://com.android.externalstorage.documents/root/primary")); + systemFallBack.setData( + Uri.parse("content://com.android.externalstorage.documents/root/primary")); return Arrays.asList(openIntent, amazeIntent, systemFallBack); } - private static void accountExport(final SQLiteDatabase db, final String uuid, final PrintWriter writer) { - final StringBuilder builder = new StringBuilder(); - final Cursor accountCursor = db.query(Account.TABLENAME, null, Account.UUID + "=?", new String[]{uuid}, null, null, null); + private static void accountExport( + final SQLiteDatabase db, final String uuid, final JsonWriter writer) + throws IOException { + final Cursor accountCursor = + db.query( + Account.TABLENAME, + null, + Account.UUID + "=?", + new String[] {uuid}, + null, + null, + null); while (accountCursor != null && accountCursor.moveToNext()) { - builder.append("INSERT INTO ").append(Account.TABLENAME).append("("); + writer.beginObject(); + writer.name("table"); + writer.value(Account.TABLENAME); + writer.name("values"); + writer.beginObject(); for (int i = 0; i < accountCursor.getColumnCount(); ++i) { - if (i != 0) { - builder.append(','); - } - builder.append(accountCursor.getColumnName(i)); - } - builder.append(") VALUES("); - for (int i = 0; i < accountCursor.getColumnCount(); ++i) { - if (i != 0) { - builder.append(','); - } + final String name = accountCursor.getColumnName(i); + writer.name(name); final String value = accountCursor.getString(i); if (value == null || Account.ROSTERVERSION.equals(accountCursor.getColumnName(i))) { - builder.append("NULL"); - } else if (Account.OPTIONS.equals(accountCursor.getColumnName(i)) && value.matches("\\d+")) { + writer.nullValue(); + } else if (Account.OPTIONS.equals(accountCursor.getColumnName(i)) + && value.matches("\\d+")) { int intValue = Integer.parseInt(value); intValue |= 1 << Account.OPTION_DISABLED; - builder.append(intValue); + writer.value(intValue); } else { - appendEscapedSQLString(builder, value); + writer.value(value); } } - builder.append(")"); - builder.append(';'); - builder.append('\n'); + writer.endObject(); + writer.endObject(); } if (accountCursor != null) { accountCursor.close(); } - writer.append(builder.toString()); } - private static void appendEscapedSQLString(final StringBuilder sb, final String sqlString) { - DatabaseUtils.appendEscapedSQLString(sb, CharMatcher.is('\u0000').removeFrom(sqlString)); - } - - private static void simpleExport(SQLiteDatabase db, String table, String column, String uuid, PrintWriter writer) { - final Cursor cursor = db.query(table, null, column + "=?", new String[]{uuid}, null, null, null); + private static void simpleExport( + final SQLiteDatabase db, + final String table, + final String column, + final String uuid, + final JsonWriter writer) + throws IOException { + final Cursor cursor = + db.query(table, null, column + "=?", new String[] {uuid}, null, null, null); while (cursor != null && cursor.moveToNext()) { - writer.write(cursorToString(table, cursor, PAGE_SIZE)); + writer.beginObject(); + writer.name("table"); + writer.value(table); + writer.name("values"); + writer.beginObject(); + for (int i = 0; i < cursor.getColumnCount(); ++i) { + final String name = cursor.getColumnName(i); + writer.name(name); + final String value = cursor.getString(i); + writer.value(value); + } + writer.endObject(); + writer.endObject(); } if (cursor != null) { cursor.close(); } } - public static byte[] getKey(final String password, final byte[] salt) throws InvalidKeySpecException { + public static byte[] getKey(final String password, final byte[] salt) + throws InvalidKeySpecException { final SecretKeyFactory factory; try { factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); } catch (NoSuchAlgorithmException e) { throw new IllegalStateException(e); } - return factory.generateSecret(new PBEKeySpec(password.toCharArray(), salt, 1024, 128)).getEncoded(); - } - - private static String cursorToString(final String table, final Cursor cursor, final int max) { - return cursorToString(table, cursor, max, false); - } - - private static String cursorToString(final String table, final Cursor cursor, int max, boolean ignore) { - final boolean identities = SQLiteAxolotlStore.IDENTITIES_TABLENAME.equals(table); - StringBuilder builder = new StringBuilder(); - builder.append("INSERT "); - if (ignore) { - builder.append("OR IGNORE "); - } - builder.append("INTO ").append(table).append("("); - int skipColumn = -1; - for (int i = 0; i < cursor.getColumnCount(); ++i) { - final String name = cursor.getColumnName(i); - if (identities && SQLiteAxolotlStore.TRUSTED.equals(name)) { - skipColumn = i; - continue; - } - if (i != 0) { - builder.append(','); - } - builder.append(name); - } - builder.append(") VALUES"); - for (int i = 0; i < max; ++i) { - if (i != 0) { - builder.append(','); - } - appendValues(cursor, builder, skipColumn); - if (i < max - 1 && !cursor.moveToNext()) { - break; - } - } - builder.append(';'); - builder.append('\n'); - return builder.toString(); - } - - private static void appendValues(final Cursor cursor, final StringBuilder builder, final int skipColumn) { - builder.append("("); - for (int i = 0; i < cursor.getColumnCount(); ++i) { - if (i == skipColumn) { - continue; - } - if (i != 0) { - builder.append(','); - } - final String value = cursor.getString(i); - if (value == null) { - builder.append("NULL"); - } else if (value.matches("[0-9]+")) { - builder.append(value); - } else { - appendEscapedSQLString(builder, value); - } - } - builder.append(")"); - + return factory.generateSecret(new PBEKeySpec(password.toCharArray(), salt, 1024, 128)) + .getEncoded(); } @Override @@ -223,49 +188,69 @@ public class ExportBackupService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { if (RUNNING.compareAndSet(false, true)) { - new Thread(() -> { - boolean success; - List files; - try { - files = export(); - success = true; - } catch (final Exception e) { - Log.d(Config.LOGTAG, "unable to create backup", e); - success = false; - files = Collections.emptyList(); - } - stopForeground(true); - RUNNING.set(false); - if (success) { - notifySuccess(files); - } - stopSelf(); - }).start(); + new Thread( + () -> { + boolean success; + List files; + try { + files = export(); + success = true; + } catch (final Exception e) { + Log.d(Config.LOGTAG, "unable to create backup", e); + success = false; + files = Collections.emptyList(); + } + stopForeground(true); + RUNNING.set(false); + if (success) { + notifySuccess(files); + } + stopSelf(); + }) + .start(); return START_STICKY; } else { - Log.d(Config.LOGTAG, "ExportBackupService. ignoring start command because already running"); + Log.d( + Config.LOGTAG, + "ExportBackupService. ignoring start command because already running"); } return START_NOT_STICKY; } - private void messageExport(SQLiteDatabase db, String uuid, PrintWriter writer, Progress progress) { - Cursor cursor = db.rawQuery("select messages.* from messages join conversations on conversations.uuid=messages.conversationUuid where conversations.accountUuid=?", new String[]{uuid}); + private void messageExport( + final SQLiteDatabase db, + final String uuid, + final JsonWriter writer, + final Progress progress) + throws IOException { + Cursor cursor = + db.rawQuery( + "select messages.* from messages join conversations on conversations.uuid=messages.conversationUuid where conversations.accountUuid=?", + new String[] {uuid}); int size = cursor != null ? cursor.getCount() : 0; Log.d(Config.LOGTAG, "exporting " + size + " messages for account " + uuid); int i = 0; int p = 0; while (cursor != null && cursor.moveToNext()) { - writer.write(cursorToString(Message.TABLENAME, cursor, PAGE_SIZE, false)); - if (i + PAGE_SIZE > size) { - i = size; - } else { - i += PAGE_SIZE; + writer.beginObject(); + writer.name("table"); + writer.value(Message.TABLENAME); + writer.name("values"); + writer.beginObject(); + for (int j = 0; j < cursor.getColumnCount(); ++j) { + final String name = cursor.getColumnName(j); + writer.name(name); + final String value = cursor.getString(j); + writer.value(value); } + writer.endObject(); + writer.endObject(); final int percentage = i * 100 / size; if (p < percentage) { p = percentage; notificationManager.notify(NOTIFICATION_ID, progress.build(p)); } + i++; } if (cursor != null) { cursor.close(); @@ -273,7 +258,8 @@ public class ExportBackupService extends Service { } private List export() throws Exception { - NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getBaseContext(), "backup"); + NotificationCompat.Builder mBuilder = + new NotificationCompat.Builder(getBaseContext(), "backup"); mBuilder.setContentTitle(getString(R.string.notification_create_backup_title)) .setSmallIcon(R.drawable.ic_archive_white_24dp) .setProgress(1, 0, false); @@ -286,17 +272,34 @@ public class ExportBackupService extends Service { for (final Account account : this.mAccounts) { final String password = account.getPassword(); if (Strings.nullToEmpty(password).trim().isEmpty()) { - Log.d(Config.LOGTAG, String.format("skipping backup for %s because password is empty. unable to encrypt", account.getJid().asBareJid())); + Log.d( + Config.LOGTAG, + String.format( + "skipping backup for %s because password is empty. unable to encrypt", + account.getJid().asBareJid())); continue; } - Log.d(Config.LOGTAG, String.format("exporting data for account %s (%s)", account.getJid().asBareJid(), account.getUuid())); + Log.d( + Config.LOGTAG, + String.format( + "exporting data for account %s (%s)", + account.getJid().asBareJid(), account.getUuid())); final byte[] IV = new byte[12]; final byte[] salt = new byte[16]; secureRandom.nextBytes(IV); secureRandom.nextBytes(salt); - final BackupFileHeader backupFileHeader = new BackupFileHeader(getString(R.string.app_name), account.getJid(), System.currentTimeMillis(), IV, salt); + final BackupFileHeader backupFileHeader = + new BackupFileHeader( + getString(R.string.app_name), + account.getJid(), + System.currentTimeMillis(), + IV, + salt); final Progress progress = new Progress(mBuilder, max, count); - final File file = new File(FileBackend.getBackupDirectory(this), account.getJid().asBareJid().toEscapedString() + ".ceb"); + final File file = + new File( + FileBackend.getBackupDirectory(this), + account.getJid().asBareJid().toEscapedString() + ".ceb"); files.add(file); final File directory = file.getParentFile(); if (directory != null && directory.mkdirs()) { @@ -307,25 +310,38 @@ public class ExportBackupService extends Service { backupFileHeader.write(dataOutputStream); dataOutputStream.flush(); - final Cipher cipher = Compatibility.twentyEight() ? Cipher.getInstance(CIPHERMODE) : Cipher.getInstance(CIPHERMODE, PROVIDER); + final Cipher cipher = + Compatibility.twentyEight() + ? Cipher.getInstance(CIPHERMODE) + : Cipher.getInstance(CIPHERMODE, PROVIDER); final byte[] key = getKey(password, salt); SecretKeySpec keySpec = new SecretKeySpec(key, KEYTYPE); IvParameterSpec ivSpec = new IvParameterSpec(IV); cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); - CipherOutputStream cipherOutputStream = new CipherOutputStream(fileOutputStream, cipher); + CipherOutputStream cipherOutputStream = + new CipherOutputStream(fileOutputStream, cipher); - GZIPOutputStream gzipOutputStream = new GZIPOutputStream(cipherOutputStream); - PrintWriter writer = new PrintWriter(gzipOutputStream); - SQLiteDatabase db = this.mDatabaseBackend.getReadableDatabase(); + final GZIPOutputStream gzipOutputStream = new GZIPOutputStream(cipherOutputStream); + final JsonWriter jsonWriter = + new JsonWriter( + new OutputStreamWriter(gzipOutputStream, StandardCharsets.UTF_8)); + jsonWriter.beginArray(); + final SQLiteDatabase db = this.mDatabaseBackend.getReadableDatabase(); final String uuid = account.getUuid(); - accountExport(db, uuid, writer); - simpleExport(db, Conversation.TABLENAME, Conversation.ACCOUNT, uuid, writer); - messageExport(db, uuid, writer, progress); - for (String table : Arrays.asList(SQLiteAxolotlStore.PREKEY_TABLENAME, SQLiteAxolotlStore.SIGNED_PREKEY_TABLENAME, SQLiteAxolotlStore.SESSION_TABLENAME, SQLiteAxolotlStore.IDENTITIES_TABLENAME)) { - simpleExport(db, table, SQLiteAxolotlStore.ACCOUNT, uuid, writer); + accountExport(db, uuid, jsonWriter); + simpleExport(db, Conversation.TABLENAME, Conversation.ACCOUNT, uuid, jsonWriter); + messageExport(db, uuid, jsonWriter, progress); + for (final String table : + Arrays.asList( + SQLiteAxolotlStore.PREKEY_TABLENAME, + SQLiteAxolotlStore.SIGNED_PREKEY_TABLENAME, + SQLiteAxolotlStore.SESSION_TABLENAME, + SQLiteAxolotlStore.IDENTITIES_TABLENAME)) { + simpleExport(db, table, SQLiteAxolotlStore.ACCOUNT, uuid, jsonWriter); } - writer.flush(); - writer.close(); + jsonWriter.endArray(); + jsonWriter.flush(); + jsonWriter.close(); mediaScannerScanFile(file); Log.d(Config.LOGTAG, "written backup to " + file.getAbsoluteFile()); count++; @@ -346,9 +362,15 @@ public class ExportBackupService extends Service { for (final Intent intent : getPossibleFileOpenIntents(this, path)) { if (intent.resolveActivityInfo(getPackageManager(), 0) != null) { - openFolderIntent = PendingIntent.getActivity(this, 189, intent, s() - ? PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT - : PendingIntent.FLAG_UPDATE_CURRENT); + openFolderIntent = + PendingIntent.getActivity( + this, + 189, + intent, + s() + ? PendingIntent.FLAG_IMMUTABLE + | PendingIntent.FLAG_UPDATE_CURRENT + : PendingIntent.FLAG_UPDATE_CURRENT); break; } } @@ -363,22 +385,39 @@ public class ExportBackupService extends Service { intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.setType(MIME_TYPE); - final Intent chooser = Intent.createChooser(intent, getString(R.string.share_backup_files)); - shareFilesIntent = PendingIntent.getActivity(this, 190, chooser, s() - ? PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT - : PendingIntent.FLAG_UPDATE_CURRENT); + final Intent chooser = + Intent.createChooser(intent, getString(R.string.share_backup_files)); + shareFilesIntent = + PendingIntent.getActivity( + this, + 190, + chooser, + s() + ? PendingIntent.FLAG_IMMUTABLE + | PendingIntent.FLAG_UPDATE_CURRENT + : PendingIntent.FLAG_UPDATE_CURRENT); } - NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getBaseContext(), "backup"); + NotificationCompat.Builder mBuilder = + new NotificationCompat.Builder(getBaseContext(), "backup"); mBuilder.setContentTitle(getString(R.string.notification_backup_created_title)) .setContentText(getString(R.string.notification_backup_created_subtitle, path)) - .setStyle(new NotificationCompat.BigTextStyle().bigText(getString(R.string.notification_backup_created_subtitle, FileBackend.getBackupDirectory(this).getAbsolutePath()))) + .setStyle( + new NotificationCompat.BigTextStyle() + .bigText( + getString( + R.string.notification_backup_created_subtitle, + FileBackend.getBackupDirectory(this) + .getAbsolutePath()))) .setAutoCancel(true) .setContentIntent(openFolderIntent) .setSmallIcon(R.drawable.ic_archive_white_24dp); if (shareFilesIntent != null) { - mBuilder.addAction(R.drawable.ic_share_white_24dp, getString(R.string.share_backup_files), shareFilesIntent); + mBuilder.addAction( + R.drawable.ic_share_white_24dp, + getString(R.string.share_backup_files), + shareFilesIntent); } notificationManager.notify(NOTIFICATION_ID, mBuilder.build()); diff --git a/src/main/java/eu/siacs/conversations/utils/BackupFileHeader.java b/src/main/java/eu/siacs/conversations/utils/BackupFileHeader.java index 54387a8ee..957ccfca1 100644 --- a/src/main/java/eu/siacs/conversations/utils/BackupFileHeader.java +++ b/src/main/java/eu/siacs/conversations/utils/BackupFileHeader.java @@ -1,5 +1,7 @@ package eu.siacs.conversations.utils; +import androidx.annotation.NonNull; + import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; @@ -8,7 +10,7 @@ import eu.siacs.conversations.xmpp.Jid; public class BackupFileHeader { - private static final int VERSION = 1; + private static final int VERSION = 2; private final String app; private final Jid jid; @@ -17,6 +19,7 @@ public class BackupFileHeader { private final byte[] salt; + @NonNull @Override public String toString() { return "BackupFileHeader{" + @@ -47,8 +50,8 @@ public class BackupFileHeader { public static BackupFileHeader read(DataInputStream inputStream) throws IOException { final int version = inputStream.readInt(); - if (version > VERSION) { - throw new IllegalArgumentException("Backup File version was " + version + " but app only supports up to version " + VERSION); + if (version != VERSION) { + throw new IllegalArgumentException("Backup File version was " + version + " but app only supports version " + VERSION); } String app = inputStream.readUTF(); String jid = inputStream.readUTF(); From 459d559a34f4b7d8626de593172f708d0ebf2afb Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 18 Aug 2023 09:01:46 +0200 Subject: [PATCH 045/402] check column name pattern --- .../services/ImportBackupService.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/conversations/java/eu/siacs/conversations/services/ImportBackupService.java b/src/conversations/java/eu/siacs/conversations/services/ImportBackupService.java index 34a2cf6d1..aba25515b 100644 --- a/src/conversations/java/eu/siacs/conversations/services/ImportBackupService.java +++ b/src/conversations/java/eu/siacs/conversations/services/ImportBackupService.java @@ -50,6 +50,7 @@ import java.util.List; import java.util.Set; import java.util.WeakHashMap; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.regex.Pattern; import java.util.zip.GZIPInputStream; import java.util.zip.ZipException; @@ -89,6 +90,8 @@ public class ImportBackupService extends Service { SQLiteAxolotlStore.SIGNED_PREKEY_TABLENAME, SQLiteAxolotlStore.SESSION_TABLENAME, SQLiteAxolotlStore.IDENTITIES_TABLENAME); + private static final Pattern COLUMN_PATTERN = Pattern.compile("^[a-zA-Z_]+$"); + @Override public void onCreate() { @@ -364,13 +367,17 @@ public class ImportBackupService extends Service { jsonReader.beginObject(); while (jsonReader.peek() != JsonToken.END_OBJECT) { final String name = jsonReader.nextName(); - if (jsonReader.peek() == JsonToken.NULL) { - jsonReader.nextNull(); - contentValues.putNull(name); - } else if (jsonReader.peek() == JsonToken.NUMBER) { - contentValues.put(name, jsonReader.nextLong()); + if (COLUMN_PATTERN.matcher(name).matches()) { + if (jsonReader.peek() == JsonToken.NULL) { + jsonReader.nextNull(); + contentValues.putNull(name); + } else if (jsonReader.peek() == JsonToken.NUMBER) { + contentValues.put(name, jsonReader.nextLong()); + } else { + contentValues.put(name, jsonReader.nextString()); + } } else { - contentValues.put(name, jsonReader.nextString()); + throw new IOException(String.format("Unexpected column name %s", name)); } } jsonReader.endObject(); From 6323b14bc0782a8c710f27c4bba24d883b9f09d7 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 18 Aug 2023 18:21:56 +0200 Subject: [PATCH 046/402] version bump to 2.12.9 + changelog --- CHANGELOG.md | 4 ++++ build.gradle | 4 ++-- fastlane/metadata/android/en-US/changelogs/42065.txt | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/42065.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index a78324e55..77be0422b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### Version 2.12.9 + +* Introduce new backup file format + ### Version 2.12.8 * Disable opening backup files (.ceb) from file manager diff --git a/build.gradle b/build.gradle index 4ad722ea5..430183eab 100644 --- a/build.gradle +++ b/build.gradle @@ -95,8 +95,8 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 33 - versionCode 42062 - versionName "2.12.8" + versionCode 42065 + versionName "2.12.9" archivesBaseName += "-$versionName" applicationId "eu.siacs.conversations" resValue "string", "applicationId", applicationId diff --git a/fastlane/metadata/android/en-US/changelogs/42065.txt b/fastlane/metadata/android/en-US/changelogs/42065.txt new file mode 100644 index 000000000..9b314f571 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/42065.txt @@ -0,0 +1 @@ +* Introduce new backup file format From 1b05cbd665122f30c3d40174cd1cf833b7cef61a Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 20 Aug 2023 07:59:39 +0200 Subject: [PATCH 047/402] use opus for voice messages on Android 10 recipients need at least Android 5 to play the message; however Conversations has been Android 5+ for a while now --- .../conversations/ui/RecordingActivity.java | 40 ++++++++++++++----- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/ui/RecordingActivity.java b/src/main/java/eu/siacs/conversations/ui/RecordingActivity.java index ad8684b72..085765163 100644 --- a/src/main/java/eu/siacs/conversations/ui/RecordingActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/RecordingActivity.java @@ -98,11 +98,20 @@ public class RecordingActivity extends Activity implements View.OnClickListener private boolean startRecording() { mRecorder = new MediaRecorder(); mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); - mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); - mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); - mRecorder.setAudioEncodingBitRate(96000); - mRecorder.setAudioSamplingRate(22050); - setupOutputFile(); + final int outputFormat; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + outputFormat = MediaRecorder.OutputFormat.OGG; + mRecorder.setOutputFormat(outputFormat); + mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.OPUS); + mRecorder.setAudioEncodingBitRate(32000); + } else { + outputFormat = MediaRecorder.OutputFormat.MPEG_4; + mRecorder.setOutputFormat(outputFormat); + mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); + mRecorder.setAudioEncodingBitRate(96000); + mRecorder.setAudioSamplingRate(22050); + } + setupOutputFile(outputFormat); mRecorder.setOutputFile(mOutputFile.getAbsolutePath()); try { @@ -110,10 +119,10 @@ public class RecordingActivity extends Activity implements View.OnClickListener mRecorder.start(); mStartTime = SystemClock.elapsedRealtime(); mHandler.postDelayed(mTickExecutor, 100); - Log.d("Voice Recorder", "started recording to " + mOutputFile.getAbsolutePath()); + Log.d(Config.LOGTAG, "started recording to " + mOutputFile.getAbsolutePath()); return true; } catch (Exception e) { - Log.e("Voice Recorder", "prepare() failed " + e.getMessage()); + Log.e(Config.LOGTAG, "prepare() failed ", e); return false; } } @@ -175,9 +184,18 @@ public class RecordingActivity extends Activity implements View.OnClickListener } } - private File generateOutputFilename() { + private File generateOutputFilename(final int outputFormat) { final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmssSSS", Locale.US); - final String filename = "RECORDING_" + dateFormat.format(new Date()) + ".m4a"; + final String extension; + if (outputFormat == MediaRecorder.OutputFormat.MPEG_4) { + extension = "m4a"; + } else if (outputFormat == MediaRecorder.OutputFormat.OGG) { + extension = "oga"; + } else { + throw new IllegalStateException("Unrecognized output format"); + } + final String filename = + String.format("RECORDING_%s.%s", dateFormat.format(new Date()), extension); final File parentDirectory; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { parentDirectory = @@ -190,8 +208,8 @@ public class RecordingActivity extends Activity implements View.OnClickListener return new File(conversationsDirectory, filename); } - private void setupOutputFile() { - mOutputFile = generateOutputFilename(); + private void setupOutputFile(final int outputFormat) { + mOutputFile = generateOutputFilename(outputFormat); final File parentDirectory = mOutputFile.getParentFile(); if (Objects.requireNonNull(parentDirectory).mkdirs()) { Log.d(Config.LOGTAG, "created " + parentDirectory.getAbsolutePath()); From d5ae2f4b4183d1159d633cb4fc91e42c16d3a61c Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 6 Sep 2023 13:47:30 +0200 Subject: [PATCH 048/402] look at roomconfig_changesubject and roominfo_changesubject fixes #90 --- src/main/java/eu/siacs/conversations/entities/MucOptions.java | 4 +++- .../eu/siacs/conversations/ui/ConferenceDetailsActivity.java | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index cc1c358de..c408d147f 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -170,7 +170,9 @@ public class MucOptions { } public boolean participantsCanChangeSubject() { - final Field field = getRoomInfoForm().getFieldByName("muc#roominfo_changesubject"); + final Field configField = getRoomInfoForm().getFieldByName("muc#roomconfig_changesubject"); + final Field infoField = getRoomInfoForm().getFieldByName("muc#roominfo_changesubject"); + final Field field = configField != null ? configField : infoField; return field != null && "1".equals(field.getValue()); } diff --git a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java index fb716044c..f5fb9c7f5 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java @@ -137,8 +137,9 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers builder.setMultiChoiceItems(configuration.names, values, (dialog, which, isChecked) -> values[which] = isChecked); builder.setNegativeButton(R.string.cancel, null); builder.setPositiveButton(R.string.confirm, (dialog, which) -> { - Bundle options = configuration.toBundle(values); + final Bundle options = configuration.toBundle(values); options.putString("muc#roomconfig_persistentroom", "1"); + options.putString("{http://prosody.im/protocol/muc}roomconfig_allowmemberinvites", options.getString("muc#roomconfig_allowinvites")); xmppConnectionService.pushConferenceConfiguration(mConversation, options, ConferenceDetailsActivity.this); From b64998bc04e1e00a9b2f8973c7fd63f9526486ce Mon Sep 17 00:00:00 2001 From: ghose Date: Fri, 18 Aug 2023 13:57:16 +0000 Subject: [PATCH 049/402] Translated using Weblate (Galician) Currently translated at 6.2% (3 of 48 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/gl/ --- fastlane/metadata/android/gl-ES/changelogs/349.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 fastlane/metadata/android/gl-ES/changelogs/349.txt diff --git a/fastlane/metadata/android/gl-ES/changelogs/349.txt b/fastlane/metadata/android/gl-ES/changelogs/349.txt new file mode 100644 index 000000000..ce9204ef3 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/349.txt @@ -0,0 +1,4 @@ +* Introdución do axuste de experta para realizar o descubrimento de canle no servidor local e non buscar en search.jabber.network +* Activadas as marcas de comprobación de entrega por defecto e eliminación do axuste +* Activar por defecto 'O botón enviar indica estado' e eliminar o axuste +* Mover os axustes Copia de Apoio e Servizo en primeiro plano á pantalla principal From de8294c2b368c89d101093db80e494fce444197d Mon Sep 17 00:00:00 2001 From: SomeTr Date: Sat, 19 Aug 2023 13:37:00 +0000 Subject: [PATCH 050/402] Translated using Weblate (Ukrainian) Currently translated at 100.0% (48 of 48 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/uk/ --- fastlane/metadata/android/uk/changelogs/387.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane/metadata/android/uk/changelogs/387.txt b/fastlane/metadata/android/uk/changelogs/387.txt index f82eb6752..a26a7642f 100644 --- a/fastlane/metadata/android/uk/changelogs/387.txt +++ b/fastlane/metadata/android/uk/changelogs/387.txt @@ -1,2 +1,2 @@ * Перероблено інтерфейс входу з сертифікатом -* Додано можливість закріплювати чати (додати до обраного) +* Додано можливість закріплювати чати (додати до вибраного) From 2901275d4302504c0c505493fd414e63fec06969 Mon Sep 17 00:00:00 2001 From: SomeTr Date: Sun, 20 Aug 2023 15:38:30 +0000 Subject: [PATCH 051/402] Translated using Weblate (Ukrainian) Currently translated at 100.0% (967 of 967 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/uk/ --- src/main/res/values-uk/strings.xml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/res/values-uk/strings.xml b/src/main/res/values-uk/strings.xml index 87f38b56b..033da344e 100644 --- a/src/main/res/values-uk/strings.xml +++ b/src/main/res/values-uk/strings.xml @@ -179,7 +179,7 @@ \nВаші контакти більше не зможуть надсилати Вам повідомлення, зашифровані OpenPGP. Публічний ключ OpenPGP опубліковано. Увімкнути обліковий запис - Ви впевнені, що хочете видалити обліковий запис\? Видалення облікового запису знищить усю історію спілкування + Ви впевнені, що хочете видалити свій обліковий запис\? Видалення облікового запису знищить усю Вашу історію спілкування Записати голос Адреса XMPP Заблокувати адресу XMPP @@ -530,10 +530,10 @@ Поділитися URI… Погодитися та продовжити Ми допоможемо Вам створити обліковий запис на conversations.im. -\nВи зможете спілкуватися з користувачами Вашого або будь-якого іншого провайдера, для цього повідомте їм свою повну адресу XMPP. +\nОбравши conversations.im в якості свого постачальника, Ви зможете спілкуватися з користувачами інших постачальників, для цього повідомте їм свою повну адресу XMPP. Ваша повна адреса XMPP: %s Створити обліковий запис - Застосувати дані мого власного провайдера + Застосувати дані мого власного постачальника Придумайте ім\'я користувача Керувати станом вручну Показувати доступність під час редагування повідомлення зі статусом. @@ -1063,4 +1063,5 @@ Не знайдено застосунку Дистриб\'ютор UnifiedPush Додати ще пісні\? + Не намагайтеся відновити резервні копії, які створили не Ви! \ No newline at end of file From 648cf3b4a6ee0cbcd87a2bd89c6953a804805476 Mon Sep 17 00:00:00 2001 From: SomeTr Date: Sun, 20 Aug 2023 16:07:22 +0000 Subject: [PATCH 052/402] Translated using Weblate (Ukrainian) Currently translated at 100.0% (13 of 13 strings) Translation: Conversations/Android App (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-conversations/uk/ --- src/conversations/res/values-uk/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conversations/res/values-uk/strings.xml b/src/conversations/res/values-uk/strings.xml index 400081358..f9e37cea7 100644 --- a/src/conversations/res/values-uk/strings.xml +++ b/src/conversations/res/values-uk/strings.xml @@ -8,7 +8,7 @@ XMPP — це мережа обміну повідомленнями, незалежна від постачальників. Можете використовувати цю програму з будь-яким XMPP-сервером, який оберете. \nПроте для зручності ми спростили створення облікового запису на conversations.im — у постачальника, спеціально налаштованого на роботу з Conversations. Вас запросили до %1$s. Ми проведемо Вас крок за кроком, щоб створити обліковий запис. -\nОбираючи %1$s в якості свого постачальника, Ви зможете спілкуватися з користувачами інших постачальників, для цього повідомте їм свою повну адресу XMPP. +\nОбравши %1$s в якості свого постачальника, Ви зможете спілкуватися з користувачами інших постачальників, для цього повідомте їм свою повну адресу XMPP. Вас запросили до %1$s. Для Вас створено ім\'я користувача. Ми проведемо Вас крок за кроком, щоб створити обліковий запис. \nВи зможете спілкуватися з користувачами інших постачальників, для цього повідомте їм свою повну адресу XMPP. Ваше запрошення до сервера From 74931f3af62036c383d2a5c03b8cd023632ee6e2 Mon Sep 17 00:00:00 2001 From: SomeTr Date: Sun, 20 Aug 2023 15:54:06 +0000 Subject: [PATCH 053/402] Translated using Weblate (Ukrainian) Currently translated at 100.0% (51 of 51 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/uk/ --- fastlane/metadata/android/uk/changelogs/42061.txt | 1 + fastlane/metadata/android/uk/changelogs/42062.txt | 1 + fastlane/metadata/android/uk/changelogs/42065.txt | 1 + 3 files changed, 3 insertions(+) create mode 100644 fastlane/metadata/android/uk/changelogs/42061.txt create mode 100644 fastlane/metadata/android/uk/changelogs/42062.txt create mode 100644 fastlane/metadata/android/uk/changelogs/42065.txt diff --git a/fastlane/metadata/android/uk/changelogs/42061.txt b/fastlane/metadata/android/uk/changelogs/42061.txt new file mode 100644 index 000000000..2b4441c6e --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42061.txt @@ -0,0 +1 @@ +* Видалено функцію пошуку каналів із версії Google Play diff --git a/fastlane/metadata/android/uk/changelogs/42062.txt b/fastlane/metadata/android/uk/changelogs/42062.txt new file mode 100644 index 000000000..f5768cc61 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42062.txt @@ -0,0 +1 @@ +* Вимкнено відкривання файлів резервних копій (.ceb) із файлового менеджера diff --git a/fastlane/metadata/android/uk/changelogs/42065.txt b/fastlane/metadata/android/uk/changelogs/42065.txt new file mode 100644 index 000000000..4a8122be7 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42065.txt @@ -0,0 +1 @@ +* Запроваджено новий формат файлу резервної копії From 088f88f4b027df3c709589d8320c9ca9199af129 Mon Sep 17 00:00:00 2001 From: nautilusx Date: Mon, 21 Aug 2023 05:07:03 +0000 Subject: [PATCH 054/402] Translated using Weblate (German) Currently translated at 100.0% (967 of 967 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/de/ --- src/main/res/values-de/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-de/strings.xml b/src/main/res/values-de/strings.xml index fd3d3d167..5a96d84a7 100644 --- a/src/main/res/values-de/strings.xml +++ b/src/main/res/values-de/strings.xml @@ -1009,4 +1009,5 @@ Als Gruppenchat speichern Gruppenchats durchsuchen Die Channelsuche verwendet einen Drittanbieterservice namens <a href=https://search.jabber.network>search.jabber.network</a>.<br><br>Wenn du diese Funktion verwendest, werden deine IP-Adresse und deine Suchbegriffe an diesen Dienst übertragen. Weitere Informationen findest du in der <a href=https://search.jabber.network/privacy>Datenschutzerklärung</a>. + Versuche nicht, Backups wiederherzustellen, die du nicht selbst erstellt hast! \ No newline at end of file From 4346609914d60c2b9bcc510d31177746c56a3806 Mon Sep 17 00:00:00 2001 From: ghose Date: Mon, 21 Aug 2023 06:48:06 +0000 Subject: [PATCH 055/402] Translated using Weblate (Galician) Currently translated at 100.0% (967 of 967 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/gl/ --- src/main/res/values-gl/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-gl/strings.xml b/src/main/res/values-gl/strings.xml index bcc2bc11a..b1ea7b272 100644 --- a/src/main/res/values-gl/strings.xml +++ b/src/main/res/values-gl/strings.xml @@ -1012,4 +1012,5 @@ Buscar conversas en grupo Conversas en grupo O descubrimento de canles usa un servizo externo chamado <a href=https://search.jabber.network>search.jabber.network</a>.<br><br>Ao usar esta ferramenta transmitirás o teu enderezo IP e termos de busca a ese servizo. Le a súa <a href=https://search.jabber.network/privacy>Política de Privacidade</a> para saber máis. + Non intentes restablecer unha copia de apoio que non tiveses creado ti! \ No newline at end of file From 03dee0d8c233919899ccb13886fc1ef1cc55f9bf Mon Sep 17 00:00:00 2001 From: random_r Date: Mon, 21 Aug 2023 09:30:45 +0000 Subject: [PATCH 056/402] Translated using Weblate (Italian) Currently translated at 100.0% (967 of 967 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/it/ --- src/main/res/values-it/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-it/strings.xml b/src/main/res/values-it/strings.xml index 171fa3e14..fafad3ad2 100644 --- a/src/main/res/values-it/strings.xml +++ b/src/main/res/values-it/strings.xml @@ -1023,4 +1023,5 @@ Salva come chat di gruppo Cerca chat di gruppo La scoperta dei canali usa un servizio di terze parti chiamato <a href=https://search.jabber.network>search.jabber.network</a>.<br><br>L\'uso di questa funzione invierà il tuo indirizzo IP e i termini di ricerca a quel servizio. Vedi la sua <a href=https://search.jabber.network/privacy>informativa sulla privacy</a> per maggiori informazioni. + Non tentare di ripristinare dei backup che non hai creato te stesso! \ No newline at end of file From 4c679af73603d3ff05436c713af27b99d035bbdf Mon Sep 17 00:00:00 2001 From: Eryk Michalak Date: Mon, 21 Aug 2023 09:10:28 +0000 Subject: [PATCH 057/402] Translated using Weblate (Polish) Currently translated at 100.0% (967 of 967 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/pl/ --- src/main/res/values-pl/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-pl/strings.xml b/src/main/res/values-pl/strings.xml index 58af2f296..458f25ac4 100644 --- a/src/main/res/values-pl/strings.xml +++ b/src/main/res/values-pl/strings.xml @@ -1042,4 +1042,5 @@ Wykrywanie kanałów korzysta z usługi innego podmiotu o nazwie <a href=https://search.jabber.network>search.jabber.network</a>.<br><br>Użycie tej funkcji spowoduje przesłanie adresu IP i wyszukiwanych terminów do tej usługi. Zobacz ich <a href=https://search.jabber.network/privacy>Politykę prywatności</a>, aby uzyskać więcej informacji. Czaty grupowe Zapisz jako czat grupowy + Nie próbuj przywracać kopii zapasowych, których nie utworzono samodzielnie! \ No newline at end of file From a3e432925924b2119135e61bc5704c543ba91f95 Mon Sep 17 00:00:00 2001 From: licaon-kter Date: Mon, 21 Aug 2023 07:09:55 +0000 Subject: [PATCH 058/402] Translated using Weblate (Romanian) Currently translated at 100.0% (967 of 967 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/ro/ --- src/main/res/values-ro-rRO/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-ro-rRO/strings.xml b/src/main/res/values-ro-rRO/strings.xml index 678480eca..f38d0f45d 100644 --- a/src/main/res/values-ro-rRO/strings.xml +++ b/src/main/res/values-ro-rRO/strings.xml @@ -1031,4 +1031,5 @@ Descoperirea de canale publice folosește un serviciu terț numit <a href=https://search.jabber.network>search.jabber.network</a>.<br><br>Folosind această funcție se va transmite adresa dumneavoastră IP și cuvintele căutate către acest serviciu. Pentru mai multe informații citiți <a href=https://search.jabber.network/privacy>Politica de confidențialitate</a> a serviciului. Salvare ca discuție de grup Caută discuții de grup + Nu încercați să restaurați copii de rezervă pe care nu le-ați creat personal! \ No newline at end of file From f12d7ef78f939f773413924524088c0b9955844d Mon Sep 17 00:00:00 2001 From: hamburger1024 Date: Mon, 21 Aug 2023 00:35:29 +0000 Subject: [PATCH 059/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (967 of 967 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index 399c5d49d..c405066ad 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -1000,4 +1000,5 @@ 另存为群聊 搜索群聊 从服务器删除账户 + 不要尝试恢复你尚未自行创建的备份! \ No newline at end of file From 296894bfa07515a502074aed9d5f800a5c7bf9ff Mon Sep 17 00:00:00 2001 From: nautilusx Date: Mon, 21 Aug 2023 05:09:48 +0000 Subject: [PATCH 060/402] Translated using Weblate (German) Currently translated at 100.0% (51 of 51 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/de/ --- fastlane/metadata/android/de-DE/changelogs/42061.txt | 1 + fastlane/metadata/android/de-DE/changelogs/42062.txt | 1 + fastlane/metadata/android/de-DE/changelogs/42065.txt | 1 + 3 files changed, 3 insertions(+) create mode 100644 fastlane/metadata/android/de-DE/changelogs/42061.txt create mode 100644 fastlane/metadata/android/de-DE/changelogs/42062.txt create mode 100644 fastlane/metadata/android/de-DE/changelogs/42065.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/42061.txt b/fastlane/metadata/android/de-DE/changelogs/42061.txt new file mode 100644 index 000000000..9673c61d8 --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/42061.txt @@ -0,0 +1 @@ +* Channelsuchfunktion aus der Google Play-Version entfernt diff --git a/fastlane/metadata/android/de-DE/changelogs/42062.txt b/fastlane/metadata/android/de-DE/changelogs/42062.txt new file mode 100644 index 000000000..7b9eff49c --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/42062.txt @@ -0,0 +1 @@ +* Öffnen von Sicherungsdateien (.ceb) im Dateimanager deaktiviert diff --git a/fastlane/metadata/android/de-DE/changelogs/42065.txt b/fastlane/metadata/android/de-DE/changelogs/42065.txt new file mode 100644 index 000000000..79d8f5738 --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/42065.txt @@ -0,0 +1 @@ +* Einführung eines neuen Formats für Sicherungsdateien From c4b92a55bb9c2097e493b60b7f58ca1d89aae9e4 Mon Sep 17 00:00:00 2001 From: ghose Date: Mon, 21 Aug 2023 06:49:44 +0000 Subject: [PATCH 061/402] Translated using Weblate (Galician) Currently translated at 13.7% (7 of 51 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/gl/ --- fastlane/metadata/android/gl-ES/changelogs/42060.txt | 1 + fastlane/metadata/android/gl-ES/changelogs/42061.txt | 1 + fastlane/metadata/android/gl-ES/changelogs/42062.txt | 1 + fastlane/metadata/android/gl-ES/changelogs/42065.txt | 1 + 4 files changed, 4 insertions(+) create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42060.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42061.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42062.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42065.txt diff --git a/fastlane/metadata/android/gl-ES/changelogs/42060.txt b/fastlane/metadata/android/gl-ES/changelogs/42060.txt new file mode 100644 index 000000000..b79b6c0a7 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42060.txt @@ -0,0 +1 @@ +* Arranxa o problema de considerar o 'q' como cirílico diff --git a/fastlane/metadata/android/gl-ES/changelogs/42061.txt b/fastlane/metadata/android/gl-ES/changelogs/42061.txt new file mode 100644 index 000000000..3173f43f4 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42061.txt @@ -0,0 +1 @@ +* Retira, da versión Google Play, a ferramenta de descubrimento de canles diff --git a/fastlane/metadata/android/gl-ES/changelogs/42062.txt b/fastlane/metadata/android/gl-ES/changelogs/42062.txt new file mode 100644 index 000000000..4d9358f7d --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42062.txt @@ -0,0 +1 @@ +* Desactiva a apertura de ficheiros de copia de apoio (.ceb) desde o xestor de ficheiros diff --git a/fastlane/metadata/android/gl-ES/changelogs/42065.txt b/fastlane/metadata/android/gl-ES/changelogs/42065.txt new file mode 100644 index 000000000..ce952a317 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42065.txt @@ -0,0 +1 @@ +* Presenta o novo formato para as copias de apoio From 8de354e3cd3b819f0465be5ff1a68a166d1da7e9 Mon Sep 17 00:00:00 2001 From: gallegonovato Date: Tue, 22 Aug 2023 14:36:13 +0000 Subject: [PATCH 062/402] Translated using Weblate (Spanish) Currently translated at 100.0% (967 of 967 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/es/ --- src/main/res/values-es/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-es/strings.xml b/src/main/res/values-es/strings.xml index 9a58b3b6d..d3f7de206 100644 --- a/src/main/res/values-es/strings.xml +++ b/src/main/res/values-es/strings.xml @@ -1023,4 +1023,5 @@ Buscar un grupo de chats La búsqueda de canales utiliza un servicio de terceros denominado <a href=https://search.jabber.network>search.jabber.network</a>.<br><br>Si utiliza esta función, tu dirección IP y la búsqueda de términos serán transferidos a este servicio. Para obtener más información, consulta la <a href=https://search.jabber.network/privacy>Política de privacidad</a>. Guardar como un chat en grupo + ¡No intentes restaurar las copias de seguridad que no creaste tu mismo! \ No newline at end of file From e3d8e54c93202197fcf298ec3281e99740604c1b Mon Sep 17 00:00:00 2001 From: SomeTr Date: Sat, 26 Aug 2023 18:01:44 +0000 Subject: [PATCH 063/402] Translated using Weblate (Ukrainian) Currently translated at 100.0% (967 of 967 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/uk/ --- src/main/res/values-uk/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/res/values-uk/strings.xml b/src/main/res/values-uk/strings.xml index 033da344e..d6e58bffd 100644 --- a/src/main/res/values-uk/strings.xml +++ b/src/main/res/values-uk/strings.xml @@ -67,7 +67,7 @@ Ніколи не питати знову Не вдалося з\'єднатися з обліковим записом Не вдалося з\'єднатися з обліковими записами - Перейти для керування обліковими записами + Торкніться, щоб керувати обліковими записами Долучити файл Цього контакту немає у Вашому списку. Бажаєте додати його\? Додати контакт From a4e5ad8684b7b701d6fa3e56c4d18846d30f55ea Mon Sep 17 00:00:00 2001 From: ghose Date: Tue, 29 Aug 2023 03:33:15 +0000 Subject: [PATCH 064/402] Translated using Weblate (Galician) Currently translated at 100.0% (967 of 967 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/gl/ --- src/main/res/values-gl/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/res/values-gl/strings.xml b/src/main/res/values-gl/strings.xml index b1ea7b272..e44df1bfb 100644 --- a/src/main/res/values-gl/strings.xml +++ b/src/main/res/values-gl/strings.xml @@ -18,7 +18,7 @@ Desbloquear dominio Bloquear persoa Desbloquear persoa - Xestionar contas + Xestionar Contas Axustes Compartir na conversa Iniciar conversa @@ -354,7 +354,7 @@ Non se atopou unha app para abrir o ficheiro Non se atopou app para abrir a ligazón Non se atopou app para ver o contacto - Información do estado + Etiquetas dinámicas Mostra o estado debaixo do nome do contacto Habilitar notificacións Non se atopou ningún servidor de conversa en grupo From 24280959e3c99a4c6ee4ab062852cd9683c2bc5b Mon Sep 17 00:00:00 2001 From: Nikita Karamov Date: Mon, 28 Aug 2023 08:30:24 +0000 Subject: [PATCH 065/402] Translated using Weblate (Russian) Currently translated at 99.8% (966 of 967 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/ru/ --- src/main/res/values-ru/strings.xml | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/res/values-ru/strings.xml b/src/main/res/values-ru/strings.xml index f6d5bcf1a..0d7689596 100644 --- a/src/main/res/values-ru/strings.xml +++ b/src/main/res/values-ru/strings.xml @@ -978,10 +978,10 @@ Невозможно включить видео. Текстовые данные - %d пропущеный звонок - %d пропущенных звонков - %d пропущеныыз звонков - %d пропущеныыз звонков + %d пропущенный вызов + %d пропущенных вызова + %d пропущенных вызовов + %d пропущенных вызовов Несовместимый клиент Групповые беседы @@ -1019,4 +1019,13 @@ Учётная запись для получения пуш-уведомлений. Выбираемый пользователем сервер для перенаправления уведомлений на Ваше устройство. Обзор каналов использует сторонний сервис <a href=https://search.jabber.network>search.jabber.network</a>.<br><br>Эта функция передаст Ваш IP-адрес и ваш поисковый запрос этому сервису. Ознакомьтесь с их <a href=https://search.jabber.network/privacy>Политикой приватности</a> для получения подробностей. + Нет (неактивно) + Вы подтверждаете ваши собственные OMEMO-ключи. Это безопасно только если вы перешли по ссылке из доверенного источника, где только вы могли разместить эту ссылку. + Не пытайтесь восстановить резервные копии, которые не были созданы вами! + + %1$d пропущенный вызов от %2$s + %1$d пропущенных вызова от %2$s + %1$d пропущенных вызовов от %2$s + %1$d пропущенных вызовов от %2$s + \ No newline at end of file From 033bdfa58f1f32165e13f9b9dd404f9bd974a3c9 Mon Sep 17 00:00:00 2001 From: botorfj Date: Mon, 28 Aug 2023 19:17:39 +0000 Subject: [PATCH 066/402] Translated using Weblate (Turkish) Currently translated at 97.9% (947 of 967 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/tr/ --- src/main/res/values-tr-rTR/strings.xml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/res/values-tr-rTR/strings.xml b/src/main/res/values-tr-rTR/strings.xml index b6880d42a..f4652e192 100644 --- a/src/main/res/values-tr-rTR/strings.xml +++ b/src/main/res/values-tr-rTR/strings.xml @@ -182,7 +182,7 @@ OpenPGP genel anahtarınız Çevrim içi durum anonsunuzdan kaldırmak istediğinizden emin misiniz?\nArtık kişileriniz size şifrelenmiş OpenPGP mesajları gönderemeyecek. OpenPGP genel anahtarı yayınlandı. Hesabı etkinleştir - Hesabınızın silinmesi bütün konuşma geçmişinizi siler + Hesabınızı silmekten emin misiniz\? Hesabınızın silinmesi bütün konuşma geçmişinizi siler Ses kaydet XMPP adresi XMPP adresini engelle @@ -976,11 +976,14 @@ Sunucu, davet oluşturulmasını desteklemiyor Bu özelliği destekleyen aktif bir hesap yok Yedekleme başlatıldı. Tamamlandığı zaman bir bildirim alacaksınız. - Video etkinleştirilemedi + Video etkinleştirilemedi. Düz metin dosyası - Hesap kayıtları desteklenmemektedir. + Hesap kayıtları desteklenmemektedir Herhangi bir XMPP adresi bulunamadı Geçici doğrulama hatası Avatar\'ı sil Tor kullanırken çağrılar devre dışı + Videoya geç + Videoya geçme isteğini reddet + XMPP Hesabı \ No newline at end of file From a509e6f887e4f9c7905d51cb9fe01c8bcd591507 Mon Sep 17 00:00:00 2001 From: botorfj Date: Mon, 28 Aug 2023 18:48:01 +0000 Subject: [PATCH 067/402] Translated using Weblate (Greek) Currently translated at 100.0% (13 of 13 strings) Translation: Conversations/Android App (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-conversations/el/ --- src/conversations/res/values-el/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conversations/res/values-el/strings.xml b/src/conversations/res/values-el/strings.xml index bb7bcadf0..c64e3d68e 100644 --- a/src/conversations/res/values-el/strings.xml +++ b/src/conversations/res/values-el/strings.xml @@ -12,5 +12,5 @@ Πατήστε το πλήκτρο διαμοιρασμού για να στείλετε στην επαφή σας μια πρόσκληση στο %1$s. Αν η επαφή σας βρίσκεται κοντά σας, μπορεί επίσης να σαρώσει τον κωδικό παρακάτω για να αποδεχτεί την πρόσκλησή σας. Μπείτε στο %1$s και συνομιλήστε μαζί μου: %2$s - Διαμοιρασμός πρόσκλησης με... + Διαμοιρασμός πρόσκλησης με… \ No newline at end of file From 610877cd41eac13f781b3ebeb9fda5908f3bc484 Mon Sep 17 00:00:00 2001 From: botorfj Date: Mon, 28 Aug 2023 18:49:35 +0000 Subject: [PATCH 068/402] Translated using Weblate (Slovak) Currently translated at 84.6% (11 of 13 strings) Translation: Conversations/Android App (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-conversations/sk/ --- src/conversations/res/values-sk/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conversations/res/values-sk/strings.xml b/src/conversations/res/values-sk/strings.xml index ed58bbefb..e280344c4 100644 --- a/src/conversations/res/values-sk/strings.xml +++ b/src/conversations/res/values-sk/strings.xml @@ -10,5 +10,5 @@ Ťuknite na tlačidlo zdieľať na odoslanie pozvánky do %1$s vášmu kontaktu. Ak je váš kontakt blízko, na prijatie vašej pozvánky si môže nasnímať kód nižšie. Pripojte sa k %1$sa rozprávajte sa so mnou: %2$s - Zdieľať pozvánku s... + Zdieľať pozvánku s… \ No newline at end of file From cb9a52dfb38e7bb5eff3d657d4b4a0e270323455 Mon Sep 17 00:00:00 2001 From: botorfj Date: Mon, 28 Aug 2023 18:33:00 +0000 Subject: [PATCH 069/402] Translated using Weblate (Turkish) Currently translated at 100.0% (13 of 13 strings) Translation: Conversations/Android App (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-conversations/tr/ --- src/conversations/res/values-tr-rTR/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/conversations/res/values-tr-rTR/strings.xml b/src/conversations/res/values-tr-rTR/strings.xml index 6fb383cf7..415bc89e0 100644 --- a/src/conversations/res/values-tr-rTR/strings.xml +++ b/src/conversations/res/values-tr-rTR/strings.xml @@ -11,6 +11,6 @@ Yanlış ayarlanmış düzenleme kodu Kişinize, %1$s grubuna davet etmek için Paylaş düğmesine basın. Kişiniz yakınınızda ise, aşağıdaki kodu tarayak daveti kabul edebilirler. - %1$s grubuna katıl ve benimle sohpet et: %2$s - Daveti şununla paylaş... + %1$s grubuna katıl ve benimle sohbet et: %2$s + Daveti şununla paylaş… \ No newline at end of file From 585c5151a16bde2c391bde42b28b57870e9493d5 Mon Sep 17 00:00:00 2001 From: botorfj Date: Mon, 28 Aug 2023 18:37:41 +0000 Subject: [PATCH 070/402] Translated using Weblate (Turkish) Currently translated at 100.0% (9 of 9 strings) Translation: Conversations/Android App (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-quicksy/tr/ --- src/quicksy/res/values-tr-rTR/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/quicksy/res/values-tr-rTR/strings.xml b/src/quicksy/res/values-tr-rTR/strings.xml index 12cef8d47..7de5749e3 100644 --- a/src/quicksy/res/values-tr-rTR/strings.xml +++ b/src/quicksy/res/values-tr-rTR/strings.xml @@ -1,7 +1,7 @@ Başka bir aygıt üstünde etkinlik algılandığında Quicksy\'nin sessiz kalma süresi - Çöküş raporu göndermeniz Quicksy\'nin geliştirlmesinde katkıda bulunacaktır. + Çöküş raporu göndermeniz Quicksy\'nin geliştirlmesinde katkıda bulunacaktır Tüm kişileriniz ne zaman Quicksy kullandığınızı görsün Ekranınız kapalıyken bile bildirim almak için Quicksy\'i korunan uygulamalara eklemelisiniz. Quicksy profil resmi @@ -9,4 +9,4 @@ Sunucu kimliği belirlenemiyor. Bilinmeyen güvenlik hatası. Sunucuya bağlanılırken zaman aşımına uğrandı. - + \ No newline at end of file From 8138330ca2d58f948ef5994df280260cd89ea7e5 Mon Sep 17 00:00:00 2001 From: SomeTr Date: Thu, 31 Aug 2023 04:30:00 +0000 Subject: [PATCH 071/402] Translated using Weblate (Ukrainian) Currently translated at 100.0% (51 of 51 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/uk/ --- fastlane/metadata/android/uk/full_description.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fastlane/metadata/android/uk/full_description.txt b/fastlane/metadata/android/uk/full_description.txt index da2b97403..39971ed55 100644 --- a/fastlane/metadata/android/uk/full_description.txt +++ b/fastlane/metadata/android/uk/full_description.txt @@ -1,6 +1,6 @@ Надійний, простий у використанні, ощадливо витрачає заряд акумулятора. Має вбудовану підтримку зображень, групових чатів і наскрізного шифрування. -Принципи проектування: +Принципи проєктування: * Бути максимально красивим та простим у використанні, не жертвуючи безпекою чи конфіденційністю * Покладатися на існуючі, добре встановлені протоколи @@ -36,4 +36,4 @@ Conversations працює з будь-яким сервером XMPP. Прот * XEP-0237: версія списку в основному для економії пропускної здатності при поганих мобільних з'єднаннях * XEP-0313: керування архівом повідомлень синхронізує історію повідомлень із сервером. Дізнавайтеся про повідомлення, надіслані, поки Conversations був офлайн. * XEP-0352: індикація стану клієнта повідомляє серверу, чи працює Conversations у фоновому режимі. Дозволяє серверу заощаджувати пропускну здатність, утримуючи неважливі пакети. -* XEP-0363: завантаження файлів HTTP дозволяє обмінюватися файлами на конференціях і з офлайн-контактами. Потрібен додатковий компонент на Вашому сервері. +* XEP-0363: завантаження файлів HTTP дозволяє обмінюватися файлами в конференціях і з офлайн-контактами. Потрібен додатковий компонент на Вашому сервері. From 51a8877475a367d6e5bbe5d1ef1f76fd1bc410ce Mon Sep 17 00:00:00 2001 From: SomeTr Date: Mon, 4 Sep 2023 16:26:00 +0000 Subject: [PATCH 072/402] Translated using Weblate (Ukrainian) Currently translated at 100.0% (9 of 9 strings) Translation: Conversations/Android App (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-quicksy/uk/ --- src/quicksy/res/values-uk/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quicksy/res/values-uk/strings.xml b/src/quicksy/res/values-uk/strings.xml index 8c678d0a2..665d4d483 100644 --- a/src/quicksy/res/values-uk/strings.xml +++ b/src/quicksy/res/values-uk/strings.xml @@ -5,7 +5,7 @@ Повідомляти співрозмовникам, що Ви користуєтеся Quicksy Щоб отримувати сповіщення навіть коли екран погас, необхідно додати Quicksy до списку захищених програм. Зображення профілю для Quicksy - Цей застосунок не доступний у Вашій країні. + Цей застосунок недоступний у Вашій країні. Автентичність сервера не підтверджено. Невідома помилка безпеки. Вичерпано час для встановлення з\'єднання із сервером. From 04b5744a2ae4c36f8ba7d7d186de8908e2a38042 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 6 Sep 2023 20:10:51 +0200 Subject: [PATCH 073/402] update doap file --- conversations.doap | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/conversations.doap b/conversations.doap index 7f5e654b2..06323a84c 100644 --- a/conversations.doap +++ b/conversations.doap @@ -399,6 +399,20 @@ 0.3.0 + + + + complete + 0.4.0 + + + + + + complete + 0.4.0 + + From 11e6cb9693d4c0ce3b7c0098a78009bc3b1b8d23 Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Thu, 7 Sep 2023 13:08:18 +0200 Subject: [PATCH 074/402] Use conversation notifications Allows for per-conversation priority and sound --- .../services/NotificationService.java | 16 +++++++++-- .../services/ShortcutService.java | 27 +++++++++++++++---- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java index 715cafe42..af7667313 100644 --- a/src/main/java/eu/siacs/conversations/services/NotificationService.java +++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java @@ -10,6 +10,7 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.content.pm.ShortcutManager; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Typeface; @@ -34,6 +35,7 @@ import androidx.core.app.NotificationManagerCompat; import androidx.core.app.Person; import androidx.core.app.RemoteInput; import androidx.core.content.ContextCompat; +import androidx.core.content.pm.ShortcutInfoCompat; import androidx.core.graphics.drawable.IconCompat; import com.google.common.base.Joiner; @@ -1283,8 +1285,8 @@ public class NotificationService { } } if (conversation.getMode() == Conversation.MODE_SINGLE) { - Contact contact = conversation.getContact(); - Uri systemAccount = contact.getSystemAccount(); + final Contact contact = conversation.getContact(); + final Uri systemAccount = contact.getSystemAccount(); if (systemAccount != null) { mBuilder.addPerson(systemAccount.toString()); } @@ -1293,6 +1295,16 @@ public class NotificationService { mBuilder.setSmallIcon(R.drawable.ic_notification); mBuilder.setDeleteIntent(createDeleteIntent(conversation)); mBuilder.setContentIntent(createContentIntent(conversation)); + final ShortcutInfoCompat info = + mXmppConnectionService + .getShortcutService() + .getShortcutInfoCompat(conversation.getContact()); + mBuilder.setShortcutInfo(info); + if (Build.VERSION.SDK_INT >= 30) { + mXmppConnectionService + .getSystemService(ShortcutManager.class) + .pushDynamicShortcut(info.toShortcutInfo()); + } } return mBuilder; } diff --git a/src/main/java/eu/siacs/conversations/services/ShortcutService.java b/src/main/java/eu/siacs/conversations/services/ShortcutService.java index 6b7106f74..57b8e9515 100644 --- a/src/main/java/eu/siacs/conversations/services/ShortcutService.java +++ b/src/main/java/eu/siacs/conversations/services/ShortcutService.java @@ -11,6 +11,9 @@ import android.os.Build; import android.util.Log; import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; +import androidx.core.content.pm.ShortcutInfoCompat; +import androidx.core.graphics.drawable.IconCompat; import java.util.ArrayList; import java.util.HashMap; @@ -88,13 +91,27 @@ public class ShortcutService { } } - @TargetApi(Build.VERSION_CODES.N_MR1) - private ShortcutInfo getShortcutInfo(Contact contact) { - return new ShortcutInfo.Builder(xmppConnectionService, getShortcutId(contact)) + public ShortcutInfoCompat getShortcutInfoCompat(final Contact contact) { + final ShortcutInfoCompat.Builder builder = + new ShortcutInfoCompat.Builder(xmppConnectionService, getShortcutId(contact)) .setShortLabel(contact.getDisplayName()) .setIntent(getShortcutIntent(contact)) - .setIcon(Icon.createWithBitmap(xmppConnectionService.getAvatarService().getRoundedShortcut(contact))) - .build(); + .setIsConversation(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + builder.setIcon( + IconCompat.createFromIcon( + xmppConnectionService, + Icon.createWithBitmap( + xmppConnectionService + .getAvatarService() + .getRoundedShortcut(contact)))); + } + return builder.build(); + } + + @TargetApi(Build.VERSION_CODES.N_MR1) + private ShortcutInfo getShortcutInfo(final Contact contact) { + return getShortcutInfoCompat(contact).toShortcutInfo(); } private static boolean contactsChanged(List needles, List haystack) { From c6501a3ad470a22b8696f00b90e0c88e22137ded Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 8 Sep 2023 14:19:18 +0200 Subject: [PATCH 075/402] fix UUIDv4 calculation --- .../conversations/utils/AccountUtils.java | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/utils/AccountUtils.java b/src/main/java/eu/siacs/conversations/utils/AccountUtils.java index b8f4855d0..6f3e4a49e 100644 --- a/src/main/java/eu/siacs/conversations/utils/AccountUtils.java +++ b/src/main/java/eu/siacs/conversations/utils/AccountUtils.java @@ -6,6 +6,10 @@ import android.view.Menu; import android.view.MenuItem; import android.widget.Toast; +import com.google.common.primitives.Bytes; +import com.google.common.primitives.Longs; + +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -24,10 +28,9 @@ public class AccountUtils { MANAGE_ACCOUNT_ACTIVITY = getManageAccountActivityClass(); } - public static boolean hasEnabledAccounts(final XmppConnectionService service) { final List accounts = service.getAccounts(); - for(Account account : accounts) { + for (Account account : accounts) { if (account.isOptionSet(Account.OPTION_DISABLED)) { return false; } @@ -42,19 +45,21 @@ public class AccountUtils { } catch (final IllegalArgumentException e) { return account.getUuid(); } - final UUID publicDeviceId = getUuid(uuid.getLeastSignificantBits(), uuid.getLeastSignificantBits()); - return publicDeviceId.toString(); - } - - protected static UUID getUuid(final long msb, final long lsb) { - final long msb0 = (msb & 0xffffffffffff0fffL) | 4; // set version - final long lsb0 = (lsb & 0x3fffffffffffffffL) | 0x8000000000000000L; // set variant - return new UUID(msb0, lsb0); + final byte[] bytes = + Bytes.concat( + Longs.toByteArray(uuid.getLeastSignificantBits()), + Longs.toByteArray(uuid.getLeastSignificantBits())); + bytes[6] &= 0x0f; /* clear version */ + bytes[6] |= 0x40; /* set to version 4 */ + bytes[8] &= 0x3f; /* clear variant */ + bytes[8] |= 0x80; /* set to IETF variant */ + final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); + return new UUID(byteBuffer.getLong(), byteBuffer.getLong()).toString(); } public static List getEnabledAccounts(final XmppConnectionService service) { - ArrayList accounts = new ArrayList<>(); - for (Account account : service.getAccounts()) { + final ArrayList accounts = new ArrayList<>(); + for (final Account account : service.getAccounts()) { if (account.getStatus() != Account.State.DISABLED) { if (Config.DOMAIN_LOCK != null) { accounts.add(account.getJid().getEscapedLocal()); @@ -68,7 +73,7 @@ public class AccountUtils { public static Account getFirstEnabled(XmppConnectionService service) { final List accounts = service.getAccounts(); - for(Account account : accounts) { + for (Account account : accounts) { if (!account.isOptionSet(Account.OPTION_DISABLED)) { return account; } @@ -78,7 +83,7 @@ public class AccountUtils { public static Account getFirst(XmppConnectionService service) { final List accounts = service.getAccounts(); - for(Account account : accounts) { + for (Account account : accounts) { return account; } return null; From 00ae1ca7623aed99ad95c1629fdeddf51cc59236 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 11 Sep 2023 16:38:57 +0200 Subject: [PATCH 076/402] fix group chat shortcuts --- .../conversations/services/AvatarService.java | 13 ++++- .../services/NotificationService.java | 11 ++-- .../services/ShortcutService.java | 55 +++++++++++++++++-- 3 files changed, 70 insertions(+), 9 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/services/AvatarService.java b/src/main/java/eu/siacs/conversations/services/AvatarService.java index 7baee23f9..e9e827c56 100644 --- a/src/main/java/eu/siacs/conversations/services/AvatarService.java +++ b/src/main/java/eu/siacs/conversations/services/AvatarService.java @@ -124,6 +124,17 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded { return avatar; } + public Bitmap getRoundedShortcut(final MucOptions mucOptions) { + final DisplayMetrics metrics = mXmppConnectionService.getResources().getDisplayMetrics(); + final int size = Math.round(metrics.density * 48); + final Bitmap bitmap = get(mucOptions, size, false); + final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); + final Canvas canvas = new Canvas(output); + final Paint paint = new Paint(); + drawAvatar(bitmap, canvas, paint); + return output; + } + public Bitmap getRoundedShortcut(final Contact contact) { return getRoundedShortcut(contact, false); } @@ -147,7 +158,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded { return output; } - private void drawAvatar(Bitmap bitmap, Canvas canvas, Paint paint) { + private static void drawAvatar(Bitmap bitmap, Canvas canvas, Paint paint) { final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java index af7667313..9fe1f923c 100644 --- a/src/main/java/eu/siacs/conversations/services/NotificationService.java +++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java @@ -1284,21 +1284,24 @@ public class NotificationService { } } } + final ShortcutInfoCompat info; if (conversation.getMode() == Conversation.MODE_SINGLE) { final Contact contact = conversation.getContact(); final Uri systemAccount = contact.getSystemAccount(); if (systemAccount != null) { mBuilder.addPerson(systemAccount.toString()); } + info = mXmppConnectionService.getShortcutService().getShortcutInfoCompat(contact); + } else { + info = + mXmppConnectionService + .getShortcutService() + .getShortcutInfoCompat(conversation.getMucOptions()); } mBuilder.setWhen(conversation.getLatestMessage().getTimeSent()); mBuilder.setSmallIcon(R.drawable.ic_notification); mBuilder.setDeleteIntent(createDeleteIntent(conversation)); mBuilder.setContentIntent(createContentIntent(conversation)); - final ShortcutInfoCompat info = - mXmppConnectionService - .getShortcutService() - .getShortcutInfoCompat(conversation.getContact()); mBuilder.setShortcutInfo(info); if (Build.VERSION.SDK_INT >= 30) { mXmppConnectionService diff --git a/src/main/java/eu/siacs/conversations/services/ShortcutService.java b/src/main/java/eu/siacs/conversations/services/ShortcutService.java index 57b8e9515..c6ae77b63 100644 --- a/src/main/java/eu/siacs/conversations/services/ShortcutService.java +++ b/src/main/java/eu/siacs/conversations/services/ShortcutService.java @@ -22,6 +22,7 @@ import java.util.List; import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; +import eu.siacs.conversations.entities.MucOptions; import eu.siacs.conversations.ui.StartConversationActivity; import eu.siacs.conversations.utils.ReplacingSerialSingleThreadExecutor; import eu.siacs.conversations.xmpp.Jid; @@ -109,6 +110,24 @@ public class ShortcutService { return builder.build(); } + public ShortcutInfoCompat getShortcutInfoCompat(final MucOptions mucOptions) { + final ShortcutInfoCompat.Builder builder = + new ShortcutInfoCompat.Builder(xmppConnectionService, getShortcutId(mucOptions)) + .setShortLabel(mucOptions.getConversation().getName()) + .setIntent(getShortcutIntent(mucOptions)) + .setIsConversation(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + builder.setIcon( + IconCompat.createFromIcon( + xmppConnectionService, + Icon.createWithBitmap( + xmppConnectionService + .getAvatarService() + .getRoundedShortcut(mucOptions)))); + } + return builder.build(); + } + @TargetApi(Build.VERSION_CODES.N_MR1) private ShortcutInfo getShortcutInfo(final Contact contact) { return getShortcutInfoCompat(contact).toShortcutInfo(); @@ -137,12 +156,40 @@ public class ShortcutService { return contact.getAccount().getJid().asBareJid().toEscapedString()+"#"+contact.getJid().asBareJid().toEscapedString(); } - private Intent getShortcutIntent(Contact contact) { + private static String getShortcutId(final MucOptions mucOptions) { + final Account account = mucOptions.getAccount(); + final Jid jid = mucOptions.getConversation().getJid(); + return account.getJid().asBareJid().toEscapedString() + + "#" + + jid.asBareJid().toEscapedString(); + } + + private Intent getShortcutIntent(final MucOptions mucOptions) { + final Account account = mucOptions.getAccount(); + return getShortcutIntent( + account, + Uri.parse( + String.format( + "xmpp:%s?join", + mucOptions + .getConversation() + .getJid() + .asBareJid() + .toEscapedString()))); + } + + private Intent getShortcutIntent(final Contact contact) { + return getShortcutIntent( + contact.getAccount(), + Uri.parse("xmpp:" + contact.getJid().asBareJid().toEscapedString())); + } + + private Intent getShortcutIntent(final Account account, final Uri uri) { Intent intent = new Intent(xmppConnectionService, StartConversationActivity.class); intent.setAction(Intent.ACTION_VIEW); - intent.setData(Uri.parse("xmpp:"+contact.getJid().asBareJid().toEscapedString())); - intent.putExtra("account",contact.getAccount().getJid().asBareJid().toString()); - intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP| Intent.FLAG_ACTIVITY_SINGLE_TOP); + intent.setData(uri); + intent.putExtra("account", account.getJid().asBareJid().toString()); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); return intent; } From 381a058db0b2ab5650aa5c73812741129c9f8480 Mon Sep 17 00:00:00 2001 From: Millesimus Date: Sun, 10 Sep 2023 11:39:35 +0200 Subject: [PATCH 077/402] Update migration docs. --- docs/user/migrating_to_new_device.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/user/migrating_to_new_device.md b/docs/user/migrating_to_new_device.md index 401a15386..e7d50a1ce 100644 --- a/docs/user/migrating_to_new_device.md +++ b/docs/user/migrating_to_new_device.md @@ -22,12 +22,11 @@ This tutorial explains how you can transfer your Conversations data from an old ## 3. Import the backup (new device) 1. Install Conversations on your new device. 2. Open Conversations for the first time. -3. Tap on "Use other server" -4. Tap on the three dot menu in the upper right corner and tap on "Import backup" -5. If your backup files are not listed, tap on the cloud symbol in the upper right corner to choose the files from the where you saved them. -6. Enter your account password to decrypt the backup. -7. Remember to activate your account (head back to "manage accounts", see step 1.2). -8. Check if chats work. +3. Tap on the three dot menu in the upper right corner and tap on "Import backup" +4. If your backup files are not listed, tap on the cloud symbol in the upper right corner to choose the files from where you saved them. +5. Enter your account password to decrypt the backup. +6. Remember to activate your account (head back to "manage accounts", see step 1.2). +7. Check if chats work. Once confirmed that the new device is running fine you can just uninstall the app from the old device. From fdd7f2926f3515b6a5b635f98fc98e058b3a471c Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 14 Sep 2023 11:21:43 +0200 Subject: [PATCH 078/402] support 'ringing' jingle message --- .../eu/siacs/conversations/parser/MessageParser.java | 3 ++- .../xmpp/jingle/JingleConnectionManager.java | 12 ++++++++++-- .../xmpp/jingle/JingleRtpConnection.java | 1 + 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 46355354a..006923bd7 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -52,7 +52,8 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss", Locale.ENGLISH); - private static final List JINGLE_MESSAGE_ELEMENT_NAMES = Arrays.asList("accept", "propose", "proceed", "reject", "retract"); + private static final List JINGLE_MESSAGE_ELEMENT_NAMES = + Arrays.asList("accept", "propose", "proceed", "reject", "retract", "ringing"); public MessageParser(XmppConnectionService service) { super(service); diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java index b39673fa5..c2422e649 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java @@ -266,6 +266,7 @@ public class JingleConnectionManager extends AbstractConnectionManager { return; } final boolean fromSelf = from.asBareJid().equals(account.getJid().asBareJid()); + // XEP version 0.6.0 sends proceed, reject, ringing to bare jid final boolean addressedDirectly = to != null && to.equals(account.getJid()); final AbstractJingleConnection.Id id; if (fromSelf) { @@ -474,12 +475,19 @@ public class JingleConnectionManager extends AbstractConnectionManager { + " to deliver reject"); } } + } else if (addressedDirectly && "ringing".equals(message.getName())) { + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": " + from + " started ringing"); + updateProposedSessionDiscovered( + account, from, sessionId, DeviceDiscoveryState.DISCOVERED); } else { Log.d( Config.LOGTAG, account.getJid().asBareJid() - + ": retrieved out of order jingle message" - + message); + + ": retrieved out of order jingle message from " + + from + + message + + ", addressedDirectly=" + + addressedDirectly); } } diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java index 139153b4a..5530a8c78 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java @@ -1504,6 +1504,7 @@ public class JingleRtpConnection extends AbstractJingleConnection } this.message.setTime(timestamp); startRinging(); + sendJingleMessage("ringing"); } else { Log.d( Config.LOGTAG, From b4c3334d7ecbb906e1a7993fe1ce0d636ea3077c Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 14 Sep 2023 14:39:32 +0200 Subject: [PATCH 079/402] add a few TODOs wrt tie breaks --- .../conversations/xmpp/jingle/JingleConnectionManager.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java index c2422e649..6646d5d7a 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java @@ -367,12 +367,14 @@ public class JingleConnectionManager extends AbstractConnectionManager { this.connections.put(id, rtpConnection); rtpConnection.setProposedMedia(ImmutableSet.copyOf(media)); rtpConnection.deliveryMessage(from, message, serverMsgId, timestamp); + // TODO actually do the automatic accept?! } else { Log.d( Config.LOGTAG, account.getJid().asBareJid() + ": our session won tie break. waiting for other party to accept. winningSession=" + ourSessionId); + // TODO reject their session with ? } return; } From 8ba90f266eed863dd5e6c13d60c21b380e0272de Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 20 Sep 2023 17:00:04 +0200 Subject: [PATCH 080/402] add explicit error message for outdated backup files --- .../ui/ImportBackupActivity.java | 3 +++ .../conversations/utils/BackupFileHeader.java | 22 ++++++++++++------- src/main/res/values/strings.xml | 1 + 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/conversations/java/eu/siacs/conversations/ui/ImportBackupActivity.java b/src/conversations/java/eu/siacs/conversations/ui/ImportBackupActivity.java index 6e4815159..ed998677b 100644 --- a/src/conversations/java/eu/siacs/conversations/ui/ImportBackupActivity.java +++ b/src/conversations/java/eu/siacs/conversations/ui/ImportBackupActivity.java @@ -30,6 +30,7 @@ import eu.siacs.conversations.databinding.DialogEnterPasswordBinding; import eu.siacs.conversations.services.ImportBackupService; import eu.siacs.conversations.ui.adapter.BackupFileAdapter; import eu.siacs.conversations.ui.util.SettingsUtils; +import eu.siacs.conversations.utils.BackupFileHeader; import eu.siacs.conversations.utils.ThemeHelper; public class ImportBackupActivity extends ActionBarActivity implements ServiceConnection, ImportBackupService.OnBackupFilesLoaded, BackupFileAdapter.OnItemClickedListener, ImportBackupService.OnBackupProcessed { @@ -131,6 +132,8 @@ public class ImportBackupActivity extends ActionBarActivity implements ServiceCo try { final ImportBackupService.BackupFile backupFile = ImportBackupService.BackupFile.read(this, uri); showEnterPasswordDialog(backupFile, finishOnCancel); + } catch (final BackupFileHeader.OutdatedBackupFileVersion e) { + Snackbar.make(binding.coordinator, R.string.outdated_backup_file_format, Snackbar.LENGTH_LONG).show(); } catch (final IOException | IllegalArgumentException e) { Log.d(Config.LOGTAG, "unable to open backup file " + uri, e); Snackbar.make(binding.coordinator, R.string.not_a_backup_file, Snackbar.LENGTH_LONG).show(); diff --git a/src/main/java/eu/siacs/conversations/utils/BackupFileHeader.java b/src/main/java/eu/siacs/conversations/utils/BackupFileHeader.java index 957ccfca1..3b536c27a 100644 --- a/src/main/java/eu/siacs/conversations/utils/BackupFileHeader.java +++ b/src/main/java/eu/siacs/conversations/utils/BackupFileHeader.java @@ -50,17 +50,19 @@ public class BackupFileHeader { public static BackupFileHeader read(DataInputStream inputStream) throws IOException { final int version = inputStream.readInt(); + final String app = inputStream.readUTF(); + final String jid = inputStream.readUTF(); + long timestamp = inputStream.readLong(); + final byte[] iv = new byte[12]; + inputStream.readFully(iv); + final byte[] salt = new byte[16]; + inputStream.readFully(salt); + if (version < VERSION) { + throw new OutdatedBackupFileVersion(); + } if (version != VERSION) { throw new IllegalArgumentException("Backup File version was " + version + " but app only supports version " + VERSION); } - String app = inputStream.readUTF(); - String jid = inputStream.readUTF(); - long timestamp = inputStream.readLong(); - byte[] iv = new byte[12]; - inputStream.readFully(iv); - byte[] salt = new byte[16]; - inputStream.readFully(salt); - return new BackupFileHeader(app, Jid.of(jid), timestamp, iv, salt); } @@ -84,4 +86,8 @@ public class BackupFileHeader { public long getTimestamp() { return timestamp; } + + public static class OutdatedBackupFileVersion extends RuntimeException { + + } } diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index d3af22e15..84b2cb61e 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -894,6 +894,7 @@ Event Open backup The file you selected is not a Conversations backup file + You are trying to import an outdated backup file format This account has already been setup Please enter the password for this account Could not perform this action From 81eb94ee46f99d484332b0cde7aed54285ebc9db Mon Sep 17 00:00:00 2001 From: Sergio Varela Date: Fri, 15 Sep 2023 20:59:37 +0000 Subject: [PATCH 081/402] Translated using Weblate (Spanish) Currently translated at 31.3% (16 of 51 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/es/ --- .../metadata/android/es-ES/changelogs/349.txt | 4 ++ .../metadata/android/es-ES/changelogs/351.txt | 3 ++ .../metadata/android/es-ES/changelogs/353.txt | 4 ++ .../metadata/android/es-ES/changelogs/360.txt | 1 + .../metadata/android/es-ES/changelogs/362.txt | 1 + .../metadata/android/es-ES/changelogs/364.txt | 2 + .../metadata/android/es-ES/changelogs/367.txt | 2 + .../metadata/android/es-ES/changelogs/379.txt | 1 + .../metadata/android/es-ES/changelogs/381.txt | 2 + .../metadata/android/es-ES/changelogs/382.txt | 2 + .../metadata/android/es-ES/changelogs/383.txt | 3 ++ .../metadata/android/es-ES/changelogs/387.txt | 2 + .../metadata/android/es-ES/changelogs/388.txt | 3 ++ .../metadata/android/es-ES/changelogs/390.txt | 1 + .../android/es-ES/full_description.txt | 39 +++++++++++++++++++ .../android/es-ES/short_description.txt | 1 + 16 files changed, 71 insertions(+) create mode 100644 fastlane/metadata/android/es-ES/changelogs/349.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/351.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/353.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/360.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/362.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/364.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/367.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/379.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/381.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/382.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/383.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/387.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/388.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/390.txt create mode 100644 fastlane/metadata/android/es-ES/full_description.txt create mode 100644 fastlane/metadata/android/es-ES/short_description.txt diff --git a/fastlane/metadata/android/es-ES/changelogs/349.txt b/fastlane/metadata/android/es-ES/changelogs/349.txt new file mode 100644 index 000000000..8f84c2432 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/349.txt @@ -0,0 +1,4 @@ +* Introducir configuración experta para realizar el descubrimiento de canales en el servidor local en lugar de search.jabber.network +* Habilitar las marcas de verificación de entrega por defecto y eliminar la configuración +* Habilitar «Enviar botón indica estado» por defecto y eliminar la configuración +* Mover los ajustes de copia de seguridad y servicio en primer plano a la pantalla principal diff --git a/fastlane/metadata/android/es-ES/changelogs/351.txt b/fastlane/metadata/android/es-ES/changelogs/351.txt new file mode 100644 index 000000000..a89b01aee --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/351.txt @@ -0,0 +1,3 @@ +* Corrección de la transferencia de archivos Jingle IBB +* Corrección de correcciones repetidas que llenaban la base de datos. +* Transición a Last Message Correction v1.1 diff --git a/fastlane/metadata/android/es-ES/changelogs/353.txt b/fastlane/metadata/android/es-ES/changelogs/353.txt new file mode 100644 index 000000000..e0f55a6b1 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/353.txt @@ -0,0 +1,4 @@ +* Permitir a los usuarios establecer su propio apodo +* reanudar la descarga de archivos encriptados OMEMO +* Los canales ahora usan '#' como símbolo en el avatar +* Quicksy utiliza «siempre» como cifrado OMEMO por defecto (oculta el icono del candado) diff --git a/fastlane/metadata/android/es-ES/changelogs/360.txt b/fastlane/metadata/android/es-ES/changelogs/360.txt new file mode 100644 index 000000000..169ae4b3e --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/360.txt @@ -0,0 +1 @@ +* Soporte para los parámetros URI de XMPP «?register» y «?register;preauth» diff --git a/fastlane/metadata/android/es-ES/changelogs/362.txt b/fastlane/metadata/android/es-ES/changelogs/362.txt new file mode 100644 index 000000000..bd88ea0f4 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/362.txt @@ -0,0 +1 @@ +* Soporte para el cambio automático de tema en Android 10 diff --git a/fastlane/metadata/android/es-ES/changelogs/364.txt b/fastlane/metadata/android/es-ES/changelogs/364.txt new file mode 100644 index 000000000..cc2be8a4d --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/364.txt @@ -0,0 +1,2 @@ +* Proporcionar vista previa de PDF en Android 5+ +* Utilizar IVs de 12 bytes para OMEMO diff --git a/fastlane/metadata/android/es-ES/changelogs/367.txt b/fastlane/metadata/android/es-ES/changelogs/367.txt new file mode 100644 index 000000000..e95c61e6b --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/367.txt @@ -0,0 +1,2 @@ +* Corregir la selección de avatar en algunos dispositivos Android 10 +* Corregir la transferencia de archivos más grandes diff --git a/fastlane/metadata/android/es-ES/changelogs/379.txt b/fastlane/metadata/android/es-ES/changelogs/379.txt new file mode 100644 index 000000000..74870d83f --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/379.txt @@ -0,0 +1 @@ +* Llamadas de audio/vídeo (requiere soporte de servidor en forma de servidores STUN y TURN detectables mediante XEP-0215) diff --git a/fastlane/metadata/android/es-ES/changelogs/381.txt b/fastlane/metadata/android/es-ES/changelogs/381.txt new file mode 100644 index 000000000..44512a40d --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/381.txt @@ -0,0 +1,2 @@ +* Respuesta audible (marcación, llamada iniciada, llamada finalizada) para llamadas de voz. +* Solucionado el problema de reintento de videollamada fallida diff --git a/fastlane/metadata/android/es-ES/changelogs/382.txt b/fastlane/metadata/android/es-ES/changelogs/382.txt new file mode 100644 index 000000000..8421f8e55 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/382.txt @@ -0,0 +1,2 @@ +* Añadir botón para cambiar de cámara durante la videollamada +* Corregidas las llamadas de voz en tablets diff --git a/fastlane/metadata/android/es-ES/changelogs/383.txt b/fastlane/metadata/android/es-ES/changelogs/383.txt new file mode 100644 index 000000000..189cd9c75 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/383.txt @@ -0,0 +1,3 @@ +* Mover el icono de llamada a la izquierda para mantener otros iconos de la barra de herramientas en un lugar coherente. +* Mostrar la duración de la llamada durante las llamadas de audio +* Desempate en las llamadas A/V (dos personas que se llaman al mismo tiempo) diff --git a/fastlane/metadata/android/es-ES/changelogs/387.txt b/fastlane/metadata/android/es-ES/changelogs/387.txt new file mode 100644 index 000000000..28af6206b --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/387.txt @@ -0,0 +1,2 @@ +* Reestructuración de la interfaz de inicio de sesión con certificado +* Añadir la posibilidad de anclar chats en la parte superior (añadir a favoritos) diff --git a/fastlane/metadata/android/es-ES/changelogs/388.txt b/fastlane/metadata/android/es-ES/changelogs/388.txt new file mode 100644 index 000000000..cd381e62a --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/388.txt @@ -0,0 +1,3 @@ +* Reducir el eco durante las llamadas en algunos dispositivos +* Arreglar el inicio de sesión cuando las contraseñas contienen caracteres especiales +* Reproducir tonos de marcado y ocupado en el altavoz durante las videollamadas diff --git a/fastlane/metadata/android/es-ES/changelogs/390.txt b/fastlane/metadata/android/es-ES/changelogs/390.txt new file mode 100644 index 000000000..7f1ba8d5e --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/390.txt @@ -0,0 +1 @@ +* Ofrecer la grabación de un mensaje de voz cuando la persona que llama está ocupada diff --git a/fastlane/metadata/android/es-ES/full_description.txt b/fastlane/metadata/android/es-ES/full_description.txt new file mode 100644 index 000000000..853549547 --- /dev/null +++ b/fastlane/metadata/android/es-ES/full_description.txt @@ -0,0 +1,39 @@ +Fácil de usar, fiable y con poca batería. Con soporte integrado para imágenes, chats de grupo y cifrado e2e. + +Principios de diseño: + +* Ser lo más bonito y fácil de usar posible sin sacrificar la seguridad ni la privacidad. +* Basarse en protocolos existentes y bien establecidos. +* No requerir una cuenta de Google o, específicamente, Google Cloud Messaging (GCM). +* Requerir el menor número de permisos posible + +Características: + +* Cifrado de extremo a extremo con OMEMO o OpenPGP. +* Envío y recepción de imágenes +* Llamadas de audio y vídeo cifradas (DTLS-SRTP) +* Interfaz de usuario intuitiva que sigue las directrices de diseño de Android +* Imágenes / Avatares para tus contactos +* Sincronización con el cliente de escritorio +* Conferencias (con soporte para marcadores) +* Integración de la libreta de direcciones +* Múltiples cuentas / bandeja de entrada unificada +* Muy bajo impacto en la duración de la batería + +Conversations hace que sea muy fácil crear una cuenta en el servidor gratuito conversations.im. Sin embargo, Conversations también funciona con cualquier otro servidor XMPP. Muchos servidores XMPP están gestionados por voluntarios y son gratuitos. + +Características de XMPP: + +Conversations funciona con todos los servidores XMPP existentes. Sin embargo, XMPP es un protocolo extensible. Estas extensiones también están estandarizadas en los llamados XEP. Conversations soporta un par de ellas para mejorar la experiencia general del usuario. Existe la posibilidad de que su actual servidor XMPP no soporte estas extensiones. Por lo tanto, para sacar el máximo provecho de Conversaciones deberías considerar o bien cambiar a un servidor XMPP que lo haga o - mejor aún - ejecutar tu propio servidor XMPP para ti y tus amigos. + +Estos XEPs son (por el momento): + +* XEP-0065: SOCKS5 Bytestreams (o mod_proxy65). Se utilizará para transferir archivos si ambas partes están detrás de un cortafuegos (NAT). +* XEP-0163: Protocolo de Evento Personal para avatares +* XEP-0191: El comando de bloqueo te permite hacer una lista negra de spammers o bloquear contactos sin eliminarlos de tu lista. +* XEP-0198: Stream Management permite a XMPP sobrevivir a pequeños cortes de red y cambios de la conexión TCP subyacente. +* XEP-0280: Message Carbons que sincroniza automáticamente los mensajes que envías a tu cliente de escritorio y por lo tanto te permite cambiar sin problemas de tu cliente móvil a tu cliente de escritorio y viceversa en una sola conversación. +* XEP-0237: Versionado de listas, principalmente para ahorrar ancho de banda en conexiones móviles deficientes. +* XEP-0313: Gestión de Archivo de Mensajes sincroniza el historial de mensajes con el servidor. Ponerse al día con los mensajes que fueron enviados mientras Conversaciones estaba fuera de línea. +* XEP-0352: Indicación del Estado del Cliente permite al servidor saber si Conversaciones está o no en segundo plano. Permite al servidor ahorrar ancho de banda reteniendo paquetes sin importancia. +* XEP-0363: Carga de Archivos HTTP permite compartir archivos en conferencias y con contactos sin conexión. Requiere un componente adicional en su servidor. diff --git a/fastlane/metadata/android/es-ES/short_description.txt b/fastlane/metadata/android/es-ES/short_description.txt new file mode 100644 index 000000000..7ed047672 --- /dev/null +++ b/fastlane/metadata/android/es-ES/short_description.txt @@ -0,0 +1 @@ +Mensajería instantánea XMPP cifrada y fácil de usar para tu dispositivo móvil From 6d1d7bd5c41a4f7412cf50f652d97a1aaa144886 Mon Sep 17 00:00:00 2001 From: ghose Date: Sun, 17 Sep 2023 04:11:15 +0000 Subject: [PATCH 082/402] Translated using Weblate (Galician) Currently translated at 29.4% (15 of 51 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/gl/ --- fastlane/metadata/android/gl-ES/changelogs/351.txt | 3 +++ fastlane/metadata/android/gl-ES/changelogs/42042.txt | 2 ++ fastlane/metadata/android/gl-ES/changelogs/42043.txt | 1 + fastlane/metadata/android/gl-ES/changelogs/42044.txt | 3 +++ fastlane/metadata/android/gl-ES/changelogs/42046.txt | 1 + fastlane/metadata/android/gl-ES/changelogs/42047.txt | 1 + fastlane/metadata/android/gl-ES/changelogs/42050.txt | 1 + fastlane/metadata/android/gl-ES/changelogs/42059.txt | 2 ++ 8 files changed, 14 insertions(+) create mode 100644 fastlane/metadata/android/gl-ES/changelogs/351.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42042.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42043.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42044.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42046.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42047.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42050.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42059.txt diff --git a/fastlane/metadata/android/gl-ES/changelogs/351.txt b/fastlane/metadata/android/gl-ES/changelogs/351.txt new file mode 100644 index 000000000..8fabff2f1 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/351.txt @@ -0,0 +1,3 @@ +* fixes for Jingle IBB file transfer +* fixes for repeated corrections filling up the database +* switched to Last Message Correction v1.1 diff --git a/fastlane/metadata/android/gl-ES/changelogs/42042.txt b/fastlane/metadata/android/gl-ES/changelogs/42042.txt new file mode 100644 index 000000000..520578662 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42042.txt @@ -0,0 +1,2 @@ +* Arranxo do reenvío contínuo en servidores que só teñen soporte sm:2 +* Mostrar 'Cambiar a vídeo' só se a outra parte tamén soporta chamada de vídeo diff --git a/fastlane/metadata/android/gl-ES/changelogs/42043.txt b/fastlane/metadata/android/gl-ES/changelogs/42043.txt new file mode 100644 index 000000000..91937ba45 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42043.txt @@ -0,0 +1 @@ +* Arranxo da regresión na transferencia de ficheiros con P2P diff --git a/fastlane/metadata/android/gl-ES/changelogs/42044.txt b/fastlane/metadata/android/gl-ES/changelogs/42044.txt new file mode 100644 index 000000000..b6df29794 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42044.txt @@ -0,0 +1,3 @@ +* Arranxo do reenvío usando SASL2 +* Arranxo dos vídeos en negro nalgúns dispositivos +* Arranxo do fallo ao usar un contrasinal baleiro diff --git a/fastlane/metadata/android/gl-ES/changelogs/42046.txt b/fastlane/metadata/android/gl-ES/changelogs/42046.txt new file mode 100644 index 000000000..ec1c1ca76 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42046.txt @@ -0,0 +1 @@ +* Integrar UnifiedPush Distributor para facilitar a entrega de mensaxes push a outras apps con UnifiedPush activado como Tusky e Fedilab diff --git a/fastlane/metadata/android/gl-ES/changelogs/42047.txt b/fastlane/metadata/android/gl-ES/changelogs/42047.txt new file mode 100644 index 000000000..359f0e958 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42047.txt @@ -0,0 +1 @@ +* Arranxar o fallo en UnifiedPush Distributor diff --git a/fastlane/metadata/android/gl-ES/changelogs/42050.txt b/fastlane/metadata/android/gl-ES/changelogs/42050.txt new file mode 100644 index 000000000..40a774b21 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42050.txt @@ -0,0 +1 @@ +* Aumentar o radio dos cantos nas imaxes de perfil diff --git a/fastlane/metadata/android/gl-ES/changelogs/42059.txt b/fastlane/metadata/android/gl-ES/changelogs/42059.txt new file mode 100644 index 000000000..44356c7e7 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42059.txt @@ -0,0 +1,2 @@ +* Establecer o Target SDK ao 33 de novo +* Arranxar problemas cos servidores con soporte SASL2 sen Stream Management en liña From c791d5baa71092bd467ed9d3f24ca600b76fd575 Mon Sep 17 00:00:00 2001 From: ghose Date: Tue, 19 Sep 2023 07:11:28 +0000 Subject: [PATCH 083/402] Translated using Weblate (Galician) Currently translated at 29.4% (15 of 51 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/gl/ --- fastlane/metadata/android/gl-ES/changelogs/353.txt | 4 ++++ fastlane/metadata/android/gl-ES/changelogs/360.txt | 1 + fastlane/metadata/android/gl-ES/changelogs/362.txt | 1 + fastlane/metadata/android/gl-ES/changelogs/364.txt | 2 ++ fastlane/metadata/android/gl-ES/changelogs/367.txt | 2 ++ fastlane/metadata/android/gl-ES/changelogs/379.txt | 1 + fastlane/metadata/android/gl-ES/changelogs/381.txt | 2 ++ fastlane/metadata/android/gl-ES/changelogs/382.txt | 2 ++ fastlane/metadata/android/gl-ES/changelogs/383.txt | 3 +++ fastlane/metadata/android/gl-ES/changelogs/387.txt | 2 ++ fastlane/metadata/android/gl-ES/changelogs/388.txt | 3 +++ fastlane/metadata/android/gl-ES/changelogs/390.txt | 1 + fastlane/metadata/android/gl-ES/changelogs/393.txt | 3 +++ fastlane/metadata/android/gl-ES/changelogs/394.txt | 2 ++ fastlane/metadata/android/gl-ES/changelogs/395.txt | 3 +++ fastlane/metadata/android/gl-ES/changelogs/397.txt | 3 +++ fastlane/metadata/android/gl-ES/changelogs/398.txt | 4 ++++ fastlane/metadata/android/gl-ES/changelogs/401.txt | 2 ++ fastlane/metadata/android/gl-ES/changelogs/402.txt | 3 +++ fastlane/metadata/android/gl-ES/changelogs/403.txt | 3 +++ fastlane/metadata/android/gl-ES/changelogs/404.txt | 1 + fastlane/metadata/android/gl-ES/changelogs/405.txt | 1 + fastlane/metadata/android/gl-ES/changelogs/407.txt | 3 +++ fastlane/metadata/android/gl-ES/changelogs/42000.txt | 4 ++++ fastlane/metadata/android/gl-ES/changelogs/42006.txt | 2 ++ fastlane/metadata/android/gl-ES/changelogs/42010.txt | 2 ++ fastlane/metadata/android/gl-ES/changelogs/42012.txt | 1 + fastlane/metadata/android/gl-ES/changelogs/42013.txt | 1 + fastlane/metadata/android/gl-ES/changelogs/42014.txt | 2 ++ fastlane/metadata/android/gl-ES/changelogs/42015.txt | 1 + fastlane/metadata/android/gl-ES/changelogs/42018.txt | 3 +++ fastlane/metadata/android/gl-ES/changelogs/42022.txt | 2 ++ fastlane/metadata/android/gl-ES/changelogs/42023.txt | 2 ++ fastlane/metadata/android/gl-ES/changelogs/42037.txt | 11 +++++++++++ fastlane/metadata/android/gl-ES/changelogs/42038.txt | 2 ++ fastlane/metadata/android/gl-ES/changelogs/42041.txt | 5 +++++ 36 files changed, 90 insertions(+) create mode 100644 fastlane/metadata/android/gl-ES/changelogs/353.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/360.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/362.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/364.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/367.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/379.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/381.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/382.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/383.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/387.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/388.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/390.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/393.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/394.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/395.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/397.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/398.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/401.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/402.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/403.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/404.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/405.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/407.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42000.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42006.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42010.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42012.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42013.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42014.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42015.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42018.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42022.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42023.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42037.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42038.txt create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42041.txt diff --git a/fastlane/metadata/android/gl-ES/changelogs/353.txt b/fastlane/metadata/android/gl-ES/changelogs/353.txt new file mode 100644 index 000000000..63b829a80 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/353.txt @@ -0,0 +1,4 @@ +* let users set their own nick name +* resume download of OMEMO encrypted files +* Channels now use '#' as symbol in avatar +* Quicksy uses 'always' as OMEMO encryption default (hides lock icon) diff --git a/fastlane/metadata/android/gl-ES/changelogs/360.txt b/fastlane/metadata/android/gl-ES/changelogs/360.txt new file mode 100644 index 000000000..87b92f033 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/360.txt @@ -0,0 +1 @@ +* Support for ?register and ?register;preauth XMPP uri parameters diff --git a/fastlane/metadata/android/gl-ES/changelogs/362.txt b/fastlane/metadata/android/gl-ES/changelogs/362.txt new file mode 100644 index 000000000..f4bbc2ab1 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/362.txt @@ -0,0 +1 @@ +* Support automatic theme switching on Android 10 diff --git a/fastlane/metadata/android/gl-ES/changelogs/364.txt b/fastlane/metadata/android/gl-ES/changelogs/364.txt new file mode 100644 index 000000000..ed2c80678 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/364.txt @@ -0,0 +1,2 @@ +* Provide PDF preview on Android 5+ +* Use 12 byte IVs for OMEMO diff --git a/fastlane/metadata/android/gl-ES/changelogs/367.txt b/fastlane/metadata/android/gl-ES/changelogs/367.txt new file mode 100644 index 000000000..2f42bd95f --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/367.txt @@ -0,0 +1,2 @@ +* Fix avatar selection on some Android 10 devices +* Fix file transfer for larger files diff --git a/fastlane/metadata/android/gl-ES/changelogs/379.txt b/fastlane/metadata/android/gl-ES/changelogs/379.txt new file mode 100644 index 000000000..a99adee16 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/379.txt @@ -0,0 +1 @@ +* Audio/Video calls (Requires server support in form of STUN and TURN servers discoverable via XEP-0215) diff --git a/fastlane/metadata/android/gl-ES/changelogs/381.txt b/fastlane/metadata/android/gl-ES/changelogs/381.txt new file mode 100644 index 000000000..a2df5e828 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/381.txt @@ -0,0 +1,2 @@ +* Audible feedback (dialing, call started, call ended) for voice calls. +* Fixed issue with retrying failed video call diff --git a/fastlane/metadata/android/gl-ES/changelogs/382.txt b/fastlane/metadata/android/gl-ES/changelogs/382.txt new file mode 100644 index 000000000..64e23e14d --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/382.txt @@ -0,0 +1,2 @@ +* Add button to switch camera during video call +* Fixed voice calls on tablets diff --git a/fastlane/metadata/android/gl-ES/changelogs/383.txt b/fastlane/metadata/android/gl-ES/changelogs/383.txt new file mode 100644 index 000000000..19c9a0116 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/383.txt @@ -0,0 +1,3 @@ +* Move call icon to the left in order to keep other toolbar icons in a consistent place +* Show call duration during audio calls +* Tie breaking for A/V calls (the same two people calling each other at the same time) diff --git a/fastlane/metadata/android/gl-ES/changelogs/387.txt b/fastlane/metadata/android/gl-ES/changelogs/387.txt new file mode 100644 index 000000000..2710be0a5 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/387.txt @@ -0,0 +1,2 @@ +* Rework Login with certificate UI +* Add ability to pin chats on top (add to favorites) diff --git a/fastlane/metadata/android/gl-ES/changelogs/388.txt b/fastlane/metadata/android/gl-ES/changelogs/388.txt new file mode 100644 index 000000000..6a4909652 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/388.txt @@ -0,0 +1,3 @@ +* Reduce echo during calls on some devices +* Fix login when passwords contains special characters +* Play dial and busy tones on speaker during video calls diff --git a/fastlane/metadata/android/gl-ES/changelogs/390.txt b/fastlane/metadata/android/gl-ES/changelogs/390.txt new file mode 100644 index 000000000..56ed78885 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/390.txt @@ -0,0 +1 @@ +* Offer to record voice message when callee is busy diff --git a/fastlane/metadata/android/gl-ES/changelogs/393.txt b/fastlane/metadata/android/gl-ES/changelogs/393.txt new file mode 100644 index 000000000..82250ee87 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/393.txt @@ -0,0 +1,3 @@ +* Show help button if A/V call fails +* Fixed some annoying crashes +* Fixed Jingle connections (file transfer + calls) with bare JIDs diff --git a/fastlane/metadata/android/gl-ES/changelogs/394.txt b/fastlane/metadata/android/gl-ES/changelogs/394.txt new file mode 100644 index 000000000..b04adbd56 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/394.txt @@ -0,0 +1,2 @@ +* Fixed notifications not showing up under certain conditions +* Fixed compatibility issues and crashes related to A/V calls diff --git a/fastlane/metadata/android/gl-ES/changelogs/395.txt b/fastlane/metadata/android/gl-ES/changelogs/395.txt new file mode 100644 index 000000000..76a654338 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/395.txt @@ -0,0 +1,3 @@ +* add 'Return to chat' to audio call screen +* Improve keyboard shortcuts +* bug fixes diff --git a/fastlane/metadata/android/gl-ES/changelogs/397.txt b/fastlane/metadata/android/gl-ES/changelogs/397.txt new file mode 100644 index 000000000..207b36708 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/397.txt @@ -0,0 +1,3 @@ +* Handle GPX files +* Improve performance for backup restore +* bug fixes diff --git a/fastlane/metadata/android/gl-ES/changelogs/398.txt b/fastlane/metadata/android/gl-ES/changelogs/398.txt new file mode 100644 index 000000000..95280ea88 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/398.txt @@ -0,0 +1,4 @@ +* Search individual conversations +* Notify user if message delivery fails +* Remember display names (nicks) from Quicksy users across restarts +* Add button to start Orbot (Tor) from notification if necessary diff --git a/fastlane/metadata/android/gl-ES/changelogs/401.txt b/fastlane/metadata/android/gl-ES/changelogs/401.txt new file mode 100644 index 000000000..907063eb6 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/401.txt @@ -0,0 +1,2 @@ +* fixed search on Android <= 5 +* optimize memory consumption diff --git a/fastlane/metadata/android/gl-ES/changelogs/402.txt b/fastlane/metadata/android/gl-ES/changelogs/402.txt new file mode 100644 index 000000000..53f461756 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/402.txt @@ -0,0 +1,3 @@ +* Offer Easy Invite generation on supporting servers +* Display GIFs send from Movim +* store avatars in cache diff --git a/fastlane/metadata/android/gl-ES/changelogs/403.txt b/fastlane/metadata/android/gl-ES/changelogs/403.txt new file mode 100644 index 000000000..99d62ca48 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/403.txt @@ -0,0 +1,3 @@ +* Fixed connectivity issues when different accounts used different SCRAM mechanisms +* Add support for SCRAM-SHA-512 +* Allow P2P (Jingle) file transfer with self contact diff --git a/fastlane/metadata/android/gl-ES/changelogs/404.txt b/fastlane/metadata/android/gl-ES/changelogs/404.txt new file mode 100644 index 000000000..d4f2e7b6d --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/404.txt @@ -0,0 +1 @@ +* minor stability improvements for A/V calls diff --git a/fastlane/metadata/android/gl-ES/changelogs/405.txt b/fastlane/metadata/android/gl-ES/changelogs/405.txt new file mode 100644 index 000000000..e858b6cd1 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/405.txt @@ -0,0 +1 @@ +* Quicksy: Automatically receive verification SMS diff --git a/fastlane/metadata/android/gl-ES/changelogs/407.txt b/fastlane/metadata/android/gl-ES/changelogs/407.txt new file mode 100644 index 000000000..e746bc7d7 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/407.txt @@ -0,0 +1,3 @@ +* Show call button for offline contacts if they previously announced support +* Back button no longer ends call when call is connected +* bug fixes diff --git a/fastlane/metadata/android/gl-ES/changelogs/42000.txt b/fastlane/metadata/android/gl-ES/changelogs/42000.txt new file mode 100644 index 000000000..1ecfe204d --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42000.txt @@ -0,0 +1,4 @@ +* Ability to select incoming call ringtone +* Fix OpenPGP key id discovery for OpenKeychain 5.6+ +* Properly verify punycode TLS certificates +* Improve stability of RTP session establishment (calling) diff --git a/fastlane/metadata/android/gl-ES/changelogs/42006.txt b/fastlane/metadata/android/gl-ES/changelogs/42006.txt new file mode 100644 index 000000000..91e2b904f --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42006.txt @@ -0,0 +1,2 @@ +* Verify A/V calls with preexisting OMEMO sessions +* Improve compatibility with non libwebrtc WebRTC implementations diff --git a/fastlane/metadata/android/gl-ES/changelogs/42010.txt b/fastlane/metadata/android/gl-ES/changelogs/42010.txt new file mode 100644 index 000000000..3a1c234c1 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42010.txt @@ -0,0 +1,2 @@ +* Various bug fixes around Tor support +* Improve call compatibility with Dino diff --git a/fastlane/metadata/android/gl-ES/changelogs/42012.txt b/fastlane/metadata/android/gl-ES/changelogs/42012.txt new file mode 100644 index 000000000..967fae964 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42012.txt @@ -0,0 +1 @@ +* fix HTTP up/download for users that don’t trust system CAs diff --git a/fastlane/metadata/android/gl-ES/changelogs/42013.txt b/fastlane/metadata/android/gl-ES/changelogs/42013.txt new file mode 100644 index 000000000..8749f0a0f --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42013.txt @@ -0,0 +1 @@ +* Fixed 'No Connectivity' issues on Android 7.1 diff --git a/fastlane/metadata/android/gl-ES/changelogs/42014.txt b/fastlane/metadata/android/gl-ES/changelogs/42014.txt new file mode 100644 index 000000000..8ae96511e --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42014.txt @@ -0,0 +1,2 @@ +* Always verify domain name. No user overwrite +* Support roster pre authentication diff --git a/fastlane/metadata/android/gl-ES/changelogs/42015.txt b/fastlane/metadata/android/gl-ES/changelogs/42015.txt new file mode 100644 index 000000000..1980efb2a --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42015.txt @@ -0,0 +1 @@ +* minor A/V improvements diff --git a/fastlane/metadata/android/gl-ES/changelogs/42018.txt b/fastlane/metadata/android/gl-ES/changelogs/42018.txt new file mode 100644 index 000000000..8f4d66caa --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42018.txt @@ -0,0 +1,3 @@ +* Show black bars when remote video does not match aspect ratio of screen +* Improve search performance +* Add setting to prevent screenshots diff --git a/fastlane/metadata/android/gl-ES/changelogs/42022.txt b/fastlane/metadata/android/gl-ES/changelogs/42022.txt new file mode 100644 index 000000000..eaaa190fa --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42022.txt @@ -0,0 +1,2 @@ +* Fix issue with some videos not being compressed +* Fix rare crash when opening notification diff --git a/fastlane/metadata/android/gl-ES/changelogs/42023.txt b/fastlane/metadata/android/gl-ES/changelogs/42023.txt new file mode 100644 index 000000000..ed3c25380 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42023.txt @@ -0,0 +1,2 @@ +* Fix crash when rendering some quotes +* Fix crash in welcome screen diff --git a/fastlane/metadata/android/gl-ES/changelogs/42037.txt b/fastlane/metadata/android/gl-ES/changelogs/42037.txt new file mode 100644 index 000000000..375905aa8 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42037.txt @@ -0,0 +1,11 @@ +Version 2.10.9 +* Ask for Bluetooth permissions when making A/V calls (You can reject this if you don’t use Bluetooth headsets) +* Fix bug when calling Movim +* Fix wrong avatar being shown for group chats +* Always ask for battery optimizations opt-out +* Set local only flag on 'x connected accounts' notifications +* Fix interaction with Google Maps Share Location Plugin +* Remove footnote with regards to server fee +* Store files in location appropriate for Android 11 +* Attempt to reconnect call after network switch +* Show caller JID and account JID in incoming call screen diff --git a/fastlane/metadata/android/gl-ES/changelogs/42038.txt b/fastlane/metadata/android/gl-ES/changelogs/42038.txt new file mode 100644 index 000000000..da3c42237 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42038.txt @@ -0,0 +1,2 @@ +* Minor bug fixes +* Restore ability to call out via JMP and other services (Playstore version) diff --git a/fastlane/metadata/android/gl-ES/changelogs/42041.txt b/fastlane/metadata/android/gl-ES/changelogs/42041.txt new file mode 100644 index 000000000..302e9719b --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42041.txt @@ -0,0 +1,5 @@ +* Implement Extensible SASL Profile, Bind 2.0 and Fast for faster reconnects +* Implement Channel Binding +* Add ability to switch from audio call to video call +* Add ability to delete own avatar +* Add notification for missed calls From 78298a2df3a68218ef982512a03e9cca75e5f3f6 Mon Sep 17 00:00:00 2001 From: nautilusx Date: Sat, 23 Sep 2023 05:27:20 +0000 Subject: [PATCH 084/402] Translated using Weblate (German) Currently translated at 100.0% (968 of 968 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/de/ --- src/main/res/values-de/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-de/strings.xml b/src/main/res/values-de/strings.xml index 5a96d84a7..8951a6f79 100644 --- a/src/main/res/values-de/strings.xml +++ b/src/main/res/values-de/strings.xml @@ -1010,4 +1010,5 @@ Gruppenchats durchsuchen Die Channelsuche verwendet einen Drittanbieterservice namens <a href=https://search.jabber.network>search.jabber.network</a>.<br><br>Wenn du diese Funktion verwendest, werden deine IP-Adresse und deine Suchbegriffe an diesen Dienst übertragen. Weitere Informationen findest du in der <a href=https://search.jabber.network/privacy>Datenschutzerklärung</a>. Versuche nicht, Backups wiederherzustellen, die du nicht selbst erstellt hast! + Du versuchst, ein veraltetes Sicherungsdateiformat zu importieren \ No newline at end of file From caec09ec7ed2f32204dfd31c80f48d797837ed16 Mon Sep 17 00:00:00 2001 From: gallegonovato Date: Fri, 22 Sep 2023 17:33:11 +0000 Subject: [PATCH 085/402] Translated using Weblate (Spanish) Currently translated at 100.0% (968 of 968 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/es/ --- src/main/res/values-es/strings.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/res/values-es/strings.xml b/src/main/res/values-es/strings.xml index d3f7de206..db9cb6adc 100644 --- a/src/main/res/values-es/strings.xml +++ b/src/main/res/values-es/strings.xml @@ -591,7 +591,7 @@ El contacto solicita ver tus actualizaciones de estado Permitir Sin permiso de acceso a %s - Servidor no encontrado + No se encontró ningún servidor remoto Tiempo de espera agotado al servidor remoto No se ha podido actualizar la cuenta Reporta esta dirección XMPP como spam. @@ -1024,4 +1024,5 @@ La búsqueda de canales utiliza un servicio de terceros denominado <a href=https://search.jabber.network>search.jabber.network</a>.<br><br>Si utiliza esta función, tu dirección IP y la búsqueda de términos serán transferidos a este servicio. Para obtener más información, consulta la <a href=https://search.jabber.network/privacy>Política de privacidad</a>. Guardar como un chat en grupo ¡No intentes restaurar las copias de seguridad que no creaste tu mismo! + Estás intentando importar un formato de copia de seguridad obsoleto \ No newline at end of file From bc4fb100fa5fff30b452e3efa8eb8bbbe6d0dae5 Mon Sep 17 00:00:00 2001 From: Eryk Michalak Date: Sat, 23 Sep 2023 12:13:18 +0000 Subject: [PATCH 086/402] Translated using Weblate (Polish) Currently translated at 100.0% (968 of 968 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/pl/ --- src/main/res/values-pl/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-pl/strings.xml b/src/main/res/values-pl/strings.xml index 458f25ac4..f000897fc 100644 --- a/src/main/res/values-pl/strings.xml +++ b/src/main/res/values-pl/strings.xml @@ -1043,4 +1043,5 @@ Czaty grupowe Zapisz jako czat grupowy Nie próbuj przywracać kopii zapasowych, których nie utworzono samodzielnie! + Próbujesz zaimportować plik kopii zapasowej o przestarzałym formacie \ No newline at end of file From 5eafc26392196281216a3de5ad4df5746a07cc99 Mon Sep 17 00:00:00 2001 From: SomeTr Date: Fri, 22 Sep 2023 19:35:06 +0000 Subject: [PATCH 087/402] Translated using Weblate (Ukrainian) Currently translated at 100.0% (968 of 968 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/uk/ --- src/main/res/values-uk/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-uk/strings.xml b/src/main/res/values-uk/strings.xml index d6e58bffd..d826a8a33 100644 --- a/src/main/res/values-uk/strings.xml +++ b/src/main/res/values-uk/strings.xml @@ -1064,4 +1064,5 @@ Дистриб\'ютор UnifiedPush Додати ще пісні\? Не намагайтеся відновити резервні копії, які створили не Ви! + Ви намагаєтеся імпортувати файл резервної копії у застарілому форматі \ No newline at end of file From 17508119782e55555f631873a4609d2846a34f9d Mon Sep 17 00:00:00 2001 From: licaon-kter Date: Fri, 22 Sep 2023 16:27:49 +0000 Subject: [PATCH 088/402] Translated using Weblate (Romanian) Currently translated at 100.0% (968 of 968 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/ro/ --- src/main/res/values-ro-rRO/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-ro-rRO/strings.xml b/src/main/res/values-ro-rRO/strings.xml index f38d0f45d..c738b8d83 100644 --- a/src/main/res/values-ro-rRO/strings.xml +++ b/src/main/res/values-ro-rRO/strings.xml @@ -1032,4 +1032,5 @@ Salvare ca discuție de grup Caută discuții de grup Nu încercați să restaurați copii de rezervă pe care nu le-ați creat personal! + Încercați să importați un fișier copie de rezervă format vechi \ No newline at end of file From 205472bcc75394b42495acad26a3cf37c7e0d11b Mon Sep 17 00:00:00 2001 From: hamburger1024 Date: Sat, 23 Sep 2023 00:36:10 +0000 Subject: [PATCH 089/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (968 of 968 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index c405066ad..956e8517f 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -1001,4 +1001,5 @@ 搜索群聊 从服务器删除账户 不要尝试恢复你尚未自行创建的备份! + 你正尝试导入过时的备份文件格式 \ No newline at end of file From 2adff4a92c8ab036b5aa492d0954df26a1bba6df Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 25 Sep 2023 09:22:29 +0200 Subject: [PATCH 090/402] catch rare instances of foreground service not allowed to start --- .../services/XmppConnectionService.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index d24b22edc..b73aef7cc 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -1367,12 +1367,12 @@ public class XmppConnectionService extends Service { if (ongoing != null) { notification = this.mNotificationService.getOngoingCallNotification(ongoing); id = NotificationService.ONGOING_CALL_NOTIFICATION_ID; - startForeground(id, notification); + startForegroundOrCatch(id, notification); mNotificationService.cancel(NotificationService.FOREGROUND_NOTIFICATION_ID); } else { notification = this.mNotificationService.createForegroundNotification(); id = NotificationService.FOREGROUND_NOTIFICATION_ID; - startForeground(id, notification); + startForegroundOrCatch(id, notification); } if (!mForceForegroundService.get()) { @@ -1392,6 +1392,14 @@ public class XmppConnectionService extends Service { Log.d(Config.LOGTAG, "ForegroundService: " + (status ? "on" : "off")); } + private void startForegroundOrCatch(final int id, final Notification notification) { + try { + startForeground(id, notification); + } catch (final IllegalStateException e) { + Log.e(Config.LOGTAG,"Could not start foreground service", e); + } + } + public boolean foregroundNotificationNeedsUpdatingWhenErrorStateChanges() { return !mForceForegroundService.get() && ongoingCall.get() == null && Compatibility.keepForegroundService(this) && hasEnabledAccounts(); } From 3e9c08a4aa8484a514bfdc68c33c6eaa27bec1fe Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 25 Sep 2023 10:54:17 +0200 Subject: [PATCH 091/402] include date in backup file name since `account.ceb` might have previously been created by a different application (for example f-droid and user is on play now) or copied over via the file manager Conversations might not have permission to write over an existing file. we include the date so we always get a new file fixes #105 --- .../conversations/services/ExportBackupService.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/services/ExportBackupService.java b/src/main/java/eu/siacs/conversations/services/ExportBackupService.java index 442fc5f4f..1462b5614 100644 --- a/src/main/java/eu/siacs/conversations/services/ExportBackupService.java +++ b/src/main/java/eu/siacs/conversations/services/ExportBackupService.java @@ -31,10 +31,13 @@ import java.nio.charset.StandardCharsets; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.spec.InvalidKeySpecException; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Date; import java.util.List; +import java.util.Locale; import java.util.concurrent.atomic.AtomicBoolean; import java.util.zip.GZIPOutputStream; @@ -58,6 +61,8 @@ import eu.siacs.conversations.utils.Compatibility; public class ExportBackupService extends Service { + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd", Locale.US); + public static final String KEYTYPE = "AES"; public static final String CIPHERMODE = "AES/GCM/NoPadding"; public static final String PROVIDER = "BC"; @@ -296,10 +301,14 @@ public class ExportBackupService extends Service { IV, salt); final Progress progress = new Progress(mBuilder, max, count); + final String filename = + String.format( + "%s.%s.ceb", + account.getJid().asBareJid().toEscapedString(), + DATE_FORMAT.format(new Date())); final File file = new File( - FileBackend.getBackupDirectory(this), - account.getJid().asBareJid().toEscapedString() + ".ceb"); + FileBackend.getBackupDirectory(this), filename); files.add(file); final File directory = file.getParentFile(); if (directory != null && directory.mkdirs()) { From 5371b100dec2e3371dd561225a0e5a19ca6f1213 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 26 Sep 2023 12:30:28 +0200 Subject: [PATCH 092/402] version bump to 2.12.10 + changelog --- CHANGELOG.md | 5 +++++ build.gradle | 4 ++-- fastlane/metadata/android/en-US/changelogs/42068.txt | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/42068.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 77be0422b..534bfee5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +### Version 2.12.10 + +* support per conversation notification settings +* use opus for voice messages on Android 10 + ### Version 2.12.9 * Introduce new backup file format diff --git a/build.gradle b/build.gradle index 430183eab..42dd80af2 100644 --- a/build.gradle +++ b/build.gradle @@ -95,8 +95,8 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 33 - versionCode 42065 - versionName "2.12.9" + versionCode 42068 + versionName "2.12.10" archivesBaseName += "-$versionName" applicationId "eu.siacs.conversations" resValue "string", "applicationId", applicationId diff --git a/fastlane/metadata/android/en-US/changelogs/42068.txt b/fastlane/metadata/android/en-US/changelogs/42068.txt new file mode 100644 index 000000000..1ddfe9ea5 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/42068.txt @@ -0,0 +1,2 @@ +* support per conversation notification settings +* use opus for voice messages on Android 10 From 05c79ff29d5522f91fe84cc213c7b3a08ba522fa Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 29 Sep 2023 16:19:01 +0200 Subject: [PATCH 093/402] version bump webrtc to m117 --- build.gradle | 2 +- .../xmpp/jingle/JingleRtpConnection.java | 32 +++++++++++-------- .../xmpp/jingle/WebRTCWrapper.java | 21 ++++++------ 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/build.gradle b/build.gradle index 42dd80af2..7d4b42dfe 100644 --- a/build.gradle +++ b/build.gradle @@ -80,7 +80,7 @@ dependencies { implementation 'com.google.guava:guava:31.1-android' quicksyImplementation 'io.michaelrocks:libphonenumber-android:8.12.49' - implementation 'im.conversations.webrtc:webrtc-android:104.0.0' + implementation 'im.conversations.webrtc:webrtc-android:117.1.0' } ext { diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java index 5530a8c78..750d89369 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java @@ -2624,6 +2624,10 @@ public class JingleRtpConnection extends AbstractJingleConnection if (port < 0 || port > 65535) { continue; } + + + + if (Arrays.asList("stun", "stuns", "turn", "turns") .contains(type) && Arrays.asList("udp", "tcp").contains(transport)) { @@ -2635,20 +2639,22 @@ public class JingleRtpConnection extends AbstractJingleConnection + ": skipping invalid combination of udp/tls in external services"); continue; } - // TODO Starting on milestone 110, Chromium will perform - // stricter validation of TURN and STUN URLs passed to the - // constructor of an RTCPeerConnection. More specifically, - // STUN URLs will not support a query section, and TURN URLs - // will support only a transport parameter in their query - // section. + + // STUN URLs do not support a query section since M110 + final String uri; + if (Arrays.asList("stun","stuns").contains(type)) { + uri = String.format("%s:%s%s", type, IP.wrapIPv6(host),port); + } else { + uri = String.format( + "%s:%s:%s?transport=%s", + type, + IP.wrapIPv6(host), + port, + transport); + } + final PeerConnection.IceServer.Builder iceServerBuilder = - PeerConnection.IceServer.builder( - String.format( - "%s:%s:%s?transport=%s", - type, - IP.wrapIPv6(host), - port, - transport)); + PeerConnection.IceServer.builder(uri); iceServerBuilder.setTlsCertPolicy( PeerConnection.TlsCertPolicy .TLS_CERT_POLICY_INSECURE_NO_CHECK); diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java index 08154260a..3c32f44a2 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java @@ -33,12 +33,12 @@ import org.webrtc.SdpObserver; import org.webrtc.SessionDescription; import org.webrtc.VideoTrack; import org.webrtc.audio.JavaAudioDeviceModule; -import org.webrtc.voiceengine.WebRtcAudioEffects; import java.util.LinkedList; import java.util.List; import java.util.Queue; import java.util.Set; +import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; @@ -260,9 +260,7 @@ public class WebRTCWrapper { Preconditions.checkNotNull(media); Preconditions.checkArgument( media.size() > 0, "media can not be empty when initializing peer connection"); - final boolean setUseHardwareAcousticEchoCanceler = - WebRtcAudioEffects.canUseAcousticEchoCanceler() - && !HARDWARE_AEC_BLACKLIST.contains(Build.MODEL); + final boolean setUseHardwareAcousticEchoCanceler = !HARDWARE_AEC_BLACKLIST.contains(Build.MODEL); Log.d( Config.LOGTAG, String.format( @@ -574,11 +572,7 @@ public class WebRTCWrapper { new SetSdpObserver() { @Override public void onSetSuccess() { - final SessionDescription description = - peerConnection.getLocalDescription(); - Log.d(EXTENDED_LOGGING_TAG, "set local description:"); - logDescription(description); - future.set(description); + future.setFuture(getLocalDescriptionFuture()); } @Override @@ -592,6 +586,15 @@ public class WebRTCWrapper { MoreExecutors.directExecutor()); } + private ListenableFuture getLocalDescriptionFuture() { + return Futures.submit(() -> { + final SessionDescription description = requirePeerConnection().getLocalDescription(); + Log.d(EXTENDED_LOGGING_TAG, "local description:"); + logDescription(description); + return description; + },executorService); + } + public static void logDescription(final SessionDescription sessionDescription) { for (final String line : sessionDescription.description.split( From 503b04e8e08b4ea5e817b7a425f6680c48ccdd86 Mon Sep 17 00:00:00 2001 From: ghose Date: Mon, 25 Sep 2023 13:30:44 +0000 Subject: [PATCH 094/402] Translated using Weblate (Galician) Currently translated at 100.0% (968 of 968 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/gl/ --- src/main/res/values-gl/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-gl/strings.xml b/src/main/res/values-gl/strings.xml index e44df1bfb..9e8926bb0 100644 --- a/src/main/res/values-gl/strings.xml +++ b/src/main/res/values-gl/strings.xml @@ -1013,4 +1013,5 @@ Conversas en grupo O descubrimento de canles usa un servizo externo chamado <a href=https://search.jabber.network>search.jabber.network</a>.<br><br>Ao usar esta ferramenta transmitirás o teu enderezo IP e termos de busca a ese servizo. Le a súa <a href=https://search.jabber.network/privacy>Política de Privacidade</a> para saber máis. Non intentes restablecer unha copia de apoio que non tiveses creado ti! + Estás intentando importar un ficheiro de apoio co formato antigo \ No newline at end of file From 86f46ece830cf0fb7b51a047cbea112e791811f7 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 29 Sep 2023 18:42:26 +0200 Subject: [PATCH 095/402] revert back to AAC for voice messages iOS can not do opus out of the box --- src/main/java/eu/siacs/conversations/Config.java | 4 ++++ .../java/eu/siacs/conversations/ui/RecordingActivity.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/eu/siacs/conversations/Config.java b/src/main/java/eu/siacs/conversations/Config.java index 812f6ae10..2299c3adb 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -83,6 +83,8 @@ public final class Config { public static final boolean XEP_0392 = true; //enables XEP-0392 v0.6.0 + + // media file formats. Homogenous Android or Conversations only deployments can switch to opus and webp public static final int AVATAR_SIZE = 192; public static final Bitmap.CompressFormat AVATAR_FORMAT = Bitmap.CompressFormat.JPEG; public static final int AVATAR_CHAR_LIMIT = 9400; @@ -91,6 +93,8 @@ public final class Config { public static final Bitmap.CompressFormat IMAGE_FORMAT = Bitmap.CompressFormat.JPEG; public static final int IMAGE_QUALITY = 75; + public static final boolean USE_OPUS_VOICE_MESSAGES = false; + public static final int MESSAGE_MERGE_WINDOW = 20; public static final int PAGE_SIZE = 50; diff --git a/src/main/java/eu/siacs/conversations/ui/RecordingActivity.java b/src/main/java/eu/siacs/conversations/ui/RecordingActivity.java index 085765163..df3dabdce 100644 --- a/src/main/java/eu/siacs/conversations/ui/RecordingActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/RecordingActivity.java @@ -99,7 +99,7 @@ public class RecordingActivity extends Activity implements View.OnClickListener mRecorder = new MediaRecorder(); mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); final int outputFormat; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (Config.USE_OPUS_VOICE_MESSAGES && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { outputFormat = MediaRecorder.OutputFormat.OGG; mRecorder.setOutputFormat(outputFormat); mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.OPUS); From 6660877bcf455e4db8dffc696cb30926a7215f5d Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 30 Sep 2023 07:52:51 +0200 Subject: [PATCH 096/402] jingle: trim media attribute values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Movim has trailing whitespace around some of their media attributes our WebRTC doesn’t like that. We trim the value even though this seems to be a Movim bug. --- .../conversations/xmpp/jingle/JingleConnectionManager.java | 4 +++- .../siacs/conversations/xmpp/jingle/SessionDescription.java | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java index 6646d5d7a..fd58fa16a 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java @@ -438,7 +438,9 @@ public class JingleConnectionManager extends AbstractConnectionManager { Log.d( Config.LOGTAG, account.getJid().asBareJid() - + ": no rtp session proposal found for " + + ": no rtp session (" + + sessionId + + ") proposal found for " + from + " to deliver proceed"); if (remoteMsgId == null) { diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/SessionDescription.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/SessionDescription.java index f0f98260b..77b598793 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/SessionDescription.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/SessionDescription.java @@ -291,7 +291,7 @@ public class SessionDescription { throw new IllegalArgumentException( "A source specific media attribute is missing its value"); } - mediaAttributes.put("ssrc", id + " " + parameterName + ":" + parameterValue); + mediaAttributes.put("ssrc", id + " " + parameterName + ":" + parameterValue.trim()); } } From 860723810bc367b6b93f19f738a6487a6543a51e Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 30 Sep 2023 10:02:22 +0200 Subject: [PATCH 097/402] support per-app language settings --- src/main/AndroidManifest.xml | 1 + src/main/res/xml/locales_config.xml | 44 +++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 src/main/res/xml/locales_config.xml diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 6676e18b4..aca21e2ed 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -87,6 +87,7 @@ android:requestLegacyExternalStorage="true" android:theme="@style/ConversationsTheme" tools:replace="android:label" + android:localeConfig="@xml/locales_config" tools:targetApi="q"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From c9b80254e46d6393111a42ef76210b5f1474629f Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 30 Sep 2023 15:56:00 +0200 Subject: [PATCH 098/402] add more logging to unroutable jingle messages --- .../conversations/xmpp/jingle/JingleConnectionManager.java | 2 +- .../eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java index fd58fa16a..9f51bec7e 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java @@ -486,7 +486,7 @@ public class JingleConnectionManager extends AbstractConnectionManager { } else { Log.d( Config.LOGTAG, - account.getJid().asBareJid() + account.getJid() + ": retrieved out of order jingle message from " + from + message diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java index 750d89369..9f2069ab2 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java @@ -1377,6 +1377,7 @@ public class JingleRtpConnection extends AbstractJingleConnection id.account.getJid().asBareJid() + ": unable to transition to accept because already in state=" + this.state); + Log.d(Config.LOGTAG, id.account.getJid() + ": received accept from " + from); } } else { Log.d( From ac3ce93c566911262f8ee18c54361e954483e755 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 1 Oct 2023 08:02:55 +0200 Subject: [PATCH 099/402] fix stun url generation --- .../eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java index 9f2069ab2..ad2702850 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java @@ -2644,7 +2644,7 @@ public class JingleRtpConnection extends AbstractJingleConnection // STUN URLs do not support a query section since M110 final String uri; if (Arrays.asList("stun","stuns").contains(type)) { - uri = String.format("%s:%s%s", type, IP.wrapIPv6(host),port); + uri = String.format("%s:%s:%s", type, IP.wrapIPv6(host),port); } else { uri = String.format( "%s:%s:%s?transport=%s", From 0dca7f8a5a6e543da81cd3730793a0162dbc1cb5 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 1 Oct 2023 08:05:36 +0200 Subject: [PATCH 100/402] JMI: send 'ringing' and receipts only for contacts fixes #110 --- .../conversations/parser/MessageParser.java | 19 ++++++++++++++++--- .../xmpp/jingle/JingleRtpConnection.java | 4 +++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 006923bd7..0378c2927 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -849,9 +849,22 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece if (serverMsgId == null) { serverMsgId = extractStanzaId(account, packet); } - mXmppConnectionService.getJingleConnectionManager().deliverMessage(account, packet.getTo(), packet.getFrom(), child, remoteMsgId, serverMsgId, timestamp); - if (!account.getJid().asBareJid().equals(from.asBareJid()) && remoteMsgId != null) { - processMessageReceipts(account, packet, remoteMsgId, query); + mXmppConnectionService + .getJingleConnectionManager() + .deliverMessage( + account, + packet.getTo(), + packet.getFrom(), + child, + remoteMsgId, + serverMsgId, + timestamp); + final Contact contact = account.getRoster().getContact(from); + if (mXmppConnectionService.confirmMessages() + && !contact.isSelf() + && remoteMsgId != null + && contact.showInContactList()) { + processMessageReceipts(account, packet, remoteMsgId, null); } } else if (query.isCatchup()) { if ("propose".equals(action)) { diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java index ad2702850..fb335ef93 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java @@ -1505,7 +1505,9 @@ public class JingleRtpConnection extends AbstractJingleConnection } this.message.setTime(timestamp); startRinging(); - sendJingleMessage("ringing"); + if (xmppConnectionService.confirmMessages() && id.getContact().showInContactList()) { + sendJingleMessage("ringing"); + } } else { Log.d( Config.LOGTAG, From 09993b83194e916497d81d77edc6777a09d6b544 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 2 Oct 2023 11:03:08 +0200 Subject: [PATCH 101/402] fetch local description on its own executor --- .../xmpp/jingle/JingleRtpConnection.java | 2 +- .../xmpp/jingle/WebRTCWrapper.java | 60 ++++++++++--------- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java index fb335ef93..87bf4bf98 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java @@ -2354,7 +2354,7 @@ public class JingleRtpConnection extends AbstractJingleConnection private void restartIce() { this.stateHistory.clear(); - this.webRTCWrapper.restartIce(); + this.webRTCWrapper.restartIceAsync(); } @Override diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java index 3c32f44a2..ba7e078f3 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java @@ -14,6 +14,10 @@ import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.SettableFuture; +import eu.siacs.conversations.Config; +import eu.siacs.conversations.services.AppRTCAudioManager; +import eu.siacs.conversations.services.XmppConnectionService; + import org.webrtc.AudioSource; import org.webrtc.AudioTrack; import org.webrtc.CandidatePairChangeEvent; @@ -38,7 +42,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Queue; import java.util.Set; -import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; @@ -46,16 +49,14 @@ import java.util.concurrent.atomic.AtomicBoolean; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import eu.siacs.conversations.Config; -import eu.siacs.conversations.services.AppRTCAudioManager; -import eu.siacs.conversations.services.XmppConnectionService; - @SuppressWarnings("UnstableApiUsage") public class WebRTCWrapper { private static final String EXTENDED_LOGGING_TAG = WebRTCWrapper.class.getSimpleName(); private final ExecutorService executorService = Executors.newSingleThreadExecutor(); + private final ExecutorService localDescriptionExecutorService = + Executors.newSingleThreadExecutor(); private static final Set HARDWARE_AEC_BLACKLIST = new ImmutableSet.Builder() @@ -260,7 +261,8 @@ public class WebRTCWrapper { Preconditions.checkNotNull(media); Preconditions.checkArgument( media.size() > 0, "media can not be empty when initializing peer connection"); - final boolean setUseHardwareAcousticEchoCanceler = !HARDWARE_AEC_BLACKLIST.contains(Build.MODEL); + final boolean setUseHardwareAcousticEchoCanceler = + !HARDWARE_AEC_BLACKLIST.contains(Build.MODEL); Log.d( Config.LOGTAG, String.format( @@ -412,21 +414,20 @@ public class WebRTCWrapper { requirePeerConnection().setConfiguration(buildConfiguration(iceServers)); } - void restartIce() { - executorService.execute( - () -> { - final PeerConnection peerConnection; - try { - peerConnection = requirePeerConnection(); - } catch (final PeerConnectionNotInitialized e) { - Log.w( - EXTENDED_LOGGING_TAG, - "PeerConnection vanished before we could execute restart"); - return; - } - setIsReadyToReceiveIceCandidates(false); - peerConnection.restartIce(); - }); + void restartIceAsync() { + this.execute(this::restartIce); + } + + private void restartIce() { + final PeerConnection peerConnection; + try { + peerConnection = requirePeerConnection(); + } catch (final PeerConnectionNotInitialized e) { + Log.w(EXTENDED_LOGGING_TAG, "PeerConnection vanished before we could execute restart"); + return; + } + setIsReadyToReceiveIceCandidates(false); + peerConnection.restartIce(); } public void setIsReadyToReceiveIceCandidates(final boolean ready) { @@ -587,12 +588,15 @@ public class WebRTCWrapper { } private ListenableFuture getLocalDescriptionFuture() { - return Futures.submit(() -> { - final SessionDescription description = requirePeerConnection().getLocalDescription(); - Log.d(EXTENDED_LOGGING_TAG, "local description:"); - logDescription(description); - return description; - },executorService); + return Futures.submit( + () -> { + final SessionDescription description = + requirePeerConnection().getLocalDescription(); + Log.d(EXTENDED_LOGGING_TAG, "local description:"); + logDescription(description); + return description; + }, + localDescriptionExecutorService); } public static void logDescription(final SessionDescription sessionDescription) { @@ -703,7 +707,7 @@ public class WebRTCWrapper { } void execute(final Runnable command) { - executorService.execute(command); + this.executorService.execute(command); } public void switchSpeakerPhonePreference(AppRTCAudioManager.SpeakerPhonePreference preference) { From 7e9980d9973e1d0d1b2c9e2c7e7e594502174169 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 2 Oct 2023 11:48:03 +0200 Subject: [PATCH 102/402] catch illegal state exception in TrackWrapper --- .../conversations/xmpp/jingle/TrackWrapper.java | 12 +++++++++--- .../conversations/xmpp/jingle/WebRTCWrapper.java | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/TrackWrapper.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/TrackWrapper.java index 31c3577ee..e62aa18fd 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/TrackWrapper.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/TrackWrapper.java @@ -6,6 +6,8 @@ import com.google.common.base.CaseFormat; import com.google.common.base.Optional; import com.google.common.base.Preconditions; +import eu.siacs.conversations.Config; + import org.webrtc.MediaStreamTrack; import org.webrtc.PeerConnection; import org.webrtc.RtpSender; @@ -16,8 +18,6 @@ import java.util.UUID; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import eu.siacs.conversations.Config; - class TrackWrapper { public final T track; public final RtpSender rtpSender; @@ -43,7 +43,13 @@ class TrackWrapper { final RtpTransceiver transceiver = peerConnection == null ? null : getTransceiver(peerConnection, trackWrapper); if (transceiver == null) { - Log.w(Config.LOGTAG, "unable to detect transceiver for " + trackWrapper.rtpSender.id()); + final String id; + try { + id = trackWrapper.rtpSender.id(); + } catch (final IllegalStateException e) { + return Optional.absent(); + } + Log.w(Config.LOGTAG, "unable to detect transceiver for " + id); return Optional.of(trackWrapper.track); } final RtpTransceiver.RtpTransceiverDirection direction = transceiver.getDirection(); diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java index ba7e078f3..c30b1d58f 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java @@ -520,7 +520,7 @@ public class WebRTCWrapper { return false; } } else { - throw new IllegalStateException("Local audio track does not exist (yet)"); + return false; } } From 17856a47dbecfba77c02b78d5d7e2e7c2b70b0a0 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 2 Oct 2023 13:54:36 +0200 Subject: [PATCH 103/402] hold back candidates until after content-add --- .../siacs/conversations/xmpp/jingle/JingleRtpConnection.java | 3 ++- .../java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java index 87bf4bf98..8aea0da9e 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java @@ -729,6 +729,7 @@ public class JingleRtpConnection extends AbstractJingleConnection + ContentAddition.summary(contentAcceptMap)); modifyLocalContentMap(rtpContentMap); sendContentAccept(contentAcceptMap); + this.webRTCWrapper.setIsReadyToReceiveIceCandidates(true); } catch (final Exception e) { Log.d(Config.LOGTAG, "unable to accept content add", Throwables.getRootCause(e)); webRTCWrapper.close(); @@ -862,7 +863,6 @@ public class JingleRtpConnection extends AbstractJingleConnection webRTCWrapper.setRemoteDescription(sdp).get(); setRemoteContentMap(restartContentMap); if (isOffer) { - webRTCWrapper.setIsReadyToReceiveIceCandidates(false); final SessionDescription localSessionDescription = setLocalSessionDescription(); setLocalContentMap(RtpContentMap.of(localSessionDescription, isInitiator())); // We need to respond OK before sending any candidates @@ -2473,6 +2473,7 @@ public class JingleRtpConnection extends AbstractJingleConnection handleIqTimeoutResponse(response); } }); + this.webRTCWrapper.setIsReadyToReceiveIceCandidates(true); } private void setLocalContentMap(final RtpContentMap rtpContentMap) { diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java index c30b1d58f..8c5d266a5 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java @@ -561,6 +561,7 @@ public class WebRTCWrapper { } synchronized ListenableFuture setLocalDescription() { + this.setIsReadyToReceiveIceCandidates(false); return Futures.transformAsync( getPeerConnectionFuture(), peerConnection -> { From d235633cc7cc40c4cb6bed9541bbc95174bff500 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 3 Oct 2023 10:50:22 +0200 Subject: [PATCH 104/402] version bump to 2.12.11 + changelog --- CHANGELOG.md | 6 ++++++ build.gradle | 4 ++-- fastlane/metadata/android/en-US/changelogs/42072.txt | 3 +++ 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/42072.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 534bfee5e..3e3277f71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +### Version 2.12.11 + +* Bump libwebrtc dependency to M117 and bump libvpx +* Go back to AAC for voice messages +* Support per app language settings + ### Version 2.12.10 * support per conversation notification settings diff --git a/build.gradle b/build.gradle index 7d4b42dfe..c54b90f33 100644 --- a/build.gradle +++ b/build.gradle @@ -95,8 +95,8 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 33 - versionCode 42068 - versionName "2.12.10" + versionCode 42072 + versionName "2.12.11" archivesBaseName += "-$versionName" applicationId "eu.siacs.conversations" resValue "string", "applicationId", applicationId diff --git a/fastlane/metadata/android/en-US/changelogs/42072.txt b/fastlane/metadata/android/en-US/changelogs/42072.txt new file mode 100644 index 000000000..6a84b9489 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/42072.txt @@ -0,0 +1,3 @@ +* Bump libwebrtc dependency to M117 and bump libvpx +* Go back to AAC for voice messages +* Support per app language settings From fd4b8ba1885a9f6e24a87e47c3a6a730f9ed15f8 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 3 Oct 2023 12:55:44 +0200 Subject: [PATCH 105/402] bring back ICE Renomination via negotiation --- .../eu/siacs/conversations/xml/Namespace.java | 1 + .../xmpp/jingle/JingleRtpConnection.java | 12 +++++ .../xmpp/jingle/SessionDescription.java | 27 +++++++---- .../jingle/stanzas/IceUdpTransportInfo.java | 45 +++++++++++++++++++ 4 files changed, 76 insertions(+), 9 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/xml/Namespace.java b/src/main/java/eu/siacs/conversations/xml/Namespace.java index b614251bd..201b11894 100644 --- a/src/main/java/eu/siacs/conversations/xml/Namespace.java +++ b/src/main/java/eu/siacs/conversations/xml/Namespace.java @@ -65,5 +65,6 @@ public final class Namespace { public static final String PARS = "urn:xmpp:pars:0"; public static final String EASY_ONBOARDING_INVITE = "urn:xmpp:invite#invite"; public static final String OMEMO_DTLS_SRTP_VERIFICATION = "http://gultsch.de/xmpp/drafts/omemo/dlts-srtp-verification"; + public static final String JINGLE_TRANSPORT_ICE_OPTION = "http://gultsch.de/xmpp/drafts/jingle/transports/ice-udp/option"; public static final String UNIFIED_PUSH = "http://gultsch.de/xmpp/drafts/unified-push"; } diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java index 8aea0da9e..766482899 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java @@ -15,6 +15,7 @@ import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.common.primitives.Ints; import com.google.common.util.concurrent.FutureCallback; @@ -237,6 +238,9 @@ public class JingleRtpConnection extends AbstractJingleConnection case CONTENT_REMOVE: receiveContentRemove(jinglePacket); break; + case CONTENT_MODIFY: + receiveContentModify(jinglePacket); + break; default: respondOk(jinglePacket); Log.d( @@ -507,6 +511,14 @@ public class JingleRtpConnection extends AbstractJingleConnection + ContentAddition.summary(receivedContentAccept)); } + private void receiveContentModify(final JinglePacket jinglePacket) { + final Map modification = + Maps.transformEntries( + jinglePacket.getJingleContents(), (key, value) -> value.getSenders()); + respondOk(jinglePacket); + Log.d(Config.LOGTAG, "receiveContentModification(" + modification + ")"); + } + private void receiveContentReject(final JinglePacket jinglePacket) { final RtpContentMap receivedContentReject; try { diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/SessionDescription.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/SessionDescription.java index 77b598793..b9d99fe6e 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/SessionDescription.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/SessionDescription.java @@ -11,23 +11,26 @@ import com.google.common.base.Strings; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableList; -import java.util.List; -import java.util.Locale; -import java.util.Map; - import eu.siacs.conversations.Config; import eu.siacs.conversations.xml.Namespace; import eu.siacs.conversations.xmpp.jingle.stanzas.Group; import eu.siacs.conversations.xmpp.jingle.stanzas.IceUdpTransportInfo; import eu.siacs.conversations.xmpp.jingle.stanzas.RtpDescription; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Map; + public class SessionDescription { public static final String LINE_DIVIDER = "\r\n"; private static final String HARDCODED_MEDIA_PROTOCOL = "UDP/TLS/RTP/SAVPF"; // probably only true for DTLS-SRTP aka when we have a fingerprint private static final int HARDCODED_MEDIA_PORT = 9; - private static final String HARDCODED_ICE_OPTIONS = "trickle"; + private static final Collection HARDCODED_ICE_OPTIONS = + Collections.singleton("trickle"); private static final String HARDCODED_CONNECTION = "IN IP4 0.0.0.0"; public final int version; @@ -128,7 +131,8 @@ public class SessionDescription { return sessionDescriptionBuilder.createSessionDescription(); } - public static SessionDescription of(final RtpContentMap contentMap, final boolean isInitiatorContentMap) { + public static SessionDescription of( + final RtpContentMap contentMap, final boolean isInitiatorContentMap) { final SessionDescriptionBuilder sessionDescriptionBuilder = new SessionDescriptionBuilder(); final ArrayListMultimap attributeMap = ArrayListMultimap.create(); final ImmutableList.Builder mediaListBuilder = new ImmutableList.Builder<>(); @@ -166,7 +170,10 @@ public class SessionDescription { } checkNoWhitespace(pwd, "pwd value must not contain any whitespaces"); mediaAttributes.put("ice-pwd", pwd); - mediaAttributes.put("ice-options", HARDCODED_ICE_OPTIONS); + final List negotiatedIceOptions = transport.getIceOptions(); + final Collection iceOptions = + negotiatedIceOptions.isEmpty() ? HARDCODED_ICE_OPTIONS : negotiatedIceOptions; + mediaAttributes.put("ice-options", Joiner.on(' ').join(iceOptions)); final IceUdpTransportInfo.Fingerprint fingerprint = transport.getFingerprint(); if (fingerprint != null) { mediaAttributes.put( @@ -291,13 +298,15 @@ public class SessionDescription { throw new IllegalArgumentException( "A source specific media attribute is missing its value"); } - mediaAttributes.put("ssrc", id + " " + parameterName + ":" + parameterValue.trim()); + mediaAttributes.put( + "ssrc", id + " " + parameterName + ":" + parameterValue.trim()); } } mediaAttributes.put("mid", name); - mediaAttributes.put(descriptionTransport.senders.asMediaAttribute(isInitiatorContentMap), ""); + mediaAttributes.put( + descriptionTransport.senders.asMediaAttribute(isInitiatorContentMap), ""); if (description.hasChild("rtcp-mux", Namespace.JINGLE_APPS_RTP) || group != null) { mediaAttributes.put("rtcp-mux", ""); } diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/IceUdpTransportInfo.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/IceUdpTransportInfo.java index 432333090..bd7e44501 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/IceUdpTransportInfo.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/IceUdpTransportInfo.java @@ -1,17 +1,23 @@ package eu.siacs.conversations.xmpp.jingle.stanzas; +import android.util.Log; + import androidx.annotation.NonNull; import com.google.common.base.Joiner; import com.google.common.base.MoreObjects; import com.google.common.base.Objects; import com.google.common.base.Preconditions; +import com.google.common.base.Splitter; import com.google.common.base.Strings; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Hashtable; import java.util.LinkedHashMap; @@ -20,6 +26,7 @@ import java.util.Locale; import java.util.Map; import java.util.UUID; +import eu.siacs.conversations.Config; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Namespace; import eu.siacs.conversations.xmpp.jingle.SessionDescription; @@ -59,6 +66,9 @@ public class IceUdpTransportInfo extends GenericTransportInfo { if (fingerprint != null) { iceUdpTransportInfo.addChild(fingerprint); } + for (final String iceOption : IceOption.of(media)) { + iceUdpTransportInfo.addChild(new IceOption(iceOption)); + } return iceUdpTransportInfo; } @@ -76,6 +86,16 @@ public class IceUdpTransportInfo extends GenericTransportInfo { return fingerprint == null ? null : Fingerprint.upgrade(fingerprint); } + public List getIceOptions() { + final ImmutableList.Builder optionBuilder = new ImmutableList.Builder<>(); + for(final Element child : this.children) { + if (Namespace.JINGLE_TRANSPORT_ICE_OPTION.equals(child.getNamespace()) && IceOption.WELL_KNOWN.contains(child.getName())) { + optionBuilder.add(child.getName()); + } + } + return optionBuilder.build(); + } + public Credentials getCredentials() { final String ufrag = this.getAttribute("ufrag"); final String password = this.getAttribute("pwd"); @@ -408,4 +428,29 @@ public class IceUdpTransportInfo extends GenericTransportInfo { throw new IllegalStateException(this.name() + " can not be flipped"); } } + + public static class IceOption extends Element { + + public static final List WELL_KNOWN = Arrays.asList("trickle", "renomination"); + + public IceOption(final String name) { + super(name, Namespace.JINGLE_TRANSPORT_ICE_OPTION); + } + + public static Collection of(SessionDescription.Media media) { + final String iceOptions = Iterables.getFirst(media.attributes.get("ice-options"), null); + if (Strings.isNullOrEmpty(iceOptions)) { + return Collections.emptyList(); + } + final ImmutableList.Builder optionBuilder = new ImmutableList.Builder<>(); + for (final String iceOption : Splitter.on(' ').split(iceOptions)) { + if (WELL_KNOWN.contains(iceOption)) { + optionBuilder.add(iceOption); + } else { + Log.w(Config.LOGTAG, "unrecognized ice option: " + iceOption); + } + } + return optionBuilder.build(); + } + } } From 8570c9f9126b9807c83c76d8abe8909820b631d1 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 3 Oct 2023 12:56:10 +0200 Subject: [PATCH 106/402] use more aggressive reconnect intervals during rtp session --- .../services/XmppConnectionService.java | 12 +++++++++--- .../siacs/conversations/xmpp/XmppConnection.java | 13 +++++++++---- .../xmpp/jingle/JingleConnectionManager.java | 16 ++++++++++++++++ 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index b73aef7cc..5a072e9c6 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -466,14 +466,15 @@ public class XmppConnectionService extends Service { } else if (account.getStatus() != Account.State.CONNECTING && account.getStatus() != Account.State.NO_INTERNET) { resetSendingToWaiting(account); if (connection != null && account.getStatus().isAttemptReconnect()) { - final int next = connection.getTimeToNextAttempt(); + final boolean aggressive = hasJingleRtpConnection(account); + final int next = connection.getTimeToNextAttempt(aggressive); final boolean lowPingTimeoutMode = isInLowPingTimeoutMode(account); if (next <= 0) { Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": error connecting account. reconnecting now. lowPingTimeout=" + lowPingTimeoutMode); reconnectAccount(account, true, false); } else { final int attempt = connection.getAttempt() + 1; - Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": error connecting account. try again in " + next + "s for the " + attempt + " time. lowPingTimeout=" + lowPingTimeoutMode); + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": error connecting account. try again in " + next + "s for the " + attempt + " time. lowPingTimeout=" + lowPingTimeoutMode+", aggressive="+aggressive); scheduleWakeUpCall(next, account.getUuid().hashCode()); } } @@ -948,7 +949,8 @@ public class XmppConnectionService extends Service { scheduleWakeUpCall((int) Math.min(timeout, discoTimeout), account.getUuid().hashCode()); } } else { - if (account.getXmppConnection().getTimeToNextAttempt() <= 0) { + final boolean aggressive = hasJingleRtpConnection(account); + if (account.getXmppConnection().getTimeToNextAttempt(aggressive) <= 0) { reconnectAccount(account, true, interactive); } } @@ -4590,6 +4592,10 @@ public class XmppConnectionService extends Service { return this.mJingleConnectionManager; } + private boolean hasJingleRtpConnection(final Account account) { + return this.mJingleConnectionManager.hasJingleRtpConnection(account); + } + public MessageArchiveService getMessageArchiveService() { return this.mMessageArchiveService; } diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 11651397a..93ab1ebf5 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -2483,10 +2483,15 @@ public class XmppConnection implements Runnable { return servers.size() > 0 ? servers.get(0) : null; } - public int getTimeToNextAttempt() { - final int additionalTime = - account.getLastErrorStatus() == Account.State.POLICY_VIOLATION ? 3 : 0; - final int interval = Math.min((int) (25 * Math.pow(1.3, (additionalTime + attempt))), 300); + public int getTimeToNextAttempt(final boolean aggressive) { + final int interval; + if (aggressive) { + interval = Math.min((int) (3 * Math.pow(1.3,attempt)), 60); + } else { + final int additionalTime = + account.getLastErrorStatus() == Account.State.POLICY_VIOLATION ? 3 : 0; + interval = Math.min((int) (25 * Math.pow(1.3, (additionalTime + attempt))), 300); + } final int secondsSinceLast = (int) ((SystemClock.elapsedRealtime() - this.lastConnect) / 1000); return interval - secondsSinceLast; diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java index 9f51bec7e..77737e5ae 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java @@ -158,6 +158,21 @@ public class JingleConnectionManager extends AbstractConnectionManager { } } + public boolean hasJingleRtpConnection(final Account account) { + for (AbstractJingleConnection connection : this.connections.values()) { + if (connection instanceof JingleRtpConnection) { + final JingleRtpConnection rtpConnection = (JingleRtpConnection) connection; + if (rtpConnection.isTerminated()) { + continue; + } + if (rtpConnection.id.account == account) { + return true; + } + } + } + return false; + } + public void notifyPhoneCallStarted() { for (AbstractJingleConnection connection : connections.values()) { if (connection instanceof JingleRtpConnection) { @@ -170,6 +185,7 @@ public class JingleConnectionManager extends AbstractConnectionManager { } } + private Optional findMatchingSessionProposal( final Account account, final Jid with, final Set media) { synchronized (this.rtpSessionProposals) { From b689b46fa819cd52a7d78712a765e25437f51337 Mon Sep 17 00:00:00 2001 From: random_r Date: Sun, 1 Oct 2023 09:39:43 +0000 Subject: [PATCH 107/402] Translated using Weblate (Italian) Currently translated at 100.0% (968 of 968 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/it/ --- src/main/res/values-it/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-it/strings.xml b/src/main/res/values-it/strings.xml index fafad3ad2..e2a16616e 100644 --- a/src/main/res/values-it/strings.xml +++ b/src/main/res/values-it/strings.xml @@ -1024,4 +1024,5 @@ Cerca chat di gruppo La scoperta dei canali usa un servizio di terze parti chiamato <a href=https://search.jabber.network>search.jabber.network</a>.<br><br>L\'uso di questa funzione invierà il tuo indirizzo IP e i termini di ricerca a quel servizio. Vedi la sua <a href=https://search.jabber.network/privacy>informativa sulla privacy</a> per maggiori informazioni. Non tentare di ripristinare dei backup che non hai creato te stesso! + Stai tentando di importare un formato di file di backup obsoleto \ No newline at end of file From cfac58c8af16c9ed7e5f3ab56d8177d1feb86ede Mon Sep 17 00:00:00 2001 From: random_r Date: Sun, 1 Oct 2023 10:01:41 +0000 Subject: [PATCH 108/402] Translated using Weblate (Italian) Currently translated at 100.0% (51 of 51 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/it/ --- fastlane/metadata/android/it-IT/changelogs/349.txt | 4 ++++ fastlane/metadata/android/it-IT/changelogs/351.txt | 3 +++ fastlane/metadata/android/it-IT/changelogs/353.txt | 4 ++++ fastlane/metadata/android/it-IT/changelogs/360.txt | 1 + fastlane/metadata/android/it-IT/changelogs/362.txt | 1 + fastlane/metadata/android/it-IT/changelogs/364.txt | 2 ++ fastlane/metadata/android/it-IT/changelogs/367.txt | 2 ++ fastlane/metadata/android/it-IT/changelogs/379.txt | 1 + fastlane/metadata/android/it-IT/changelogs/381.txt | 2 ++ fastlane/metadata/android/it-IT/changelogs/382.txt | 2 ++ fastlane/metadata/android/it-IT/changelogs/383.txt | 3 +++ fastlane/metadata/android/it-IT/changelogs/387.txt | 2 ++ fastlane/metadata/android/it-IT/changelogs/388.txt | 3 +++ fastlane/metadata/android/it-IT/changelogs/390.txt | 1 + fastlane/metadata/android/it-IT/changelogs/393.txt | 3 +++ fastlane/metadata/android/it-IT/changelogs/394.txt | 2 ++ fastlane/metadata/android/it-IT/changelogs/395.txt | 3 +++ fastlane/metadata/android/it-IT/changelogs/397.txt | 3 +++ fastlane/metadata/android/it-IT/changelogs/398.txt | 4 ++++ fastlane/metadata/android/it-IT/changelogs/401.txt | 2 ++ fastlane/metadata/android/it-IT/changelogs/402.txt | 3 +++ fastlane/metadata/android/it-IT/changelogs/403.txt | 3 +++ fastlane/metadata/android/it-IT/changelogs/404.txt | 1 + fastlane/metadata/android/it-IT/changelogs/405.txt | 1 + fastlane/metadata/android/it-IT/changelogs/407.txt | 3 +++ fastlane/metadata/android/it-IT/changelogs/42000.txt | 4 ++++ fastlane/metadata/android/it-IT/changelogs/42006.txt | 2 ++ fastlane/metadata/android/it-IT/changelogs/42010.txt | 2 ++ fastlane/metadata/android/it-IT/changelogs/42012.txt | 1 + fastlane/metadata/android/it-IT/changelogs/42013.txt | 1 + fastlane/metadata/android/it-IT/changelogs/42014.txt | 2 ++ fastlane/metadata/android/it-IT/changelogs/42015.txt | 1 + fastlane/metadata/android/it-IT/changelogs/42018.txt | 3 +++ fastlane/metadata/android/it-IT/changelogs/42022.txt | 2 ++ fastlane/metadata/android/it-IT/changelogs/42023.txt | 2 ++ fastlane/metadata/android/it-IT/changelogs/42037.txt | 11 +++++++++++ fastlane/metadata/android/it-IT/changelogs/42038.txt | 2 ++ fastlane/metadata/android/it-IT/changelogs/42041.txt | 5 +++++ fastlane/metadata/android/it-IT/changelogs/42042.txt | 2 ++ fastlane/metadata/android/it-IT/changelogs/42043.txt | 1 + fastlane/metadata/android/it-IT/changelogs/42044.txt | 3 +++ fastlane/metadata/android/it-IT/changelogs/42046.txt | 1 + fastlane/metadata/android/it-IT/changelogs/42047.txt | 1 + fastlane/metadata/android/it-IT/changelogs/42050.txt | 1 + fastlane/metadata/android/it-IT/changelogs/42059.txt | 2 ++ fastlane/metadata/android/it-IT/changelogs/42060.txt | 1 + fastlane/metadata/android/it-IT/changelogs/42061.txt | 1 + fastlane/metadata/android/it-IT/changelogs/42062.txt | 1 + fastlane/metadata/android/it-IT/changelogs/42065.txt | 1 + 49 files changed, 112 insertions(+) create mode 100644 fastlane/metadata/android/it-IT/changelogs/349.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/351.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/353.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/360.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/362.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/364.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/367.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/379.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/381.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/382.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/383.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/387.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/388.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/390.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/393.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/394.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/395.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/397.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/398.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/401.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/402.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/403.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/404.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/405.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/407.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42000.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42006.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42010.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42012.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42013.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42014.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42015.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42018.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42022.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42023.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42037.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42038.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42041.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42042.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42043.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42044.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42046.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42047.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42050.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42059.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42060.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42061.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42062.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42065.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/349.txt b/fastlane/metadata/android/it-IT/changelogs/349.txt new file mode 100644 index 000000000..170eda951 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/349.txt @@ -0,0 +1,4 @@ +* Introdotta l'impostazione per esperti per eseguire la ricerca dei canali sul server locale invece che su search.jabber.network +* Attivati i segni di spunta per la consegna in modo predefinito e rimossa l'impostazione +* Attivato "Il pulsante di invio indica lo stato" in modo predefinito e rimossa l'impostazione +* Spostate le impostazioni del servizio di backup e di primo piano nella schermata principale diff --git a/fastlane/metadata/android/it-IT/changelogs/351.txt b/fastlane/metadata/android/it-IT/changelogs/351.txt new file mode 100644 index 000000000..3c3b94459 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/351.txt @@ -0,0 +1,3 @@ +* Correzioni per il trasferimento di file Jingle IBB +* Risolte le correzioni ripetute che riempivano il database +* Transizione a Last Message Correction v1.1 diff --git a/fastlane/metadata/android/it-IT/changelogs/353.txt b/fastlane/metadata/android/it-IT/changelogs/353.txt new file mode 100644 index 000000000..dc3a5160d --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/353.txt @@ -0,0 +1,4 @@ +* Consente agli utenti di impostare il proprio nick name +* Riprende il download dei file criptati OMEMO +* I canali ora usano '#' come simbolo nell'avatar. +* Quicksy imposta "sempre" come crittografia OMEMO in modo predefinito (nasconde l'icona del lucchetto) diff --git a/fastlane/metadata/android/it-IT/changelogs/360.txt b/fastlane/metadata/android/it-IT/changelogs/360.txt new file mode 100644 index 000000000..82fbedd2d --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/360.txt @@ -0,0 +1 @@ +* Supporto per i parametri uri XMPP ?register e ?register;preauth diff --git a/fastlane/metadata/android/it-IT/changelogs/362.txt b/fastlane/metadata/android/it-IT/changelogs/362.txt new file mode 100644 index 000000000..c276d02c2 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/362.txt @@ -0,0 +1 @@ +* Supporto del cambio automatico dei temi su Android 10 diff --git a/fastlane/metadata/android/it-IT/changelogs/364.txt b/fastlane/metadata/android/it-IT/changelogs/364.txt new file mode 100644 index 000000000..7b461a350 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/364.txt @@ -0,0 +1,2 @@ +* Fornisce l'anteprima PDF su Android 5+ +* Utilizzo di IVs a 12 byte per OMEMO diff --git a/fastlane/metadata/android/it-IT/changelogs/367.txt b/fastlane/metadata/android/it-IT/changelogs/367.txt new file mode 100644 index 000000000..89239a58f --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/367.txt @@ -0,0 +1,2 @@ +* Corretta la selezione dell'avatar su alcuni dispositivi Android 10 +* Corretto il trasferimento di file più grandi diff --git a/fastlane/metadata/android/it-IT/changelogs/379.txt b/fastlane/metadata/android/it-IT/changelogs/379.txt new file mode 100644 index 000000000..fe27f8ec6 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/379.txt @@ -0,0 +1 @@ +* Chiamate audio/video (richiede il supporto di server sotto forma di server STUN e TURN rilevabili tramite XEP-0215) diff --git a/fastlane/metadata/android/it-IT/changelogs/381.txt b/fastlane/metadata/android/it-IT/changelogs/381.txt new file mode 100644 index 000000000..39bd79c54 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/381.txt @@ -0,0 +1,2 @@ +* Feedback acustico (composizione, inizio e fine chiamata) per le chiamate vocali. +* Risolto un problema con la ripetizione di una videochiamata fallita diff --git a/fastlane/metadata/android/it-IT/changelogs/382.txt b/fastlane/metadata/android/it-IT/changelogs/382.txt new file mode 100644 index 000000000..8a8bd6863 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/382.txt @@ -0,0 +1,2 @@ +* Aggiunto un pulsante per cambiare telecamera durante la videochiamata +* Corrette le chiamate vocali sui tablet diff --git a/fastlane/metadata/android/it-IT/changelogs/383.txt b/fastlane/metadata/android/it-IT/changelogs/383.txt new file mode 100644 index 000000000..32d16941b --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/383.txt @@ -0,0 +1,3 @@ +* Spostata l'icona della chiamata a sinistra per mantenere le altre icone della barra degli strumenti in una posizione coerente +* Mostra la durata della chiamata durante le chiamate audio +* Interruzione della parità per le chiamate A/V (due persone che si chiamano contemporaneamente) diff --git a/fastlane/metadata/android/it-IT/changelogs/387.txt b/fastlane/metadata/android/it-IT/changelogs/387.txt new file mode 100644 index 000000000..e78cea033 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/387.txt @@ -0,0 +1,2 @@ +* Ristrutturata l'interfaccia utente per l'accesso con certificato +* Aggiunta la possibilità di fissare le chat in alto (aggiungi ai preferiti) diff --git a/fastlane/metadata/android/it-IT/changelogs/388.txt b/fastlane/metadata/android/it-IT/changelogs/388.txt new file mode 100644 index 000000000..20b0c18fa --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/388.txt @@ -0,0 +1,3 @@ +* Riduzione dell'eco durante le chiamate su alcuni dispositivi +* Corretto l'accesso quando le password contengono caratteri speciali +* Riproduzione dei toni di chiamata e di occupato sull'altoparlante durante le videochiamate diff --git a/fastlane/metadata/android/it-IT/changelogs/390.txt b/fastlane/metadata/android/it-IT/changelogs/390.txt new file mode 100644 index 000000000..35b00a97d --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/390.txt @@ -0,0 +1 @@ +* Offerta di registrazione del messaggio vocale quando il chiamante è occupato diff --git a/fastlane/metadata/android/it-IT/changelogs/393.txt b/fastlane/metadata/android/it-IT/changelogs/393.txt new file mode 100644 index 000000000..3238e8910 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/393.txt @@ -0,0 +1,3 @@ +* Mostra il pulsante di aiuto se la chiamata A/V fallisce +* Risolti alcuni fastidiosi arresti anomali +* Corrette le connessioni Jingle (trasferimento di file + chiamate) con JID nudi diff --git a/fastlane/metadata/android/it-IT/changelogs/394.txt b/fastlane/metadata/android/it-IT/changelogs/394.txt new file mode 100644 index 000000000..d94866c6d --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/394.txt @@ -0,0 +1,2 @@ +* Corrette le notifiche che non vengono visualizzate in determinate condizioni +* Corretti i problemi di compatibilità e gli arresti anomali relativi alle chiamate A/V diff --git a/fastlane/metadata/android/it-IT/changelogs/395.txt b/fastlane/metadata/android/it-IT/changelogs/395.txt new file mode 100644 index 000000000..264021fd3 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/395.txt @@ -0,0 +1,3 @@ +* Aggiunta la funzione "Torna alla chat" alla schermata delle chiamate audio +* Migliorate le scorciatoie da tastiera +* Correzioni di errori diff --git a/fastlane/metadata/android/it-IT/changelogs/397.txt b/fastlane/metadata/android/it-IT/changelogs/397.txt new file mode 100644 index 000000000..295266e01 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/397.txt @@ -0,0 +1,3 @@ +* Gestisce i file GPX +* Migliorate le prestazioni per il ripristino dei backup +* Correzioni di errori diff --git a/fastlane/metadata/android/it-IT/changelogs/398.txt b/fastlane/metadata/android/it-IT/changelogs/398.txt new file mode 100644 index 000000000..5efa2686e --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/398.txt @@ -0,0 +1,4 @@ +* Ricerca di conversazioni individuali +* Notifica all'utente se la consegna del messaggio fallisce +* Ricorda i nomi visualizzati (nick) degli utenti di Quicksy durante i vari riavvii +* Aggiunto un pulsante per avviare Orbot (Tor) dalla notifica, se necessario diff --git a/fastlane/metadata/android/it-IT/changelogs/401.txt b/fastlane/metadata/android/it-IT/changelogs/401.txt new file mode 100644 index 000000000..fbcf70c2a --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/401.txt @@ -0,0 +1,2 @@ +* Corretta la ricerca su Android <= 5 +* Ottimizzato il consumo di memoria diff --git a/fastlane/metadata/android/it-IT/changelogs/402.txt b/fastlane/metadata/android/it-IT/changelogs/402.txt new file mode 100644 index 000000000..e4a1a9fa0 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/402.txt @@ -0,0 +1,3 @@ +* Offre la generazione di inviti facili sui server di supporto +* Visualizzazione delle GIF inviate da Movim +* Memorizzazione degli avatar nella cache diff --git a/fastlane/metadata/android/it-IT/changelogs/403.txt b/fastlane/metadata/android/it-IT/changelogs/403.txt new file mode 100644 index 000000000..c0ee371d8 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/403.txt @@ -0,0 +1,3 @@ +* Corretti i problemi di connettività quando profili diversi usavano meccanismi SCRAM diversi +* Aggiunto il supporto per SCRAM-SHA-512 +* Consente il trasferimento di file P2P (Jingle) con l'auto contatto diff --git a/fastlane/metadata/android/it-IT/changelogs/404.txt b/fastlane/metadata/android/it-IT/changelogs/404.txt new file mode 100644 index 000000000..6346ddb12 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/404.txt @@ -0,0 +1 @@ +* Miglioramenti di stabilità minori per le chiamate A/V diff --git a/fastlane/metadata/android/it-IT/changelogs/405.txt b/fastlane/metadata/android/it-IT/changelogs/405.txt new file mode 100644 index 000000000..7325ea2a9 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/405.txt @@ -0,0 +1 @@ +* Quicksy: ricevi automaticamente SMS di verifica diff --git a/fastlane/metadata/android/it-IT/changelogs/407.txt b/fastlane/metadata/android/it-IT/changelogs/407.txt new file mode 100644 index 000000000..2ba4dd4fd --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/407.txt @@ -0,0 +1,3 @@ +* Mostra il pulsante di chiamata per i contatti offline se hanno precedentemente annunciato il supporto +* Il pulsante Indietro non termina più la chiamata quando questa è connessa +* Correzioni di errori diff --git a/fastlane/metadata/android/it-IT/changelogs/42000.txt b/fastlane/metadata/android/it-IT/changelogs/42000.txt new file mode 100644 index 000000000..5697c2ed2 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42000.txt @@ -0,0 +1,4 @@ +* Possibilità di selezionare la suoneria delle chiamate in arrivo +* Correzione del rilevamento dell'id della chiave OpenPGP per OpenKeychain 5.6+ +* Verifica corretta dei certificati TLS con codice punycode +* Miglioramento della stabilità della creazione di sessioni RTP (chiamate) diff --git a/fastlane/metadata/android/it-IT/changelogs/42006.txt b/fastlane/metadata/android/it-IT/changelogs/42006.txt new file mode 100644 index 000000000..dda32ef6a --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42006.txt @@ -0,0 +1,2 @@ +* Verifica delle chiamate A/V con le sessioni OMEMO preesistenti +* Miglioramento della compatibilità con le implementazioni WebRTC non libwebrtc diff --git a/fastlane/metadata/android/it-IT/changelogs/42010.txt b/fastlane/metadata/android/it-IT/changelogs/42010.txt new file mode 100644 index 000000000..2140a3a44 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42010.txt @@ -0,0 +1,2 @@ +* Correzione di vari errori relativi al supporto di Tor +* Migliorata la compatibilità delle chiamate con Dino diff --git a/fastlane/metadata/android/it-IT/changelogs/42012.txt b/fastlane/metadata/android/it-IT/changelogs/42012.txt new file mode 100644 index 000000000..9da7d48df --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42012.txt @@ -0,0 +1 @@ +* Corretto l'up/download HTTP per gli utenti che non si fidano delle CA di sistema diff --git a/fastlane/metadata/android/it-IT/changelogs/42013.txt b/fastlane/metadata/android/it-IT/changelogs/42013.txt new file mode 100644 index 000000000..f58811956 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42013.txt @@ -0,0 +1 @@ +* Risolti i problemi di "assenza di connettività" su Android 7.1 diff --git a/fastlane/metadata/android/it-IT/changelogs/42014.txt b/fastlane/metadata/android/it-IT/changelogs/42014.txt new file mode 100644 index 000000000..95c2355ff --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42014.txt @@ -0,0 +1,2 @@ +* Verifica sempre il nome del dominio. Nessuna sovrascrittura dell'utente +* Supporto della pre-autenticazione del roster diff --git a/fastlane/metadata/android/it-IT/changelogs/42015.txt b/fastlane/metadata/android/it-IT/changelogs/42015.txt new file mode 100644 index 000000000..b296f82ca --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42015.txt @@ -0,0 +1 @@ +* Miglioramenti A/V minori diff --git a/fastlane/metadata/android/it-IT/changelogs/42018.txt b/fastlane/metadata/android/it-IT/changelogs/42018.txt new file mode 100644 index 000000000..a6eac7a8f --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42018.txt @@ -0,0 +1,3 @@ +* Mostra barre nere quando il video remoto non corrisponde alle proporzioni dello schermo +* Migliorate le prestazioni della ricerca +* Aggiunta un'impostazione per impedire gli screenshot diff --git a/fastlane/metadata/android/it-IT/changelogs/42022.txt b/fastlane/metadata/android/it-IT/changelogs/42022.txt new file mode 100644 index 000000000..1ff223875 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42022.txt @@ -0,0 +1,2 @@ +* Corretto il problema di alcuni video che non vengono compressi +* Corretti rari arresti anomali all'apertura delle notifiche diff --git a/fastlane/metadata/android/it-IT/changelogs/42023.txt b/fastlane/metadata/android/it-IT/changelogs/42023.txt new file mode 100644 index 000000000..a75ef6f39 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42023.txt @@ -0,0 +1,2 @@ +* Corretto l'arresto anomalo durante il rendering di alcune citazioni +* Corretto l'arresto anomalo nella schermata di benvenuto diff --git a/fastlane/metadata/android/it-IT/changelogs/42037.txt b/fastlane/metadata/android/it-IT/changelogs/42037.txt new file mode 100644 index 000000000..9b2cf0e25 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42037.txt @@ -0,0 +1,11 @@ +2.10.9 +* Permessi Bluetooth per chiamate A/V (puoi rifiutare) +* Correto bug chiamando Movim +* Corretti avatar nelle chat di gruppo +* Chiedi sempre opt-out di ottimizzazione batteria +* Flag solo locale su notifiche "x profili connessi" +* Corretta interazione con plugin di condivisione posizione Google Maps +* Rimossa nota del costo del server +* Archivia i file nel posto giusto su Android 11 +* Ricollega chiamata dopo il cambio di rete +* Mostra JID chiamante e JID profilo nelle chiamate in entrata diff --git a/fastlane/metadata/android/it-IT/changelogs/42038.txt b/fastlane/metadata/android/it-IT/changelogs/42038.txt new file mode 100644 index 000000000..04af5aca6 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42038.txt @@ -0,0 +1,2 @@ +* Correzione di errori minori +* Ripristino della possibilità di richiamare tramite JMP e altri servizi (versione Playstore) diff --git a/fastlane/metadata/android/it-IT/changelogs/42041.txt b/fastlane/metadata/android/it-IT/changelogs/42041.txt new file mode 100644 index 000000000..2331de300 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42041.txt @@ -0,0 +1,5 @@ +* Implementato il profilo SASL estensibile, Bind 2.0 e Fast per riconnettersi più velocemente +* Implementato il Channel Binding +* Aggiunta la possibilità di passare da una chiamata audio a una videochiamata +* Aggiunta la possibilità di cancellare il proprio avatar +* Aggiunta la notifica per le chiamate perse diff --git a/fastlane/metadata/android/it-IT/changelogs/42042.txt b/fastlane/metadata/android/it-IT/changelogs/42042.txt new file mode 100644 index 000000000..3bc5bb2b7 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42042.txt @@ -0,0 +1,2 @@ +* Corretto un loop di reinvio sui server che supportano solo sm:2 +* Mostra 'Passa al video' solo se l'altra parte supporta il video diff --git a/fastlane/metadata/android/it-IT/changelogs/42043.txt b/fastlane/metadata/android/it-IT/changelogs/42043.txt new file mode 100644 index 000000000..95b94c630 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42043.txt @@ -0,0 +1 @@ +* Corretta regressione nel trasferimento di file P2P diff --git a/fastlane/metadata/android/it-IT/changelogs/42044.txt b/fastlane/metadata/android/it-IT/changelogs/42044.txt new file mode 100644 index 000000000..8354cbf1e --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42044.txt @@ -0,0 +1,3 @@ +* Corretto il reinvio dei messaggi quando si usa SASL2 +* Corretto il video nero tra alcuni dispositivi +* Corretto l'arresto anomalo delle password vuote diff --git a/fastlane/metadata/android/it-IT/changelogs/42046.txt b/fastlane/metadata/android/it-IT/changelogs/42046.txt new file mode 100644 index 000000000..e8a8d3d2e --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42046.txt @@ -0,0 +1 @@ +* Integra il distributore UnifiedPush per facilitare i messaggi push ad altre app abilitate a UnifiedPush come Tusky e Fedilab diff --git a/fastlane/metadata/android/it-IT/changelogs/42047.txt b/fastlane/metadata/android/it-IT/changelogs/42047.txt new file mode 100644 index 000000000..abc0c9e6c --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42047.txt @@ -0,0 +1 @@ +* Corretto l'arresto anomalo del distributore UnifiedPush diff --git a/fastlane/metadata/android/it-IT/changelogs/42050.txt b/fastlane/metadata/android/it-IT/changelogs/42050.txt new file mode 100644 index 000000000..071ad6d75 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42050.txt @@ -0,0 +1 @@ +* Aumenta il raggio degli angoli nelle immagini del profilo diff --git a/fastlane/metadata/android/it-IT/changelogs/42059.txt b/fastlane/metadata/android/it-IT/changelogs/42059.txt new file mode 100644 index 000000000..405597cd0 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42059.txt @@ -0,0 +1,2 @@ +* Aggiornato l'SDK di destinazione di nuovo alla versione 33 +* Corretti problemi sui server che supportano SASL2 senza gestione inline dei flussi diff --git a/fastlane/metadata/android/it-IT/changelogs/42060.txt b/fastlane/metadata/android/it-IT/changelogs/42060.txt new file mode 100644 index 000000000..14a8a6a1f --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42060.txt @@ -0,0 +1 @@ +* Corretta la 'q' che viene erroneamente riconosciuta come cirillico diff --git a/fastlane/metadata/android/it-IT/changelogs/42061.txt b/fastlane/metadata/android/it-IT/changelogs/42061.txt new file mode 100644 index 000000000..00af956c5 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42061.txt @@ -0,0 +1 @@ +* Rimossa la funzione di scoperta dei canali dalla versione di Google Play diff --git a/fastlane/metadata/android/it-IT/changelogs/42062.txt b/fastlane/metadata/android/it-IT/changelogs/42062.txt new file mode 100644 index 000000000..c2d024121 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42062.txt @@ -0,0 +1 @@ +* Disattiva l'apertura dei file di backup (.ceb) dal file manager diff --git a/fastlane/metadata/android/it-IT/changelogs/42065.txt b/fastlane/metadata/android/it-IT/changelogs/42065.txt new file mode 100644 index 000000000..ae3fca640 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42065.txt @@ -0,0 +1 @@ +* Introdotto un nuovo formato di file di backup From 1aeae9c7f67763f5eed7813fef8daeaf4714c196 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 3 Oct 2023 14:16:48 +0200 Subject: [PATCH 109/402] set local-only flag on ongoing call notification --- .../eu/siacs/conversations/services/NotificationService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java index 9fe1f923c..44d21bed6 100644 --- a/src/main/java/eu/siacs/conversations/services/NotificationService.java +++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java @@ -642,6 +642,7 @@ public class NotificationService { createCallAction( id.sessionId, XmppConnectionService.ACTION_END_CALL, 104)) .build()); + builder.setLocalOnly(true); return builder.build(); } From 8e7d0b9e4e140f5b0e010de1fdf772ebfeb13c10 Mon Sep 17 00:00:00 2001 From: nautilusx Date: Mon, 2 Oct 2023 10:54:08 +0000 Subject: [PATCH 110/402] Translated using Weblate (German) Currently translated at 100.0% (52 of 52 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/de/ --- fastlane/metadata/android/de-DE/changelogs/42068.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/de-DE/changelogs/42068.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/42068.txt b/fastlane/metadata/android/de-DE/changelogs/42068.txt new file mode 100644 index 000000000..8204a5fe5 --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/42068.txt @@ -0,0 +1,2 @@ +* Unterstützung der Benachrichtigungseinstellungen pro Unterhaltung +* Verwendung von Opus für Sprachnachrichten unter Android 10 From fbd7931cc7a4d6d8535ad4dd0b225666419dca3e Mon Sep 17 00:00:00 2001 From: ghose Date: Mon, 2 Oct 2023 11:43:46 +0000 Subject: [PATCH 111/402] Translated using Weblate (Galician) Currently translated at 30.7% (16 of 52 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/gl/ --- fastlane/metadata/android/gl-ES/changelogs/42068.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42068.txt diff --git a/fastlane/metadata/android/gl-ES/changelogs/42068.txt b/fastlane/metadata/android/gl-ES/changelogs/42068.txt new file mode 100644 index 000000000..49d898d51 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42068.txt @@ -0,0 +1,2 @@ +* soporte para os axustes das notificacións por conversa +* usar opus para as mensaxes de voz en Android 10 From 112d80a3924d23d2659b127dd34ad04118e3fbf7 Mon Sep 17 00:00:00 2001 From: SomeTr Date: Mon, 2 Oct 2023 12:28:14 +0000 Subject: [PATCH 112/402] Translated using Weblate (Ukrainian) Currently translated at 100.0% (52 of 52 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/uk/ --- fastlane/metadata/android/uk/changelogs/42068.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/uk/changelogs/42068.txt diff --git a/fastlane/metadata/android/uk/changelogs/42068.txt b/fastlane/metadata/android/uk/changelogs/42068.txt new file mode 100644 index 000000000..eabdf5366 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42068.txt @@ -0,0 +1,2 @@ +* Підтримка налаштування сповіщень окремо для кожної розмови +* Використання Opus для голосових повідомлень на Android 10 From a91b1ed4b62b4e2947815909060c75487d23736e Mon Sep 17 00:00:00 2001 From: nautilusx Date: Tue, 3 Oct 2023 13:48:00 +0000 Subject: [PATCH 113/402] Translated using Weblate (German) Currently translated at 100.0% (53 of 53 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/de/ --- fastlane/metadata/android/de-DE/changelogs/42072.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 fastlane/metadata/android/de-DE/changelogs/42072.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/42072.txt b/fastlane/metadata/android/de-DE/changelogs/42072.txt new file mode 100644 index 000000000..bc6504828 --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/42072.txt @@ -0,0 +1,3 @@ +* Änderung der libwebrtc-Abhängigkeit auf M117 und Änderung von libvpx +* Rückkehr zu AAC für Sprachnachrichten +* Unterstützung von Spracheinstellungen innerhalb einer App From a986fbd20cf0acdf2ecb4d320cc11a3c5637cfa7 Mon Sep 17 00:00:00 2001 From: ghose Date: Tue, 3 Oct 2023 12:56:40 +0000 Subject: [PATCH 114/402] Translated using Weblate (Galician) Currently translated at 32.0% (17 of 53 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/gl/ --- fastlane/metadata/android/gl-ES/changelogs/42072.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42072.txt diff --git a/fastlane/metadata/android/gl-ES/changelogs/42072.txt b/fastlane/metadata/android/gl-ES/changelogs/42072.txt new file mode 100644 index 000000000..534c20ed1 --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42072.txt @@ -0,0 +1,3 @@ +*Subir a dependencia libwebrtc a M117 e tamén libvpx +* Volver a AAC para as mensaxes de voz +* Soporte para indicar na app os axustes do idioma From bda4d5ecbb95ef958aaa677c3e413beda75c04ec Mon Sep 17 00:00:00 2001 From: SomeTr Date: Tue, 3 Oct 2023 19:25:15 +0000 Subject: [PATCH 115/402] Translated using Weblate (Ukrainian) Currently translated at 100.0% (53 of 53 strings) Translation: Conversations/App Store Metadata Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/uk/ --- fastlane/metadata/android/uk/changelogs/42072.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 fastlane/metadata/android/uk/changelogs/42072.txt diff --git a/fastlane/metadata/android/uk/changelogs/42072.txt b/fastlane/metadata/android/uk/changelogs/42072.txt new file mode 100644 index 000000000..b8ff7f7c7 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42072.txt @@ -0,0 +1,3 @@ +* Підвищено залежність libwebrtc до M117 і оновлено libvpx +* Повернення до AAC для голосових повідомлень +* Підтримка своїх налаштувань мови в додатку From ef80b92c88ed29b076d0e0c68780c7935c99fdff Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 4 Oct 2023 08:30:34 +0200 Subject: [PATCH 116/402] create fastlane folders per flavor --- .../android/da-DK/short_description.txt | 0 .../metadata/android/de-DE/full_description.txt | 0 .../android/de-DE/short_description.txt | 0 .../metadata/android/en-US/full_description.txt | 0 .../metadata/android/en-US/images/icon.png | Bin 0 -> 43974 bytes .../android/en-US/short_description.txt | 0 .../metadata/android/es-ES/full_description.txt | 0 .../android/es-ES/short_description.txt | 0 .../metadata/android/gl-ES/full_description.txt | 0 .../android/gl-ES/short_description.txt | 0 .../metadata/android/it-IT/full_description.txt | 0 .../android/it-IT/short_description.txt | 0 .../metadata/android/pl-PL/full_description.txt | 0 .../android/pl-PL/short_description.txt | 0 .../metadata/android/ro/short_description.txt | 0 .../metadata/android/sq/full_description.txt | 0 .../metadata/android/sq/short_description.txt | 0 .../metadata/android/sv-SE/full_description.txt | 0 .../android/sv-SE/short_description.txt | 0 .../metadata/android/uk/full_description.txt | 0 .../metadata/android/uk/short_description.txt | 0 .../metadata/android/zh-TW/full_description.txt | 0 .../android/zh-TW/short_description.txt | 0 .../metadata/android/en-US/images/icon.png | Bin 0 -> 34816 bytes 24 files changed, 0 insertions(+), 0 deletions(-) rename {fastlane => src/conversations/fastlane}/metadata/android/da-DK/short_description.txt (100%) rename {fastlane => src/conversations/fastlane}/metadata/android/de-DE/full_description.txt (100%) rename {fastlane => src/conversations/fastlane}/metadata/android/de-DE/short_description.txt (100%) rename {fastlane => src/conversations/fastlane}/metadata/android/en-US/full_description.txt (100%) create mode 100644 src/conversations/fastlane/metadata/android/en-US/images/icon.png rename {fastlane => src/conversations/fastlane}/metadata/android/en-US/short_description.txt (100%) rename {fastlane => src/conversations/fastlane}/metadata/android/es-ES/full_description.txt (100%) rename {fastlane => src/conversations/fastlane}/metadata/android/es-ES/short_description.txt (100%) rename {fastlane => src/conversations/fastlane}/metadata/android/gl-ES/full_description.txt (100%) rename {fastlane => src/conversations/fastlane}/metadata/android/gl-ES/short_description.txt (100%) rename {fastlane => src/conversations/fastlane}/metadata/android/it-IT/full_description.txt (100%) rename {fastlane => src/conversations/fastlane}/metadata/android/it-IT/short_description.txt (100%) rename {fastlane => src/conversations/fastlane}/metadata/android/pl-PL/full_description.txt (100%) rename {fastlane => src/conversations/fastlane}/metadata/android/pl-PL/short_description.txt (100%) rename {fastlane => src/conversations/fastlane}/metadata/android/ro/short_description.txt (100%) rename {fastlane => src/conversations/fastlane}/metadata/android/sq/full_description.txt (100%) rename {fastlane => src/conversations/fastlane}/metadata/android/sq/short_description.txt (100%) rename {fastlane => src/conversations/fastlane}/metadata/android/sv-SE/full_description.txt (100%) rename {fastlane => src/conversations/fastlane}/metadata/android/sv-SE/short_description.txt (100%) rename {fastlane => src/conversations/fastlane}/metadata/android/uk/full_description.txt (100%) rename {fastlane => src/conversations/fastlane}/metadata/android/uk/short_description.txt (100%) rename {fastlane => src/conversations/fastlane}/metadata/android/zh-TW/full_description.txt (100%) rename {fastlane => src/conversations/fastlane}/metadata/android/zh-TW/short_description.txt (100%) create mode 100644 src/quicksy/fastlane/metadata/android/en-US/images/icon.png diff --git a/fastlane/metadata/android/da-DK/short_description.txt b/src/conversations/fastlane/metadata/android/da-DK/short_description.txt similarity index 100% rename from fastlane/metadata/android/da-DK/short_description.txt rename to src/conversations/fastlane/metadata/android/da-DK/short_description.txt diff --git a/fastlane/metadata/android/de-DE/full_description.txt b/src/conversations/fastlane/metadata/android/de-DE/full_description.txt similarity index 100% rename from fastlane/metadata/android/de-DE/full_description.txt rename to src/conversations/fastlane/metadata/android/de-DE/full_description.txt diff --git a/fastlane/metadata/android/de-DE/short_description.txt b/src/conversations/fastlane/metadata/android/de-DE/short_description.txt similarity index 100% rename from fastlane/metadata/android/de-DE/short_description.txt rename to src/conversations/fastlane/metadata/android/de-DE/short_description.txt diff --git a/fastlane/metadata/android/en-US/full_description.txt b/src/conversations/fastlane/metadata/android/en-US/full_description.txt similarity index 100% rename from fastlane/metadata/android/en-US/full_description.txt rename to src/conversations/fastlane/metadata/android/en-US/full_description.txt diff --git a/src/conversations/fastlane/metadata/android/en-US/images/icon.png b/src/conversations/fastlane/metadata/android/en-US/images/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..046dbfb3a09088f55918613caf3ec002ab521551 GIT binary patch literal 43974 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 DUB#Ih literal 0 HcmV?d00001 From af0f9bfd782ed572fd0c2cb47e3358b6e2915c81 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 4 Oct 2023 08:37:01 +0200 Subject: [PATCH 117/402] add fastlane description for Quicksy --- .../metadata/android/en-US/full_description.txt | 14 ++++++++++++++ .../metadata/android/en-US/short_description.txt | 1 + 2 files changed, 15 insertions(+) create mode 100644 src/quicksy/fastlane/metadata/android/en-US/full_description.txt create mode 100644 src/quicksy/fastlane/metadata/android/en-US/short_description.txt diff --git a/src/quicksy/fastlane/metadata/android/en-US/full_description.txt b/src/quicksy/fastlane/metadata/android/en-US/full_description.txt new file mode 100644 index 000000000..b756980e3 --- /dev/null +++ b/src/quicksy/fastlane/metadata/android/en-US/full_description.txt @@ -0,0 +1,14 @@ +Quicksy is a spin off of the popular Jabber/XMPP client Conversations with automatic contact discovery. + +You sign up with your phone number and Quicksy will automatically—based on the phone numbers in your address book—suggest possible contacts to you. + +Under the hood Quicksy is a full-fledged Jabber client that lets you communicate with any user on any publicly federating server. Likewise users on Quicksy can be contacted from the outside simply by adding +phonenumber@quicksy.im to your contact list. + +Aside from the contact sync the user interface is deliberately as close to Conversations as possible. This allows users to eventually migrate from Quicksy to Conversations without having to relearn how the app works. + +Suggested contacts consists of other Quicksy users and regular Jabber/XMPP users who have entered their Jabber ID into the Quicksy Directory (https://quicksy.im/#get-listed). + +NOTE: To enter (https://quicksy.im/enter/) your Jabber ID in the Quicksy +Directory an one time registration fee is required. + +Read the Privacy Policy (https://quicksy.im/#privacy) for more info. diff --git a/src/quicksy/fastlane/metadata/android/en-US/short_description.txt b/src/quicksy/fastlane/metadata/android/en-US/short_description.txt new file mode 100644 index 000000000..d57be03b7 --- /dev/null +++ b/src/quicksy/fastlane/metadata/android/en-US/short_description.txt @@ -0,0 +1 @@ +Jabber/XMPP with Easy Entry and Easy Discovery From a98738ae9d6499a1fe5217e89cc80e5b49c703e8 Mon Sep 17 00:00:00 2001 From: Outbreak2096 <178168oh22hgq6d6unw8k24c5ik4th@yadim.dismail.de> Date: Wed, 4 Oct 2023 04:22:31 +0000 Subject: [PATCH 118/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (968 of 968 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index 956e8517f..79ba09b4e 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -20,7 +20,7 @@ 解封成员 管理账户 设置 - 通过Conversations分享 + 通过 Conversations 分享 开始对话 选择联系人 选择联系人 @@ -34,9 +34,9 @@ 发送中… 正在解密信息。请稍候…… - OpenPGP加密的信息 + OpenPGP 加密的信息 用户名已存在 - 无效用户名 + 无效的用户名 管理员 所有者 群主 @@ -980,7 +980,7 @@ 不支持注册账户 未找到 XMPP 地址 临时认证失败 - 删除群聊 + 删除头像 使用 Tor 时通话被禁用 切换到视频 拒绝切换到视频的请求 From 6bc3cad7de4afb9d1f065411d1d8681012a463a2 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 4 Oct 2023 10:43:27 +0200 Subject: [PATCH 119/402] apply ice-options when adding content or restarting ice --- .../xmpp/jingle/RtpContentMap.java | 13 +++++---- .../jingle/stanzas/IceUdpTransportInfo.java | 27 +++++++++++++------ 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpContentMap.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpContentMap.java index 994c3a233..08671ae03 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpContentMap.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpContentMap.java @@ -210,6 +210,12 @@ public class RtpContentMap { throw new IllegalStateException("Content map does not have distinct credentials"); } + private Set getCombinedIceOptions() { + final Collection> combinedIceOptions = + Collections2.transform(contents.values(), dt -> dt.transport.getIceOptions()); + return ImmutableSet.copyOf(Iterables.concat(combinedIceOptions)); + } + public Set getCredentials() { final Set credentials = ImmutableSet.copyOf( @@ -339,14 +345,11 @@ public class RtpContentMap { public RtpContentMap addContent( final RtpContentMap modification, final IceUdpTransportInfo.Setup setup) { final IceUdpTransportInfo.Credentials credentials = getDistinctCredentials(); + final Collection iceOptions = getCombinedIceOptions(); final DTLS dtls = getDistinctDtls(); final IceUdpTransportInfo iceUdpTransportInfo = - IceUdpTransportInfo.of(credentials, setup, dtls.hash, dtls.fingerprint); + IceUdpTransportInfo.of(credentials, iceOptions, setup, dtls.hash, dtls.fingerprint); final Map combined = merge(contents, modification.contents); - /*new ImmutableMap.Builder() - .putAll(contents) - .putAll(modification.contents) - .build();*/ final Map combinedFixedTransport = Maps.transformValues( combined, diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/IceUdpTransportInfo.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/IceUdpTransportInfo.java index bd7e44501..35251f929 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/IceUdpTransportInfo.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/IceUdpTransportInfo.java @@ -15,6 +15,11 @@ import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; +import eu.siacs.conversations.Config; +import eu.siacs.conversations.xml.Element; +import eu.siacs.conversations.xml.Namespace; +import eu.siacs.conversations.xmpp.jingle.SessionDescription; + import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -26,11 +31,6 @@ import java.util.Locale; import java.util.Map; import java.util.UUID; -import eu.siacs.conversations.Config; -import eu.siacs.conversations.xml.Element; -import eu.siacs.conversations.xml.Namespace; -import eu.siacs.conversations.xmpp.jingle.SessionDescription; - public class IceUdpTransportInfo extends GenericTransportInfo { public static final IceUdpTransportInfo STUB = new IceUdpTransportInfo(); @@ -73,11 +73,18 @@ public class IceUdpTransportInfo extends GenericTransportInfo { } public static IceUdpTransportInfo of( - final Credentials credentials, final Setup setup, final String hash, final String fingerprint) { + final Credentials credentials, + final Collection iceOptions, + final Setup setup, + final String hash, + final String fingerprint) { final IceUdpTransportInfo iceUdpTransportInfo = new IceUdpTransportInfo(); iceUdpTransportInfo.addChild(Fingerprint.of(setup, hash, fingerprint)); iceUdpTransportInfo.setAttribute("ufrag", credentials.ufrag); iceUdpTransportInfo.setAttribute("pwd", credentials.password); + for(final String iceOption : iceOptions) { + iceUdpTransportInfo.addChild(new IceOption(iceOption)); + } return iceUdpTransportInfo; } @@ -88,8 +95,9 @@ public class IceUdpTransportInfo extends GenericTransportInfo { public List getIceOptions() { final ImmutableList.Builder optionBuilder = new ImmutableList.Builder<>(); - for(final Element child : this.children) { - if (Namespace.JINGLE_TRANSPORT_ICE_OPTION.equals(child.getNamespace()) && IceOption.WELL_KNOWN.contains(child.getName())) { + for (final Element child : this.children) { + if (Namespace.JINGLE_TRANSPORT_ICE_OPTION.equals(child.getNamespace()) + && IceOption.WELL_KNOWN.contains(child.getName())) { optionBuilder.add(child.getName()); } } @@ -132,6 +140,9 @@ public class IceUdpTransportInfo extends GenericTransportInfo { transportInfo.addChild(fingerprint); } } + for (final String iceOption : this.getIceOptions()) { + transportInfo.addChild(new IceOption(iceOption)); + } return transportInfo; } From 1b5d2151d017c9d8ab7f061a14493d373b9a1524 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 4 Oct 2023 13:07:06 +0200 Subject: [PATCH 120/402] warn early when SDP is likely to be invalid --- .../xmpp/jingle/SessionDescription.java | 51 +++++++++++++++---- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/SessionDescription.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/SessionDescription.java index b9d99fe6e..2d2dc9570 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/SessionDescription.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/SessionDescription.java @@ -176,8 +176,15 @@ public class SessionDescription { mediaAttributes.put("ice-options", Joiner.on(' ').join(iceOptions)); final IceUdpTransportInfo.Fingerprint fingerprint = transport.getFingerprint(); if (fingerprint != null) { - mediaAttributes.put( - "fingerprint", fingerprint.getHash() + " " + fingerprint.getContent()); + final String hashFunction = fingerprint.getHash(); + final String hash = fingerprint.getContent(); + if (Strings.isNullOrEmpty(hashFunction) || Strings.isNullOrEmpty(hash)) { + throw new IllegalArgumentException("DTLS-SRTP missing hash"); + } + checkNoWhitespace( + hashFunction, "DTLS-SRTP hash function must not contain whitespace"); + checkNoWhitespace(hash, "DTLS-SRTP hash must not contain whitespace"); + mediaAttributes.put("fingerprint", hashFunction + " " + hash); final IceUdpTransportInfo.Setup setup = fingerprint.getSetup(); if (setup != null) { mediaAttributes.put("setup", setup.toString().toLowerCase(Locale.ROOT)); @@ -214,12 +221,14 @@ public class SessionDescription { } checkNoWhitespace( type, "feedback negotiation type must not contain whitespace"); - mediaAttributes.put( - "rtcp-fb", - id - + " " - + type - + (Strings.isNullOrEmpty(subtype) ? "" : " " + subtype)); + if (Strings.isNullOrEmpty(subtype)) { + mediaAttributes.put("rtcp-fb", id + " " + type); + } else { + checkNoWhitespace( + subtype, + "feedback negotiation subtype must not contain whitespace"); + mediaAttributes.put("rtcp-fb", id + " " + type + " " + subtype); + } } for (RtpDescription.FeedbackNegotiationTrrInt feedbackNegotiationTrrInt : payloadType.feedbackNegotiationTrrInts()) { @@ -236,9 +245,13 @@ public class SessionDescription { throw new IllegalArgumentException("a feedback negotiation is missing type"); } checkNoWhitespace(type, "feedback negotiation type must not contain whitespace"); - mediaAttributes.put( - "rtcp-fb", - "* " + type + (Strings.isNullOrEmpty(subtype) ? "" : " " + subtype)); + if (Strings.isNullOrEmpty(subtype)) { + mediaAttributes.put("rtcp-fb", "* " + type); + } else { + checkNoWhitespace( + subtype, "feedback negotiation subtype must not contain whitespace"); + mediaAttributes.put("rtcp-fb", "* " + type + " " + subtype); /**/ + } } for (final RtpDescription.FeedbackNegotiationTrrInt feedbackNegotiationTrrInt : description.feedbackNegotiationTrrInts()) { @@ -275,6 +288,9 @@ public class SessionDescription { if (groups.size() == 0) { throw new IllegalArgumentException("A SSRC group is missing SSRC ids"); } + for (final String source : groups) { + checkNoWhitespace(source, "Sources must not contain whitespace"); + } mediaAttributes.put( "ssrc-group", String.format("%s %s", semantics, Joiner.on(' ').join(groups))); @@ -298,6 +314,12 @@ public class SessionDescription { throw new IllegalArgumentException( "A source specific media attribute is missing its value"); } + checkNoWhitespace( + parameterName, + "A source specific media attribute name not not contain whitespace"); + checkNoNewline( + parameterValue, + "A source specific media attribute value must not contain new lines"); mediaAttributes.put( "ssrc", id + " " + parameterName + ":" + parameterValue.trim()); } @@ -338,6 +360,13 @@ public class SessionDescription { return input; } + public static String checkNoNewline(final String input, final String message) { + if (CharMatcher.anyOf("\r\n").matchesAnyOf(message)) { + throw new IllegalArgumentException(message); + } + return input; + } + public static int ignorantIntParser(final String input) { try { return Integer.parseInt(input); From a8241c72df7cb6e5cff28e4b63d40b053659be09 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 4 Oct 2023 13:30:39 +0200 Subject: [PATCH 121/402] use url safe jingle session ids Movim does not like slashes (/) in jingle session ids. When proposing a session called 'wBKabx1kRIfkgNxAShip/w' Movim will accept (proceed) a session called 'wBKabx1kRIfkgNxAShip' which the initiator of course does not know about. (Conversations will get stuck at ringing/discovering devices) This is likely because a click on 'Reply' (accept call) in Movim opens upa pop up window where both the full jid as well as the session id are transmitted as part of the URL. (Full jids can contain more than on slash btw) --- .../conversations/xmpp/jingle/JingleConnectionManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java index 77737e5ae..1872f6b32 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java @@ -73,7 +73,7 @@ public class JingleConnectionManager extends AbstractConnectionManager { static String nextRandomId() { final byte[] id = new byte[16]; new SecureRandom().nextBytes(id); - return Base64.encodeToString(id, Base64.NO_WRAP | Base64.NO_PADDING); + return Base64.encodeToString(id, Base64.NO_WRAP | Base64.NO_PADDING | Base64.URL_SAFE); } public void deliverPacket(final Account account, final JinglePacket packet) { From 601a8cb3bcc15d15fdcc7dde387394848fa6e180 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 5 Oct 2023 16:23:43 +0200 Subject: [PATCH 122/402] process content-modify for pending content-adds --- .../xmpp/jingle/JingleRtpConnection.java | 29 +++++- .../xmpp/jingle/RtpContentMap.java | 99 ++++++++++++++++--- .../jingle/stanzas/IceUdpTransportInfo.java | 4 + 3 files changed, 116 insertions(+), 16 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java index 766482899..2995c41ad 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java @@ -503,6 +503,7 @@ public class JingleRtpConnection extends AbstractJingleConnection sendSessionTerminate(Reason.FAILED_APPLICATION, cause.getMessage()); return; } + processCandidates(receivedContentAccept.contents.entrySet()); updateEndUserState(); Log.d( Config.LOGTAG, @@ -516,7 +517,31 @@ public class JingleRtpConnection extends AbstractJingleConnection Maps.transformEntries( jinglePacket.getJingleContents(), (key, value) -> value.getSenders()); respondOk(jinglePacket); + final RtpContentMap currentOutgoing = this.outgoingContentAdd; + final Set currentOutgoingMediaIds = currentOutgoing == null ? Collections.emptySet() : currentOutgoing.contents.keySet(); Log.d(Config.LOGTAG, "receiveContentModification(" + modification + ")"); + if (currentOutgoing != null && currentOutgoingMediaIds.containsAll(modification.keySet())) { + final boolean isInitiator = isInitiator(); + final RtpContentMap modifiedContentMap; + try { + modifiedContentMap = currentOutgoing.modifiedSendersChecked(isInitiator, modification); + } catch (final IllegalArgumentException e) { + webRTCWrapper.close(); + sendSessionTerminate(Reason.FAILED_APPLICATION, e.getMessage()); + return; + } + this.outgoingContentAdd = modifiedContentMap; + Log.d(Config.LOGTAG, id.account.getJid().asBareJid()+": processed content-modification for pending content-add"); + } else { + webRTCWrapper.close(); + sendSessionTerminate( + Reason.FAILED_APPLICATION, + String.format( + "%s only supports %s as a means to modify a not yet accepted %s", + BuildConfig.APP_NAME, + JinglePacket.Action.CONTENT_MODIFY, + JinglePacket.Action.CONTENT_ADD)); + } } private void receiveContentReject(final JinglePacket jinglePacket) { @@ -613,7 +638,7 @@ public class JingleRtpConnection extends AbstractJingleConnection "%s only supports %s as a means to retract a not yet accepted %s", BuildConfig.APP_NAME, JinglePacket.Action.CONTENT_REMOVE, - JinglePacket.Action.CONTENT_ACCEPT)); + JinglePacket.Action.CONTENT_ADD)); } } @@ -796,6 +821,8 @@ public class JingleRtpConnection extends AbstractJingleConnection // ICE-restart // and if that's the case we are seeing an answer. // This might be more spec compliant but also more error prone potentially + final boolean isSignalStateStable = this.webRTCWrapper.getSignalingState() == PeerConnection.SignalingState.STABLE; + // TODO a stable signal state can be another indicator that we have an offer to restart ICE final boolean isOffer = rtpContentMap.emptyCandidates(); final RtpContentMap restartContentMap; try { diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpContentMap.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpContentMap.java index 08671ae03..45effba4d 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpContentMap.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpContentMap.java @@ -13,14 +13,6 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.common.collect.Sets; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.annotation.Nonnull; - import eu.siacs.conversations.xmpp.jingle.stanzas.Content; import eu.siacs.conversations.xmpp.jingle.stanzas.GenericDescription; import eu.siacs.conversations.xmpp.jingle.stanzas.GenericTransportInfo; @@ -30,6 +22,14 @@ import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket; import eu.siacs.conversations.xmpp.jingle.stanzas.OmemoVerifiedIceUdpTransportInfo; import eu.siacs.conversations.xmpp.jingle.stanzas.RtpDescription; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.annotation.Nonnull; + public class RtpContentMap { public final Group group; @@ -94,7 +94,7 @@ public class RtpContentMap { } public Set getSenders() { - return ImmutableSet.copyOf(Collections2.transform(contents.values(),dt -> dt.senders)); + return ImmutableSet.copyOf(Collections2.transform(contents.values(), dt -> dt.senders)); } public List getNames() { @@ -300,6 +300,57 @@ public class RtpContentMap { dt -> new DescriptionTransport(senders, dt.description, dt.transport))); } + public RtpContentMap modifiedSendersChecked( + final boolean isInitiator, final Map modification) { + final ImmutableMap.Builder contentMapBuilder = + new ImmutableMap.Builder<>(); + for (final Map.Entry content : contents.entrySet()) { + final String id = content.getKey(); + final DescriptionTransport descriptionTransport = content.getValue(); + final Content.Senders currentSenders = descriptionTransport.senders; + final Content.Senders targetSenders = modification.get(id); + if (targetSenders == null || currentSenders == targetSenders) { + contentMapBuilder.put(id, descriptionTransport); + } else { + checkSenderModification(isInitiator, currentSenders, targetSenders); + contentMapBuilder.put( + id, + new DescriptionTransport( + targetSenders, + descriptionTransport.description, + descriptionTransport.transport)); + } + } + return new RtpContentMap(this.group, contentMapBuilder.build()); + } + + private static void checkSenderModification( + final boolean isInitiator, + final Content.Senders current, + final Content.Senders target) { + if (isInitiator) { + // we were both sending and now other party only wants to receive + if (current == Content.Senders.BOTH && target == Content.Senders.INITIATOR) { + return; + } + // only we were sending but now other party wants to send too + if (current == Content.Senders.INITIATOR && target == Content.Senders.BOTH) { + return; + } + } else { + // we were both sending and now other party only wants to receive + if (current == Content.Senders.BOTH && target == Content.Senders.RESPONDER) { + return; + } + // only we were sending but now other party wants to send too + if (current == Content.Senders.RESPONDER && target == Content.Senders.BOTH) { + return; + } + } + throw new IllegalArgumentException( + String.format("Unsupported senders modification %s -> %s", current, target)); + } + public RtpContentMap toContentModification(final Collection modifications) { return new RtpContentMap( this.group, @@ -323,7 +374,8 @@ public class RtpContentMap { } public RtpContentMap activeContents() { - return new RtpContentMap(group, Maps.filterValues(this.contents, dt -> dt.senders != Content.Senders.NONE)); + return new RtpContentMap( + group, Maps.filterValues(this.contents, dt -> dt.senders != Content.Senders.NONE)); } public Diff diff(final RtpContentMap rtpContentMap) { @@ -347,15 +399,32 @@ public class RtpContentMap { final IceUdpTransportInfo.Credentials credentials = getDistinctCredentials(); final Collection iceOptions = getCombinedIceOptions(); final DTLS dtls = getDistinctDtls(); - final IceUdpTransportInfo iceUdpTransportInfo = - IceUdpTransportInfo.of(credentials, iceOptions, setup, dtls.hash, dtls.fingerprint); final Map combined = merge(contents, modification.contents); final Map combinedFixedTransport = Maps.transformValues( combined, - dt -> - new DescriptionTransport( - dt.senders, dt.description, iceUdpTransportInfo)); + dt -> { + final IceUdpTransportInfo iceUdpTransportInfo; + if (dt.transport.emptyCredentials()) { + iceUdpTransportInfo = + IceUdpTransportInfo.of( + credentials, + iceOptions, + setup, + dtls.hash, + dtls.fingerprint); + } else { + iceUdpTransportInfo = + IceUdpTransportInfo.of( + dt.transport.getCredentials(), + iceOptions, + setup, + dtls.hash, + dtls.fingerprint); + } + return new DescriptionTransport( + dt.senders, dt.description, iceUdpTransportInfo); + }); return new RtpContentMap(modification.group, combinedFixedTransport); } diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/IceUdpTransportInfo.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/IceUdpTransportInfo.java index 35251f929..a30e2ff91 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/IceUdpTransportInfo.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/IceUdpTransportInfo.java @@ -110,6 +110,10 @@ public class IceUdpTransportInfo extends GenericTransportInfo { return new Credentials(ufrag, password); } + public boolean emptyCredentials() { + return Strings.isNullOrEmpty(this.getAttribute("ufrag")) || Strings.isNullOrEmpty(this.getAttribute("pwd")); + } + public List getCandidates() { final ImmutableList.Builder builder = new ImmutableList.Builder<>(); for (final Element child : getChildren()) { From 9ecfb7a7650018323716733e15cb81d0c65868b7 Mon Sep 17 00:00:00 2001 From: licaon-kter Date: Wed, 4 Oct 2023 08:04:50 +0000 Subject: [PATCH 123/402] Translated using Weblate (Romanian) Currently translated at 100.0% (2 of 2 strings) Translation: Conversations/App Store Metadata (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata-conversations/ro/ --- .../metadata/android/ro/full_description.txt | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/conversations/fastlane/metadata/android/ro/full_description.txt diff --git a/src/conversations/fastlane/metadata/android/ro/full_description.txt b/src/conversations/fastlane/metadata/android/ro/full_description.txt new file mode 100644 index 000000000..2d4ae419d --- /dev/null +++ b/src/conversations/fastlane/metadata/android/ro/full_description.txt @@ -0,0 +1,38 @@ +Ușor de utilizat, fiabil, prietenos cu bateria. Cu suport încorporat pentru imagini, discuții de grup și criptare E2E. + +Principii de proiectare: + +* Să fie cât mai frumos și mai ușor de utilizat posibil, fără a sacrifica securitatea sau confidențialitatea. +* Să se bazeze pe protocoale existente și bine stabilite +* Nu necesită un cont Google sau în mod specific Google Cloud Messaging (GCM). +* Să necesite cât mai puține permisiuni posibil + +Caracteristici: + +* Criptare de la un capăt-la-altul (E2E) cu OMEMO sau OpenPGP +* Trimiterea și primirea de imagini +* Apeluri audio și video criptate (DTLS-SRTP) +* Interfață intuitivă care respectă liniile directoare Android Design +* Imagini / Avataruri pentru contactele dvs. +* Se sincronizează cu clientul desktop +* Conferințe (cu suport pentru marcaje) +* Integrare cu lista de contacte +* Conturi multiple / căsuță de mesaje unificată +* Impact foarte redus asupra duratei de viață a bateriei + +Conversations face foarte ușoară crearea unui cont pe serverul gratuit conversations.im. Cu toate acestea, Conversations va funcționa și cu orice alt server XMPP. O mulțime de servere XMPP sunt administrate de voluntari și sunt gratuite. + +Caracteristici XMPP: + +Conversations funcționează cu orice server XMPP existent. Cu toate acestea, XMPP este un protocol extensibil. Aceste extensii sunt, de asemenea, standardizate în așa-numitele XEP-uri. Conversations suportă câteva dintre acestea pentru a îmbunătăți experiența generală a utilizatorului. Există o șansă ca serverul XMPP actual să nu suporte aceste extensii. Prin urmare, pentru a profita la maximum de Conversations, ar trebui să luați în considerare fie trecerea la un server XMPP care să suporte aceste extensii, fie - și mai bine - să rulați propriul server XMPP pentru dumneavoastră și prietenii dumneavoastră. + +Aceste XEP-uri sunt - deocamdată: +* XEP-0065: SOCKS5 Bytestreams (sau mod_proxy65). Va fi utilizat pentru a transfera fișiere dacă ambele părți se află în spatele unui firewall (NAT). +* XEP-0163: Protocol de evenimente personale pentru avatare. +* XEP-0191: Comanda de blocare vă permite să puneți pe lista neagră spamerii sau să blocați contactele fără a le elimina din listă. +* XEP-0198: Stream Management permite XMPP să supraviețuiască unor mici întreruperi de rețea și schimbărilor conexiunii TCP de bază. +* XEP-0280: Message Carbons, care sincronizează automat mesajele pe care le trimiteți în clientul desktop și vă permite astfel să treceți fără probleme de la clientul mobil la clientul desktop și înapoi în cadrul unei singure conversații. +* XEP-0237: Roster Versioning în principal pentru a economisi lățimea de bandă în cazul conexiunilor mobile slabe +* XEP-0313: Gestionarea arhivei de mesaje sincronizează istoricul mesajelor cu serverul. Recuperați mesajele care au fost trimise în timp ce Conversations era deconectat. +* XEP-0352: Client State Indication permite serverului să știe dacă Conversations este sau nu în fundal. Permite serverului să economisească lățimea de bandă prin reținerea pachetelor neimportante. +* XEP-0363: HTTP File Upload vă permite să partajați fișiere în cadrul conferințelor și cu contactele deconectate. Necesită o componentă suplimentară pe serverul dumneavoastră. From 8a1aa41263c685ef28825fe4afa6a6478ceceb6c Mon Sep 17 00:00:00 2001 From: licaon-kter Date: Wed, 4 Oct 2023 07:47:47 +0000 Subject: [PATCH 124/402] Translated using Weblate (Romanian) Currently translated at 100.0% (2 of 2 strings) Translation: Conversations/App Store Metadata (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata-quicksy/ro/ --- .../metadata/android/ro/full_description.txt | 14 ++++++++++++++ .../metadata/android/ro/short_description.txt | 1 + 2 files changed, 15 insertions(+) create mode 100644 src/quicksy/fastlane/metadata/android/ro/full_description.txt create mode 100644 src/quicksy/fastlane/metadata/android/ro/short_description.txt diff --git a/src/quicksy/fastlane/metadata/android/ro/full_description.txt b/src/quicksy/fastlane/metadata/android/ro/full_description.txt new file mode 100644 index 000000000..922dcce2a --- /dev/null +++ b/src/quicksy/fastlane/metadata/android/ro/full_description.txt @@ -0,0 +1,14 @@ +Quicksy este un derivat al popularului client Jabber/XMPP Conversations cu descoperire automată a contactelor. + +Vă înscrieți cu numărul de telefon, iar Quicksy vă va sugera automat, pe baza numerelor de telefon din agenda dvs., posibile contacte. + +Sub capota Quicksy este un client Jabber complet care vă permite să comunicați cu orice utilizator de pe orice server public federat. De asemenea, utilizatorii de pe Quicksy pot fi contactați din exterior prin simpla adăugare a +numărdetelefon@quicksy.im la lista dvs. de contacte. + +În afară de sincronizarea contactelor, interfața utilizatorului este în mod deliberat cât mai apropiată de Conversations. Acest lucru permite utilizatorilor să migreze în cele din urmă de la Quicksy la Conversations fără a fi nevoiți să învețe din nou cum funcționează aplicația. + +Contactele sugerate constau din alți utilizatori Quicksy și utilizatori obișnuiți de Jabber/XMPP care și-au introdus adresa XMPP în Directorul Quicksy (https://quicksy.im/#get-listed). + +NOTĂ: Pentru a vă introduce (https://quicksy.im/enter/) adresa XMPP în Directorul +Quicksy este necesară o taxă de înregistrare unică. + +Citiți Politica de confidențialitate (https://quicksy.im/#privacy) pentru mai multe informații. diff --git a/src/quicksy/fastlane/metadata/android/ro/short_description.txt b/src/quicksy/fastlane/metadata/android/ro/short_description.txt new file mode 100644 index 000000000..599b73161 --- /dev/null +++ b/src/quicksy/fastlane/metadata/android/ro/short_description.txt @@ -0,0 +1 @@ +Jabber/XMPP cu acces și descoperire facilă From 6f0ff17665c18089b8e966413ca28c47771010ea Mon Sep 17 00:00:00 2001 From: nautilusx Date: Wed, 4 Oct 2023 15:32:26 +0000 Subject: [PATCH 125/402] Translated using Weblate (German) Currently translated at 100.0% (2 of 2 strings) Translation: Conversations/App Store Metadata (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata-quicksy/de/ --- .../metadata/android/de-DE/full_description.txt | 14 ++++++++++++++ .../metadata/android/de-DE/short_description.txt | 1 + 2 files changed, 15 insertions(+) create mode 100644 src/quicksy/fastlane/metadata/android/de-DE/full_description.txt create mode 100644 src/quicksy/fastlane/metadata/android/de-DE/short_description.txt diff --git a/src/quicksy/fastlane/metadata/android/de-DE/full_description.txt b/src/quicksy/fastlane/metadata/android/de-DE/full_description.txt new file mode 100644 index 000000000..bad1226e1 --- /dev/null +++ b/src/quicksy/fastlane/metadata/android/de-DE/full_description.txt @@ -0,0 +1,14 @@ +Quicksy ist ein Ableger des beliebten Jabber/XMPP-Clients Conversations mit automatischer Kontaktsuche. + +Du meldest dich mit deiner Telefonnummer an und Quicksy schlägt dir automatisch — basierend auf den Telefonnummern in deinem Adressbuch — mögliche Kontakte vor. + +Unter der Oberfläche ist Quicksy ein vollwertiger Jabber-Client, mit dem du mit jedem Benutzer auf jedem öffentlich zugänglichen Server kommunizieren kannst. Ebenso können Benutzer auf Quicksy von außen kontaktiert werden, indem du einfach +telefonnummer@quicksy.im zu deiner Kontaktliste hinzufügst. + +Abgesehen von der Kontaktsynchronisation ist die Benutzeroberfläche bewusst so nah wie möglich an Conversations gehalten. Dies ermöglicht es den Nutzern, von Quicksy zu Conversations zu wechseln, ohne die Funktionsweise der App neu erlernen zu müssen. + +Die vorgeschlagenen Kontakte bestehen aus anderen Quicksy-Benutzern und normalen Jabber/XMPP-Benutzern, die ihre Jabber-ID in das Quicksy-Verzeichnis (https://quicksy.im/#get-listed) eingegeben haben. + +HINWEIS: Für den Eintrag (https://quicksy.im/enter/) deiner Jabber-ID in das Quicksy- +Verzeichnis einzutragen, ist eine einmalige Registrierungsgebühr erforderlich. + +Lies die Datenschutzrichtlinien (https://quicksy.im/#privacy) für weitere Informationen. diff --git a/src/quicksy/fastlane/metadata/android/de-DE/short_description.txt b/src/quicksy/fastlane/metadata/android/de-DE/short_description.txt new file mode 100644 index 000000000..cc3737ee7 --- /dev/null +++ b/src/quicksy/fastlane/metadata/android/de-DE/short_description.txt @@ -0,0 +1 @@ +Jabber/XMPP mit einfacher Anmeldung und leichter Erkennung From d9c9baf516f74658b761fb41d4b5d919a3a72e85 Mon Sep 17 00:00:00 2001 From: ghose Date: Thu, 5 Oct 2023 03:32:03 +0000 Subject: [PATCH 126/402] Translated using Weblate (Galician) Currently translated at 50.0% (1 of 2 strings) Translation: Conversations/App Store Metadata (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata-quicksy/gl/ --- .../fastlane/metadata/android/gl-ES/short_description.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/quicksy/fastlane/metadata/android/gl-ES/short_description.txt diff --git a/src/quicksy/fastlane/metadata/android/gl-ES/short_description.txt b/src/quicksy/fastlane/metadata/android/gl-ES/short_description.txt new file mode 100644 index 000000000..6367e2079 --- /dev/null +++ b/src/quicksy/fastlane/metadata/android/gl-ES/short_description.txt @@ -0,0 +1 @@ +Jabber/XMPP fácil de Usar e Atopar aos teus Contactos From 95aea4291e2690f9e39c75eaf7cddbd0cbbc0ffd Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 5 Oct 2023 20:28:47 +0200 Subject: [PATCH 127/402] don't attempt to figure out file path on Android 11+ fixes #117 --- .../eu/siacs/conversations/persistance/FileBackend.java | 9 +++++++-- .../java/eu/siacs/conversations/utils/FileUtils.java | 4 +--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java index 3c193219e..d8050646a 100644 --- a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java @@ -648,8 +648,13 @@ public class FileBackend { } } - public String getOriginalPath(Uri uri) { - return FileUtils.getPath(mXmppConnectionService, uri); + public String getOriginalPath(final Uri uri) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + // On Android 11+ we don’t have access to the original file + return null; + } else { + return FileUtils.getPath(mXmppConnectionService, uri); + } } private void copyFileToPrivateStorage(File file, Uri uri) throws FileCopyException { diff --git a/src/main/java/eu/siacs/conversations/utils/FileUtils.java b/src/main/java/eu/siacs/conversations/utils/FileUtils.java index 43e3da118..e439ab030 100644 --- a/src/main/java/eu/siacs/conversations/utils/FileUtils.java +++ b/src/main/java/eu/siacs/conversations/utils/FileUtils.java @@ -34,10 +34,8 @@ public class FileUtils { return null; } - final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; - // DocumentProvider - if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { + if (DocumentsContract.isDocumentUri(context, uri)) { // ExternalStorageProvider if (isExternalStorageDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); From 541c8ba80d35f60500ff82d4cdd7ba1ccca45660 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 6 Oct 2023 12:34:07 +0200 Subject: [PATCH 128/402] modify mime type detection for shared files add support for audiobooks --- .../ui/adapter/MediaAdapter.java | 2 + .../ui/adapter/MediaPreviewAdapter.java | 2 +- .../siacs/conversations/utils/MimeUtils.java | 79 +++++++++++-------- .../siacs/conversations/utils/UIHelper.java | 2 + .../res/drawable/ic_play_lesson_black_24.xml | 6 ++ .../drawable/ic_play_lesson_white_48dp.xml | 6 ++ src/main/res/values/attrs.xml | 1 + src/main/res/values/strings.xml | 1 + src/main/res/values/themes.xml | 2 + 9 files changed, 66 insertions(+), 35 deletions(-) create mode 100644 src/main/res/drawable/ic_play_lesson_black_24.xml create mode 100644 src/main/res/drawable/ic_play_lesson_white_48dp.xml diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MediaAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MediaAdapter.java index 2733e7b8b..2683876c7 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MediaAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MediaAdapter.java @@ -74,6 +74,8 @@ public class MediaAdapter extends RecyclerView.Adapter PATH_PRECEDENCE_MIME_TYPE = Arrays.asList("audio/x-m4b"); + private static void add(String mimeType, String extension) { // If we have an existing x -> y mapping, we do not want to // override it with another mapping x -> y2. @@ -537,44 +543,49 @@ public final class MimeUtils { } public static String guessMimeTypeFromUriAndMime(final Context context, final Uri uri, final String mime) { - Log.d(Config.LOGTAG, "guessMimeTypeFromUriAndMime " + uri + " and mime=" + mime); - if (mime == null || mime.equals("application/octet-stream")) { - final String guess = guessMimeTypeFromUri(context, uri); - if (guess != null) { - return guess; - } else { - return mime; - } + Log.d(Config.LOGTAG, "guessMimeTypeFromUriAndMime(" + uri + "," + mime+")"); + final String mimeFromUri = guessMimeTypeFromUri(context, uri); + Log.d(Config.LOGTAG,"mimeFromUri:"+mimeFromUri); + if (PATH_PRECEDENCE_MIME_TYPE.contains(mimeFromUri)) { + return mimeFromUri; + } else if (mime == null || mime.equals("application/octet-stream")) { + return mimeFromUri; + } else { + return mime; } - return guessMimeTypeFromUri(context, uri); } - public static String guessMimeTypeFromUri(Context context, Uri uri) { - // try the content resolver - String mimeType; + public static String guessMimeTypeFromUri(final Context context, final Uri uri) { + final String mimeTypeContentResolver = guessFromContentResolver(context, uri); + final String mimeTypeFromQueryParameter = uri.getQueryParameter("mimeType"); + final String name = "content".equals(uri.getScheme()) ? getDisplayName(context, uri) : null; + final String mimeTypeFromName = Strings.isNullOrEmpty(name) ? null : guessFromPath(name); + final String path = uri.getPath(); + final String mimeTypeFromPath = Strings.isNullOrEmpty(path) ? null : guessFromPath(path); + if (PATH_PRECEDENCE_MIME_TYPE.contains(mimeTypeFromName)) { + return mimeTypeFromName; + } + if (PATH_PRECEDENCE_MIME_TYPE.contains(mimeTypeFromPath)) { + return mimeTypeFromPath; + } + if (mimeTypeContentResolver != null && !"application/octet-stream".equals(mimeTypeContentResolver)) { + return mimeTypeContentResolver; + } + if (mimeTypeFromName != null) { + return mimeTypeFromName; + } + if (mimeTypeFromQueryParameter != null) { + return mimeTypeFromQueryParameter; + } + return mimeTypeFromPath; + } + + private static String guessFromContentResolver(final Context context, final Uri uri) { try { - mimeType = context.getContentResolver().getType(uri); - } catch (final Throwable throwable) { - mimeType = null; + return context.getContentResolver().getType(uri); + } catch (final Throwable e) { + return null; } - // try the extension - if (mimeType == null || mimeType.equals("application/octet-stream")) { - final String path = uri.getPath(); - if (path != null) { - mimeType = guessFromPath(path); - } - } - if (mimeType == null && "content".equals(uri.getScheme())) { - final String name = getDisplayName(context, uri); - if (name != null) { - mimeType = guessFromPath(name); - } - } - // sometimes this works (as with the commit content api) - if (mimeType == null) { - mimeType = uri.getQueryParameter("mimeType"); - } - return mimeType; } private static String getDisplayName(final Context context, final Uri uri) { diff --git a/src/main/java/eu/siacs/conversations/utils/UIHelper.java b/src/main/java/eu/siacs/conversations/utils/UIHelper.java index b70bfc558..da72ba9bd 100644 --- a/src/main/java/eu/siacs/conversations/utils/UIHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/UIHelper.java @@ -481,6 +481,8 @@ public class UIHelper { return context.getString(R.string.file); } else if (MimeUtils.AMBIGUOUS_CONTAINER_FORMATS.contains(mime)) { return context.getString(R.string.multimedia_file); + } else if (mime.equals("audio/x-m4b")) { + return context.getString(R.string.audiobook); } else if (mime.startsWith("audio/")) { return context.getString(R.string.audio); } else if (mime.startsWith("video/")) { diff --git a/src/main/res/drawable/ic_play_lesson_black_24.xml b/src/main/res/drawable/ic_play_lesson_black_24.xml new file mode 100644 index 000000000..4c4a46ce7 --- /dev/null +++ b/src/main/res/drawable/ic_play_lesson_black_24.xml @@ -0,0 +1,6 @@ + + + + diff --git a/src/main/res/drawable/ic_play_lesson_white_48dp.xml b/src/main/res/drawable/ic_play_lesson_white_48dp.xml new file mode 100644 index 000000000..67fe7c696 --- /dev/null +++ b/src/main/res/drawable/ic_play_lesson_white_48dp.xml @@ -0,0 +1,6 @@ + + + + diff --git a/src/main/res/values/attrs.xml b/src/main/res/values/attrs.xml index 2a9a4a8e6..f66437bf4 100644 --- a/src/main/res/values/attrs.xml +++ b/src/main/res/values/attrs.xml @@ -70,6 +70,7 @@ + diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 84b2cb61e..4981128de 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -420,6 +420,7 @@ multimedia file PDF document Android App + Audiobook Contact Avatar has been published! Sending %s diff --git a/src/main/res/values/themes.xml b/src/main/res/values/themes.xml index 9e757a626..75fd896af 100644 --- a/src/main/res/values/themes.xml +++ b/src/main/res/values/themes.xml @@ -88,6 +88,7 @@ @drawable/baseline_tour_black_48 @drawable/ic_person_black_48dp @drawable/ic_android_black_48dp + @drawable/ic_play_lesson_black_24 @drawable/ic_event_black_48dp @drawable/ic_archive_black_48dp @drawable/ic_book_black_48dp @@ -244,6 +245,7 @@ @drawable/baseline_tour_white_48 @drawable/ic_person_white_48dp @drawable/ic_android_white_48dp + @drawable/ic_play_lesson_white_48dp @drawable/ic_event_white_48dp @drawable/ic_archive_white_48dp @drawable/ic_book_white_48dp From 1c5a1b8c71675cf6c41c153ff35d15db53cbc0af Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 6 Oct 2023 12:34:41 +0200 Subject: [PATCH 129/402] keep order of rtp contents --- .../java/eu/siacs/conversations/xmpp/jingle/RtpContentMap.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpContentMap.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpContentMap.java index 45effba4d..5b940e7b8 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpContentMap.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpContentMap.java @@ -24,6 +24,7 @@ import eu.siacs.conversations.xmpp.jingle.stanzas.RtpDescription; import java.util.Collection; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -430,7 +431,7 @@ public class RtpContentMap { private static Map merge( final Map a, final Map b) { - final Map combined = new HashMap<>(); + final Map combined = new LinkedHashMap<>(); combined.putAll(a); combined.putAll(b); return ImmutableMap.copyOf(combined); From 77631c97a7c1c7d4a3c4deb31dee729b7a9e5a4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne-Br=C3=BCn=20Vogelsang?= Date: Sun, 8 Oct 2023 18:25:20 +0000 Subject: [PATCH 130/402] Update src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java Add Fairphone 4 to AEC Blacklist to fix Echo problems: https://github.com/iNPUTmice/Conversations/issues/4439 --- .../java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java index 8c5d266a5..6e538a7a3 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java @@ -71,6 +71,7 @@ public class WebRTCWrapper { .add("E5823") // Sony z5 compact .add("Redmi Note 5") .add("FP2") // Fairphone FP2 + .add("FP4") //Fairphone FP4 .add("MI 5") .add("GT-I9515") // Samsung Galaxy S4 Value Edition (jfvelte) .add("GT-I9515L") // Samsung Galaxy S4 Value Edition (jfvelte) From 1a7e75235a5f48501d520d5ba3f240060176bab8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne-Br=C3=BCn=20Vogelsang?= Date: Sun, 8 Oct 2023 18:25:47 +0000 Subject: [PATCH 131/402] Update src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java just a space --- .../java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java index 6e538a7a3..5b841b88a 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java @@ -71,7 +71,7 @@ public class WebRTCWrapper { .add("E5823") // Sony z5 compact .add("Redmi Note 5") .add("FP2") // Fairphone FP2 - .add("FP4") //Fairphone FP4 + .add("FP4") // Fairphone FP4 .add("MI 5") .add("GT-I9515") // Samsung Galaxy S4 Value Edition (jfvelte) .add("GT-I9515L") // Samsung Galaxy S4 Value Edition (jfvelte) From 1ef40377ce5a242fa8a75b208db37e0a75abd1bd Mon Sep 17 00:00:00 2001 From: Outbreak2096 <178168oh22hgq6d6unw8k24c5ik4th@yadim.dismail.de> Date: Fri, 6 Oct 2023 00:37:40 +0000 Subject: [PATCH 132/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (968 of 968 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 34 +++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index 79ba09b4e..a941bcf33 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -136,7 +136,7 @@ OpenKeychain报告一个错误。 错误的加密密钥。 接受 - 产生了一个错误 + 出现了一个错误 错误 你的账户 发送在线状态更新 @@ -188,7 +188,7 @@ 你确定删除账户吗?如果您删除账户,您的所有聊天记录将会丢失 录制音频 XMPP地址 - 拦截XMPP地址 + 封禁XMPP地址 username@example.com 密码 这不是有效的XMPP地址 @@ -208,13 +208,13 @@ 有效 无效 缺少公钥 - 刚来过 - 一分钟前来过 - %d分钟来过 - 一小时前来过 - %d小时前来过 - 一天前来过 - %d天前来过 + 最后上线于刚才 + 最后上线于一分钟前 + 最后上线于%d分钟前 + 最后上线于一小时前 + 最后上线于%d小时前 + 最后上线于一天前 + 最后上线于%d天前 加密信息。请安装OpenKeychain以解密。 发现新OpenPGP加密信息 OpenPGP密钥ID @@ -277,7 +277,7 @@ 启用 需要密码才能进入该群聊 输入密码 - 请先请求联系人在线状态更新。 + 请先向您的联系人请求在线状态更新。 \n \n这将被用来判断您的联系人正在使用的聊天应用 现在请求 @@ -298,7 +298,7 @@ 同步书签 加入或离开多用户聊天时设置 “autojoin\" 标志,并回应其他客户端所做更改。 OMEMO指纹已拷贝到剪贴板 - 您被封禁了 + 您被此群聊封禁 这个群聊只允许成员聊天 资源限制 您被从此群聊踢出 @@ -336,7 +336,7 @@ 此备份文件已经存储在%s 正在恢复备份 备份已恢复 - 别忘了启用帐号。 + 别忘了启用账户。 选择文件 正在下载%1$s(已完成%2$d%%) 下载%s @@ -385,11 +385,11 @@ 成员 高级模式 授予成员权限 - 吊销成员权限 + 撤销成员权限 授予管理员权限 - 吊销管理员权限 + 撤销管理员权限 授予所有者权限 - 吊销所有者权限 + 撤销所有者权限 从群聊中移除 从频道中移除 不能修改%s的从属关系 @@ -408,7 +408,7 @@ 无法更改群聊设置 从不 直至另行通知 - 小睡 + 稍后提醒 回复 标记为已读 输入 @@ -554,7 +554,7 @@ 有空聊天 在线 离开 - 没时间 + 不在 忙碌 安全密码已生成 该设备不支持禁用电池优化 From 48bd845323e160f97cfb2e5193d8604e9f41f11f Mon Sep 17 00:00:00 2001 From: SomeTr Date: Fri, 6 Oct 2023 15:18:16 +0000 Subject: [PATCH 133/402] Translated using Weblate (Ukrainian) Currently translated at 100.0% (2 of 2 strings) Translation: Conversations/App Store Metadata (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata-quicksy/uk/ --- .../metadata/android/uk/full_description.txt | 14 ++++++++++++++ .../metadata/android/uk/short_description.txt | 1 + 2 files changed, 15 insertions(+) create mode 100644 src/quicksy/fastlane/metadata/android/uk/full_description.txt create mode 100644 src/quicksy/fastlane/metadata/android/uk/short_description.txt diff --git a/src/quicksy/fastlane/metadata/android/uk/full_description.txt b/src/quicksy/fastlane/metadata/android/uk/full_description.txt new file mode 100644 index 000000000..a95f3e940 --- /dev/null +++ b/src/quicksy/fastlane/metadata/android/uk/full_description.txt @@ -0,0 +1,14 @@ +Quicksy є відгалуженням Conversations — популярного клієнта Jabber/XMPP, з автоматичним пошуком контактів. + +Реєструйтеся за допомогою свого номера телефону, і Quicksy автоматично — за номерами телефонів у Вашій адресній книзі — запропонує Вам можливі контакти. + +Під капотом Quicksy — це повноцінний клієнт Jabber, який дозволяє вам спілкуватися з будь-яким користувачем на будь-якому загальнодоступному сервері. Так само з користувачами Quicksy можна зв’язатися ззовні, просто додавши +phonenumber@quicksy.im до свого списку контактів. + +Окрім синхронізації контактів, інтерфейс користувача навмисно максимально наближений до Conversations. Це дозволяє користувачам зрештою перейти з Quicksy на Conversations без необхідності перевчатися. + +Пропоновані контакти складаються з інших користувачів Quicksy і звичайних користувачів Jabber/XMPP, які ввели свій Jabber ID у каталог Quicksy (https://quicksy.im/#get-listed). + +ПРИМІТКА. Щоб ввести (https://quicksy.im/enter/) свій Jabber ID у каталог Quicksy, +потрібно сплатити одноразовий реєстраційний внесок. + +Для отримання додаткової інформації прочитайте Політику конфіденційності (https://quicksy.im/#privacy). diff --git a/src/quicksy/fastlane/metadata/android/uk/short_description.txt b/src/quicksy/fastlane/metadata/android/uk/short_description.txt new file mode 100644 index 000000000..abd1a47ca --- /dev/null +++ b/src/quicksy/fastlane/metadata/android/uk/short_description.txt @@ -0,0 +1 @@ +Jabber/XMPP із простим входом і легким пошуком From d3d582759f907b5872bfbc2325374d2574019a03 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 9 Oct 2023 13:17:14 +0200 Subject: [PATCH 134/402] support omemo verification in non stub transport content modifications Dino (and this is probably correct behaviour) expects a fingerprint in the content-add message. (and not a stub transport as indicated in the examples). however if we start to include them we also need to encrypt and verify them properly. --- .../xmpp/jingle/JingleRtpConnection.java | 105 ++++++++++++++++-- .../xmpp/jingle/RtpContentMap.java | 41 ++++--- .../jingle/stanzas/IceUdpTransportInfo.java | 8 +- 3 files changed, 126 insertions(+), 28 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java index 2995c41ad..38cba946f 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java @@ -370,6 +370,7 @@ public class JingleRtpConnection extends AbstractJingleConnection } private void receiveContentAdd(final JinglePacket jinglePacket) { + // TODO check if in session accepted final RtpContentMap modification; try { modification = RtpContentMap.of(jinglePacket); @@ -385,7 +386,29 @@ public class JingleRtpConnection extends AbstractJingleConnection return; } if (isInState(State.SESSION_ACCEPTED)) { - receiveContentAdd(jinglePacket, modification); + final boolean hasFullTransportInfo = modification.hasFullTransportInfo(); + final ListenableFuture future = + receiveRtpContentMap( + modification, this.omemoVerification.hasFingerprint() && hasFullTransportInfo); + Futures.addCallback(future, new FutureCallback() { + @Override + public void onSuccess(final RtpContentMap rtpContentMap) { + receiveContentAdd(jinglePacket, rtpContentMap); + } + + @Override + public void onFailure(@NonNull Throwable throwable) { + respondOk(jinglePacket); + final Throwable rootCause = Throwables.getRootCause(throwable); + Log.d( + Config.LOGTAG, + id.account.getJid().asBareJid() + + ": improperly formatted contents in content-add", + throwable); + webRTCWrapper.close(); + sendSessionTerminate(Reason.ofThrowable(rootCause), rootCause.getMessage()); + } + }, MoreExecutors.directExecutor()); } else { terminateWithOutOfOrder(jinglePacket); } @@ -470,7 +493,22 @@ public class JingleRtpConnection extends AbstractJingleConnection if (ourSummary.equals(ContentAddition.summary(receivedContentAccept))) { this.outgoingContentAdd = null; respondOk(jinglePacket); - receiveContentAccept(receivedContentAccept); + final boolean hasFullTransportInfo = receivedContentAccept.hasFullTransportInfo(); + final ListenableFuture future = + receiveRtpContentMap( + receivedContentAccept, this.omemoVerification.hasFingerprint() && hasFullTransportInfo); + Futures.addCallback(future, new FutureCallback() { + @Override + public void onSuccess(final RtpContentMap result) { + receiveContentAccept(result); + } + + @Override + public void onFailure(@NonNull final Throwable throwable) { + webRTCWrapper.close(); + sendSessionTerminate(Reason.ofThrowable(throwable), throwable.getMessage()); + } + }, MoreExecutors.directExecutor()); } else { Log.d(Config.LOGTAG, "received content-accept did not match our outgoing content-add"); terminateWithOutOfOrder(jinglePacket); @@ -759,14 +797,29 @@ public class JingleRtpConnection extends AbstractJingleConnection final RtpContentMap contentAcceptMap = rtpContentMap.toContentModification( Collections2.transform(contentAddition, ca -> ca.name)); + Log.d( Config.LOGTAG, id.getAccount().getJid().asBareJid() + ": sending content-accept " + ContentAddition.summary(contentAcceptMap)); modifyLocalContentMap(rtpContentMap); - sendContentAccept(contentAcceptMap); - this.webRTCWrapper.setIsReadyToReceiveIceCandidates(true); + final ListenableFuture future = prepareOutgoingContentMap(contentAcceptMap); + Futures.addCallback( + future, + new FutureCallback() { + @Override + public void onSuccess(final RtpContentMap rtpContentMap) { + sendContentAccept(rtpContentMap); + webRTCWrapper.setIsReadyToReceiveIceCandidates(true); + } + + @Override + public void onFailure(@NonNull final Throwable throwable) { + failureToPerformAction(JinglePacket.Action.CONTENT_ACCEPT, throwable); + } + }, + MoreExecutors.directExecutor()); } catch (final Exception e) { Log.d(Config.LOGTAG, "unable to accept content add", Throwables.getRootCause(e)); webRTCWrapper.close(); @@ -979,12 +1032,20 @@ public class JingleRtpConnection extends AbstractJingleConnection private ListenableFuture receiveRtpContentMap( final JinglePacket jinglePacket, final boolean expectVerification) { - final RtpContentMap receivedContentMap; try { - receivedContentMap = RtpContentMap.of(jinglePacket); + return receiveRtpContentMap(RtpContentMap.of(jinglePacket), expectVerification); } catch (final Exception e) { return Futures.immediateFailedFuture(e); } + } + private ListenableFuture receiveRtpContentMap(final RtpContentMap receivedContentMap, final boolean expectVerification) { + Log.d( + Config.LOGTAG, + "receiveRtpContentMap(" + + receivedContentMap.getClass().getSimpleName() + + ",expectVerification=" + + expectVerification + + ")"); if (receivedContentMap instanceof OmemoVerifiedRtpContentMap) { final ListenableFuture> future = id.account @@ -1287,6 +1348,16 @@ public class JingleRtpConnection extends AbstractJingleConnection sendSessionTerminate(Reason.ofThrowable(rootCause), rootCause.getMessage()); } + private void failureToPerformAction(final JinglePacket.Action action, final Throwable throwable) { + if (isTerminated()) { + return; + } + final Throwable rootCause = Throwables.getRootCause(throwable); + Log.d(Config.LOGTAG, "unable to send " + action, rootCause); + webRTCWrapper.close(); + sendSessionTerminate(Reason.ofThrowable(rootCause), rootCause.getMessage()); + } + private void addIceCandidatesFromBlackLog() { Map.Entry foo; while ((foo = this.pendingIceCandidates.poll()) != null) { @@ -2486,6 +2557,27 @@ public class JingleRtpConnection extends AbstractJingleConnection private void sendContentAdd(final RtpContentMap rtpContentMap, final Collection added) { final RtpContentMap contentAdd = rtpContentMap.toContentModification(added); this.outgoingContentAdd = contentAdd; + final ListenableFuture outgoingContentMapFuture = + prepareOutgoingContentMap(contentAdd); + Futures.addCallback( + outgoingContentMapFuture, + new FutureCallback() { + @Override + public void onSuccess(final RtpContentMap outgoingContentMap) { + sendContentAdd(outgoingContentMap); + webRTCWrapper.setIsReadyToReceiveIceCandidates(true); + } + + @Override + public void onFailure(@NonNull Throwable throwable) { + failureToPerformAction(JinglePacket.Action.CONTENT_ADD, throwable); + } + }, + MoreExecutors.directExecutor()); + } + + private void sendContentAdd(final RtpContentMap contentAdd) { + final JinglePacket jinglePacket = contentAdd.toJinglePacket(JinglePacket.Action.CONTENT_ADD, id.sessionId); jinglePacket.setTo(id.with); @@ -2512,7 +2604,6 @@ public class JingleRtpConnection extends AbstractJingleConnection handleIqTimeoutResponse(response); } }); - this.webRTCWrapper.setIsReadyToReceiveIceCandidates(true); } private void setLocalContentMap(final RtpContentMap rtpContentMap) { diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpContentMap.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpContentMap.java index 5b940e7b8..5ffd74ee3 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpContentMap.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpContentMap.java @@ -23,7 +23,6 @@ import eu.siacs.conversations.xmpp.jingle.stanzas.OmemoVerifiedIceUdpTransportIn import eu.siacs.conversations.xmpp.jingle.stanzas.RtpDescription; import java.util.Collection; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -275,6 +274,11 @@ public class RtpContentMap { return count == 0; } + public boolean hasFullTransportInfo() { + return Collections2.transform(this.contents.values(), dt -> dt.transport.isStub()) + .contains(false); + } + public RtpContentMap modifiedCredentials( IceUdpTransportInfo.Credentials credentials, final IceUdpTransportInfo.Setup setup) { final ImmutableMap.Builder contentMapBuilder = @@ -354,12 +358,7 @@ public class RtpContentMap { public RtpContentMap toContentModification(final Collection modifications) { return new RtpContentMap( - this.group, - Maps.transformValues( - Maps.filterKeys(contents, Predicates.in(modifications)), - dt -> - new DescriptionTransport( - dt.senders, dt.description, IceUdpTransportInfo.STUB))); + this.group, Maps.filterKeys(contents, Predicates.in(modifications))); } public RtpContentMap toStub() { @@ -396,37 +395,43 @@ public class RtpContentMap { } public RtpContentMap addContent( - final RtpContentMap modification, final IceUdpTransportInfo.Setup setup) { - final IceUdpTransportInfo.Credentials credentials = getDistinctCredentials(); - final Collection iceOptions = getCombinedIceOptions(); - final DTLS dtls = getDistinctDtls(); + final RtpContentMap modification, final IceUdpTransportInfo.Setup setupOverwrite) { final Map combined = merge(contents, modification.contents); final Map combinedFixedTransport = Maps.transformValues( combined, dt -> { final IceUdpTransportInfo iceUdpTransportInfo; - if (dt.transport.emptyCredentials()) { + if (dt.transport.isStub()) { + final IceUdpTransportInfo.Credentials credentials = + getDistinctCredentials(); + final Collection iceOptions = getCombinedIceOptions(); + final DTLS dtls = getDistinctDtls(); iceUdpTransportInfo = IceUdpTransportInfo.of( credentials, iceOptions, - setup, + setupOverwrite, dtls.hash, dtls.fingerprint); } else { + final IceUdpTransportInfo.Fingerprint fp = + dt.transport.getFingerprint(); + final IceUdpTransportInfo.Setup setup = fp.getSetup(); iceUdpTransportInfo = IceUdpTransportInfo.of( dt.transport.getCredentials(), - iceOptions, - setup, - dtls.hash, - dtls.fingerprint); + dt.transport.getIceOptions(), + setup == IceUdpTransportInfo.Setup.ACTPASS + ? setupOverwrite + : setup, + fp.getHash(), + fp.getContent()); } return new DescriptionTransport( dt.senders, dt.description, iceUdpTransportInfo); }); - return new RtpContentMap(modification.group, combinedFixedTransport); + return new RtpContentMap(modification.group, ImmutableMap.copyOf(combinedFixedTransport)); } private static Map merge( diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/IceUdpTransportInfo.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/IceUdpTransportInfo.java index a30e2ff91..8939ecb1b 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/IceUdpTransportInfo.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/IceUdpTransportInfo.java @@ -82,7 +82,7 @@ public class IceUdpTransportInfo extends GenericTransportInfo { iceUdpTransportInfo.addChild(Fingerprint.of(setup, hash, fingerprint)); iceUdpTransportInfo.setAttribute("ufrag", credentials.ufrag); iceUdpTransportInfo.setAttribute("pwd", credentials.password); - for(final String iceOption : iceOptions) { + for (final String iceOption : iceOptions) { iceUdpTransportInfo.addChild(new IceOption(iceOption)); } return iceUdpTransportInfo; @@ -110,8 +110,10 @@ public class IceUdpTransportInfo extends GenericTransportInfo { return new Credentials(ufrag, password); } - public boolean emptyCredentials() { - return Strings.isNullOrEmpty(this.getAttribute("ufrag")) || Strings.isNullOrEmpty(this.getAttribute("pwd")); + public boolean isStub() { + return Strings.isNullOrEmpty(this.getAttribute("ufrag")) + && Strings.isNullOrEmpty(this.getAttribute("pwd")) + && this.children.isEmpty(); } public List getCandidates() { From 8f014d5525e234a7bd25f120b27480dd15044c82 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 6 Oct 2023 13:28:55 +0200 Subject: [PATCH 135/402] implement Private DNS (DoT) due to limitations in the MiniDNS library this does not work when 'Validate hostname with DNSSEC' is enabled in the expert settings --- .../de/gultsch/minidns/AndroidDNSClient.java | 123 ++++++++++++ .../java/de/gultsch/minidns/DNSServer.java | 104 ++++++++++ .../java/de/gultsch/minidns/DNSSocket.java | 190 ++++++++++++++++++ .../de/gultsch/minidns/NetworkDataSource.java | 160 +++++++++++++++ .../java/de/gultsch/minidns/Transport.java | 23 +++ .../siacs/conversations/utils/Resolver.java | 5 +- 6 files changed, 604 insertions(+), 1 deletion(-) create mode 100644 src/main/java/de/gultsch/minidns/AndroidDNSClient.java create mode 100644 src/main/java/de/gultsch/minidns/DNSServer.java create mode 100644 src/main/java/de/gultsch/minidns/DNSSocket.java create mode 100644 src/main/java/de/gultsch/minidns/NetworkDataSource.java create mode 100644 src/main/java/de/gultsch/minidns/Transport.java diff --git a/src/main/java/de/gultsch/minidns/AndroidDNSClient.java b/src/main/java/de/gultsch/minidns/AndroidDNSClient.java new file mode 100644 index 000000000..194ad23bd --- /dev/null +++ b/src/main/java/de/gultsch/minidns/AndroidDNSClient.java @@ -0,0 +1,123 @@ +package de.gultsch.minidns; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.LinkProperties; +import android.net.Network; +import android.os.Build; + +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableList; + +import de.measite.minidns.AbstractDNSClient; +import de.measite.minidns.DNSMessage; + +import java.io.IOException; +import java.net.InetAddress; +import java.util.List; + +public class AndroidDNSClient extends AbstractDNSClient { + private final Context context; + private final NetworkDataSource networkDataSource = new NetworkDataSource(); + private boolean askForDnssec = false; + + public AndroidDNSClient(final Context context) { + super(); + this.setDataSource(networkDataSource); + this.context = context; + } + + private static String getPrivateDnsServerName(final LinkProperties linkProperties) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + return linkProperties.getPrivateDnsServerName(); + } else { + return null; + } + } + + private static boolean isPrivateDnsActive(final LinkProperties linkProperties) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + return linkProperties.isPrivateDnsActive(); + } else { + return false; + } + } + + @Override + protected DNSMessage.Builder newQuestion(final DNSMessage.Builder message) { + message.setRecursionDesired(true); + message.getEdnsBuilder() + .setUdpPayloadSize(networkDataSource.getUdpPayloadSize()) + .setDnssecOk(askForDnssec); + return message; + } + + @Override + protected DNSMessage query(final DNSMessage.Builder queryBuilder) throws IOException { + final DNSMessage question = newQuestion(queryBuilder).build(); + for (final DNSServer dnsServer : getDNSServers()) { + final DNSMessage response = this.networkDataSource.query(question, dnsServer); + if (response == null) { + continue; + } + switch (response.responseCode) { + case NO_ERROR: + case NX_DOMAIN: + break; + default: + continue; + } + + return response; + } + return null; + } + + public boolean isAskForDnssec() { + return askForDnssec; + } + + public void setAskForDnssec(boolean askForDnssec) { + this.askForDnssec = askForDnssec; + } + + private List getDNSServers() { + final ImmutableList.Builder dnsServerBuilder = new ImmutableList.Builder<>(); + final ConnectivityManager connectivityManager = + (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + final Network[] networks = getActiveNetworks(connectivityManager); + for (final Network network : networks) { + final LinkProperties linkProperties = connectivityManager.getLinkProperties(network); + if (linkProperties == null) { + continue; + } + final String privateDnsServerName = getPrivateDnsServerName(linkProperties); + if (Strings.isNullOrEmpty(privateDnsServerName)) { + final boolean isPrivateDns = isPrivateDnsActive(linkProperties); + for (final InetAddress dnsServer : linkProperties.getDnsServers()) { + if (isPrivateDns) { + dnsServerBuilder.add(new DNSServer(dnsServer, Transport.TLS)); + } else { + dnsServerBuilder.add(new DNSServer(dnsServer)); + } + } + } else { + dnsServerBuilder.add(new DNSServer(privateDnsServerName, Transport.TLS)); + } + } + return dnsServerBuilder.build(); + } + + private Network[] getActiveNetworks(final ConnectivityManager connectivityManager) { + if (connectivityManager == null) { + return new Network[0]; + } + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { + final Network activeNetwork = connectivityManager.getActiveNetwork(); + if (activeNetwork != null) { + return new Network[] {activeNetwork}; + } + } + return connectivityManager.getAllNetworks(); + } +} diff --git a/src/main/java/de/gultsch/minidns/DNSServer.java b/src/main/java/de/gultsch/minidns/DNSServer.java new file mode 100644 index 000000000..7486ec2c6 --- /dev/null +++ b/src/main/java/de/gultsch/minidns/DNSServer.java @@ -0,0 +1,104 @@ +package de.gultsch.minidns; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.collect.Iterables; + +import java.net.InetAddress; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import javax.annotation.Nonnull; + +public final class DNSServer { + + public final InetAddress inetAddress; + public final String hostname; + public final int port; + public final List transports; + + public DNSServer(InetAddress inetAddress, Integer port, Transport transport) { + this.inetAddress = inetAddress; + this.port = port == null ? 0 : port; + this.transports = Collections.singletonList(transport); + this.hostname = null; + } + + public DNSServer(final String hostname, final Integer port, final Transport transport) { + Preconditions.checkArgument( + Arrays.asList(Transport.HTTPS, Transport.TLS).contains(transport), + "hostname validation only works with TLS based transports"); + this.hostname = hostname; + this.port = port == null ? 0 : port; + this.transports = Collections.singletonList(transport); + this.inetAddress = null; + } + + public DNSServer(final String hostname, final Transport transport) { + this(hostname, Transport.DEFAULT_PORTS.get(transport), transport); + } + + public DNSServer(InetAddress inetAddress, Transport transport) { + this(inetAddress, Transport.DEFAULT_PORTS.get(transport), transport); + } + + public DNSServer(final InetAddress inetAddress) { + this(inetAddress, 53, Arrays.asList(Transport.UDP, Transport.TCP)); + } + + public DNSServer(final InetAddress inetAddress, int port, List transports) { + this(inetAddress, null, port, transports); + } + + private DNSServer( + final InetAddress inetAddress, + final String hostname, + final int port, + final List transports) { + this.inetAddress = inetAddress; + this.hostname = hostname; + this.port = port; + this.transports = transports; + } + + public Transport uniqueTransport() { + return Iterables.getOnlyElement(this.transports); + } + + public DNSServer asUniqueTransport(final Transport transport) { + Preconditions.checkArgument( + this.transports.contains(transport), + "This DNS server does not have transport ", + transport); + return new DNSServer(inetAddress, hostname, port, Collections.singletonList(transport)); + } + + @Override + @Nonnull + public String toString() { + return MoreObjects.toStringHelper(this) + .add("inetAddress", inetAddress) + .add("hostname", hostname) + .add("port", port) + .add("transports", transports) + .toString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DNSServer dnsServer = (DNSServer) o; + return port == dnsServer.port + && Objects.equal(inetAddress, dnsServer.inetAddress) + && Objects.equal(hostname, dnsServer.hostname) + && Objects.equal(transports, dnsServer.transports); + } + + @Override + public int hashCode() { + return Objects.hashCode(inetAddress, hostname, port, transports); + } +} diff --git a/src/main/java/de/gultsch/minidns/DNSSocket.java b/src/main/java/de/gultsch/minidns/DNSSocket.java new file mode 100644 index 000000000..4b096e0b2 --- /dev/null +++ b/src/main/java/de/gultsch/minidns/DNSSocket.java @@ -0,0 +1,190 @@ +package de.gultsch.minidns; + +import android.util.Log; + +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.SettableFuture; + +import de.measite.minidns.DNSMessage; + +import eu.siacs.conversations.Config; + +import org.conscrypt.OkHostnameVerifier; + +import java.io.Closeable; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.EOFException; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketAddress; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Semaphore; + +import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; + +final class DNSSocket implements Closeable { + + private static final int CONNECT_TIMEOUT = 5_000; + + private final Semaphore semaphore = new Semaphore(1); + private final Map> inFlightQueries = new HashMap<>(); + private final Socket socket; + private final DataInputStream dataInputStream; + private final DataOutputStream dataOutputStream; + + private DNSSocket( + final Socket socket, + final DataInputStream dataInputStream, + final DataOutputStream dataOutputStream) { + this.socket = socket; + this.dataInputStream = dataInputStream; + this.dataOutputStream = dataOutputStream; + new Thread(this::readDNSMessages).start(); + } + + private void readDNSMessages() { + try { + while (socket.isConnected()) { + final DNSMessage response = readDNSMessage(); + final SettableFuture future; + synchronized (inFlightQueries) { + future = inFlightQueries.remove(response.id); + } + if (future != null) { + future.set(response); + } else { + Log.e(Config.LOGTAG, "no in flight query found for response id " + response.id); + } + } + evictInFlightQueries(new EOFException()); + } catch (final IOException e) { + evictInFlightQueries(e); + } + } + + private void evictInFlightQueries(final Exception e) { + synchronized (inFlightQueries) { + final Iterator>> iterator = + inFlightQueries.entrySet().iterator(); + while (iterator.hasNext()) { + final Map.Entry> entry = iterator.next(); + entry.getValue().setException(e); + iterator.remove(); + } + } + } + + private static DNSSocket of(final Socket socket) throws IOException { + final DataInputStream dataInputStream = new DataInputStream(socket.getInputStream()); + final DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream()); + return new DNSSocket(socket, dataInputStream, dataOutputStream); + } + + public static DNSSocket connect(final DNSServer dnsServer) throws IOException { + switch (dnsServer.uniqueTransport()) { + case TCP: + return connectTcpSocket(dnsServer); + case TLS: + return connectTlsSocket(dnsServer); + default: + throw new IllegalStateException("This is not a socket based transport"); + } + } + + private static DNSSocket connectTcpSocket(final DNSServer dnsServer) throws IOException { + Preconditions.checkArgument(dnsServer.uniqueTransport() == Transport.TCP); + final SocketAddress socketAddress = + new InetSocketAddress(dnsServer.inetAddress, dnsServer.port); + final Socket socket = new Socket(); + socket.connect(socketAddress, CONNECT_TIMEOUT); + return DNSSocket.of(socket); + } + + private static DNSSocket connectTlsSocket(final DNSServer dnsServer) throws IOException { + Preconditions.checkArgument(dnsServer.uniqueTransport() == Transport.TLS); + final SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); + final SSLSocket sslSocket; + if (Strings.isNullOrEmpty(dnsServer.hostname)) { + final SocketAddress socketAddress = + new InetSocketAddress(dnsServer.inetAddress, dnsServer.port); + sslSocket = (SSLSocket) factory.createSocket(dnsServer.inetAddress, dnsServer.port); + sslSocket.connect(socketAddress, 5_000); + } else { + sslSocket = (SSLSocket) factory.createSocket(dnsServer.hostname, dnsServer.port); + final SSLSession session = sslSocket.getSession(); + final Certificate[] peerCertificates = session.getPeerCertificates(); + if (peerCertificates.length == 0 || !(peerCertificates[0] instanceof X509Certificate)) { + throw new IOException("Peer did not provide X509 certificates"); + } + final X509Certificate certificate = (X509Certificate) peerCertificates[0]; + if (!OkHostnameVerifier.strictInstance().verify(dnsServer.hostname, certificate)) { + throw new SSLPeerUnverifiedException("Peer did not provide valid certificates"); + } + } + return DNSSocket.of(sslSocket); + } + + public DNSMessage query(final DNSMessage query) throws IOException, InterruptedException { + try { + return queryAsync(query).get(); + } catch (final ExecutionException e) { + final Throwable cause = e.getCause(); + if (cause instanceof IOException) { + throw (IOException) cause; + } else { + throw new IOException(e); + } + } + } + + public ListenableFuture queryAsync(final DNSMessage query) + throws InterruptedException, IOException { + final SettableFuture responseFuture = SettableFuture.create(); + synchronized (this.inFlightQueries) { + this.inFlightQueries.put(query.id, responseFuture); + } + this.semaphore.acquire(); + try { + query.writeTo(this.dataOutputStream); + this.dataOutputStream.flush(); + } finally { + this.semaphore.release(); + } + return responseFuture; + } + + private DNSMessage readDNSMessage() throws IOException { + final int length = this.dataInputStream.readUnsignedShort(); + byte[] data = new byte[length]; + int read = 0; + while (read < length) { + read += this.dataInputStream.read(data, read, length - read); + } + return new DNSMessage(data); + } + + @Override + public void close() throws IOException { + this.socket.close(); + } + + public void closeQuietly() { + try { + this.socket.close(); + } catch (final IOException ignored) { + + } + } +} diff --git a/src/main/java/de/gultsch/minidns/NetworkDataSource.java b/src/main/java/de/gultsch/minidns/NetworkDataSource.java new file mode 100644 index 000000000..1ba56f3c0 --- /dev/null +++ b/src/main/java/de/gultsch/minidns/NetworkDataSource.java @@ -0,0 +1,160 @@ +package de.gultsch.minidns; + +import android.util.Log; + +import androidx.annotation.NonNull; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.cache.RemovalListener; +import com.google.common.collect.ImmutableList; + +import de.measite.minidns.DNSMessage; +import de.measite.minidns.MiniDNSException; +import de.measite.minidns.source.DNSDataSource; +import de.measite.minidns.util.MultipleIoException; + +import eu.siacs.conversations.Config; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +public class NetworkDataSource extends DNSDataSource { + + private static final LoadingCache socketCache = + CacheBuilder.newBuilder() + .removalListener( + (RemovalListener) + notification -> { + final DNSServer dnsServer = notification.getKey(); + final DNSSocket dnsSocket = notification.getValue(); + if (dnsSocket == null) { + return; + } + Log.d(Config.LOGTAG, "closing connection to " + dnsServer); + dnsSocket.closeQuietly(); + }) + .expireAfterAccess(5, TimeUnit.MINUTES) + .build( + new CacheLoader() { + @Override + @NonNull + public DNSSocket load(@NonNull final DNSServer dnsServer) + throws Exception { + Log.d(Config.LOGTAG, "establishing connection to " + dnsServer); + return DNSSocket.connect(dnsServer); + } + }); + + private static List transportsForPort(final int port) { + final ImmutableList.Builder transportBuilder = new ImmutableList.Builder<>(); + for (final Map.Entry entry : Transport.DEFAULT_PORTS.entrySet()) { + if (entry.getValue().equals(port)) { + transportBuilder.add(entry.getKey()); + } + } + return transportBuilder.build(); + } + + @Override + public DNSMessage query(final DNSMessage message, final InetAddress address, final int port) + throws IOException { + final List transports = transportsForPort(port); + Log.w( + Config.LOGTAG, + "using legacy DataSource interface. guessing transports " + + transports + + " from port"); + if (transports.isEmpty()) { + throw new IOException(String.format("No transports found for port %d", port)); + } + return query(message, new DNSServer(address, port, transports)); + } + + public DNSMessage query(final DNSMessage message, final DNSServer dnsServer) + throws IOException { + Log.d(Config.LOGTAG, "using " + dnsServer); + final List ioExceptions = new ArrayList<>(); + for (final Transport transport : dnsServer.transports) { + try { + final DNSMessage response = + queryWithUniqueTransport(message, dnsServer.asUniqueTransport(transport)); + if (response != null && !response.truncated) { + return response; + } + } catch (final IOException e) { + ioExceptions.add(e); + } catch (final InterruptedException e) { + return null; + } + } + MultipleIoException.throwIfRequired(ioExceptions); + return null; + } + + private DNSMessage queryWithUniqueTransport(final DNSMessage message, final DNSServer dnsServer) + throws IOException, InterruptedException { + final Transport transport = dnsServer.uniqueTransport(); + switch (transport) { + case UDP: + return queryUdp(message, dnsServer.inetAddress, dnsServer.port); + case TCP: + case TLS: + return queryDnsSocket(message, dnsServer); + default: + throw new IOException( + String.format("Transport %s has not been implemented", transport)); + } + } + + protected DNSMessage queryUdp( + final DNSMessage message, final InetAddress address, final int port) + throws IOException { + final DatagramPacket request = message.asDatagram(address, port); + final byte[] buffer = new byte[udpPayloadSize]; + try (final DatagramSocket socket = new DatagramSocket()) { + socket.setSoTimeout(timeout); + socket.send(request); + final DatagramPacket response = new DatagramPacket(buffer, buffer.length); + socket.receive(response); + DNSMessage dnsMessage = new DNSMessage(response.getData()); + if (dnsMessage.id != message.id) { + throw new MiniDNSException.IdMismatch(message, dnsMessage); + } + return dnsMessage; + } + } + + protected DNSMessage queryDnsSocket(final DNSMessage message, final DNSServer dnsServer) + throws IOException, InterruptedException { + final DNSSocket cachedDnsSocket = socketCache.getIfPresent(dnsServer); + if (cachedDnsSocket != null) { + try { + return cachedDnsSocket.query(message); + } catch (final IOException e) { + Log.d( + Config.LOGTAG, + "IOException occurred at cached socket. invalidating and falling through to new socket creation"); + socketCache.invalidate(dnsServer); + } + } + try { + return socketCache.get(dnsServer).query(message); + } catch (final ExecutionException e) { + final Throwable cause = e.getCause(); + if (cause instanceof IOException) { + throw (IOException) cause; + } else { + throw new IOException(cause); + } + } + } +} diff --git a/src/main/java/de/gultsch/minidns/Transport.java b/src/main/java/de/gultsch/minidns/Transport.java new file mode 100644 index 000000000..3aabfacaa --- /dev/null +++ b/src/main/java/de/gultsch/minidns/Transport.java @@ -0,0 +1,23 @@ +package de.gultsch.minidns; + +import com.google.common.collect.ImmutableMap; + +import java.util.Map; + +public enum Transport { + UDP, + TCP, + TLS, + HTTPS; + + public static final Map DEFAULT_PORTS; + + static { + final ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + builder.put(Transport.UDP, 53); + builder.put(Transport.TCP, 53); + builder.put(Transport.TLS, 853); + builder.put(Transport.HTTPS, 443); + DEFAULT_PORTS = builder.build(); + } +} diff --git a/src/main/java/eu/siacs/conversations/utils/Resolver.java b/src/main/java/eu/siacs/conversations/utils/Resolver.java index 463d6eb73..444deda4a 100644 --- a/src/main/java/eu/siacs/conversations/utils/Resolver.java +++ b/src/main/java/eu/siacs/conversations/utils/Resolver.java @@ -15,6 +15,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import de.gultsch.minidns.AndroidDNSClient; import de.measite.minidns.AbstractDNSClient; import de.measite.minidns.DNSCache; import de.measite.minidns.DNSClient; @@ -274,7 +275,9 @@ public class Resolver { private static ResolverResult resolveWithFallback(DNSName dnsName, Class type, boolean validateHostname) throws IOException { final Question question = new Question(dnsName, Record.TYPE.getType(type)); if (!validateHostname) { - return ResolverApi.INSTANCE.resolve(question); + final AndroidDNSClient androidDNSClient = new AndroidDNSClient(SERVICE); + final ResolverApi resolverApi = new ResolverApi(androidDNSClient); + return resolverApi.resolve(question); } try { return DnssecResolverApi.INSTANCE.resolveDnssecReliable(question); From c53e035935c85d6d42d9ef4450065b3a81af4687 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 9 Oct 2023 16:23:02 +0200 Subject: [PATCH 136/402] do not use JMI if any rtp capable device does not support it --- .../conversations/entities/Presences.java | 14 --------- .../ui/ConversationFragment.java | 30 +++++++++---------- .../conversations/ui/RtpSessionActivity.java | 7 ++--- .../xmpp/jingle/RtpCapability.java | 14 +++++++++ 4 files changed, 31 insertions(+), 34 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/entities/Presences.java b/src/main/java/eu/siacs/conversations/entities/Presences.java index 04d378cc2..59480b0ce 100644 --- a/src/main/java/eu/siacs/conversations/entities/Presences.java +++ b/src/main/java/eu/siacs/conversations/entities/Presences.java @@ -134,20 +134,6 @@ public class Presences { return true; } - public boolean anySupport(final String namespace) { - synchronized (this.presences) { - if (this.presences.size() == 0) { - return true; - } - for (Presence presence : this.presences.values()) { - ServiceDiscoveryResult disco = presence.getServiceDiscoveryResult(); - if (disco != null && disco.getFeatures().contains(namespace)) { - return true; - } - } - } - return false; - } public Pair, Map> toTypeAndNameMap() { Map typeMap = new HashMap<>(); diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 11348b6b7..79d938274 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -64,19 +64,6 @@ import androidx.databinding.DataBindingUtil; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.atomic.AtomicBoolean; - import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.axolotl.AxolotlService; @@ -123,13 +110,11 @@ import eu.siacs.conversations.utils.Compatibility; import eu.siacs.conversations.utils.GeoHelper; import eu.siacs.conversations.utils.MessageUtils; import eu.siacs.conversations.utils.NickValidityChecker; -import eu.siacs.conversations.utils.Patterns; import eu.siacs.conversations.utils.PermissionUtils; import eu.siacs.conversations.utils.QuickLoader; import eu.siacs.conversations.utils.StylingHelper; import eu.siacs.conversations.utils.TimeFrameUtils; import eu.siacs.conversations.utils.UIHelper; -import eu.siacs.conversations.xml.Namespace; import eu.siacs.conversations.xmpp.Jid; import eu.siacs.conversations.xmpp.XmppConnection; import eu.siacs.conversations.xmpp.chatstate.ChatState; @@ -140,6 +125,19 @@ import eu.siacs.conversations.xmpp.jingle.Media; import eu.siacs.conversations.xmpp.jingle.OngoingRtpSession; import eu.siacs.conversations.xmpp.jingle.RtpCapability; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; + public class ConversationFragment extends XmppFragment implements EditMessage.KeyboardListener, MessageAdapter.OnContactPictureLongClicked, @@ -1611,7 +1609,7 @@ public class ConversationFragment extends XmppFragment return; } final Contact contact = conversation.getContact(); - if (contact.getPresences().anySupport(Namespace.JINGLE_MESSAGE)) { + if (RtpCapability.jmiSupport(contact)) { triggerRtpSession(contact.getAccount(), contact.getJid().asBareJid(), action); } else { final RtpCapability.Capability capability; diff --git a/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java b/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java index b7352aa27..10cf93129 100644 --- a/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java @@ -70,6 +70,7 @@ import eu.siacs.conversations.xmpp.jingle.ContentAddition; import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager; import eu.siacs.conversations.xmpp.jingle.JingleRtpConnection; import eu.siacs.conversations.xmpp.jingle.Media; +import eu.siacs.conversations.xmpp.jingle.RtpCapability; import eu.siacs.conversations.xmpp.jingle.RtpEndUserState; public class RtpSessionActivity extends XmppActivity @@ -1484,10 +1485,8 @@ public class RtpSessionActivity extends XmppActivity final Account account, Jid with, final RtpEndUserState state, final Set media) { final Intent intent = new Intent(Intent.ACTION_VIEW); intent.putExtra(EXTRA_ACCOUNT, account.getJid().toEscapedString()); - if (account.getRoster() - .getContact(with) - .getPresences() - .anySupport(Namespace.JINGLE_MESSAGE)) { + if (RtpCapability.jmiSupport(account.getRoster() + .getContact(with))) { intent.putExtra(EXTRA_WITH, with.asBareJid().toEscapedString()); } else { intent.putExtra(EXTRA_WITH, with.toEscapedString()); diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpCapability.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpCapability.java index 8a7581f04..b53f0b9e8 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpCapability.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpCapability.java @@ -1,9 +1,11 @@ package eu.siacs.conversations.xmpp.jingle; import com.google.common.base.Strings; +import com.google.common.collect.Collections2; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; @@ -77,6 +79,18 @@ public class RtpCapability { return result; } + // do all devices that support Rtp Call also support JMI? + public static boolean jmiSupport(final Contact contact) { + return !Collections2.transform( + Collections2.filter( + contact.getPresences().getPresences(), + p -> RtpCapability.check(p) != RtpCapability.Capability.NONE), + p -> { + ServiceDiscoveryResult disco = p.getServiceDiscoveryResult(); + return disco != null && disco.getFeatures().contains(Namespace.JINGLE_MESSAGE); + }).contains(false); + } + public enum Capability { NONE, AUDIO, VIDEO; From 39194d111cdf2c9cd1a980ebac0626da33d03645 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 10 Oct 2023 09:35:59 +0200 Subject: [PATCH 137/402] QR code scan: take disabled accounts into consideration when making register or add contact decision --- .../conversations/ui/UriHandlerActivity.java | 102 +++++++++++------- 1 file changed, 61 insertions(+), 41 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/ui/UriHandlerActivity.java b/src/main/java/eu/siacs/conversations/ui/UriHandlerActivity.java index 1e0cf41d3..de284264d 100644 --- a/src/main/java/eu/siacs/conversations/ui/UriHandlerActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/UriHandlerActivity.java @@ -18,13 +18,6 @@ import androidx.databinding.DataBindingUtil; import com.google.common.base.Strings; -import org.jetbrains.annotations.NotNull; - -import java.io.IOException; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.databinding.ActivityUriHandlerBinding; @@ -35,12 +28,20 @@ import eu.siacs.conversations.utils.ProvisioningUtils; import eu.siacs.conversations.utils.SignupUtils; import eu.siacs.conversations.utils.XmppUri; import eu.siacs.conversations.xmpp.Jid; + import okhttp3.Call; import okhttp3.Callback; import okhttp3.HttpUrl; import okhttp3.Request; import okhttp3.Response; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + public class UriHandlerActivity extends AppCompatActivity { public static final String ACTION_SCAN_QR_CODE = "scan_qr_code"; @@ -58,7 +59,9 @@ public class UriHandlerActivity extends AppCompatActivity { } public static void scan(final Activity activity, final boolean provisioning) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M || ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M + || ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) + == PackageManager.PERMISSION_GRANTED) { final Intent intent = new Intent(activity, UriHandlerActivity.class); intent.setAction(UriHandlerActivity.ACTION_SCAN_QR_CODE); if (provisioning) { @@ -68,14 +71,17 @@ public class UriHandlerActivity extends AppCompatActivity { activity.startActivity(intent); } else { activity.requestPermissions( - new String[]{Manifest.permission.CAMERA}, - provisioning ? REQUEST_CAMERA_PERMISSIONS_TO_SCAN_AND_PROVISION : REQUEST_CAMERA_PERMISSIONS_TO_SCAN - ); + new String[] {Manifest.permission.CAMERA}, + provisioning + ? REQUEST_CAMERA_PERMISSIONS_TO_SCAN_AND_PROVISION + : REQUEST_CAMERA_PERMISSIONS_TO_SCAN); } } - public static void onRequestPermissionResult(Activity activity, int requestCode, int[] grantResults) { - if (requestCode != REQUEST_CAMERA_PERMISSIONS_TO_SCAN && requestCode != REQUEST_CAMERA_PERMISSIONS_TO_SCAN_AND_PROVISION) { + public static void onRequestPermissionResult( + Activity activity, int requestCode, int[] grantResults) { + if (requestCode != REQUEST_CAMERA_PERMISSIONS_TO_SCAN + && requestCode != REQUEST_CAMERA_PERMISSIONS_TO_SCAN_AND_PROVISION) { return; } if (grantResults.length > 0) { @@ -86,7 +92,11 @@ public class UriHandlerActivity extends AppCompatActivity { scan(activity); } } else { - Toast.makeText(activity, R.string.qr_code_scanner_needs_access_to_camera, Toast.LENGTH_SHORT).show(); + Toast.makeText( + activity, + R.string.qr_code_scanner_needs_access_to_camera, + Toast.LENGTH_SHORT) + .show(); } } } @@ -116,7 +126,7 @@ public class UriHandlerActivity extends AppCompatActivity { private boolean handleUri(final Uri uri, final boolean scanned) { final Intent intent; final XmppUri xmppUri = new XmppUri(uri); - final List accounts = DatabaseBackend.getInstance(this).getAccountJids(true); + final List accounts = DatabaseBackend.getInstance(this).getAccountJids(false); if (SignupUtils.isSupportTokenRegistry() && xmppUri.isValidJid()) { final String preAuth = xmppUri.getParameter(XmppUri.PARAMETER_PRE_AUTH); @@ -130,7 +140,12 @@ public class UriHandlerActivity extends AppCompatActivity { startActivity(intent); return true; } - if (accounts.size() == 0 && xmppUri.isAction(XmppUri.ACTION_ROSTER) && "y".equals(xmppUri.getParameter(XmppUri.PARAMETER_IBR))) { + if (accounts.size() == 0 + && xmppUri.isAction(XmppUri.ACTION_ROSTER) + && "y" + .equalsIgnoreCase( + Strings.nullToEmpty(xmppUri.getParameter(XmppUri.PARAMETER_IBR)) + .trim())) { intent = SignupUtils.getTokenRegistrationIntent(this, jid.getDomain(), preAuth); intent.putExtra(StartConversationActivity.EXTRA_INVITE_URI, xmppUri.toString()); startActivity(intent); @@ -197,29 +212,28 @@ public class UriHandlerActivity extends AppCompatActivity { private void checkForLinkHeader(final HttpUrl url) { Log.d(Config.LOGTAG, "checking for link header on " + url); - this.call = HttpConnectionManager.OK_HTTP_CLIENT.newCall(new Request.Builder() - .url(url) - .head() - .build()); - this.call.enqueue(new Callback() { - @Override - public void onFailure(@NotNull Call call, @NotNull IOException e) { - Log.d(Config.LOGTAG, "unable to check HTTP url", e); - showError(R.string.no_xmpp_adddress_found); - } - - @Override - public void onResponse(@NotNull Call call, @NotNull Response response) { - if (response.isSuccessful()) { - final String linkHeader = response.header("Link"); - if (linkHeader != null && processLinkHeader(linkHeader)) { - return; + this.call = + HttpConnectionManager.OK_HTTP_CLIENT.newCall( + new Request.Builder().url(url).head().build()); + this.call.enqueue( + new Callback() { + @Override + public void onFailure(@NotNull Call call, @NotNull IOException e) { + Log.d(Config.LOGTAG, "unable to check HTTP url", e); + showError(R.string.no_xmpp_adddress_found); } - } - showError(R.string.no_xmpp_adddress_found); - } - }); + @Override + public void onResponse(@NotNull Call call, @NotNull Response response) { + if (response.isSuccessful()) { + final String linkHeader = response.header("Link"); + if (linkHeader != null && processLinkHeader(linkHeader)) { + return; + } + } + showError(R.string.no_xmpp_adddress_found); + } + }); } private boolean processLinkHeader(final String header) { @@ -256,7 +270,8 @@ public class UriHandlerActivity extends AppCompatActivity { } switch (action) { case Intent.ACTION_MAIN: - binding.progress.setVisibility(call != null && !call.isCanceled() ? View.VISIBLE : View.INVISIBLE); + binding.progress.setVisibility( + call != null && !call.isCanceled() ? View.VISIBLE : View.INVISIBLE); break; case Intent.ACTION_VIEW: case Intent.ACTION_SENDTO: @@ -280,7 +295,8 @@ public class UriHandlerActivity extends AppCompatActivity { private boolean allowProvisioning() { final Intent launchIntent = getIntent(); - return launchIntent != null && launchIntent.getBooleanExtra(EXTRA_ALLOW_PROVISIONING, false); + return launchIntent != null + && launchIntent.getBooleanExtra(EXTRA_ALLOW_PROVISIONING, false); } @Override @@ -303,13 +319,17 @@ public class UriHandlerActivity extends AppCompatActivity { showError(R.string.no_xmpp_adddress_found); } return; - } else if (QuickConversationsService.isConversations() && looksLikeJsonObject(result) && allowProvisioning) { + } else if (QuickConversationsService.isConversations() + && looksLikeJsonObject(result) + && allowProvisioning) { ProvisioningUtils.provision(this, result); finish(); return; } final Uri uri = Uri.parse(result.trim()); - if (allowProvisioning && "https".equalsIgnoreCase(uri.getScheme()) && !XmppUri.INVITE_DOMAIN.equalsIgnoreCase(uri.getHost())) { + if (allowProvisioning + && "https".equalsIgnoreCase(uri.getScheme()) + && !XmppUri.INVITE_DOMAIN.equalsIgnoreCase(uri.getHost())) { final HttpUrl httpUrl = HttpUrl.parse(uri.toString()); if (httpUrl != null) { checkForLinkHeader(httpUrl); From 1e898b022fcce27f1ff3bb9f0047918984c32235 Mon Sep 17 00:00:00 2001 From: nautilusx Date: Sat, 7 Oct 2023 20:25:28 +0000 Subject: [PATCH 138/402] Translated using Weblate (German) Currently translated at 100.0% (969 of 969 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/de/ --- src/main/res/values-de/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-de/strings.xml b/src/main/res/values-de/strings.xml index 8951a6f79..3c465681c 100644 --- a/src/main/res/values-de/strings.xml +++ b/src/main/res/values-de/strings.xml @@ -1011,4 +1011,5 @@ Die Channelsuche verwendet einen Drittanbieterservice namens <a href=https://search.jabber.network>search.jabber.network</a>.<br><br>Wenn du diese Funktion verwendest, werden deine IP-Adresse und deine Suchbegriffe an diesen Dienst übertragen. Weitere Informationen findest du in der <a href=https://search.jabber.network/privacy>Datenschutzerklärung</a>. Versuche nicht, Backups wiederherzustellen, die du nicht selbst erstellt hast! Du versuchst, ein veraltetes Sicherungsdateiformat zu importieren + Hörbuch \ No newline at end of file From 4121b9746d197ba8d4c83256a79b0ab9cd1bee5a Mon Sep 17 00:00:00 2001 From: gallegonovato Date: Sat, 7 Oct 2023 13:13:21 +0000 Subject: [PATCH 139/402] Translated using Weblate (Spanish) Currently translated at 100.0% (969 of 969 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/es/ --- src/main/res/values-es/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-es/strings.xml b/src/main/res/values-es/strings.xml index db9cb6adc..35a07ad76 100644 --- a/src/main/res/values-es/strings.xml +++ b/src/main/res/values-es/strings.xml @@ -1025,4 +1025,5 @@ Guardar como un chat en grupo ¡No intentes restaurar las copias de seguridad que no creaste tu mismo! Estás intentando importar un formato de copia de seguridad obsoleto + Audiolibro \ No newline at end of file From a1edb1804edb59fc662526afc96f15d1fd481ec1 Mon Sep 17 00:00:00 2001 From: ghose Date: Sat, 7 Oct 2023 11:45:06 +0000 Subject: [PATCH 140/402] Translated using Weblate (Galician) Currently translated at 100.0% (969 of 969 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/gl/ --- src/main/res/values-gl/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-gl/strings.xml b/src/main/res/values-gl/strings.xml index 9e8926bb0..60281767b 100644 --- a/src/main/res/values-gl/strings.xml +++ b/src/main/res/values-gl/strings.xml @@ -1014,4 +1014,5 @@ O descubrimento de canles usa un servizo externo chamado <a href=https://search.jabber.network>search.jabber.network</a>.<br><br>Ao usar esta ferramenta transmitirás o teu enderezo IP e termos de busca a ese servizo. Le a súa <a href=https://search.jabber.network/privacy>Política de Privacidade</a> para saber máis. Non intentes restablecer unha copia de apoio que non tiveses creado ti! Estás intentando importar un ficheiro de apoio co formato antigo + Audiolibro \ No newline at end of file From f5a57574e6aa33b688cf9de0127c2a9f87ebcac9 Mon Sep 17 00:00:00 2001 From: Eryk Michalak Date: Sun, 8 Oct 2023 11:23:36 +0000 Subject: [PATCH 141/402] Translated using Weblate (Polish) Currently translated at 100.0% (969 of 969 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/pl/ --- src/main/res/values-pl/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-pl/strings.xml b/src/main/res/values-pl/strings.xml index f000897fc..3d2557561 100644 --- a/src/main/res/values-pl/strings.xml +++ b/src/main/res/values-pl/strings.xml @@ -1044,4 +1044,5 @@ Zapisz jako czat grupowy Nie próbuj przywracać kopii zapasowych, których nie utworzono samodzielnie! Próbujesz zaimportować plik kopii zapasowej o przestarzałym formacie + Audiobook \ No newline at end of file From 1bd6defd5376ac1da6998d6c8641083d493203be Mon Sep 17 00:00:00 2001 From: SomeTr Date: Sat, 7 Oct 2023 17:31:56 +0000 Subject: [PATCH 142/402] Translated using Weblate (Ukrainian) Currently translated at 100.0% (969 of 969 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/uk/ --- src/main/res/values-uk/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-uk/strings.xml b/src/main/res/values-uk/strings.xml index d826a8a33..f192c50db 100644 --- a/src/main/res/values-uk/strings.xml +++ b/src/main/res/values-uk/strings.xml @@ -1065,4 +1065,5 @@ Додати ще пісні\? Не намагайтеся відновити резервні копії, які створили не Ви! Ви намагаєтеся імпортувати файл резервної копії у застарілому форматі + Аудіокнига \ No newline at end of file From 7d59a2da421ea13046e7477524bfb45358eb69d0 Mon Sep 17 00:00:00 2001 From: alextecplayz Date: Mon, 9 Oct 2023 09:03:31 +0000 Subject: [PATCH 143/402] Translated using Weblate (Romanian) Currently translated at 100.0% (969 of 969 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/ro/ --- src/main/res/values-ro-rRO/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-ro-rRO/strings.xml b/src/main/res/values-ro-rRO/strings.xml index c738b8d83..5b8de225e 100644 --- a/src/main/res/values-ro-rRO/strings.xml +++ b/src/main/res/values-ro-rRO/strings.xml @@ -1033,4 +1033,5 @@ Caută discuții de grup Nu încercați să restaurați copii de rezervă pe care nu le-ați creat personal! Încercați să importați un fișier copie de rezervă format vechi + Carte audio \ No newline at end of file From 72aca8941a1e2d43429ca56ff400000631071dd5 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Mon, 9 Oct 2023 07:24:54 +0000 Subject: [PATCH 144/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (969 of 969 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 475 +++++++++++++------------ 1 file changed, 245 insertions(+), 230 deletions(-) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index a941bcf33..d131fbd28 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -2,13 +2,13 @@ 设置 新对话 - 管理账户 - 管理账户 + 管理账号 + 管理账号 关闭 Conversation 联系人详情 群聊详情 频道详情 - 添加账户 + 添加账号 编辑名称 添加到通讯录 从通讯录中删除 @@ -18,23 +18,23 @@ 解封域名 封禁成员 解封成员 - 管理账户 + 管理账号 设置 通过 Conversations 分享 开始对话 选择联系人 选择联系人 - 通过账户分享 + 通过账号分享 封禁列表 - 刚刚 - 1分钟前 - %d分钟前 + 刚才 + 1 分钟前 + %d 分钟前 - %d 未读会话 + %d 个未读会话 发送中… - 正在解密信息。请稍候…… - OpenPGP 加密的信息 + 正在解密消息。请稍候…… + OpenPGP 加密的消息 用户名已存在 无效的用户名 管理员 @@ -42,15 +42,15 @@ 群主 成员 访客 - 将%s从XMPP联系人中移除?与该联系人的会话消息不会清除。 - 您想封禁%s吗? - 您想解封%s吗? + 你要将%s从 XMPP 联系人中移除吗?与该联系人的会话消息不会清除。 + 你想封禁 %s向你发送信息吗? + 你想解除对%s的封禁,让他们给你发送信息吗? 封禁%s中的所有联系人? 解封%s中所有联系人? 联系人已封禁 已封禁 - 从书签中移除%s?相关会话消息不会被清除。 - 在服务器上注册新账户 + 你想从书签中移除%s吗?相关会话消息不会被清除。 + 在服务器上注册新账号 在服务器上修改密码 分享… 开始聊天 @@ -68,12 +68,12 @@ 保存 完成 %1$s已崩溃 - 用你的 XMPP 账户发送堆栈跟踪来帮助持续开发 %1$s。 + 用你的 XMPP 账号发送堆栈跟踪来帮助持续开发 %1$s。 立即发送 不再询问 - 账户无法连接 - 无法连接到多个账户 - 点击管理账户 + 账号无法连接 + 无法连接到多个账号 + 点击管理账号 发送文件 该联系人不在您的通讯录中,需要添加吗 ? 添加联系人 @@ -83,33 +83,39 @@ 正在分享文件,请稍候… 清除历史记录 清除聊天记录 - 您确定要删除此聊天中的所有消息吗?\n\n警告:这不会删除存储在其他设备或服务器上的那些消息的副本。 + 你想删除此聊天中的所有消息吗? +\n +\n警告:这不会删除存储在其他设备或服务器上的那些消息的副本。 删除文件 - 您确定要删除此文件吗? + 你确定要删除此文件吗? \n \n警告:这不会删除存储在其他设备或服务器上的此文件的副本。 之后关闭此聊天 选择设备 - 发送未加密的信息 - 发送信息 - 发信息给%s - 发送OMEMO加密信息 - 发送v\\OMEMO加密信息 - 发送OpenPGP加密信息 + 发送未加密的消息 + 发送消息 + 发消息给%s + 发送 OMEMO 加密消息 + 发送 v\\OMEMO 加密消息 + 发送 OpenPGP 加密消息 昵称已被使用 不加密发送 - 解密失败,可能是私钥不正确。 + 解密失败,也许你没有正确的私钥。 OpenKeychain - OpenKeychain来加密和解密消息并管理你的公钥。

它在 GPLv3+ 许可证下授权并可在 F-Droid 和 Google Play 上获得。

(请之后重启 %1$s)]]>
+ %1$s使用 <b>OpenKeychain</b>来加密和解密消息并管理你的公钥。<br><br>它在 GPLv3+ 许可证下授权并可在 F-Droid 和 Google Play 上获得。<br><br><small>(请稍后重新启动%1$s。)</small> 重启 安装 - 请安装OpenKeychain以解密 + 请安装 OpenKeychain 以解密 提供… 等待… - 无OpenPGP密钥 - 因您的联系人未公布其公钥,无法加密您的信息。\n\n请通知您的联系人设置OpenPGP。 - 无OpenPGP密钥 - 因您的联系人未公布其公钥,无法加密您的信息。\n\n请通知您的联系人设置OpenPGP。 + 无 OpenPGP 密钥 + 由于你的联系人未公布其公钥,无法加密你的消息。 +\n +\n请通知你的联系人设置 OpenPGP。 + 无 OpenPGP 密钥 + 由于你的联系人未公布其公钥,无法加密你的消息。 +\n +\n请通知你的联系人设置 OpenPGP。 常规 接收文件 自动接收小于此大小的文件… @@ -124,37 +130,37 @@ 新消息通知铃声 来电响铃 静默时间段 - 在其他设备上检测到活动之后,通知在此时间段内将被静音。 + 在你的其他设备上检测到活动之后,通知在此时间段内将被静音。 高级 从不发送崩溃报告 - 通过发送堆栈跟踪,您可以为开发提供帮助 + 通过发送堆栈跟踪,你可以为开发提供帮助 确认消息 让对方知道你收到并阅读了他们的消息 防止截屏 在应用切换中隐藏应用程序内容并阻止截图 用户界面 - OpenKeychain报告一个错误。 + OpenKeychain 出现了一个错误。 错误的加密密钥。 接受 出现了一个错误 错误 - 你的账户 + 你的账号 发送在线状态更新 接收在线状态更新 请求在线状态更新 选择图片 拍摄图片 预先同意订阅请求 - 您选择的文件不是图像 + 你所选的文件不是图片 无法转换图片文件 未找到文件 - 常规I/O错误。可能是存储空间不足? + 常规 I/O 错误。也许你的存储空间不够了? 你用来选择图片的应用没有提供读取文件的足够权限。 \n \n使用不同的文件管理器来选择图片. 你用来共享此文件的应用程序没有提供足够的权限。 未知 - 暂时不可用 + 暂时禁用 在线 连接中\u2026 离线 @@ -162,12 +168,12 @@ 未找到服务器 未连接网络 注册失败 - 用户名已存在 + 用户名已使用 注册完成 服务器不支持注册 无效的注册令牌 - TLS协商失败 - 域名不可验证 + TLS 协商失败 + 域名无法验证 违反政策 服务器不兼容 不兼容的客户端 @@ -177,23 +183,24 @@ OTR OpenPGP OMEMO - 删除账户 - 暂时不可用 + 删除账号 + 暂时禁用 发布头像 - 发布OpenPGP公钥 - 移除OpenPGP公钥 - 您确定要从在线状态中移除OpenPGP公钥吗?\n您的联系人将无法再向您发送 OpenPGP 加密信息。 + 发布 OpenPGP 公钥 + 移除 OpenPGP 公钥 + 你确定要从在线状态中移除 OpenPGP 公钥吗? +\n你的联系人将无法再向你发送 OpenPGP 加密消息。 OpenPGP 公钥已发布。 - 启用账户 - 你确定删除账户吗?如果您删除账户,您的所有聊天记录将会丢失 + 启用账号 + 你确定删除账号吗?如果你删除账号,你的所有聊天记录将会丢失 录制音频 - XMPP地址 - 封禁XMPP地址 + XMPP 地址 + 封禁 XMPP 地址 username@example.com 密码 - 这不是有效的XMPP地址 + 这不是有效的 XMPP 地址 空间不足。图片过大 - 是否添加%s到通讯录? + 是否添加%s到你的通讯录? 服务器属性 XEP-0313:消息存档管理 XEP-0280:消息抄送 @@ -209,21 +216,21 @@ 无效 缺少公钥 最后上线于刚才 - 最后上线于一分钟前 - 最后上线于%d分钟前 - 最后上线于一小时前 - 最后上线于%d小时前 - 最后上线于一天前 - 最后上线于%d天前 - 加密信息。请安装OpenKeychain以解密。 - 发现新OpenPGP加密信息 - OpenPGP密钥ID - OMEMO指纹 - v\\OMEMO指纹 - OMEMO 指纹 (消息来源) - v\\OMEMO 指纹 (消息来源) + 最后上线于 1 分钟前 + 最后上线于 %d 分钟前 + 最后上线于 1 小时前 + 最后上线于 %d 小时前 + 最后上线于 1 天前 + 最后上线于 %d 天前 + 加密消息。请安装 OpenKeychain 以解密。 + 发现新 OpenPGP 加密消息 + OpenPGP 密钥 ID + OMEMO 指纹 + v\\OMEMO 指纹 + OMEMO 指纹(消息来源) + v\\OMEMO 指纹(消息来源) 其他设备 - 信任的OMEMO指纹 + 信任的 OMEMO 指纹 获取密钥中… 完成 解密 @@ -243,8 +250,12 @@ 删除书签 解散群聊 解散频道 - 您确定要解散此群聊吗?\n\n警告:此群聊将在服务器上完全删除。 - 您确定要解散此公共频道吗?\n\n警告:该频道将在服务器上完全删除。 + 你确定要解散此群聊吗? +\n +\n警告:此群聊将在服务器上完全删除。 + 你确定要解散此公共频道吗? +\n +\n警告:该频道将在服务器上完全删除。 无法解散群聊 无法解散频道 编辑群聊主题 @@ -260,16 +271,16 @@ 发布 点击头像以选择图片 正在发布… - 服务器拒绝了您的发布请求 - 无法转换图片 + 服务器拒绝了你的发布请求 + 无法转换你的图片 不能将头像保存至磁盘 - (长按以恢复默认) + (或长按恢复默认) 服务器不支持头像 私聊 至%s 与%s私聊 连接 - 该账户已存在 + 该账号已存在 下一步 会话已建立 跳过 @@ -277,15 +288,17 @@ 启用 需要密码才能进入该群聊 输入密码 - 请先向您的联系人请求在线状态更新。 + 请先向你的联系人请求在线状态更新。 \n -\n这将被用来判断您的联系人正在使用的聊天应用 - 现在请求 +\n这将被用来判断你的联系人正在使用的聊天应用 + 立即请求 忽略 - 警告:在没有相互更新在线状态的情况下发送将会出现未知问题。\n\n前往联系人详情以验证您订阅的在线状态。 + 警告:在没有相互更新在线状态的情况下发送将会出现未知问题。 +\n +\n前往联系人详情以验证你订阅的在线状态。 安全 允许更正消息 - 允许对方发送后编辑信息 + 允许对方发送后编辑消息 高级设置 请谨慎使用 关于%s @@ -297,34 +310,34 @@ 其他 同步书签 加入或离开多用户聊天时设置 “autojoin\" 标志,并回应其他客户端所做更改。 - OMEMO指纹已拷贝到剪贴板 + OMEMO 指纹已复制到剪贴板 您被此群聊封禁 这个群聊只允许成员聊天 资源限制 您被从此群聊踢出 这个群聊已被关闭 您已不在该群组 - 你出于技术原因离开了群聊 - 使用账户%s + 你由于技术原因离开了群聊 + 使用账号%s 托管于%s - 正在HTTP服务器中检查%s + 正在 HTTP 服务器中检查%s 未连接。请稍后重试 检查%s的大小 在%2$s上检查%1$s的大小 消息选项 引用 作为引用粘贴 - 复制原始URL + 复制原始 URL 重新发送 - 文件URL - 已经拷贝URL到剪贴板 - 已复制XMPP地址到剪贴板 + 文件 URL + 已经复制 URL 到剪贴板 + 已复制 XMPP 地址到剪贴板 已复制错误信息到剪贴板 - web地址 + 网址 扫描二维码 显示二维码 显示封禁列表 - 账户详情 + 账号详情 确认 重试 前台服务 @@ -336,9 +349,9 @@ 此备份文件已经存储在%s 正在恢复备份 备份已恢复 - 别忘了启用账户。 + 别忘了启用账号。 选择文件 - 正在下载%1$s(已完成%2$d%%) + 正在下载%1$s(已完成%2$d%%) 下载%s 删除%s 文件 @@ -358,11 +371,11 @@ 启用通知 未找到群聊服务器 群聊创建失败 - 账户头像 - 复制OMEMO指纹到剪贴板 - 重新生成OMEMO密钥 + 账号头像 + 复制 OMEMO 指纹到剪贴板 + 重新生成 OMEMO 密钥 清除设备 - 清除所有其他设备的OMEMO通告?下次设备连接时将重新通告,但可能收不到你发送的消息。 + 清除所有其他设备的 OMEMO 通告?下次设备连接时将重新通告,但可能收不到你发送的消息。 此联系人没有可用的密钥。 \n无法从服务器获取新密钥。也许你的联系人所在服务器发生问题了? 没有可以用于这个账户的密钥。\n请确保你有相互的在线状态的订阅。 @@ -376,8 +389,8 @@ 当前密码 新密码 密码不能为空 - 启用所有账户 - 禁用所有账户 + 启用所有账号 + 禁用所有账号 选择一个操作 没有从属关系 离线 @@ -395,15 +408,15 @@ 不能修改%s的从属关系 从群聊中封禁 从频道中封禁 - %s将被从公共频道中移除。只有将此用户封禁才能将他永远移除。 - 立刻封禁 + %s将被从公共频道中移除。唯一的办法就是永远封禁该用户。 + 立即封禁 不能修改%s的角色 私密群聊设置 公开频道设置 私密,只有成员可以加入 - 使XMPP地址对所有人可见 + 使 XMPP 地址对所有人可见 使频道受到管理 - 您尚未参与 + 你未参与 群聊设置修改成功! 无法更改群聊设置 从不 @@ -413,7 +426,7 @@ 标记为已读 输入 点击回车发送 - 使用Enter键发送消息。即使禁用此选项,也可以使用Ctrl+Enter发送消息。 + 使用 Enter 键发送消息。即使禁用此选项,也可以使用 Ctrl+Enter 发送消息。 显示回车键 将表情键改为回车键 音频 @@ -421,7 +434,7 @@ 图片 矢量图 多媒体文件 - PDF文档 + PDF 文档 Android App 联系人 头像已经发布! @@ -441,7 +454,7 @@ 聊天已关闭 离开私密群聊 离开公开频道 - 不信任系统CA + 不信任系统证书 所有证书必须手动通过 移除证书 删除手动通过的证书 @@ -450,9 +463,9 @@ 删除已选 取消 - %d个证书已被删除 + %d 个证书已被删除 - 以快捷操作替代发送按钮 + 以快捷操作替代“发送”按钮 快捷操作 刚用过的 @@ -468,7 +481,7 @@ 下载失败:无法连接到服务器 下载失败:不能写入文件 下载失败:无效文件 - Tor网络不可用 + Tor 网络不可用 绑定失败 服务器不能为域名做出响应 损坏 @@ -480,7 +493,7 @@ 将振动看作静音 设备振动时显示为忙碌 高级连接设置 - 注册账户时显示主机名和端口 + 注册账号时显示主机名和端口 xmpp.example.com 用证书登录 无法解析证书 @@ -491,22 +504,22 @@ 需要验证码 输入上图文字 证书链不受信任 - XMPP地址与证书不匹配 + XMPP 地址与证书不匹配 更新证书 - 获取OMEMO密钥时发生错误! - 请用证书验证OMEMO密钥! + 获取 OMEMO 密钥时发生错误! + 请用证书验证 OMEMO 密钥! 您的设备不支持客户端证书选择! 连接 - 通过Tor连接 - 所有连接使用Tor网络传输,需要Orbot + 通过 Tor 连接 + 所有连接使用 Tor 网络传输,需要 Orbot 服务器名 端口 - 服务器或者.onion地址 + 服务器或者 .onion 地址 该端口号无效 该主机名无效 - 已连接%2$d个中的%1$d个账户 + 已连接 %2$d 个中的 %1$d 个账号 - %d条消息 + %d 条消息 加载更多消息 文件已分享给%s @@ -517,11 +530,11 @@ 授予 %1$s 相机访问权限 同步联系人 %1$s想要访问通讯录的权限来将它与你的 XMPP 联系人列表相匹配。\n这会显示你的联系人的完整姓名和头像。\n\n%1$s只会读取你的通讯录并在本地进行匹配,不会将信息上传到你的服务器。 - 为所有信息显示通知 + 为所有消息显示通知 只在被提到时通知 通知已禁用 通知已暂停 - 图像压缩 + 图片压缩 提示:使用“选择文件”发送原图。这将忽略此设置。 总是 仅大图片 @@ -532,26 +545,26 @@ \n你将被请求禁用这些优化。
禁用 选择区域过大 - (没有启用的账户) + (没有启用的账号) 必填 更正消息 发送更正后的消息 - 您已经验证了该用户。点击“完成”让%s加入群聊。 - 你已经禁用了此账户 + 你已经验证了该用户。点击“完成”让%s加入群聊。 + 你已经禁用了此账号 安全错误:文件访问无效! 未找到可以分享此链接的应用 分享链接…… 同意并继续 - 此向导将为您在conversations.im 上创建一个账户。 -\n您的联系人可以通过您的XMPP完整地址与您聊天。 - 您的XMPP完整地址将是:%s - 创建账户 + 此向导将为你在 conversations.im 上创建一个账号。 +\n你的联系人可以通过你的完整 XMPP 地址与你聊天。 + 你的完整 XMPP 地址将是:%s + 创建账号 使用我自己的服务器 - 输入您的用户名 + 输入你的用户名 手动更改在线状态 - 编辑状态信息时设置您是否有空。 + 在编辑状态信息时设置你的空闲时间。 状态信息 - 有空聊天 + 随时可聊 在线 离开 不在 @@ -568,7 +581,7 @@ 广播使用应用的时间 - 让你的联系人知道你使用Conversations的时间 + 让你的联系人知道你使用 Conversations 的时间 隐私 主题 选择主题色彩 @@ -577,7 +590,7 @@ 灰暗 绿色背景 接收到的消息使用绿色背景 - 无法连接到OpenKeychain + 无法连接到 OpenKeychain 不再使用此设备 电脑 手机 @@ -592,13 +605,13 @@ 无权访问%s 找不到远程服务器 远程服务器超时 - 无法更新账户 + 无法更新账号 举报此 XMPP 地址发送垃圾信息。 - 删除OMEMO身份 - 重新生成OMEMO密钥。所有联系人都需要再次认证。请将此作为最后的办法。 + 删除 OMEMO 身份 + 重新生成 OMEMO 密钥。所有联系人都需要再次认证。请将此作为最后的办法。 删除选择的密钥 你需要连接才能发布头像。 - 显示出错消息 + 显示出错信息 出错信息 省流量模式已启用 你的操作系统正限制 %1$s 在后台时访问互联网。要接收新消息通知,你应当在 \'数据节省\' 处于启用状态时允许 %1$s 不受限制的访问。\n%1$s 在可能的时候仍会试图节省数据。 @@ -612,8 +625,8 @@ 使用相机扫描联系人条码 请等待获取密钥 分享条码 - 分享XMPP URI - 分享HTTP链接 + 分享 XMPP URI + 分享 HTTP 链接 验证前盲目信任 自动信任陌生人的设备,但在验证过联系人添加设备时手动确认。 盲目信任的 OMEMO 密钥,表示它们可能时其他人或者某人可能冒充别人发送消息。 @@ -622,33 +635,34 @@ 清理缓存文件夹(由相机应用使用) 清除缓存 清除私密存储 - 清除保存私密文件的存储 (可以从服务器上重新下载) + 清除保存私密文件的存储(可从服务器重新下载) 此链接的源头是可信的 - 点击链接后将会开始校验%1$s的OMEMO密钥。只有%2$s发布的链接才是安全的。 - 您将验证您自己账户的 OMEMO 密钥。只有当您从可信的来源跟踪此链接时,这才是安全的。“可信”指的是此链接只可能是你在来源中发布的。 + 点击链接后将会开始校验%1$s的 OMEMO 密钥。只有%2$s当你从一个只有你才能发布此链接的可信来源点击此链接时,这才是安全的。 + 你将验证你自己账号的 OMEMO 密钥。只有当你从一个只有你才能发布此链接的可信来源点击此链接时,这才是安全的。 继续 - 校验OMEMO密钥 + 校验 OMEMO 密钥 显示不活跃设备 隐藏不活跃设备 不再信任设备 - 你确认要移除此设备的验证吗?\n此设备及从其发送的信息将会被标识为不可信。 + 你确认要移除此设备的验证吗? +\n此设备及从其发送的消息将会被标识为不可信。 - %d秒 + %d 秒 - %d分钟 + %d 分钟 - %d小时 + %d 小时 - %d天 + %d 天 - %d周 + %d 周 - %d个月 + %d 个月 自动删除消息 自动从此设备上删除超过配置时间段的消息。 @@ -659,13 +673,13 @@ 联系人已封禁。 陌生人的消息也通知 提醒来自陌生人的消息与通话。 - 已收到陌生人的信息 + 已收到陌生人的消息 封禁陌生人 封禁整个域名 当前在线 重试解密 会话失败 - 已降级的SASL机制 + 已降级的 SASL 机制 服务器要求在网站上注册 打开网站 没有可以打开网站的应用 @@ -673,22 +687,22 @@ 显示顶部通知 今天 昨天 - 通过DNSSEC验证主机名 + 通过 DNSSEC 验证主机名 包含主机名的服务器证书被认为是已验证的 - 证书不包含XMPP地址 + 证书不包含 XMPP 地址 一部分 录制视频 - 复制 + 复制到剪贴板 消息已被复制 消息 禁止私信 受保护的应用 - 为了在屏幕关闭时也可收到消息提醒,您需要将Conversations加入受保护的应用列表。 + 为了在屏幕关闭时也可收到消息提醒,你需要将 Conversations 加入受保护的应用列表。 接受未知的证书? 服务器证书未由已知证书机构签发。 接受不匹配的服务器名称? 由于“%s”,服务器无法验证。证书仅对此有效: - 您仍希望连接吗? + 你仍要连接吗? 证书详情: 仅一次 二维码扫描器需要摄像头权限 @@ -701,13 +715,14 @@ 无法获取设备列表 无法获取密钥 提示:某些情况下,可以将对方加入联系人列表,以解决此问题。 - 确认要禁用此会话的OMEMO加密吗?\n这会允许您的服务器管理员阅读你们的消息,但这可能是和使用过时客户端的人会话的唯一方式。 + 你确定要禁用此会话的 OMEMO 加密吗? +\n这将允许服务器管理员阅读你的消息,但这可能是与使用过时客户端的用户进行交流的唯一方法。 立即禁用 草稿: - OMEMO加密 - OMEMO将始终用于一对一和私人群组聊天。 - OMEMO将默认用于新对话。 - OMEMO将明确地被用于新对话。 + OMEMO 加密 + OMEMO 将始终用于一对一和私人群组聊天。 + OMEMO 将默认用于新对话。 + OMEMO 将明确地被用于新对话。 创建快捷方式 字体大小 应用内使用的相对字体大小。 @@ -717,7 +732,7 @@ 消息未对本设备加密。 - 解密OMEMO消息失败。 + 解密 OMEMO 消息失败。 撤销 位置分享已停用 固定位置 @@ -732,13 +747,13 @@ 请等待… 授权 %1$s 访问麦克风 搜索消息 - GIF动图 + GIF 查看聊天 位置分享插件 不使用内置地图,使用“位置分享”插件 - 复制web地址 - 复制XMPP地址 - 用于S3的HTTP文件共享 + 复制网址 + 复制 XMPP 地址 + 用于 S3 的 HTTP 文件共享 直接搜索 在“开始对话”屏幕上打开键盘并将光标放在搜索栏中 群聊头像 @@ -755,15 +770,15 @@ 这个通知类别用于展示一条表明 %1$s 正在运行的永久通知。 状态信息 连接问题 - 此通知类别用于显示账户连接问题通知。 + 此通知类别用于显示账号连接问题通知。 消息 通话 消息 来电 正在进行的通话 未接来电 - 无声消息 - 此通知组用于显示不应触发任何声音的通知。 例如,当在另一个设备上激活时(宽限期)。 + 静默信息 + 此通知组用于显示不应触发任何声音的通知。 例如,在另一台设备上处于活动状态时(宽限期)。 发送失败 消息通知设置 来电通知设置 @@ -783,89 +798,89 @@ 无效国家代码 选择国家 手机号 - 验证手机号 - Quicksy将发送验证码短信(运营商可能收费)。请输入国家代码和手机号: -
%s

。电话号码正确吗?]]>
- %s不是有效的电话号码。 - 请输入手机号。 + 验证你的手机号 + Quicksy 将发送短信(运营商可能收费)验证你的电话号码。请输入你的国家代码和手机号: + 我们将验证这个电话号码

%s

,这样可以吗?或者你想编辑这个号码?
+ %s 不是有效的电话号码。 + 请输入你的手机号。 搜索国家 验证%s - %s。]]> - 已发送另一条6位数验证码短信。 - 请在下方输入6位数的PIN。 + 我们已向你发送短信 %s + 我们已经向你发送了另一条带有 6 位数验证码的短信。 + 请在下方输入 6 位数的PIN。 重新发送短信 - 重发短信(%s) - 请稍候(%s) + 重发短信 (%s) + 请稍候 (%s) 返回 - 自动从剪贴板粘贴了可能是PIN码的数据。 - 请输入6位数PIN码。 - 确定放弃注册? + 自动从剪贴板粘贴了可能是 PIN 码的数据。 + 请输入你的 6 位数 PIN 码。 + 你确定要取消注册程序吗? 正在验证… 正请求短信… - 验证码错误。 - 我们发给你的PIN码已失效。 + 你输入的 PIN 码有误。 + 我们发给你的 PIN 码已过期。 未知网络错误。 未知服务器响应。 无法连接服务器。 无法建立安全连接。 找不到服务器。 - 处理请求时出错。 + 处理你的请求时出了问题。 用户输入无效 暂时无法连接。请稍候再试。 无网络连接. - 请在%s后重试 + 请在 %s 后重试 你被限制速率 尝试次数过多 您正在使用此应用程序的过时版本。 更新 - 此号码已在其他设备上登录。 - 请输入您的姓名。这样,对方就能知道您是谁。 - 您的姓名 - 输入姓名 - 点击编辑按钮以编辑用户名。 + 此电话号码目前已在其他设备上登录。 + 请输入你的名字,以便让通讯录中没有你的人知道你是谁。 + 你的名字 + 输入你的名字 + 使用编辑按钮设置你的名字。 拒绝请求 - 安装Orbot - 启动Orbot + 安装 Orbot + 启动 Orbot 未安装应用商店。 - 此频道将公开你的XMPP地址 + 此频道将公开你的 XMPP 地址 电子书 原始(未压缩) 打开方式… Conversations 个人资料图片 - 选择账户 + 选择账号 恢复备份 恢复 - 输入%s账户的密码以恢复备份。 - 请勿使用恢复备份功能来尝试克隆安装的应用程序(同时运行)。恢复备份功能仅用于迁移或丢失原始设备的情况。 + 输入你的%s账号的密码以恢复备份。 + 请勿使用恢复备份功能尝试克隆(同时运行)安装。恢复备份仅适用于迁移或你丢失原始设备的情况。 无法恢复备份。 无法解密备份。密码是否正确? 备份与恢复 - 输入XMPP地址 + 输入 XMPP 地址 创建群聊 加入公开频道 创建私密群聊 创建公开频道 频道名称 - XMPP地址 + XMPP 地址 请提供频道名 - 请提供XMPP地址 - 这是一个XMPP地址。请提供一个名称。 + 请提供 XMPP 地址 + 这是一个 XMPP 地址。请提供一个名称。 创建公开频道… 频道已存在 您加入了一个已经存在的频道 无法配置频道 - 允许任何成员修改主题 - 允许任何成员邀请其他人 + 允许任何人编辑话题 + 允许任何人邀请别人 任何人可以编辑话题。 - 所有者可修改话题。 - 管理员可修改话题。 - 所有者可以邀请其他人。 - 允许任何成员邀请其他人。 - XMPP地址对管理员可见。 - XMPP 地址对所有人可见。 - 此公开频道无成员。邀请成员或使用分享按钮分享地址。 + 所有者可以编辑话题。 + 管理员可以编辑话题。 + 所有者可以邀请别人。 + 任何人可以邀请别人。 + XMPP 地址对管理员可见。 + XMPP 地址对任何人可见。 + 此公开频道无成员。邀请你的联系人或使用共享按钮分享其 XMPP 地址。 此私密群聊无成员。 管理权限 搜索成员 @@ -874,9 +889,9 @@ 发现频道 搜索频道 可能侵犯隐私! - 我已有账户 - 添加已有账户 - 注册新账户 + 我已有账号 + 添加已有账号 + 注册新账号 这好像是一个域名地址 仍然添加 这好像是一个频道地址 @@ -885,19 +900,19 @@ 事件 打开备份 选择的文件不是备份文件 - 账户已设置 - 请输入此账户的密码 + 账号已设置 + 请输入此账号的密码 无法执行此操作 加入公开频道… - 分享程序没有访问文件的权限。 + 共享应用程序未授予访问此文件的权限。 jabber.network 本地服务器 - 大多数用户应该选择“jabber.network”以从整个XMPP生态系统中获得更好的建议。 + 大多数用户应该选择“jabber.network”以从整个 XMPP 生态系统中获得更好的建议。 频道发现方法 备份 关于 - 请启用一个账户 + 请启用一个账号 进行通话 来电 视频来电 @@ -923,7 +938,7 @@ 正在进行的视频通话 重连通话 重连视频通话 - 禁用Tor以拨打电话 + 禁用 Tor 以拨打电话 来电 错过的通话 · %s 去电 @@ -947,22 +962,22 @@ 无法切换摄像头 置顶 取消置顶 - GPX轨迹 + GPX 轨迹 无法更正消息 所有会话 该会话 你的头像 %s的头像 - 用OMEMO加密 - 用OpenPGP加密 + 用 OMEMO 加密 + 用 OpenPGP 加密 未加密 退出 语音邮件录音 播放音频 暂停音频播放 - 添加联系人、创建或加入群组会话,或发现频道 + 添加联系人、创建或加入群聊,或发现频道 - 查看%1$d成员 + 查看 %1$d 位成员 一些消息无法发送 @@ -973,33 +988,33 @@ 邀请到 Conversations 无法解析邀请 服务器不支持生成邀请 - 没有活跃账户支持此功能 + 没有活动账号支持此功能 已启动备份。一旦完成,你会收到通知。 无法启用视频。 纯文本文档 - 不支持注册账户 + 不支持注册账号 未找到 XMPP 地址 临时认证失败 删除头像 使用 Tor 时通话被禁用 切换到视频 拒绝切换到视频的请求 - XMPP 账户 + XMPP 账号 推送服务器 无(未激活) UnifiedPush 分发程序 - 将通过该账户接收推送消息。 + 将通过该账号接收推送消息。 用户选择的推送服务器,通过 XMPP 将推送消息传递到你的设备。 拒绝 来电 (%s) · %s 去电 (%s) · %s 去电 · %s 频道发现功能使用第三方服务 <a href=https://search.jabber.network>search.jabber.network</a>。<br><br>使用此功能会发送你的 IP 地址和搜索词条到该服务。更多信息见 <a href=https://search.jabber.network/privacy>隐私政策</a>。 - 无法从服务器删除账户 + 无法从服务器删除账号 群聊 另存为群聊 搜索群聊 - 从服务器删除账户 + 从服务器删除账号 不要尝试恢复你尚未自行创建的备份! 你正尝试导入过时的备份文件格式
\ No newline at end of file From 138462f13f38e6466855fcd4de96f9748e2c75f5 Mon Sep 17 00:00:00 2001 From: hamburger1024 Date: Sat, 7 Oct 2023 04:17:57 +0000 Subject: [PATCH 145/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (969 of 969 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index d131fbd28..4f577cfa3 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -1017,4 +1017,5 @@ 从服务器删除账号 不要尝试恢复你尚未自行创建的备份! 你正尝试导入过时的备份文件格式 + 有声书 \ No newline at end of file From 3104cee60223a38f7d4fabfc1837bb99f051d9ba Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Mon, 9 Oct 2023 03:25:40 +0000 Subject: [PATCH 146/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (13 of 13 strings) Translation: Conversations/Android App (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-conversations/zh_Hans/ --- src/conversations/res/values-zh-rCN/strings.xml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/conversations/res/values-zh-rCN/strings.xml b/src/conversations/res/values-zh-rCN/strings.xml index 961973b8c..bc4c9d730 100644 --- a/src/conversations/res/values-zh-rCN/strings.xml +++ b/src/conversations/res/values-zh-rCN/strings.xml @@ -2,11 +2,15 @@ 选择您的 XMPP 提供者 使用 conversations.im - 创建新账户 - 您有 XMPP 账户吗?如果您之前使用过其他的 XMPP 客户端,那么您已经拥有这种账户了。如果没有的话,您现在可以创建一个。\n提示:有些电子邮件服务也提供XMPP账户。 - XMPP 是独立于提供者的即时消息网络。您可以将此客户端与任意 XMPP 服务器一同使用。\n不过,您可以很容易地在 conversations.im 上创建账户;它是特别适合与“Conversations”一起使用的提供者。 - 您已受邀加入 %1$s。我们将指导您完成创建帐户的过程。\n使用 %1$s 作为提供者时,您可以通过您的完整 XMPP 地址与其他提供者的用户进行交流。 - 您已受邀加入 %1$s。已为您选择了一个用户名。我们将指导您完成创建帐户的过程。\n您可以使用完整的 XMPP 地址来与其他提供者的用户进行交流。 + 创建新账号 + 您有 XMPP 账号吗?如果您之前使用过其他的 XMPP 客户端,那么您已经拥有这种账号了。如果没有的话,您现在可以创建一个。 +\n提示:有些电子邮件服务也提供XMPP账号。 + XMPP 是独立于提供者的即时消息网络。您可以将此客户端与任意 XMPP 服务器一同使用。 +\n不过,您可以很容易地在 conversations.im 上创建账号;它是特别适合与“Conversations”一起使用的提供者。 + 您已受邀加入 %1$s。我们将指导您完成创建账号的过程。 +\n使用 %1$s 作为提供者时,您可以通过您的完整 XMPP 地址与其他提供者的用户进行交流。 + 您已受邀加入 %1$s。已为您选择了一个用户名。我们将指导您完成创建账号的过程。 +\n您可以使用完整的 XMPP 地址来与其他提供者的用户进行交流。 你的服务器邀请 格式不正确的配置代码 点击分享按钮向您的联系人发送加入 %1$s 的邀请。 From c15b4f8ac8e3ebc88a7ed1698be6cfa8d7352336 Mon Sep 17 00:00:00 2001 From: alextecplayz Date: Mon, 9 Oct 2023 09:21:00 +0000 Subject: [PATCH 147/402] Translated using Weblate (Romanian) Currently translated at 29.4% (15 of 51 strings) Translation: Conversations/App Store Metadata (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/ro/ --- fastlane/metadata/android/ro/changelogs/349.txt | 4 ++++ fastlane/metadata/android/ro/changelogs/351.txt | 3 +++ fastlane/metadata/android/ro/changelogs/353.txt | 4 ++++ fastlane/metadata/android/ro/changelogs/360.txt | 1 + fastlane/metadata/android/ro/changelogs/362.txt | 1 + fastlane/metadata/android/ro/changelogs/364.txt | 2 ++ fastlane/metadata/android/ro/changelogs/367.txt | 2 ++ fastlane/metadata/android/ro/changelogs/379.txt | 1 + fastlane/metadata/android/ro/changelogs/381.txt | 2 ++ fastlane/metadata/android/ro/changelogs/382.txt | 2 ++ fastlane/metadata/android/ro/changelogs/383.txt | 3 +++ fastlane/metadata/android/ro/changelogs/387.txt | 2 ++ fastlane/metadata/android/ro/changelogs/388.txt | 3 +++ fastlane/metadata/android/ro/changelogs/390.txt | 1 + fastlane/metadata/android/ro/changelogs/393.txt | 3 +++ 15 files changed, 34 insertions(+) create mode 100644 fastlane/metadata/android/ro/changelogs/349.txt create mode 100644 fastlane/metadata/android/ro/changelogs/351.txt create mode 100644 fastlane/metadata/android/ro/changelogs/353.txt create mode 100644 fastlane/metadata/android/ro/changelogs/360.txt create mode 100644 fastlane/metadata/android/ro/changelogs/362.txt create mode 100644 fastlane/metadata/android/ro/changelogs/364.txt create mode 100644 fastlane/metadata/android/ro/changelogs/367.txt create mode 100644 fastlane/metadata/android/ro/changelogs/379.txt create mode 100644 fastlane/metadata/android/ro/changelogs/381.txt create mode 100644 fastlane/metadata/android/ro/changelogs/382.txt create mode 100644 fastlane/metadata/android/ro/changelogs/383.txt create mode 100644 fastlane/metadata/android/ro/changelogs/387.txt create mode 100644 fastlane/metadata/android/ro/changelogs/388.txt create mode 100644 fastlane/metadata/android/ro/changelogs/390.txt create mode 100644 fastlane/metadata/android/ro/changelogs/393.txt diff --git a/fastlane/metadata/android/ro/changelogs/349.txt b/fastlane/metadata/android/ro/changelogs/349.txt new file mode 100644 index 000000000..0f1ea5501 --- /dev/null +++ b/fastlane/metadata/android/ro/changelogs/349.txt @@ -0,0 +1,4 @@ +* Introducerea setărilor pentru experți pentru a efectua descoperirea canalelor pe serverul local în loc de search.jabber.network +* Activarea marcajelor de verificare a livrării în mod implicit și eliminarea setării +* Activarea "Butonul de trimitere indică starea" în mod implicit și eliminarea setării +*Mutarea setărilor Serviciului de rezervă și ale Serviciului de prim-plan în ecranul principal diff --git a/fastlane/metadata/android/ro/changelogs/351.txt b/fastlane/metadata/android/ro/changelogs/351.txt new file mode 100644 index 000000000..629d86109 --- /dev/null +++ b/fastlane/metadata/android/ro/changelogs/351.txt @@ -0,0 +1,3 @@ +* reparații pentru transferul de fișiere Jingle IBB +* reparații pentru corecțiile repetate care umplu baza de date +* schimbarea la Corectarea Ultimului Mesaj v1.1 diff --git a/fastlane/metadata/android/ro/changelogs/353.txt b/fastlane/metadata/android/ro/changelogs/353.txt new file mode 100644 index 000000000..1c788dab6 --- /dev/null +++ b/fastlane/metadata/android/ro/changelogs/353.txt @@ -0,0 +1,4 @@ +* utilizatorii pot să își seteze propria poreclă +* continuarea descărcării de fișiere criptate OMEMO +* Canalele folosesc '#' ca simbol în avatar +* Quicksy folosește 'mereu' ca și criptare implicită OMEMO (ascunde iconița lacăt) diff --git a/fastlane/metadata/android/ro/changelogs/360.txt b/fastlane/metadata/android/ro/changelogs/360.txt new file mode 100644 index 000000000..7949e0d14 --- /dev/null +++ b/fastlane/metadata/android/ro/changelogs/360.txt @@ -0,0 +1 @@ +* Suport pentru parametrii uri ?register și ?register;preauth XMPP diff --git a/fastlane/metadata/android/ro/changelogs/362.txt b/fastlane/metadata/android/ro/changelogs/362.txt new file mode 100644 index 000000000..46a802c73 --- /dev/null +++ b/fastlane/metadata/android/ro/changelogs/362.txt @@ -0,0 +1 @@ +* Suport pentru comutarea automată a temei pe Android 10 diff --git a/fastlane/metadata/android/ro/changelogs/364.txt b/fastlane/metadata/android/ro/changelogs/364.txt new file mode 100644 index 000000000..95ea86302 --- /dev/null +++ b/fastlane/metadata/android/ro/changelogs/364.txt @@ -0,0 +1,2 @@ +* Furnizarea de previzualizări PDF pe Android 5+ +* Folosirea IV-urilor de 12 biți pentru OMEMO diff --git a/fastlane/metadata/android/ro/changelogs/367.txt b/fastlane/metadata/android/ro/changelogs/367.txt new file mode 100644 index 000000000..9575f811d --- /dev/null +++ b/fastlane/metadata/android/ro/changelogs/367.txt @@ -0,0 +1,2 @@ +* Repararea selecției de avatar pe unele dispozitive ce rulează Android 10 +* Repararea transferului de fișiere pentru fișiere mari diff --git a/fastlane/metadata/android/ro/changelogs/379.txt b/fastlane/metadata/android/ro/changelogs/379.txt new file mode 100644 index 000000000..7bbc1c965 --- /dev/null +++ b/fastlane/metadata/android/ro/changelogs/379.txt @@ -0,0 +1 @@ +* Apeluri Audio/Video (Necesită suport pe server în formă de servere STUN și TURN descoperibile prin XEP-0125) diff --git a/fastlane/metadata/android/ro/changelogs/381.txt b/fastlane/metadata/android/ro/changelogs/381.txt new file mode 100644 index 000000000..9d8e76ba3 --- /dev/null +++ b/fastlane/metadata/android/ro/changelogs/381.txt @@ -0,0 +1,2 @@ +* Feedback auditoriu (apelare, apel început, apel terminat) pentru apeluri vocale +* Problemă rezolvată cu reîncercarea apelului video eșuat diff --git a/fastlane/metadata/android/ro/changelogs/382.txt b/fastlane/metadata/android/ro/changelogs/382.txt new file mode 100644 index 000000000..f9eb35219 --- /dev/null +++ b/fastlane/metadata/android/ro/changelogs/382.txt @@ -0,0 +1,2 @@ +* Adăugarea butonului pentru a schimba camera în timpul apelului video +* Repararea apelurilor voce pe tablete diff --git a/fastlane/metadata/android/ro/changelogs/383.txt b/fastlane/metadata/android/ro/changelogs/383.txt new file mode 100644 index 000000000..ee79d607e --- /dev/null +++ b/fastlane/metadata/android/ro/changelogs/383.txt @@ -0,0 +1,3 @@ +* Mutarea iconiței de apel către stânga pentru a ține celelalte iconițe din bara de instrumente într-un loc consistent +* Afișarea durației apelurilor în timpul apelurilor audio +* Ruperea egalității pentru apeluri audio/video (aceleași două persoane care se sună între ele în același timp) diff --git a/fastlane/metadata/android/ro/changelogs/387.txt b/fastlane/metadata/android/ro/changelogs/387.txt new file mode 100644 index 000000000..4faeea6b1 --- /dev/null +++ b/fastlane/metadata/android/ro/changelogs/387.txt @@ -0,0 +1,2 @@ +* Refacerea logării cu UI pentru certificate +* Adăugarea abilității de a fixa conversații sus (adăugarea la favorite) diff --git a/fastlane/metadata/android/ro/changelogs/388.txt b/fastlane/metadata/android/ro/changelogs/388.txt new file mode 100644 index 000000000..0fbd0d92e --- /dev/null +++ b/fastlane/metadata/android/ro/changelogs/388.txt @@ -0,0 +1,3 @@ +* Reducerea ecoului în timpul apelurilor pe unele dispozitive +* Repararea logării când parolele conțin caractere speciale +* Redarea tonurilor de apel și ocupat pe difuzor în timpul apelurilor video diff --git a/fastlane/metadata/android/ro/changelogs/390.txt b/fastlane/metadata/android/ro/changelogs/390.txt new file mode 100644 index 000000000..8ae2da5cb --- /dev/null +++ b/fastlane/metadata/android/ro/changelogs/390.txt @@ -0,0 +1 @@ +* Oferirea de a înregistra mesaj vocal când persoana apelată este ocupată diff --git a/fastlane/metadata/android/ro/changelogs/393.txt b/fastlane/metadata/android/ro/changelogs/393.txt new file mode 100644 index 000000000..712b8e420 --- /dev/null +++ b/fastlane/metadata/android/ro/changelogs/393.txt @@ -0,0 +1,3 @@ +* Afișarea butonului de ajutor dacă apelul audio/video eșuează +* Repararea unor crash-uri enervante +* Repararea conexiunilor Jingle (transfer fișiere + apeluri) cu JID-uri goale From 458cd4bf8dc58305732dbea7d112847ad36df179 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Tue, 10 Oct 2023 05:15:47 +0000 Subject: [PATCH 148/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (969 of 969 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 142 +++++++++++++------------ 1 file changed, 72 insertions(+), 70 deletions(-) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index 4f577cfa3..0e88b78ed 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -1,10 +1,10 @@ 设置 - 新对话 + 新会话 管理账号 管理账号 - 关闭 Conversation + 关闭会话 联系人详情 群聊详情 频道详情 @@ -20,8 +20,8 @@ 解封成员 管理账号 设置 - 通过 Conversations 分享 - 开始对话 + 分享至会话 + 开始会话 选择联系人 选择联系人 通过账号分享 @@ -42,18 +42,18 @@ 群主 成员 访客 - 你要将%s从 XMPP 联系人中移除吗?与该联系人的会话消息不会清除。 - 你想封禁 %s向你发送信息吗? - 你想解除对%s的封禁,让他们给你发送信息吗? - 封禁%s中的所有联系人? - 解封%s中所有联系人? + 你想从通讯录中移除%s吗?此联系人的会话不会被移除。 + 你想封禁 %s向你发送消息吗? + 你想解除对%s的封禁,并允许他们给你发送消息吗? + 封禁来自%s的所有联系人吗\? + 解封来自%s的所有联系人吗? 联系人已封禁 已封禁 - 你想从书签中移除%s吗?相关会话消息不会被清除。 + 你想从书签中移除%s吗?此书签的会话将不会被清除。 在服务器上注册新账号 在服务器上修改密码 分享… - 开始聊天 + 开始会话 邀请联系人 邀请 联系人 @@ -68,29 +68,29 @@ 保存 完成 %1$s已崩溃 - 用你的 XMPP 账号发送堆栈跟踪来帮助持续开发 %1$s。 + 用你的 XMPP 账号发送堆栈跟踪有助于%1$s的持续开发。 立即发送 不再询问 - 账号无法连接 + 无法连接账号 无法连接到多个账号 点击管理账号 发送文件 - 该联系人不在您的通讯录中,需要添加吗 ? + 该联系人不在你的通讯录中,需要添加吗 \? 添加联系人 传递失败 准备发送图片 准备发送图片 正在分享文件,请稍候… 清除历史记录 - 清除聊天记录 - 你想删除此聊天中的所有消息吗? + 清除会话记录 + 你想删除此会话中的所有消息吗? \n \n警告:这不会删除存储在其他设备或服务器上的那些消息的副本。 删除文件 你确定要删除此文件吗? \n \n警告:这不会删除存储在其他设备或服务器上的此文件的副本。 - 之后关闭此聊天 + 之后关闭此会话 选择设备 发送未加密的消息 发送消息 @@ -98,8 +98,8 @@ 发送 OMEMO 加密消息 发送 v\\OMEMO 加密消息 发送 OpenPGP 加密消息 - 昵称已被使用 - 不加密发送 + 新昵称正在使用 + 发送未加密 解密失败,也许你没有正确的私钥。 OpenKeychain %1$s使用 <b>OpenKeychain</b>来加密和解密消息并管理你的公钥。<br><br>它在 GPLv3+ 许可证下授权并可在 F-Droid 和 Google Play 上获得。<br><br><small>(请稍后重新启动%1$s。)</small> @@ -165,11 +165,11 @@ 连接中\u2026 离线 未授权 - 未找到服务器 + 服务器未找到 未连接网络 注册失败 用户名已使用 - 注册完成 + 注册已完成 服务器不支持注册 无效的注册令牌 TLS 协商失败 @@ -192,7 +192,7 @@ \n你的联系人将无法再向你发送 OpenPGP 加密消息。 OpenPGP 公钥已发布。 启用账号 - 你确定删除账号吗?如果你删除账号,你的所有聊天记录将会丢失 + 你确定删除账号吗?如果你删除账号,你的所有会话记录将会丢失 录制音频 XMPP 地址 封禁 XMPP 地址 @@ -264,18 +264,18 @@ 离开 联系人已添加你到通讯录 反向添加 - %s读到这里了 - %s读到这里了 - %1$s和另外%2$d人读到这里了 - 所有人都读到这里了 + %s 已阅读至此 + %s 已阅读至此 + %1$s和另外%2$d人都已阅读至此 + 所有人都已阅读至此 发布 - 点击头像以选择图片 + 点击头像从图库中选择图片 正在发布… 服务器拒绝了你的发布请求 无法转换你的图片 不能将头像保存至磁盘 (或长按恢复默认) - 服务器不支持头像 + 你的服务器不支持发布头像 私聊 至%s 与%s私聊 @@ -311,28 +311,28 @@ 同步书签 加入或离开多用户聊天时设置 “autojoin\" 标志,并回应其他客户端所做更改。 OMEMO 指纹已复制到剪贴板 - 您被此群聊封禁 - 这个群聊只允许成员聊天 + 你被此群聊封禁 + 这个群聊只对成员开放 资源限制 - 您被从此群聊踢出 - 这个群聊已被关闭 - 您已不在该群组 + 你被此群聊踢出 + 此群聊已被关闭 + 你已不在此群聊 你由于技术原因离开了群聊 使用账号%s 托管于%s 正在 HTTP 服务器中检查%s - 未连接。请稍后重试 + 你没有连接。稍后再试 检查%s的大小 在%2$s上检查%1$s的大小 消息选项 引用 - 作为引用粘贴 + 粘贴为引用 复制原始 URL 重新发送 文件 URL - 已经复制 URL 到剪贴板 + 已复制 URL 到剪贴板 已复制 XMPP 地址到剪贴板 - 已复制错误信息到剪贴板 + 已复制错误消息到剪贴板 网址 扫描二维码 显示二维码 @@ -344,7 +344,7 @@ 防止操作系统中断连接 创建备份 备份文件将保存在%s - 正在备份文件 + 创建备份文件中 备份已创建 此备份文件已经存储在%s 正在恢复备份 @@ -363,8 +363,8 @@ 文件传输失败 文件传输已取消 文件已经删除 - 没有可以打开此文件的应用 - 没有可以打开此链接的应用 + 未找到可以打开此文件的应用 + 未找到可以打开此链接的应用 未找到可以查看联系人的应用 动态标签 在联系人下方显示只读标签 @@ -375,10 +375,11 @@ 复制 OMEMO 指纹到剪贴板 重新生成 OMEMO 密钥 清除设备 - 清除所有其他设备的 OMEMO 通告?下次设备连接时将重新通告,但可能收不到你发送的消息。 + 你确定要从 OMEMO 公布中清除所有其他设备吗?下次你的设备连接时,它们将重新公布自己,但可能不会收到同时发送的消息。 此联系人没有可用的密钥。 -\n无法从服务器获取新密钥。也许你的联系人所在服务器发生问题了? - 没有可以用于这个账户的密钥。\n请确保你有相互的在线状态的订阅。 +\n无法从服务器获取新密钥。也许是你联系人的服务器出了问题?
+ 该联系人没有可用的密钥。 +\n确保你们双方都有在线状态订阅。 出错了 正在从服务器获取历史记录 服务器上没有更多历史记录 @@ -391,7 +392,7 @@ 密码不能为空 启用所有账号 禁用所有账号 - 选择一个操作 + 执行操作 没有从属关系 离线 已逐出 @@ -408,13 +409,13 @@ 不能修改%s的从属关系 从群聊中封禁 从频道中封禁 - %s将被从公共频道中移除。唯一的办法就是永远封禁该用户。 + 你正在尝试从公共频道中移除%s。唯一的办法就是永远封禁此用户。 立即封禁 不能修改%s的角色 私密群聊设置 公开频道设置 - 私密,只有成员可以加入 - 使 XMPP 地址对所有人可见 + 私密,仅限成员 + 使 XMPP 地址对任何人可见 使频道受到管理 你未参与 群聊设置修改成功! @@ -446,12 +447,12 @@ %s正在输入…… %s已停止输入 输入通知 - 让对方知道你正在输入 + 让对方知道你正在写消息 发送位置 显示位置 - 无法找到显示位置的应用 + 未找到显示位置的应用 位置 - 聊天已关闭 + 会话已关闭 离开私密群聊 离开公开频道 不信任系统证书 @@ -555,15 +556,15 @@ 未找到可以分享此链接的应用 分享链接…… 同意并继续 - 此向导将为你在 conversations.im 上创建一个账号。 -\n你的联系人可以通过你的完整 XMPP 地址与你聊天。 + 在 conversations.im 上有创建一个账号的指南。 +\n选择 conversations.im 作为提供商时,你只需提供完整的 XMPP 地址,就能与其他提供商的用户进行交流。 你的完整 XMPP 地址将是:%s 创建账号 使用我自己的服务器 输入你的用户名 - 手动更改在线状态 - 在编辑状态信息时设置你的空闲时间。 - 状态信息 + 手动管理可用性 + 在编辑状态消息时设置你的可用时间。 + 状态消息 随时可聊 在线 离开 @@ -603,7 +604,7 @@ 联系人请求在线状态订阅 允许 无权访问%s - 找不到远程服务器 + 远程服务器未找到 远程服务器超时 无法更新账号 举报此 XMPP 地址发送垃圾信息。 @@ -611,16 +612,17 @@ 重新生成 OMEMO 密钥。所有联系人都需要再次认证。请将此作为最后的办法。 删除选择的密钥 你需要连接才能发布头像。 - 显示出错信息 - 出错信息 + 显示出错消息 + 出错消息 省流量模式已启用 - 你的操作系统正限制 %1$s 在后台时访问互联网。要接收新消息通知,你应当在 \'数据节省\' 处于启用状态时允许 %1$s 不受限制的访问。\n%1$s 在可能的时候仍会试图节省数据。 + 你的操作系统正限制 %1$s 在后台时访问互联网。要接收新消息通知,你应当在“数据节省”处于启用状态时允许 %1$s 不受限制的访问。 +\n%1$s 在可能的时候仍会试图节省数据。 你的设备不支持对 %1$s 禁用数据节省器。 无法创建临时文件 已验证此设备 复制指纹 你已验证了你拥有的所有 OMEMO 密钥 - 条码不包含用于聊天的指纹。 + 条形码不包含此次会话的指纹。 已验证的指纹 使用相机扫描联系人条码 请等待获取密钥 @@ -682,7 +684,7 @@ 已降级的 SASL 机制 服务器要求在网站上注册 打开网站 - 没有可以打开网站的应用 + 未找到可以打开网站的应用 顶部通知 显示顶部通知 今天 @@ -708,8 +710,8 @@ 二维码扫描器需要摄像头权限 滚动到底部 发送消息后滚动到底部 - 编辑状态信息 - 编辑状态信息 + 编辑状态消息 + 编辑状态消息 禁用加密 %1$s 无法发送加密消息到 %2$s。这可能是因为你的联系人使用了过期的服务器或者无法处理 OMEMO 的客户端。 无法获取设备列表 @@ -721,7 +723,7 @@ 草稿: OMEMO 加密 OMEMO 将始终用于一对一和私人群组聊天。 - OMEMO 将默认用于新对话。 + OMEMO 将默认用于新会话。 OMEMO 将明确地被用于新对话。 创建快捷方式 字体大小 @@ -748,14 +750,14 @@ 授权 %1$s 访问麦克风 搜索消息 GIF - 查看聊天 + 查看会话 位置分享插件 不使用内置地图,使用“位置分享”插件 复制网址 复制 XMPP 地址 用于 S3 的 HTTP 文件共享 直接搜索 - 在“开始对话”屏幕上打开键盘并将光标放在搜索栏中 + 在“开始会话”屏幕上打开键盘并将光标放在搜索栏中 群聊头像 主机不支持群聊头像 只有所有者才能更改群聊头像 @@ -896,10 +898,10 @@ 仍然添加 这好像是一个频道地址 分享备份文件 - 备份文件 + Conversations 备份 事件 打开备份 - 选择的文件不是备份文件 + 选择的文件不是 Conversations 备份文件 账号已设置 请输入此账号的密码 无法执行此操作 @@ -955,7 +957,7 @@ 语音通话 视频通话 帮助 - 切换到对话 + 切换到会话 麦克风不可用 一次只能打一通电话。 返回正在进行的通话 @@ -984,7 +986,7 @@ 发送失败 更多选项 - 没有找到应用程序 + 未找到应用程序 邀请到 Conversations 无法解析邀请 服务器不支持生成邀请 From 8cb802e7c1b2483d5446ec57f4b2d70a282e6386 Mon Sep 17 00:00:00 2001 From: hamburger1024 Date: Tue, 10 Oct 2023 03:01:22 +0000 Subject: [PATCH 149/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (969 of 969 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index 0e88b78ed..a5bab88ff 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -699,7 +699,7 @@ 消息 禁止私信 受保护的应用 - 为了在屏幕关闭时也可收到消息提醒,你需要将 Conversations 加入受保护的应用列表。 + 为了在屏幕关闭时也能收到消息提醒,你需要将 Conversations 加入受保护的应用列表。 接受未知的证书? 服务器证书未由已知证书机构签发。 接受不匹配的服务器名称? From dbf71e5d54bae57f3c506248fb17f7c18dd98ec9 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 10 Oct 2023 18:42:23 +0200 Subject: [PATCH 150/402] handle senders modification via content-modify Dino uses this to enable/disable video when a video content is already present --- .../xmpp/jingle/JingleConnectionManager.java | 4 +- .../xmpp/jingle/JingleRtpConnection.java | 88 ++++++++++++++++--- .../jingle/stanzas/IceUdpTransportInfo.java | 67 +++++++------- 3 files changed, 117 insertions(+), 42 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java index 1872f6b32..1a55b9a96 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java @@ -251,7 +251,9 @@ public class JingleConnectionManager extends AbstractConnectionManager { final Element error = response.addChild("error"); error.setAttribute("type", conditionType); error.addChild(condition, "urn:ietf:params:xml:ns:xmpp-stanzas"); - error.addChild(jingleCondition, Namespace.JINGLE_ERRORS); + if (jingleCondition != null) { + error.addChild(jingleCondition, Namespace.JINGLE_ERRORS); + } account.getXmppConnection().sendIqPacket(response, null); } diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java index 38cba946f..fa54a9886 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java @@ -14,8 +14,11 @@ import com.google.common.base.Throwables; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; import com.google.common.collect.Sets; import com.google.common.primitives.Ints; import com.google.common.util.concurrent.FutureCallback; @@ -551,15 +554,17 @@ public class JingleRtpConnection extends AbstractJingleConnection } private void receiveContentModify(final JinglePacket jinglePacket) { + // TODO check session accepted final Map modification = Maps.transformEntries( jinglePacket.getJingleContents(), (key, value) -> value.getSenders()); - respondOk(jinglePacket); + final boolean isInitiator = isInitiator(); final RtpContentMap currentOutgoing = this.outgoingContentAdd; + final RtpContentMap remoteContentMap = this.getRemoteContentMap(); final Set currentOutgoingMediaIds = currentOutgoing == null ? Collections.emptySet() : currentOutgoing.contents.keySet(); Log.d(Config.LOGTAG, "receiveContentModification(" + modification + ")"); if (currentOutgoing != null && currentOutgoingMediaIds.containsAll(modification.keySet())) { - final boolean isInitiator = isInitiator(); + respondOk(jinglePacket); final RtpContentMap modifiedContentMap; try { modifiedContentMap = currentOutgoing.modifiedSendersChecked(isInitiator, modification); @@ -570,18 +575,72 @@ public class JingleRtpConnection extends AbstractJingleConnection } this.outgoingContentAdd = modifiedContentMap; Log.d(Config.LOGTAG, id.account.getJid().asBareJid()+": processed content-modification for pending content-add"); + } else if (remoteContentMap != null && remoteContentMap.contents.keySet().containsAll(modification.keySet())) { + respondOk(jinglePacket); + final RtpContentMap modifiedRemoteContentMap; + try { + modifiedRemoteContentMap = remoteContentMap.modifiedSendersChecked(isInitiator, modification); + } catch (final IllegalArgumentException e) { + webRTCWrapper.close(); + sendSessionTerminate(Reason.FAILED_APPLICATION, e.getMessage()); + return; + } + final SessionDescription offer; + try { + offer = SessionDescription.of(modifiedRemoteContentMap, !isInitiator()); + } catch (final IllegalArgumentException | NullPointerException e) { + Log.d(Config.LOGTAG, id.getAccount().getJid().asBareJid() + ": unable convert offer from content-modify to SDP", e); + webRTCWrapper.close(); + sendSessionTerminate(Reason.FAILED_APPLICATION, e.getMessage()); + return; + } + Log.d(Config.LOGTAG, id.account.getJid().asBareJid()+": auto accepting content-modification"); + this.autoAcceptContentModify(modifiedRemoteContentMap, offer); } else { - webRTCWrapper.close(); - sendSessionTerminate( - Reason.FAILED_APPLICATION, - String.format( - "%s only supports %s as a means to modify a not yet accepted %s", - BuildConfig.APP_NAME, - JinglePacket.Action.CONTENT_MODIFY, - JinglePacket.Action.CONTENT_ADD)); + Log.d(Config.LOGTAG,"received unsupported content modification "+modification); + respondWithItemNotFound(jinglePacket); } } + private void autoAcceptContentModify(final RtpContentMap modifiedRemoteContentMap, final SessionDescription offer) { + this.setRemoteContentMap(modifiedRemoteContentMap); + final org.webrtc.SessionDescription sdp = + new org.webrtc.SessionDescription( + org.webrtc.SessionDescription.Type.OFFER, offer.toString()); + try { + this.webRTCWrapper.setRemoteDescription(sdp).get(); + // auto accept is only done when we already have tracks + final SessionDescription answer = setLocalSessionDescription(); + final RtpContentMap rtpContentMap = RtpContentMap.of(answer, isInitiator()); + modifyLocalContentMap(rtpContentMap); + // we do not need to send an answer but do we have to resend the candidates currently in SDP? + //resendCandidatesFromSdp(answer); + webRTCWrapper.setIsReadyToReceiveIceCandidates(true); + } catch (final Exception e) { + Log.d(Config.LOGTAG, "unable to accept content add", Throwables.getRootCause(e)); + webRTCWrapper.close(); + sendSessionTerminate(Reason.FAILED_APPLICATION); + } + } + + private void resendCandidatesFromSdp(final SessionDescription answer) { + final ImmutableMultimap.Builder candidateBuilder = new ImmutableMultimap.Builder<>(); + for(final SessionDescription.Media media : answer.media) { + final String mid = Iterables.getFirst(media.attributes.get("mid"), null); + if (Strings.isNullOrEmpty(mid)) { + continue; + } + for(final String sdpCandidate : media.attributes.get("candidate")) { + final IceUdpTransportInfo.Candidate candidate = IceUdpTransportInfo.Candidate.fromSdpAttributeValue(sdpCandidate, null); + if (candidate != null) { + candidateBuilder.put(mid,candidate); + } + } + } + final ImmutableMultimap candidates = candidateBuilder.build(); + sendTransportInfo(candidates); + } + private void receiveContentReject(final JinglePacket jinglePacket) { final RtpContentMap receivedContentReject; try { @@ -1942,6 +2001,11 @@ public class JingleRtpConnection extends AbstractJingleConnection send(jinglePacket); } + private void sendTransportInfo(final Multimap candidates) { + // TODO send all candidates in one transport-info + } + + private void send(final JinglePacket jinglePacket) { jinglePacket.setTo(id.with); xmppConnectionService.sendIqPacket(id.account, jinglePacket, this::handleIqResponse); @@ -2028,6 +2092,10 @@ public class JingleRtpConnection extends AbstractJingleConnection respondWithJingleError(jinglePacket, "out-of-order", "unexpected-request", "wait"); } + private void respondWithItemNotFound(final JinglePacket jinglePacket) { + respondWithJingleError(jinglePacket, null, "item-not-found", "cancel"); + } + void respondWithJingleError( final IqPacket original, String jingleCondition, diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/IceUdpTransportInfo.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/IceUdpTransportInfo.java index 8939ecb1b..026adbd02 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/IceUdpTransportInfo.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/IceUdpTransportInfo.java @@ -202,41 +202,46 @@ public class IceUdpTransportInfo extends GenericTransportInfo { public static Candidate fromSdpAttribute(final String attribute, String currentUfrag) { final String[] pair = attribute.split(":", 2); if (pair.length == 2 && "candidate".equals(pair[0])) { - final String[] segments = pair[1].split(" "); - if (segments.length >= 6) { - final String id = UUID.randomUUID().toString(); - final String foundation = segments[0]; - final String component = segments[1]; - final String transport = segments[2].toLowerCase(Locale.ROOT); - final String priority = segments[3]; - final String connectionAddress = segments[4]; - final String port = segments[5]; - final HashMap additional = new HashMap<>(); - for (int i = 6; i < segments.length - 1; i = i + 2) { - additional.put(segments[i], segments[i + 1]); - } - final String ufrag = additional.get("ufrag"); - if (ufrag != null && !ufrag.equals(currentUfrag)) { - return null; - } - final Candidate candidate = new Candidate(); - candidate.setAttribute("component", component); - candidate.setAttribute("foundation", foundation); - candidate.setAttribute("generation", additional.get("generation")); - candidate.setAttribute("rel-addr", additional.get("raddr")); - candidate.setAttribute("rel-port", additional.get("rport")); - candidate.setAttribute("id", id); - candidate.setAttribute("ip", connectionAddress); - candidate.setAttribute("port", port); - candidate.setAttribute("priority", priority); - candidate.setAttribute("protocol", transport); - candidate.setAttribute("type", additional.get("typ")); - return candidate; - } + return fromSdpAttributeValue(pair[1], currentUfrag); } return null; } + public static Candidate fromSdpAttributeValue(final String value, final String currentUfrag) { + final String[] segments = value.split(" "); + if (segments.length < 6) { + return null; + } + final String id = UUID.randomUUID().toString(); + final String foundation = segments[0]; + final String component = segments[1]; + final String transport = segments[2].toLowerCase(Locale.ROOT); + final String priority = segments[3]; + final String connectionAddress = segments[4]; + final String port = segments[5]; + final HashMap additional = new HashMap<>(); + for (int i = 6; i < segments.length - 1; i = i + 2) { + additional.put(segments[i], segments[i + 1]); + } + final String ufrag = additional.get("ufrag"); + if (currentUfrag != null && ufrag != null && !ufrag.equals(currentUfrag)) { + return null; + } + final Candidate candidate = new Candidate(); + candidate.setAttribute("component", component); + candidate.setAttribute("foundation", foundation); + candidate.setAttribute("generation", additional.get("generation")); + candidate.setAttribute("rel-addr", additional.get("raddr")); + candidate.setAttribute("rel-port", additional.get("rport")); + candidate.setAttribute("id", id); + candidate.setAttribute("ip", connectionAddress); + candidate.setAttribute("port", port); + candidate.setAttribute("priority", priority); + candidate.setAttribute("protocol", transport); + candidate.setAttribute("type", additional.get("typ")); + return candidate; + } + public int getComponent() { return getAttributeAsInt("component"); } From 788565b29961e0dec9d7fdcfce3f8ec21690abd3 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 11 Oct 2023 11:38:09 +0200 Subject: [PATCH 151/402] upgrade to 'both' upon accepting recvonly content-add --- .../xmpp/jingle/JingleRtpConnection.java | 62 ++++++++++++++----- .../xmpp/jingle/stanzas/Content.java | 5 ++ 2 files changed, 50 insertions(+), 17 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java index fa54a9886..2f26c7fc9 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java @@ -61,6 +61,7 @@ import eu.siacs.conversations.utils.IP; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Namespace; import eu.siacs.conversations.xmpp.Jid; +import eu.siacs.conversations.xmpp.OnIqPacketReceived; import eu.siacs.conversations.xmpp.jingle.stanzas.Content; import eu.siacs.conversations.xmpp.jingle.stanzas.Group; import eu.siacs.conversations.xmpp.jingle.stanzas.IceUdpTransportInfo; @@ -352,28 +353,36 @@ public class JingleRtpConnection extends AbstractJingleConnection final JinglePacket jinglePacket, final RtpContentMap contentMap) { final Set> candidates = contentMap.contents.entrySet(); - if (this.state == State.SESSION_ACCEPTED) { - // zero candidates + modified credentials are an ICE restart offer - if (checkForIceRestart(jinglePacket, contentMap)) { - return; - } - respondOk(jinglePacket); - try { - processCandidates(candidates); - } catch (final WebRTCWrapper.PeerConnectionNotInitialized e) { - Log.w( - Config.LOGTAG, - id.account.getJid().asBareJid() - + ": PeerConnection was not initialized when processing transport info. this usually indicates a race condition that can be ignored"); - } - } else { + final RtpContentMap remote = getRemoteContentMap(); + final Set remoteContentIds = remote == null ? Collections.emptySet() : remote.contents.keySet(); + if (Collections.disjoint(remoteContentIds, contentMap.contents.keySet())) { + Log.d(Config.LOGTAG,"received transport-info for unknown contents "+contentMap.contents.keySet()+" (known: "+remoteContentIds+")"); respondOk(jinglePacket); pendingIceCandidates.addAll(candidates); + return; + } + if (this.state != State.SESSION_ACCEPTED) { + Log.d(Config.LOGTAG,"received transport-info prematurely. adding to backlog"); + respondOk(jinglePacket); + pendingIceCandidates.addAll(candidates); + return; + } + // zero candidates + modified credentials are an ICE restart offer + if (checkForIceRestart(jinglePacket, contentMap)) { + return; + } + respondOk(jinglePacket); + try { + processCandidates(candidates); + } catch (final WebRTCWrapper.PeerConnectionNotInitialized e) { + Log.w( + Config.LOGTAG, + id.account.getJid().asBareJid() + + ": PeerConnection was not initialized when processing transport info. this usually indicates a race condition that can be ignored"); } } private void receiveContentAdd(final JinglePacket jinglePacket) { - // TODO check if in session accepted final RtpContentMap modification; try { modification = RtpContentMap.of(jinglePacket); @@ -810,7 +819,23 @@ public class JingleRtpConnection extends AbstractJingleConnection if (contentAddition.equals(ContentAddition.summary(incomingContentAdd))) { this.incomingContentAdd = null; - acceptContentAdd(contentAddition, incomingContentAdd); + final Set senders = incomingContentAdd.getSenders(); + Log.d(Config.LOGTAG,"senders of incoming content-add: "+senders); + if (senders.equals(Content.Senders.receiveOnly(isInitiator()))) { + Log.d(Config.LOGTAG,"content addition is receive only. we want to upgrade to 'both'"); + final RtpContentMap modifiedSenders = incomingContentAdd.modifiedSenders(Content.Senders.BOTH); + final JinglePacket proposedContentModification = modifiedSenders.toStub().toJinglePacket(JinglePacket.Action.CONTENT_MODIFY, id.sessionId); + proposedContentModification.setTo(id.with); + xmppConnectionService.sendIqPacket(id.account, proposedContentModification, (account, response) -> { + if (response.getType() == IqPacket.TYPE.RESULT) { + Log.d(Config.LOGTAG,id.account.getJid().asBareJid()+": remote has accepted our upgrade to senders=both"); + acceptContentAdd(ContentAddition.summary(modifiedSenders), modifiedSenders); + } else { + Log.d(Config.LOGTAG,id.account.getJid().asBareJid()+": remote has rejected our upgrade to senders=both"); + acceptContentAdd(contentAddition, incomingContentAdd); + } + }); + } } else { throw new IllegalStateException("Accepted content add does not match pending content-add"); } @@ -862,6 +887,9 @@ public class JingleRtpConnection extends AbstractJingleConnection id.getAccount().getJid().asBareJid() + ": sending content-accept " + ContentAddition.summary(contentAcceptMap)); + + addIceCandidatesFromBlackLog(); + modifyLocalContentMap(rtpContentMap); final ListenableFuture future = prepareOutgoingContentMap(contentAcceptMap); Futures.addCallback( diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java index 061cea752..0cca6527a 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java @@ -6,6 +6,7 @@ import androidx.annotation.NonNull; import com.google.common.base.Preconditions; import com.google.common.base.Strings; +import com.google.common.collect.ImmutableSet; import java.util.Locale; import java.util.Set; @@ -147,6 +148,10 @@ public class Content extends Element { return BOTH; } + public static Set receiveOnly(final boolean initiator) { + return ImmutableSet.of(initiator ? RESPONDER : INITIATOR); + } + @Override @NonNull public String toString() { From c9ffade5b04e5830f9982e09951503fd8c175a3e Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 11 Oct 2023 14:47:05 +0200 Subject: [PATCH 152/402] no longer recommend ejabberd. most servers are fine --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7484a02ad..d0fb75d61 100644 --- a/README.md +++ b/README.md @@ -99,11 +99,11 @@ Learn more about [conversations.im Jabber/XMPP domain hosting](https://account.c ##### Running your own If you already have a server somewhere and are willing and able to put the necessary work in you can run your own XMPP server. -As of 2019 we recommend you use [ejabberd](https://ejabberd.im). The default configuration file already enables everything you need to pass the [Conversations Compliance Suite](https://compliance.conversations.im). Make sure your Linux distribution ships a fairly recent version. +As of 2023 XMPP has reached a level of maturity where all major XMPP servers ([ejabberd](https://ejabberd.im), [Prosody](https://prosody.im), [Openfire](https://www.igniterealtime.org/projects/openfire/), [Tigase](https://tigase.net/xmpp-server/)) should work well with Conversations. -With a little bit of effort [Prosody](https://prosody.im) can be configured to support all necessary extensions as well. However you will have to rely on so called [Community Modules](https://modules.prosody.im/) of varying quality. Prosody can be interesting to people who like to modify their server and create / prototype own modules. +Interoperability with Prosody and ejabberd is tested fairly regularly just because of their market share but we occasionally test with other servers too and fix issues as soon as we are being made aware of them. -Performance wise - for small deployments - both ejabberd and Prosody should be fine. +The default configurations are usually fine but you might want to use the [Conversations Compliance Suite](https://compliance.conversations.im) after install just to be sure. #### Where can I set up a custom hostname / port Conversations will automatically look up the SRV records for your domain name From 336e454f2cfd316592d1a31414141f168c3e7c68 Mon Sep 17 00:00:00 2001 From: butterflyoffire Date: Wed, 11 Oct 2023 10:43:05 +0000 Subject: [PATCH 153/402] Translated using Weblate (Arabic) Currently translated at 64.6% (626 of 969 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/ar/ --- src/main/res/values-ar/strings.xml | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/main/res/values-ar/strings.xml b/src/main/res/values-ar/strings.xml index c8a5c3bad..052caaa66 100644 --- a/src/main/res/values-ar/strings.xml +++ b/src/main/res/values-ar/strings.xml @@ -621,7 +621,7 @@ كتاب إلكتروني أصلي (غير مضغوط) إفتح بـ... - صورة حساب كونفرسايشنز + صورة حساب Conversations إختيار الحساب استرجِع نسخة احتياطية استرجِع @@ -652,4 +652,23 @@ يرجى إدخال الكلمة السرية للحساب مشغول خيارات أخرى - + قم بإنهاء هذه المحادثة بعد ذلك + للمواصلة في إستقبال التنبيهات، حتى والشاشة مغلقة، يجب عليك أن تضيف تطبيق Conversations إلى قائمة التطبيقات المحميّة. + إنشاء الحسابات غير مدعومة مِن طرف الخادم + خادمك لا يدعم نشر الصور الرمزية + XEP-0215: استكشاف خدمة خارجية + محادثات جماعية + عبر إرسال أثار الأخطاء تقوم بالمساعدة في التطوير + اضغط على الصورة الرمزية لاختيار صورة مِن المعرض + نغمة المكالمات الواردة + اضغط لإدارة حساباتك + لقد أَبلَغَ OpenKeychain عند حدوث خطأ. + تم نشر مفتاح OpenPGP العمومي. + منع أخذ لقطات للشاشة + آخِر ظهور البارحة + آخر ظهور منذ ساعة + احفظه كمحادثة جماعية + رمز التسجيل غير صالح + مفتاح تعمية خاطئ. + هذا ليس عنوان XMPP صالح + \ No newline at end of file From 5db067d09d3de68c9b12016975637543eefb8cc8 Mon Sep 17 00:00:00 2001 From: butterflyoffire Date: Wed, 11 Oct 2023 10:38:33 +0000 Subject: [PATCH 154/402] Translated using Weblate (French) Currently translated at 100.0% (969 of 969 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/fr/ --- src/main/res/values-fr/strings.xml | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/main/res/values-fr/strings.xml b/src/main/res/values-fr/strings.xml index c614d08a0..fcd0cc811 100644 --- a/src/main/res/values-fr/strings.xml +++ b/src/main/res/values-fr/strings.xml @@ -150,7 +150,9 @@ Impossible de convertir l\'image Impossible de trouver le fichier Erreur générale d\'E/S. Avez-vous encore de l\'espace libre ? - L\'application utilisée ne donne pas la permission de lire l\'image.\n\nUtilisez une autre application pour choisir une image. + L\'application utilisée pour sélectionner cette image ne donne pas les autorisations nécessaires afin de lire le fichier. +\n +\nUtilisez un autre gestionnaire de fichiers pour choisir une image. L\'app avec laquelle vous avez partagé ce fichier n\'a pas fourni assez de permissions. Inconnu Désactivé temporairement @@ -182,7 +184,7 @@ Supprimer la clé publique OpenPGP Êtes-vous sûr de vouloir supprimer votre clé publique OpenPGP de votre annonce de présence ?\nVos contacts ne pourront plus vous envoyer de message chiffrés avec OpenPGP. Clé publique OpenPGP publiée. - Activer + Activer le compter Êtes-vous sûr de vouloir supprimer votre compte \? Supprimer votre compte effacera l\'historique de vos conversations Enregistrer un son Adresse XMPP @@ -276,7 +278,9 @@ Activer Le groupe requiert un mot de passe Entrer le mot de passe - Veuillez demander à votre contact de partager ses mises à jour de disponibilité.\n\nElles seront utilisées pour déterminer l\'application qu\'il utilise. + Veuillez demander à votre contact de partager ses mises à jour de disponibilité. +\n +\nElles seront utilisées pour déterminer quelle application de discussion il utilise. Demander maintenant Ignorer Attention : peut poser problème si l\'un des deux correspondants n\'a pas activé les mises à jour de disponibilité.\n\nVérifiez dans « Détails du contact » que vous y avez bien souscrit. @@ -521,7 +525,9 @@ Grandes images seulement Optimisations de batterie activées Votre appareil applique d\'importantes optimisations de batterie pour %1$s pouvant entraîner des retards de notifications, voire des pertes de messages.\nIl est recommandé de les désactiver. - Votre appareil applique d\'importantes optimisations de batterie pour %1$s pouvant entraîner des retards de notifications, voire des pertes de messages.\nVous allez être invité à les désactiver. + Votre appareil applique d\'importantes optimisations de batterie pour %1$s pouvant entraîner des retards de notifications, voire des pertes de messages. +\n +\nVous allez être invité à les désactiver. Désactiver La zone sélectionnée est trop grande (Aucun compte activé) @@ -785,7 +791,7 @@ Choisissez un pays Numéro de téléphone Vérifier votre numéro de téléphone - Quicksy va envoyer un message SMS (des frais opérateurs sont possibles) pour vérifier votre numéro de téléphone. Entrez votre code pays et votre No de téléphone. + Quicksy va envoyer un message SMS (des frais opérateurs sont possibles) pour vérifier votre numéro de téléphone. Saisissez votre code de pays et votre numéro de téléphone :
%s

. Est-ce correct ou souhaitez-vous modifier le numéro ?]]>
%s n\'est pas un numéro de téléphone valide. Veuillez saisir votre numéro de téléphone. @@ -1026,4 +1032,8 @@ Document texte Échec temporaire de l\'authentification Supprimer l\'avatar + Vous essayez d\'importer un format de fichier de sauvegarde obsolète + Livre audio + Distributeur UnifiedPush + Ne tentez pas de restaurer des sauvegardes que vous n\'avez pas créées vous-même ! \ No newline at end of file From c8b511deabc13b304b0f6aac56796ccac258eb34 Mon Sep 17 00:00:00 2001 From: random_r Date: Wed, 11 Oct 2023 08:59:28 +0000 Subject: [PATCH 155/402] Translated using Weblate (Italian) Currently translated at 100.0% (969 of 969 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/it/ --- src/main/res/values-it/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-it/strings.xml b/src/main/res/values-it/strings.xml index e2a16616e..07bc8d01b 100644 --- a/src/main/res/values-it/strings.xml +++ b/src/main/res/values-it/strings.xml @@ -1025,4 +1025,5 @@ La scoperta dei canali usa un servizio di terze parti chiamato <a href=https://search.jabber.network>search.jabber.network</a>.<br><br>L\'uso di questa funzione invierà il tuo indirizzo IP e i termini di ricerca a quel servizio. Vedi la sua <a href=https://search.jabber.network/privacy>informativa sulla privacy</a> per maggiori informazioni. Non tentare di ripristinare dei backup che non hai creato te stesso! Stai tentando di importare un formato di file di backup obsoleto + Audiolibro \ No newline at end of file From d1b6a3ccca2f356c2b5854b7eef29d1054b90398 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Wed, 11 Oct 2023 07:54:23 +0000 Subject: [PATCH 156/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (969 of 969 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 299 +++++++++++++------------ 1 file changed, 151 insertions(+), 148 deletions(-) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index a5bab88ff..09aca869b 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -32,19 +32,19 @@ %d 个未读会话 - 发送中… - 正在解密消息。请稍候…… + 正在发送…… + 解密消息中。请稍候…… OpenPGP 加密的消息 - 用户名已存在 - 无效的用户名 + 昵称已使用 + 无效的昵称 管理员 所有者 群主 成员 访客 - 你想从通讯录中移除%s吗?此联系人的会话不会被移除。 + 你想从通讯录中移除%s吗?此联系人的会话不会被清除。 你想封禁 %s向你发送消息吗? - 你想解除对%s的封禁,并允许他们给你发送消息吗? + 你想解封%s并允许他们向你发送消息吗? 封禁来自%s的所有联系人吗\? 解封来自%s的所有联系人吗? 联系人已封禁 @@ -52,7 +52,7 @@ 你想从书签中移除%s吗?此书签的会话将不会被清除。 在服务器上注册新账号 在服务器上修改密码 - 分享… + 分享至…… 开始会话 邀请联系人 邀请 @@ -73,14 +73,14 @@ 不再询问 无法连接账号 无法连接到多个账号 - 点击管理账号 + 点击管理你的账号 发送文件 该联系人不在你的通讯录中,需要添加吗 \? 添加联系人 传递失败 准备发送图片 准备发送图片 - 正在分享文件,请稍候… + 分享文件中。请稍候…… 清除历史记录 清除会话记录 你想删除此会话中的所有消息吗? @@ -98,38 +98,38 @@ 发送 OMEMO 加密消息 发送 v\\OMEMO 加密消息 发送 OpenPGP 加密消息 - 新昵称正在使用 + 新昵称使用中 发送未加密 解密失败,也许你没有正确的私钥。 OpenKeychain %1$s使用 <b>OpenKeychain</b>来加密和解密消息并管理你的公钥。<br><br>它在 GPLv3+ 许可证下授权并可在 F-Droid 和 Google Play 上获得。<br><br><small>(请稍后重新启动%1$s。)</small> 重启 安装 - 请安装 OpenKeychain 以解密 - 提供… - 等待… - 无 OpenPGP 密钥 + 请安装 OpenKeychain + 正在提供…… + 正在等候…… + 未找到 OpenPGP 密钥 由于你的联系人未公布其公钥,无法加密你的消息。 \n \n请通知你的联系人设置 OpenPGP。 - 无 OpenPGP 密钥 + 未找到 OpenPGP 密钥 由于你的联系人未公布其公钥,无法加密你的消息。 \n \n请通知你的联系人设置 OpenPGP。 常规 接收文件 - 自动接收小于此大小的文件… + 自动接收小于此大小的文件…… 附件 通知 振动 收到新消息时振动 - 通知灯 + LED 通知 收到新消息时闪烁通知灯 铃声 通知铃声 新消息通知铃声 来电响铃 - 静默时间段 + 静默期 在你的其他设备上检测到活动之后,通知在此时间段内将被静音。 高级 从不发送崩溃报告 @@ -153,20 +153,20 @@ 预先同意订阅请求 你所选的文件不是图片 无法转换图片文件 - 未找到文件 - 常规 I/O 错误。也许你的存储空间不够了? + 文件未找到 + 常规 I/O 错误。也许你的存储空间已用完? 你用来选择图片的应用没有提供读取文件的足够权限。 \n \n使用不同的文件管理器来选择图片. - 你用来共享此文件的应用程序没有提供足够的权限。 + 你用来分享此文件的应用程序没有提供足够的权限。 未知 暂时禁用 在线 - 连接中\u2026 + 连接中…… 离线 未授权 服务器未找到 - 未连接网络 + 未连接 注册失败 用户名已使用 注册已完成 @@ -188,11 +188,11 @@ 发布头像 发布 OpenPGP 公钥 移除 OpenPGP 公钥 - 你确定要从在线状态中移除 OpenPGP 公钥吗? + 你确定要从在线状态公布中移除 OpenPGP 公钥吗? \n你的联系人将无法再向你发送 OpenPGP 加密消息。 OpenPGP 公钥已发布。 启用账号 - 你确定删除账号吗?如果你删除账号,你的所有会话记录将会丢失 + 你确定删除账号吗?删除账号会删除你的全部会话历史记录 录制音频 XMPP 地址 封禁 XMPP 地址 @@ -201,7 +201,7 @@ 这不是有效的 XMPP 地址 空间不足。图片过大 是否添加%s到你的通讯录? - 服务器属性 + 服务器信息 XEP-0313:消息存档管理 XEP-0280:消息抄送 XEP-0352:客户端状态指示 @@ -214,7 +214,7 @@ XEP-0357:推送 有效 无效 - 缺少公钥 + 缺少公钥公布 最后上线于刚才 最后上线于 1 分钟前 最后上线于 %d 分钟前 @@ -223,7 +223,7 @@ 最后上线于 1 天前 最后上线于 %d 天前 加密消息。请安装 OpenKeychain 以解密。 - 发现新 OpenPGP 加密消息 + 发现新的 OpenPGP 加密消息 OpenPGP 密钥 ID OMEMO 指纹 v\\OMEMO 指纹 @@ -231,7 +231,7 @@ v\\OMEMO 指纹(消息来源) 其他设备 信任的 OMEMO 指纹 - 获取密钥中… + 获取密钥中…… 完成 解密 搜索 @@ -260,17 +260,17 @@ 无法解散频道 编辑群聊主题 主题 - 正在加入群聊… + 正在加入群聊…… 离开 联系人已添加你到通讯录 反向添加 %s 已阅读至此 %s 已阅读至此 - %1$s和另外%2$d人都已阅读至此 + %1$s和其他%2$d人都已阅读至此 所有人都已阅读至此 发布 点击头像从图库中选择图片 - 正在发布… + 正在发布…… 服务器拒绝了你的发布请求 无法转换你的图片 不能将头像保存至磁盘 @@ -302,33 +302,33 @@ 高级设置 请谨慎使用 关于%s - 静默时间段 + 静默时段 开始时间 结束时间 - 启用静默时间段 - 在静默时间段内通知将保持静音 + 启用静默时段 + 静默时段通知将被静音 其他 同步书签 加入或离开多用户聊天时设置 “autojoin\" 标志,并回应其他客户端所做更改。 OMEMO 指纹已复制到剪贴板 你被此群聊封禁 - 这个群聊只对成员开放 + 此群聊仅限成员参与 资源限制 你被此群聊踢出 此群聊已被关闭 你已不在此群聊 - 你由于技术原因离开了群聊 + 由于技术原因你离开了此群聊 使用账号%s 托管于%s - 正在 HTTP 服务器中检查%s - 你没有连接。稍后再试 + 正在 HTTP 主机上检查%s + 你未连接。稍后再试 检查%s的大小 在%2$s上检查%1$s的大小 消息选项 引用 粘贴为引用 复制原始 URL - 重新发送 + 再次发送 文件 URL 已复制 URL 到剪贴板 已复制 XMPP 地址到剪贴板 @@ -343,24 +343,24 @@ 前台服务 防止操作系统中断连接 创建备份 - 备份文件将保存在%s + 备份文件将存储在%s 创建备份文件中 备份已创建 - 此备份文件已经存储在%s + 此备份文件已存储在%s 正在恢复备份 备份已恢复 别忘了启用账号。 选择文件 - 正在下载%1$s(已完成%2$d%%) + 接收%1$s(已完成%2$d%%) 下载%s 删除%s 文件 打开%s 正在发送(已完成%1$d%%) - 准备传输文件 + 准备分享文件 可以下载%s 取消传输 - 文件传输失败 + 无法分享文件 文件传输已取消 文件已经删除 未找到可以打开此文件的应用 @@ -369,13 +369,13 @@ 动态标签 在联系人下方显示只读标签 启用通知 - 未找到群聊服务器 - 群聊创建失败 + 群聊服务器未找到 + 无法创建群聊 账号头像 复制 OMEMO 指纹到剪贴板 重新生成 OMEMO 密钥 清除设备 - 你确定要从 OMEMO 公布中清除所有其他设备吗?下次你的设备连接时,它们将重新公布自己,但可能不会收到同时发送的消息。 + 你确定要从 OMEMO 公布中清除所有其他设备吗?下次设备连接时,它们会重新公布自己,但可能不会收到在此期间发送的消息。 此联系人没有可用的密钥。 \n无法从服务器获取新密钥。也许是你联系人的服务器出了问题? 该联系人没有可用的密钥。 @@ -383,7 +383,7 @@ 出错了 正在从服务器获取历史记录 服务器上没有更多历史记录 - 更新中… + 更新中…… 密码已修改! 不能修改密码 修改密码 @@ -426,10 +426,10 @@ 回复 标记为已读 输入 - 点击回车发送 - 使用 Enter 键发送消息。即使禁用此选项,也可以使用 Ctrl+Enter 发送消息。 - 显示回车键 - 将表情键改为回车键 + Enter 即发送 + 使用 Enter 键发送消息。即使禁用此选项,你始终可以使用 Ctrl+Enter 发送消息。 + 显示 Enter 键 + 将表情键更改为 Enter 键 音频 视频 图片 @@ -450,16 +450,16 @@ 让对方知道你正在写消息 发送位置 显示位置 - 未找到显示位置的应用 + 未找到可以显示位置的应用 位置 会话已关闭 离开私密群聊 离开公开频道 不信任系统证书 - 所有证书必须手动通过 + 所有证书必须手动批准 移除证书 - 删除手动通过的证书 - 没有手动通过的证书 + 删除手动批准的证书 + 没有手动批准的证书 移除证书 删除已选 取消 @@ -469,7 +469,7 @@ 以快捷操作替代“发送”按钮 快捷操作 - 刚用过的 + 最近使用 选择快捷操作 搜索联系人 发送私密消息 @@ -477,8 +477,8 @@ 用户名 用户名 该用户名无效 - 下载失败:未找到服务器 - 下载失败:未找到文件 + 下载失败:服务器未找到 + 下载失败:文件未找到 下载失败:无法连接到服务器 下载失败:不能写入文件 下载失败:无效文件 @@ -488,37 +488,37 @@ 损坏 可用性 当设备锁定时离开 - 当设备锁定时显示状态为离开 - 在静音模式显示为忙碌 - 设备处于静音模式时显示为忙碌 + 当设备锁定时显示为离开 + 静音模式时忙碌 + 当设备处于静音模式时显示为忙碌 将振动看作静音 - 设备振动时显示为忙碌 - 高级连接设置 - 注册账号时显示主机名和端口 + 当设备振动时显示为忙碌 + 扩展连接设置 + 设置账号时显示主机名和端口设置 xmpp.example.com 用证书登录 无法解析证书 - 存档设置 - 服务端聊天历史存档设置 - 正在获取存档设置。请稍候…… - 无法获取存档设置 + 存档首选项 + 服务器端存档首选项 + 获取存档首选项。请稍候…… + 无法获取存档首选项 需要验证码 - 输入上图文字 - 证书链不受信任 + 输入上图中的文字 + 不受信任的证书链 XMPP 地址与证书不匹配 更新证书 - 获取 OMEMO 密钥时发生错误! - 请用证书验证 OMEMO 密钥! - 您的设备不支持客户端证书选择! + 获取 OMEMO 密钥时出错! + 通过证书验证 OMEMO 密钥! + 你的设备不支持选择客户端证书! 连接 通过 Tor 连接 - 所有连接使用 Tor 网络传输,需要 Orbot - 服务器名 + 通过 Tor 网络传输所有连接。需要 Orbot + 主机名 端口 - 服务器或者 .onion 地址 + 服务器或 .onion 地址 该端口号无效 该主机名无效 - 已连接 %2$d 个中的 %1$d 个账号 + 已连接 %2$d 个账号中的 %1$d 个 %d 条消息 @@ -528,39 +528,42 @@ 图片已分享给%s 文本已分享给%s 授予 %1$s 访问外部存储的权限 - 授予 %1$s 相机访问权限 + 授予 %1$s 访问相机的权限 同步联系人 - %1$s想要访问通讯录的权限来将它与你的 XMPP 联系人列表相匹配。\n这会显示你的联系人的完整姓名和头像。\n\n%1$s只会读取你的通讯录并在本地进行匹配,不会将信息上传到你的服务器。 - 为所有消息显示通知 - 只在被提到时通知 + %1$s想要访问通讯录的权限来将它与你的 XMPP 通讯录相匹配。 +\n这会显示你的联系人的完整姓名和头像。 +\n +\n%1$s只会读取你的通讯录并在本地进行匹配,不会将信息上传到你的服务器。 + 通知所有消息 + 仅在提及时通知 通知已禁用 通知已暂停 图片压缩 - 提示:使用“选择文件”发送原图。这将忽略此设置。 + 提示:无论此设置如何,使用“选择文件”而不是“选择图片”会发送未压缩的单张图片。 总是 - 仅大图片 + 仅限大图 已启用节电模式 你的设备正对 %1$s 实施强力电池优化,这可能导致通知延迟甚至消息丢失。\n建议禁用这些优化。 你的设备正对 %1$s 实施强力电池优化,这可能导致通知延迟甚至消息丢失。 \n \n你将被请求禁用这些优化。 禁用 - 选择区域过大 + 所选区域太大 (没有启用的账号) 必填 更正消息 发送更正后的消息 - 你已经验证了该用户。点击“完成”让%s加入群聊。 + 你已经安全地验证了此人指纹以确认信任。通过选择“完成”,你只是确认%s是此群聊的一部分。 你已经禁用了此账号 安全错误:文件访问无效! 未找到可以分享此链接的应用 分享链接…… 同意并继续 - 在 conversations.im 上有创建一个账号的指南。 -\n选择 conversations.im 作为提供商时,你只需提供完整的 XMPP 地址,就能与其他提供商的用户进行交流。 + 在 conversations.im 上有创建账号的指南。 +\n选择 conversations.im 作为提供者时,你只需提供完整的 XMPP 地址,就能与其他提供者的用户进行交流。 你的完整 XMPP 地址将是:%s 创建账号 - 使用我自己的服务器 + 使用我自己的提供者 输入你的用户名 手动管理可用性 在编辑状态消息时设置你的可用时间。 @@ -571,18 +574,18 @@ 不在 忙碌 安全密码已生成 - 该设备不支持禁用电池优化 - 注册失败:请稍后重试 + 你的设备不支持禁用电池优化 + 注册失败:稍后再试 注册失败:密码太弱 选择成员 - 正在创建群聊… - 重新邀请 + 正在创建群聊…… + 再次邀请 禁用 - 广播使用应用的时间 - 让你的联系人知道你使用 Conversations 的时间 + 广播使用 + 让联系人知道你在使用 Conversations 隐私 主题 选择主题色彩 @@ -590,16 +593,16 @@ 明亮 灰暗 绿色背景 - 接收到的消息使用绿色背景 + 对收到的消息使用绿色背景 无法连接到 OpenKeychain - 不再使用此设备 + 此设备已不再使用 电脑 手机 平板 浏览器 控制台 需要付款 - 允许联网 + 授予使用互联网的权限 联系人请求在线状态订阅 允许 @@ -609,29 +612,29 @@ 无法更新账号 举报此 XMPP 地址发送垃圾信息。 删除 OMEMO 身份 - 重新生成 OMEMO 密钥。所有联系人都需要再次认证。请将此作为最后的办法。 + 重新生成 OMEMO 密钥。所有联系人都需要再次验证。请将此作为最后的办法。 删除选择的密钥 你需要连接才能发布头像。 显示出错消息 出错消息 省流量模式已启用 - 你的操作系统正限制 %1$s 在后台时访问互联网。要接收新消息通知,你应当在“数据节省”处于启用状态时允许 %1$s 不受限制的访问。 + 你的操作系统正限制 %1$s 在后台时访问互联网。要接收新消息通知,你应当在“省流量模式”处于启用状态时允许 %1$s 不受限制的访问。 \n%1$s 在可能的时候仍会试图节省数据。 - 你的设备不支持对 %1$s 禁用数据节省器。 + 你的设备不支持对 %1$s 禁用省流量模式。 无法创建临时文件 - 已验证此设备 + 此设备已验证 复制指纹 你已验证了你拥有的所有 OMEMO 密钥 条形码不包含此次会话的指纹。 已验证的指纹 - 使用相机扫描联系人条码 + 使用相机扫描联系人的条形码 请等待获取密钥 - 分享条码 + 分享条形码 分享 XMPP URI 分享 HTTP 链接 验证前盲目信任 - 自动信任陌生人的设备,但在验证过联系人添加设备时手动确认。 - 盲目信任的 OMEMO 密钥,表示它们可能时其他人或者某人可能冒充别人发送消息。 + 自动信任陌生人的设备,但对于已验证的联系人,提示手动确认新设备。 + 盲目信任的 OMEMO 密钥,表示它们可能是其他人或者某人可能冒充别人发送消息。 不信任的 无效二维码 清理缓存文件夹(由相机应用使用) @@ -639,10 +642,10 @@ 清除私密存储 清除保存私密文件的存储(可从服务器重新下载) 此链接的源头是可信的 - 点击链接后将会开始校验%1$s的 OMEMO 密钥。只有%2$s当你从一个只有你才能发布此链接的可信来源点击此链接时,这才是安全的。 - 你将验证你自己账号的 OMEMO 密钥。只有当你从一个只有你才能发布此链接的可信来源点击此链接时,这才是安全的。 + 点击链接后将会开始验证%1$s的 OMEMO 密钥。只有当你从仅%2$s才能发布此链接的可信来源点击此链接时,这才是安全的。 + 你将验证你自己账号的 OMEMO 密钥。只有当你从仅你才能发布此链接的可信来源点击此链接时,这才是安全的。 继续 - 校验 OMEMO 密钥 + 验证 OMEMO 密钥 显示不活跃设备 隐藏不活跃设备 不再信任设备 @@ -671,11 +674,11 @@ 消息加密中 由于本地保留期限设置,无法提取消息。 正在压缩视频 - 相应的对话已关闭。 + 相应的会话已关闭。 联系人已封禁。 - 陌生人的消息也通知 - 提醒来自陌生人的消息与通话。 - 已收到陌生人的消息 + 来自陌生人的通知 + 收到陌生人的消息和电话时进行通知。 + 收到陌生人发来的消息 封禁陌生人 封禁整个域名 当前在线 @@ -695,7 +698,7 @@ 一部分 录制视频 复制到剪贴板 - 消息已被复制 + 消息已复制到剪贴板 消息 禁止私信 受保护的应用 @@ -705,9 +708,9 @@ 接受不匹配的服务器名称? 由于“%s”,服务器无法验证。证书仅对此有效: 你仍要连接吗? - 证书详情: + 证书详情: 仅一次 - 二维码扫描器需要摄像头权限 + 二维码扫描器需要访问摄像头 滚动到底部 发送消息后滚动到底部 编辑状态消息 @@ -716,7 +719,7 @@ %1$s 无法发送加密消息到 %2$s。这可能是因为你的联系人使用了过期的服务器或者无法处理 OMEMO 的客户端。 无法获取设备列表 无法获取密钥 - 提示:某些情况下,可以将对方加入联系人列表,以解决此问题。 + 提示:某些情况下,可以将对方加入你的通讯录,以解决此问题。 你确定要禁用此会话的 OMEMO 加密吗? \n这将允许服务器管理员阅读你的消息,但这可能是与使用过时客户端的用户进行交流的唯一方法。 立即禁用 @@ -724,7 +727,7 @@ OMEMO 加密 OMEMO 将始终用于一对一和私人群组聊天。 OMEMO 将默认用于新会话。 - OMEMO 将明确地被用于新对话。 + OMEMO 将必须为新会话明确打开。 创建快捷方式 字体大小 应用内使用的相对字体大小。 @@ -736,7 +739,7 @@ 消息未对本设备加密。 解密 OMEMO 消息失败。 撤销 - 位置分享已停用 + 位置分享已禁用 固定位置 取消固定位置 复制位置 @@ -746,16 +749,16 @@ 显示位置 分享 无法开始录制 - 请等待… + 请等待…… 授权 %1$s 访问麦克风 搜索消息 GIF 查看会话 位置分享插件 - 不使用内置地图,使用“位置分享”插件 + 使用共享位置插件代替内置地图 复制网址 复制 XMPP 地址 - 用于 S3 的 HTTP 文件共享 + 用于 S3 的 HTTP 文件分享 直接搜索 在“开始会话”屏幕上打开键盘并将光标放在搜索栏中 群聊头像 @@ -766,10 +769,10 @@ 名称 提供名称是可选的 群聊名称 - 群聊已被解散 - 无法保存录制的文件 + 此群聊已被解散 + 无法保存录制 前台服务 - 这个通知类别用于展示一条表明 %1$s 正在运行的永久通知。 + 此通知类别用于显示 %1$s 正在运行的永久通知。 状态信息 连接问题 此通知类别用于显示账号连接问题通知。 @@ -779,8 +782,8 @@ 来电 正在进行的通话 未接来电 - 静默信息 - 此通知组用于显示不应触发任何声音的通知。 例如,在另一台设备上处于活动状态时(宽限期)。 + 静音消息 + 此通知组用于显示不应触发任何声音的通知。 例如,在另一台设备上处于活动状态时(静默期)。 发送失败 消息通知设置 来电通知设置 @@ -789,7 +792,7 @@ 查看媒体文件 成员 媒体浏览器 - 文件由于违反安全策略而被删除。 + 文件由于违反安全规定被删除。 视频质量 画质越低意味着文件越小 中(360p) @@ -809,18 +812,18 @@ 验证%s 我们已向你发送短信 %s 我们已经向你发送了另一条带有 6 位数验证码的短信。 - 请在下方输入 6 位数的PIN。 + 请在下方输入 6 位数的 PIN 码。 重新发送短信 重发短信 (%s) 请稍候 (%s) 返回 - 自动从剪贴板粘贴了可能是 PIN 码的数据。 + 已自动从剪贴板粘贴可能的 PIN 码。 请输入你的 6 位数 PIN 码。 你确定要取消注册程序吗? - 正在验证… - 正请求短信… + 正在验证…… + 正在请求短信…… 你输入的 PIN 码有误。 我们发给你的 PIN 码已过期。 未知网络错误。 @@ -831,11 +834,11 @@ 处理你的请求时出了问题。 用户输入无效 暂时无法连接。请稍候再试。 - 无网络连接. + 无网络连接。 请在 %s 后重试 你被限制速率 尝试次数过多 - 您正在使用此应用程序的过时版本。 + 你使用的是过时版本的应用程序。 更新 此电话号码目前已在其他设备上登录。 请输入你的名字,以便让通讯录中没有你的人知道你是谁。 @@ -849,7 +852,7 @@ 此频道将公开你的 XMPP 地址 电子书 原始(未压缩) - 打开方式… + 打开为…… Conversations 个人资料图片 选择账号 恢复备份 @@ -869,10 +872,10 @@ 请提供频道名 请提供 XMPP 地址 这是一个 XMPP 地址。请提供一个名称。 - 创建公开频道… + 创建公开频道…… 频道已存在 - 您加入了一个已经存在的频道 - 无法配置频道 + 你加入了一个已经存在的频道 + 无法保存频道配置 允许任何人编辑话题 允许任何人邀请别人 任何人可以编辑话题。 @@ -905,7 +908,7 @@ 账号已设置 请输入此账号的密码 无法执行此操作 - 加入公开频道… + 加入公开频道…… 共享应用程序未授予访问此文件的权限。 jabber.network @@ -959,7 +962,7 @@ 帮助 切换到会话 麦克风不可用 - 一次只能打一通电话。 + 你每次只能拨打一个电话。 返回正在进行的通话 无法切换摄像头 置顶 @@ -974,7 +977,7 @@ 用 OpenPGP 加密 未加密 退出 - 语音邮件录音 + 录制语音邮件 播放音频 暂停音频播放 添加联系人、创建或加入群聊,或发现频道 @@ -982,9 +985,9 @@ 查看 %1$d 位成员 - 一些消息无法发送 + 一些消息无法送达 - 发送失败 + 送达失败 更多选项 未找到应用程序 邀请到 Conversations @@ -996,17 +999,17 @@ 纯文本文档 不支持注册账号 未找到 XMPP 地址 - 临时认证失败 + 验证暂时失败 删除头像 使用 Tor 时通话被禁用 切换到视频 - 拒绝切换到视频的请求 + 拒绝视频切换请求 XMPP 账号 推送服务器 - 无(未激活) + 无(已停用) UnifiedPush 分发程序 将通过该账号接收推送消息。 - 用户选择的推送服务器,通过 XMPP 将推送消息传递到你的设备。 + 用户选择的推送服务器,通过 XMPP 将消息推送到你的设备。 拒绝 来电 (%s) · %s 去电 (%s) · %s From e30e0ef5837a48893a0c3945f017081177a48c59 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Tue, 10 Oct 2023 13:00:47 +0000 Subject: [PATCH 157/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (13 of 13 strings) Translation: Conversations/Android App (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-conversations/zh_Hans/ --- .../res/values-zh-rCN/strings.xml | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/conversations/res/values-zh-rCN/strings.xml b/src/conversations/res/values-zh-rCN/strings.xml index bc4c9d730..4b2d740a2 100644 --- a/src/conversations/res/values-zh-rCN/strings.xml +++ b/src/conversations/res/values-zh-rCN/strings.xml @@ -1,19 +1,19 @@ - 选择您的 XMPP 提供者 + 选择你的 XMPP 提供者 使用 conversations.im 创建新账号 - 您有 XMPP 账号吗?如果您之前使用过其他的 XMPP 客户端,那么您已经拥有这种账号了。如果没有的话,您现在可以创建一个。 -\n提示:有些电子邮件服务也提供XMPP账号。 - XMPP 是独立于提供者的即时消息网络。您可以将此客户端与任意 XMPP 服务器一同使用。 -\n不过,您可以很容易地在 conversations.im 上创建账号;它是特别适合与“Conversations”一起使用的提供者。 - 您已受邀加入 %1$s。我们将指导您完成创建账号的过程。 -\n使用 %1$s 作为提供者时,您可以通过您的完整 XMPP 地址与其他提供者的用户进行交流。 - 您已受邀加入 %1$s。已为您选择了一个用户名。我们将指导您完成创建账号的过程。 -\n您可以使用完整的 XMPP 地址来与其他提供者的用户进行交流。 + 你已经有一个 XMPP 账号了吗?如果你之前使用过其他的 XMPP 客户端,那么你已经拥有这种账号了。如果没有的话,你现在可以创建一个。 +\n提示:有些电子邮件服务也提供 XMPP 账号。 + XMPP 是独立于提供者的即时消息网络。你可以将此客户端与任意 XMPP 服务器一同使用。 +\n不过,你可以很容易地在 conversations.im 上创建一个账号;它是特别适合与“Conversations”一起使用的提供者。 + 你已受邀加入 %1$s。我们将指导你完成创建账号的过程。 +\n使用 %1$s 作为提供者时,你可以通过你的完整 XMPP 地址与其他提供者的用户进行交流。 + 你已受邀加入 %1$s。已为你选择了一个用户名。我们将指导你完成创建账号的过程。 +\n你可以使用完整的 XMPP 地址来与其他提供者的用户进行交流。 你的服务器邀请 格式不正确的配置代码 - 点击分享按钮向您的联系人发送加入 %1$s 的邀请。 + 点击分享按钮向你的联系人发送加入 %1$s 的邀请。 如果你的联系人在附近,他们也可以扫描下面的代码来接受你的邀请。 加入 %1$s 和我聊天:%2$s 分享邀请… From 59ea3e60d8250157b6a07e9d1d05b366fe424d11 Mon Sep 17 00:00:00 2001 From: random_r Date: Wed, 11 Oct 2023 09:00:49 +0000 Subject: [PATCH 158/402] Translated using Weblate (Italian) Currently translated at 100.0% (51 of 51 strings) Translation: Conversations/App Store Metadata (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/it/ --- fastlane/metadata/android/it-IT/changelogs/42068.txt | 2 ++ fastlane/metadata/android/it-IT/changelogs/42072.txt | 3 +++ 2 files changed, 5 insertions(+) create mode 100644 fastlane/metadata/android/it-IT/changelogs/42068.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/42072.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/42068.txt b/fastlane/metadata/android/it-IT/changelogs/42068.txt new file mode 100644 index 000000000..801dbb015 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42068.txt @@ -0,0 +1,2 @@ +* supporta impostazioni di notifica per singola conversazione +* usa opus per i messaggi vocali su Android 10 diff --git a/fastlane/metadata/android/it-IT/changelogs/42072.txt b/fastlane/metadata/android/it-IT/changelogs/42072.txt new file mode 100644 index 000000000..c497edc32 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42072.txt @@ -0,0 +1,3 @@ +* Aggiornata la dipendenza libwebrtc a M117 e libvpx +* Ritorno a AAC per i messaggi vocali +* Supporta impostazioni di lingua per app From 0c23f8e33a68c4421b3841d68350f40139072043 Mon Sep 17 00:00:00 2001 From: ghose Date: Wed, 11 Oct 2023 12:12:27 +0000 Subject: [PATCH 159/402] Translated using Weblate (Galician) Currently translated at 100.0% (2 of 2 strings) Translation: Conversations/App Store Metadata (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata-quicksy/gl/ --- .../metadata/android/gl-ES/full_description.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/quicksy/fastlane/metadata/android/gl-ES/full_description.txt diff --git a/src/quicksy/fastlane/metadata/android/gl-ES/full_description.txt b/src/quicksy/fastlane/metadata/android/gl-ES/full_description.txt new file mode 100644 index 000000000..f901df67c --- /dev/null +++ b/src/quicksy/fastlane/metadata/android/gl-ES/full_description.txt @@ -0,0 +1,14 @@ +Quicksy é unha aplicación derivada do coñecido cliente Conversations para Jabber/XMPP co engadido do descubremento automático dos contactos. + +Accedes co teu número de móbil e Quicksy suxerirá automáticamente posibles contactos en función dos números da libreta de enderezos. + +Por debaixo estarás desfrutando dun completo cliente Jabber que che permite comunicarte con calquera usuaria doutros servidores federados. Do mesmo xeito, as persoas que usan Quicksy poden ser contactadas simplemente engadindo +numerodemobil@quicksy.im á túa lista de contactos. + +Fóra da sincronización de contactos o resto da interface é o máis semellante posible a Conversations. Deste xeito as usuarias poden migrar de Quicksy a Conversations sen maiores dificultades e sen ter que volver a aprender a usar a aplicación. + +Os contactos suxeridos proveñen doutras usuarias de Quicksy e usuarias regulares de Jabber/XMPP que engadiron o seu ID de Jabber ao Directorio Quicksy (https://quicksy.im/#get-listed). + +NOTA: Para engadir (https://quicksy.im/enter/) o teu ID de Jabber ao Directorio +Quicksy requírese facer unha pequena aportación só unha vez. + +Le a Política de Privacidade (https://quicksy.im/#privacy) para ter máis información. From 1f63ec97f68ed35ac15ed344c64bfd4f0efe67af Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Tue, 10 Oct 2023 12:55:41 +0000 Subject: [PATCH 160/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (2 of 2 strings) Translation: Conversations/App Store Metadata (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata-conversations/zh_Hans/ --- .../android/zh-CN/full_description.txt | 39 +++++++++++++++++++ .../android/zh-CN/short_description.txt | 1 + 2 files changed, 40 insertions(+) create mode 100644 src/conversations/fastlane/metadata/android/zh-CN/full_description.txt create mode 100644 src/conversations/fastlane/metadata/android/zh-CN/short_description.txt diff --git a/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt b/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt new file mode 100644 index 000000000..6853d2e19 --- /dev/null +++ b/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt @@ -0,0 +1,39 @@ +易于使用、性能可靠、省电。内置支持图片、群组聊天和 e2e 加密功能。 + +设计原则: + +* 在不牺牲安全性和隐私性的前提下,尽可能美观易用 +* 依托现有的、成熟的协议 +* 不需要 Google 账号或特定的 Google 云信息服务(GCM) +* 要求尽可能少的权限 + +特点: + +* 使用 OMEMOOpenPGP 进行端对端加密 +* 发送和接收图片 +* 加密音视频通话(DTLS-SRTP) +* 直观的用户界面,遵循 Android 设计准则 +* 为你的联系人添加图片/头像 +* 与桌面客户端同步 +* 群聊(支持书签功能) +* 通讯录集成 +* 多账号/统一收件箱 +* 对电池寿命的影响非常小 + +Conversations 使在免费的 conversations.im 服务器上创建账号变得非常简单。不过,Conversations 也适用于任何其他 XMPP 服务器。许多 XMPP 服务器都是由志愿者免费运行的。 + +XMPP 功能: + +Conversations 适用于所有 XMPP 服务器。然而,XMPP是一种可扩展的协议。这些扩展也在所谓的 XEP 中进行了标准化。Conversations 支持其中的几项功能,使整体用户体验更好。你当前的 XMPP 服务器可能不支持这些扩展。因此,要想最大限度地利用 Conversations 功能,你应该考虑切换到一个支持 Conversations 功能的 XMPP 服务器,或者为你和你的朋友运行自己的 XMPP 服务器(这更好)。 + +到目前为止,这些 XEP 是: + +* XEP-0065:SOCKS5字节流(or mod_proxy65)。如果双方都在防火墙(NAT)后面,将用于传输文件。 +* XEP-0163:个人事件协议对于头像 +* XEP-0191:屏蔽指令可让你将垃圾邮件发送者列入黑名单或封禁的联系人中,而不会将其从通讯录中删除。 +* XEP-0198:流管理允许 XMPP 在小规模网络中断和底层 TCP 连接发生变化时继续运行。 +* XEP-0280:消息抄送,可自动将你发送的消息同步到桌面客户端,因此你可以在一次会话中从手机客户端无缝切换到桌面客户端,然后再返回。 +* XEP-0237:通讯录版本化主要是为了在移动连接不佳的情况下节省带宽 +* XEP-0313:消息存档管理与服务器同步消息历史记录。传递 Conversations 离线时发送的消息。 +* XEP-0352:客户端状态指示让服务器知道 Conversations 是否在后台。允许服务器保留不重要的数据包,从而节省带宽。 +* XEP-0363:通过 HTTP 文件上传功能,你可以在群聊中与离线联系人共享文件。需要在服务器上安装额外组件。 diff --git a/src/conversations/fastlane/metadata/android/zh-CN/short_description.txt b/src/conversations/fastlane/metadata/android/zh-CN/short_description.txt new file mode 100644 index 000000000..ced555912 --- /dev/null +++ b/src/conversations/fastlane/metadata/android/zh-CN/short_description.txt @@ -0,0 +1 @@ +为你的移动设备提供加密、易用的 XMPP 即时信使 From 8af1c24788b8467096abd99d6e872e4ca75c7705 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Wed, 11 Oct 2023 00:46:32 +0000 Subject: [PATCH 161/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (51 of 51 strings) Translation: Conversations/App Store Metadata (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/zh_Hans/ --- fastlane/metadata/android/zh-CN/changelogs/349.txt | 4 ++++ fastlane/metadata/android/zh-CN/changelogs/351.txt | 3 +++ fastlane/metadata/android/zh-CN/changelogs/353.txt | 4 ++++ fastlane/metadata/android/zh-CN/changelogs/360.txt | 1 + fastlane/metadata/android/zh-CN/changelogs/362.txt | 1 + fastlane/metadata/android/zh-CN/changelogs/364.txt | 2 ++ fastlane/metadata/android/zh-CN/changelogs/367.txt | 2 ++ fastlane/metadata/android/zh-CN/changelogs/379.txt | 1 + fastlane/metadata/android/zh-CN/changelogs/381.txt | 2 ++ fastlane/metadata/android/zh-CN/changelogs/382.txt | 2 ++ fastlane/metadata/android/zh-CN/changelogs/383.txt | 3 +++ fastlane/metadata/android/zh-CN/changelogs/387.txt | 2 ++ fastlane/metadata/android/zh-CN/changelogs/388.txt | 3 +++ fastlane/metadata/android/zh-CN/changelogs/390.txt | 1 + fastlane/metadata/android/zh-CN/changelogs/393.txt | 3 +++ fastlane/metadata/android/zh-CN/changelogs/394.txt | 2 ++ fastlane/metadata/android/zh-CN/changelogs/395.txt | 3 +++ fastlane/metadata/android/zh-CN/changelogs/397.txt | 3 +++ fastlane/metadata/android/zh-CN/changelogs/398.txt | 4 ++++ fastlane/metadata/android/zh-CN/changelogs/401.txt | 2 ++ fastlane/metadata/android/zh-CN/changelogs/402.txt | 3 +++ fastlane/metadata/android/zh-CN/changelogs/403.txt | 3 +++ fastlane/metadata/android/zh-CN/changelogs/404.txt | 1 + fastlane/metadata/android/zh-CN/changelogs/405.txt | 1 + fastlane/metadata/android/zh-CN/changelogs/407.txt | 3 +++ fastlane/metadata/android/zh-CN/changelogs/42000.txt | 4 ++++ fastlane/metadata/android/zh-CN/changelogs/42006.txt | 2 ++ fastlane/metadata/android/zh-CN/changelogs/42010.txt | 2 ++ fastlane/metadata/android/zh-CN/changelogs/42012.txt | 1 + fastlane/metadata/android/zh-CN/changelogs/42013.txt | 1 + fastlane/metadata/android/zh-CN/changelogs/42014.txt | 2 ++ fastlane/metadata/android/zh-CN/changelogs/42015.txt | 1 + fastlane/metadata/android/zh-CN/changelogs/42018.txt | 3 +++ fastlane/metadata/android/zh-CN/changelogs/42022.txt | 2 ++ fastlane/metadata/android/zh-CN/changelogs/42023.txt | 2 ++ fastlane/metadata/android/zh-CN/changelogs/42037.txt | 11 +++++++++++ fastlane/metadata/android/zh-CN/changelogs/42038.txt | 2 ++ fastlane/metadata/android/zh-CN/changelogs/42041.txt | 5 +++++ fastlane/metadata/android/zh-CN/changelogs/42042.txt | 2 ++ fastlane/metadata/android/zh-CN/changelogs/42043.txt | 1 + fastlane/metadata/android/zh-CN/changelogs/42044.txt | 3 +++ fastlane/metadata/android/zh-CN/changelogs/42046.txt | 1 + fastlane/metadata/android/zh-CN/changelogs/42047.txt | 1 + fastlane/metadata/android/zh-CN/changelogs/42050.txt | 1 + fastlane/metadata/android/zh-CN/changelogs/42059.txt | 2 ++ fastlane/metadata/android/zh-CN/changelogs/42060.txt | 1 + fastlane/metadata/android/zh-CN/changelogs/42061.txt | 1 + fastlane/metadata/android/zh-CN/changelogs/42062.txt | 1 + fastlane/metadata/android/zh-CN/changelogs/42065.txt | 1 + fastlane/metadata/android/zh-CN/changelogs/42068.txt | 2 ++ fastlane/metadata/android/zh-CN/changelogs/42072.txt | 3 +++ 51 files changed, 117 insertions(+) create mode 100644 fastlane/metadata/android/zh-CN/changelogs/349.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/351.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/353.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/360.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/362.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/364.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/367.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/379.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/381.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/382.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/383.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/387.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/388.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/390.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/393.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/394.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/395.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/397.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/398.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/401.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/402.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/403.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/404.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/405.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/407.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42000.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42006.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42010.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42012.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42013.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42014.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42015.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42018.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42022.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42023.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42037.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42038.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42041.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42042.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42043.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42044.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42046.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42047.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42050.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42059.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42060.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42061.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42062.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42065.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42068.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42072.txt diff --git a/fastlane/metadata/android/zh-CN/changelogs/349.txt b/fastlane/metadata/android/zh-CN/changelogs/349.txt new file mode 100644 index 000000000..d5d84b8bc --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/349.txt @@ -0,0 +1,4 @@ +* 引入专家设置在本地服务器上执行频道发现而不是 search.jabber.network +* 默认启用发送复选标记并删除设置 +* 默认启用“发送按钮指示状态”并删除设置 +* 将备份和前台服务设置移至主屏幕 diff --git a/fastlane/metadata/android/zh-CN/changelogs/351.txt b/fastlane/metadata/android/zh-CN/changelogs/351.txt new file mode 100644 index 000000000..c3ff6bc46 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/351.txt @@ -0,0 +1,3 @@ +* 修复了 Jingle IBB 文件传输问题 +* 修复了重复更正填满数据库的问题 +* 切换到最后消息更正 v1.1 diff --git a/fastlane/metadata/android/zh-CN/changelogs/353.txt b/fastlane/metadata/android/zh-CN/changelogs/353.txt new file mode 100644 index 000000000..75d7425d1 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/353.txt @@ -0,0 +1,4 @@ +* 让用户设置自己的昵称 +* 恢复 OMEMO 加密文件的下载 +* 频道现在使用“#”作为头像中的符号 +* Quicksy 使用“始终”作为 OMEMO 加密默认值(隐藏锁定图标) diff --git a/fastlane/metadata/android/zh-CN/changelogs/360.txt b/fastlane/metadata/android/zh-CN/changelogs/360.txt new file mode 100644 index 000000000..fc2e905de --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/360.txt @@ -0,0 +1 @@ +* 支持 ?register 和 ?register;preauth XMPP uri 参数 diff --git a/fastlane/metadata/android/zh-CN/changelogs/362.txt b/fastlane/metadata/android/zh-CN/changelogs/362.txt new file mode 100644 index 000000000..27249c94f --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/362.txt @@ -0,0 +1 @@ +* 支持在 Android 10 上自动切换主题 diff --git a/fastlane/metadata/android/zh-CN/changelogs/364.txt b/fastlane/metadata/android/zh-CN/changelogs/364.txt new file mode 100644 index 000000000..2b4d64fcb --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/364.txt @@ -0,0 +1,2 @@ +* 在 Android 5 以上版本上提供 PDF 预览 +* 为 OMEMO 使用 12 byte IVs diff --git a/fastlane/metadata/android/zh-CN/changelogs/367.txt b/fastlane/metadata/android/zh-CN/changelogs/367.txt new file mode 100644 index 000000000..59ac67d50 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/367.txt @@ -0,0 +1,2 @@ +* 修复部分 Android 10 设备上的头像选择问题 +* 修复较大文件的文件传输 diff --git a/fastlane/metadata/android/zh-CN/changelogs/379.txt b/fastlane/metadata/android/zh-CN/changelogs/379.txt new file mode 100644 index 000000000..9bd6e9e93 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/379.txt @@ -0,0 +1 @@ +* 音频/视频通话(需要通过 XEP-0215 发现的 STUN 和 TURN 服务器形式的服务器支持) diff --git a/fastlane/metadata/android/zh-CN/changelogs/381.txt b/fastlane/metadata/android/zh-CN/changelogs/381.txt new file mode 100644 index 000000000..b8db10afd --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/381.txt @@ -0,0 +1,2 @@ +* 语音通话的声音反馈(拨号、通话开始、通话结束)。 +* 修复了重试失败视频通话的问题 diff --git a/fastlane/metadata/android/zh-CN/changelogs/382.txt b/fastlane/metadata/android/zh-CN/changelogs/382.txt new file mode 100644 index 000000000..334e75d43 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/382.txt @@ -0,0 +1,2 @@ +* 添加视频通话时切换摄像头的按钮 +* 修复了平板电脑上的语音通话问题 diff --git a/fastlane/metadata/android/zh-CN/changelogs/383.txt b/fastlane/metadata/android/zh-CN/changelogs/383.txt new file mode 100644 index 000000000..31ee7aa89 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/383.txt @@ -0,0 +1,3 @@ +* 将通话图标移至左侧,以保持其他工具栏图标在一致的位置 +* 音频通话时显示通话时长 +* 音频/视频通话打破僵局(两个人同时打电话给对方) diff --git a/fastlane/metadata/android/zh-CN/changelogs/387.txt b/fastlane/metadata/android/zh-CN/changelogs/387.txt new file mode 100644 index 000000000..e8c9f29a3 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/387.txt @@ -0,0 +1,2 @@ +* 重新设计使用证书登录的用户界面 +* 添加将聊天固定在顶部的功能(添加到收藏夹) diff --git a/fastlane/metadata/android/zh-CN/changelogs/388.txt b/fastlane/metadata/android/zh-CN/changelogs/388.txt new file mode 100644 index 000000000..8b8536bbe --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/388.txt @@ -0,0 +1,3 @@ +* 在某些设备上通话时减少回声 +* 修复密码包含特殊字符时的登录问题 +* 视频通话期间扬声器上播放拨号音和忙音 diff --git a/fastlane/metadata/android/zh-CN/changelogs/390.txt b/fastlane/metadata/android/zh-CN/changelogs/390.txt new file mode 100644 index 000000000..2b6300e5f --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/390.txt @@ -0,0 +1 @@ +* 在接听者忙时提供语音留言服务 diff --git a/fastlane/metadata/android/zh-CN/changelogs/393.txt b/fastlane/metadata/android/zh-CN/changelogs/393.txt new file mode 100644 index 000000000..f432818ff --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/393.txt @@ -0,0 +1,3 @@ +* 如果音频/视频通话失败则显示帮助按钮 +* 修复了一些恼人的崩溃问题 +* 修复了带有裸 JID 的 Jingle 连接(文件传输 + 通话) diff --git a/fastlane/metadata/android/zh-CN/changelogs/394.txt b/fastlane/metadata/android/zh-CN/changelogs/394.txt new file mode 100644 index 000000000..df4f52a34 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/394.txt @@ -0,0 +1,2 @@ +* 修复了某些情况下不显示通知的问题 +* 修复了与音频/视频通话相关的兼容性问题和崩溃 diff --git a/fastlane/metadata/android/zh-CN/changelogs/395.txt b/fastlane/metadata/android/zh-CN/changelogs/395.txt new file mode 100644 index 000000000..010d78c4d --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/395.txt @@ -0,0 +1,3 @@ +* 在音频通话屏幕中添加“返回聊天” +* 改进键盘快捷键 +* bug 修复 diff --git a/fastlane/metadata/android/zh-CN/changelogs/397.txt b/fastlane/metadata/android/zh-CN/changelogs/397.txt new file mode 100644 index 000000000..96c3815c3 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/397.txt @@ -0,0 +1,3 @@ +* 处理 GPX 文件 +* 提高备份恢复性能 +* bug 修复 diff --git a/fastlane/metadata/android/zh-CN/changelogs/398.txt b/fastlane/metadata/android/zh-CN/changelogs/398.txt new file mode 100644 index 000000000..c4bf43212 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/398.txt @@ -0,0 +1,4 @@ +* 搜索个人会话 +* 消息发送失败时通知用户 +* 重新启动时记住 Quicksy 用户的显示名称(昵称) +* 如有必要,添加按钮以从通知中启动 Orbot(Tor) diff --git a/fastlane/metadata/android/zh-CN/changelogs/401.txt b/fastlane/metadata/android/zh-CN/changelogs/401.txt new file mode 100644 index 000000000..df75923de --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/401.txt @@ -0,0 +1,2 @@ +* 修复了 Android <= 5 上的搜索 +* 优化内存消耗 diff --git a/fastlane/metadata/android/zh-CN/changelogs/402.txt b/fastlane/metadata/android/zh-CN/changelogs/402.txt new file mode 100644 index 000000000..7bcabf3b9 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/402.txt @@ -0,0 +1,3 @@ +* 在支持的服务器上提供简易邀请生成功能 +* 显示从 Movim 发送的 GIF +* 在缓存中存储头像 diff --git a/fastlane/metadata/android/zh-CN/changelogs/403.txt b/fastlane/metadata/android/zh-CN/changelogs/403.txt new file mode 100644 index 000000000..52a13575a --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/403.txt @@ -0,0 +1,3 @@ +* 修复了不同账号使用不同 SCRAM 机制时的连接问题 +* 添加对 SCRAM-SHA-512 的支持 +* 允许通过自联系进行 P2P(Jingle)文件传输 diff --git a/fastlane/metadata/android/zh-CN/changelogs/404.txt b/fastlane/metadata/android/zh-CN/changelogs/404.txt new file mode 100644 index 000000000..4619eb7cc --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/404.txt @@ -0,0 +1 @@ +* 对音频/视频通话的稳定性略有改善 diff --git a/fastlane/metadata/android/zh-CN/changelogs/405.txt b/fastlane/metadata/android/zh-CN/changelogs/405.txt new file mode 100644 index 000000000..a0fa53f8b --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/405.txt @@ -0,0 +1 @@ +* Quicksy:自动接收验证短信 diff --git a/fastlane/metadata/android/zh-CN/changelogs/407.txt b/fastlane/metadata/android/zh-CN/changelogs/407.txt new file mode 100644 index 000000000..33e0919ad --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/407.txt @@ -0,0 +1,3 @@ +* 如果离线联系人之前已宣布支持,则显示呼叫按钮 +* 通话接通后,后退按钮不再结束通话 +* bug 修复 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42000.txt b/fastlane/metadata/android/zh-CN/changelogs/42000.txt new file mode 100644 index 000000000..8aedfaed8 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42000.txt @@ -0,0 +1,4 @@ +* 能够选择来电铃声 +* 修复 OpenKeychain 5.6+ 的 OpenPGP 密钥 ID 发现问题 +* 正确验证 punycode TLS 证书 +* 提高 RTP 会话建立(呼叫)的稳定性 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42006.txt b/fastlane/metadata/android/zh-CN/changelogs/42006.txt new file mode 100644 index 000000000..d9f60038f --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42006.txt @@ -0,0 +1,2 @@ +* 使用预先存在的 OMEMO 会话验证音频/视频通话 +* 提高与非 libwebrtc WebRTC 实现的兼容性 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42010.txt b/fastlane/metadata/android/zh-CN/changelogs/42010.txt new file mode 100644 index 000000000..09fddc261 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42010.txt @@ -0,0 +1,2 @@ +* 修复了有关 Tor 支持的各种错误 +* 改进与 Dino 的通话兼容性 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42012.txt b/fastlane/metadata/android/zh-CN/changelogs/42012.txt new file mode 100644 index 000000000..ac5dd6eee --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42012.txt @@ -0,0 +1 @@ +* 修复不信任系统证书的用户的 HTTP 上传/下载问题 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42013.txt b/fastlane/metadata/android/zh-CN/changelogs/42013.txt new file mode 100644 index 000000000..801cf42fb --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42013.txt @@ -0,0 +1 @@ +* 修复了 Android 7.1 上的“无连接”问题 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42014.txt b/fastlane/metadata/android/zh-CN/changelogs/42014.txt new file mode 100644 index 000000000..11afbe025 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42014.txt @@ -0,0 +1,2 @@ +* 始终验证域名。 没有用户覆盖 +* 支持通讯录预验证 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42015.txt b/fastlane/metadata/android/zh-CN/changelogs/42015.txt new file mode 100644 index 000000000..b9ce380d6 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42015.txt @@ -0,0 +1 @@ +* 在音频和视频方面略有改进 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42018.txt b/fastlane/metadata/android/zh-CN/changelogs/42018.txt new file mode 100644 index 000000000..974bd0292 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42018.txt @@ -0,0 +1,3 @@ +* 当远程视频与屏幕宽高比不匹配时显示黑条 +* 提高搜索性能 +* 添加防止截图的设置 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42022.txt b/fastlane/metadata/android/zh-CN/changelogs/42022.txt new file mode 100644 index 000000000..08c03bff7 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42022.txt @@ -0,0 +1,2 @@ +* 修复某些视频无法压缩的问题 +* 修复打开通知时罕见的崩溃问题 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42023.txt b/fastlane/metadata/android/zh-CN/changelogs/42023.txt new file mode 100644 index 000000000..e24d2373f --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42023.txt @@ -0,0 +1,2 @@ +* 修复渲染某些引用时的崩溃问题 +* 修复欢迎屏幕崩溃问题 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42037.txt b/fastlane/metadata/android/zh-CN/changelogs/42037.txt new file mode 100644 index 000000000..b1a32f6ad --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42037.txt @@ -0,0 +1,11 @@ +版本2.10.9 +* 进行音视频通话时请求蓝牙权限(如果你不使用蓝牙耳机可以拒绝) +* 修复呼叫 Movim 时的错误 +* 修复群聊时显示错误头像的问题 +* 始终要求选择退出电池优化 +* 在“x 个已连接账号”通知上设置仅本地标志 +* 修复与 Google 地图共享位置插件的交互 +* 删除有关服务器费用的脚注 +* 将文件存储在适合 Android 11 的位置 +* 网络切换后尝试重新连接通话 +* 在来电屏幕中显示来电者JID和帐户JID diff --git a/fastlane/metadata/android/zh-CN/changelogs/42038.txt b/fastlane/metadata/android/zh-CN/changelogs/42038.txt new file mode 100644 index 000000000..99c2ed862 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42038.txt @@ -0,0 +1,2 @@ +* 修正了一些小错误 +* 恢复通过 JMP 和其他服务呼叫的能力(Playstore 版本) diff --git a/fastlane/metadata/android/zh-CN/changelogs/42041.txt b/fastlane/metadata/android/zh-CN/changelogs/42041.txt new file mode 100644 index 000000000..b809c9854 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42041.txt @@ -0,0 +1,5 @@ +* 实施可扩展 SASL Profile、Bind 2.0 和 Fast,以加快重新连接速度 +* 实现频道绑定 +* 增加从音频通话切换到视频通话的功能 +* 增加删除自己头像的功能 +* 增加未接来电通知功能 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42042.txt b/fastlane/metadata/android/zh-CN/changelogs/42042.txt new file mode 100644 index 000000000..2c5975c38 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42042.txt @@ -0,0 +1,2 @@ +* 修复仅支持 sm:2 的服务器上的重发循环 +* 仅当对方支持视频时才显示“切换到视频” diff --git a/fastlane/metadata/android/zh-CN/changelogs/42043.txt b/fastlane/metadata/android/zh-CN/changelogs/42043.txt new file mode 100644 index 000000000..d830a7f32 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42043.txt @@ -0,0 +1 @@ +* 修复了 P2P 文件传输中的缺陷 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42044.txt b/fastlane/metadata/android/zh-CN/changelogs/42044.txt new file mode 100644 index 000000000..f0e54c458 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42044.txt @@ -0,0 +1,3 @@ +* 修复使用 SASL2 时重新发送消息的问题 +* 修复部分设备之间的黑屏问题 +* 修复空密码崩溃问题 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42046.txt b/fastlane/metadata/android/zh-CN/changelogs/42046.txt new file mode 100644 index 000000000..a4a5e4c1a --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42046.txt @@ -0,0 +1 @@ +* 集成 UnifiedPush 分发程序,以便将消息推送到其他支持 UnifiedPush 的应用程序,例如 Tusky 和 Fedilab diff --git a/fastlane/metadata/android/zh-CN/changelogs/42047.txt b/fastlane/metadata/android/zh-CN/changelogs/42047.txt new file mode 100644 index 000000000..c67da1843 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42047.txt @@ -0,0 +1 @@ +* 修复 UnifiedPush 分发程序中的崩溃问题 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42050.txt b/fastlane/metadata/android/zh-CN/changelogs/42050.txt new file mode 100644 index 000000000..28c946e81 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42050.txt @@ -0,0 +1 @@ +* 增加个人资料图片的圆角半径 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42059.txt b/fastlane/metadata/android/zh-CN/changelogs/42059.txt new file mode 100644 index 000000000..faeaa2ff1 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42059.txt @@ -0,0 +1,2 @@ +* 将 Target SDK 再次提升至 33 +* 修复支持 SASL2 且不支持内联流管理的服务器上的问题 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42060.txt b/fastlane/metadata/android/zh-CN/changelogs/42060.txt new file mode 100644 index 000000000..72a78b5cb --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42060.txt @@ -0,0 +1 @@ +* 修复“q”被错误识别为西里尔字母的问题 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42061.txt b/fastlane/metadata/android/zh-CN/changelogs/42061.txt new file mode 100644 index 000000000..4cf6ebea1 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42061.txt @@ -0,0 +1 @@ +* 从 Google Play 版本中移除频道发现功能 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42062.txt b/fastlane/metadata/android/zh-CN/changelogs/42062.txt new file mode 100644 index 000000000..e15f64892 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42062.txt @@ -0,0 +1 @@ +* 禁止从文件管理器打开备份文件(.ceb) diff --git a/fastlane/metadata/android/zh-CN/changelogs/42065.txt b/fastlane/metadata/android/zh-CN/changelogs/42065.txt new file mode 100644 index 000000000..419c47a53 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42065.txt @@ -0,0 +1 @@ +* 引入新的备份文件格式 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42068.txt b/fastlane/metadata/android/zh-CN/changelogs/42068.txt new file mode 100644 index 000000000..b022e0fd2 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42068.txt @@ -0,0 +1,2 @@ +* 支持每个会话通知设置 +* 在 Android 10 上使用 opus 发送语音消息 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42072.txt b/fastlane/metadata/android/zh-CN/changelogs/42072.txt new file mode 100644 index 000000000..e37ca41e6 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42072.txt @@ -0,0 +1,3 @@ +* 将 libwebrtc 依赖项提升到 M117 并提升 libvpx +* 回到 AAC 语音信息 +* 支持每个应用程序语言设置 From da413b3771d76d4cce379018d530a105106eecd9 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Wed, 11 Oct 2023 11:36:05 +0000 Subject: [PATCH 162/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (2 of 2 strings) Translation: Conversations/App Store Metadata (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata-quicksy/zh_Hans/ --- .../metadata/android/zh-CN/full_description.txt | 14 ++++++++++++++ .../metadata/android/zh-CN/short_description.txt | 1 + 2 files changed, 15 insertions(+) create mode 100644 src/quicksy/fastlane/metadata/android/zh-CN/full_description.txt create mode 100644 src/quicksy/fastlane/metadata/android/zh-CN/short_description.txt diff --git a/src/quicksy/fastlane/metadata/android/zh-CN/full_description.txt b/src/quicksy/fastlane/metadata/android/zh-CN/full_description.txt new file mode 100644 index 000000000..8dd32119d --- /dev/null +++ b/src/quicksy/fastlane/metadata/android/zh-CN/full_description.txt @@ -0,0 +1,14 @@ +Quicksy 是流行的 Jabber/XMPP 客户端 Conversations 的衍生产品,具有自动发现联系人的功能。 + +你只需用电话号码注册,Quicksy 就会自动—根据你通讯录中的电话号码—向你推荐可能的联系人。 + +从本质上讲,Quicksy 是一个成熟的 Jabber 客户端,可让你与任何公共联合服务器上的任何用户进行交流。同样,只需将 +phonenumber@quicksy.im 添加到你的通讯录中,即可从外部联系 Quicksy 上的用户。 + +除了联系人同步之外,用户界面尽可能地接近 Conversations。这使得用户最终可以从 Quicksy 迁移到 Conversations,而无需重新学习应用程序的工作方式。 + +建议的联系人包括其他 Quicksy 用户和在 Quicksy 目录中输入 Jabber ID 的普通 Jabber/XMPP 用户。(https://quicksy.im/#get-listed)。 + +注意:要在 Quicksy 中输入(https://quicksy.im/enter/)你的 Jabber ID +目录一次性注册费用是必需的。 + +请阅读隐私政策(https://quicksy.im/#privacy),了解更多信息。 diff --git a/src/quicksy/fastlane/metadata/android/zh-CN/short_description.txt b/src/quicksy/fastlane/metadata/android/zh-CN/short_description.txt new file mode 100644 index 000000000..55a138f37 --- /dev/null +++ b/src/quicksy/fastlane/metadata/android/zh-CN/short_description.txt @@ -0,0 +1 @@ +Jabber/XMPP 轻松进入和易于发现 From 1392250edec6d2d943626bad59fcc75b505d64f7 Mon Sep 17 00:00:00 2001 From: random_r Date: Wed, 11 Oct 2023 09:25:47 +0000 Subject: [PATCH 163/402] Translated using Weblate (Italian) Currently translated at 100.0% (2 of 2 strings) Translation: Conversations/App Store Metadata (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata-quicksy/it/ --- .../metadata/android/it-IT/full_description.txt | 14 ++++++++++++++ .../metadata/android/it-IT/short_description.txt | 1 + 2 files changed, 15 insertions(+) create mode 100644 src/quicksy/fastlane/metadata/android/it-IT/full_description.txt create mode 100644 src/quicksy/fastlane/metadata/android/it-IT/short_description.txt diff --git a/src/quicksy/fastlane/metadata/android/it-IT/full_description.txt b/src/quicksy/fastlane/metadata/android/it-IT/full_description.txt new file mode 100644 index 000000000..0768c2847 --- /dev/null +++ b/src/quicksy/fastlane/metadata/android/it-IT/full_description.txt @@ -0,0 +1,14 @@ +Quicksy è uno spin off del popolare client Jabber/XMPP Conversations con ricerca automatica dei contatti. + +Ti registri con il numero di telefono e Quicksy ti proporrà automaticamente, in base ai numeri di telefono nella tua rubrica, i possibili contatti. + +Sotto il cofano Quicksy è un vero e proprio client Jabber che ti consente di comunicare con qualsiasi utente su qualsiasi server federato pubblicamente. Allo stesso modo gli utenti su Quicksy possono essere contattati dall'esterno semplicemente aggiungendo +numeroditelefono@quicksy.im al tuo elenco di contatti. + +A parte la sincronizzazione dei contatti, l'interfaccia utente è deliberatamente il più possibile simile a quella di Conversations. Ciò permette agli utenti eventualmente di migrare da Quicksy a Conversations senza il bisogno di imparare di nuovo come funziona l'app. + +I contatti proposti consistono in altri utenti di Quicksy e utenti regolari di Jabber/XMPP che hanno inserito il loro ID Jabber nella Directory di Quicksy (https://quicksy.im/#get-listed). + +NOTA: per inserire (https://quicksy.im/enter/) il tuo ID Jabber nella Directory +di Quicksy è richiesto un pagamento una tantum per la registrazione. + +Leggi l'informativa sulla privacy (https://quicksy.im/#privacy) per maggiori informazioni. diff --git a/src/quicksy/fastlane/metadata/android/it-IT/short_description.txt b/src/quicksy/fastlane/metadata/android/it-IT/short_description.txt new file mode 100644 index 000000000..ba7acf963 --- /dev/null +++ b/src/quicksy/fastlane/metadata/android/it-IT/short_description.txt @@ -0,0 +1 @@ +Jabber/XMPP con Easy Entry e Easy Discovery From e5b915d8b410a1e43e293331144b63b84c815c3d Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Thu, 12 Oct 2023 01:07:48 +0000 Subject: [PATCH 164/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (969 of 969 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 44 +++++++++++++------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index 09aca869b..5b56ecb70 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -16,8 +16,8 @@ 解封联系人 封禁域名 解封域名 - 封禁成员 - 解封成员 + 封禁参与者 + 解封参与者 管理账号 设置 分享至会话 @@ -40,7 +40,7 @@ 管理员 所有者 群主 - 成员 + 参与者 访客 你想从通讯录中移除%s吗?此联系人的会话不会被清除。 你想封禁 %s向你发送消息吗? @@ -75,7 +75,7 @@ 无法连接到多个账号 点击管理你的账号 发送文件 - 该联系人不在你的通讯录中,需要添加吗 \? + 此联系人不在你的通讯录中,需要添加吗 \? 添加联系人 传递失败 准备发送图片 @@ -162,7 +162,7 @@ 未知 暂时禁用 在线 - 连接中…… + 正在连接…… 离线 未授权 服务器未找到 @@ -255,7 +255,7 @@ \n警告:此群聊将在服务器上完全删除。 你确定要解散此公共频道吗? \n -\n警告:该频道将在服务器上完全删除。 +\n警告:此频道将在服务器上完全删除。 无法解散群聊 无法解散频道 编辑群聊主题 @@ -280,13 +280,13 @@ 至%s 与%s私聊 连接 - 该账号已存在 + 此账号已存在 下一步 会话已建立 跳过 关闭通知 启用 - 需要密码才能进入该群聊 + 需要密码才能进入此群聊 输入密码 请先向你的联系人请求在线状态更新。 \n @@ -378,7 +378,7 @@ 你确定要从 OMEMO 公布中清除所有其他设备吗?下次设备连接时,它们会重新公布自己,但可能不会收到在此期间发送的消息。 此联系人没有可用的密钥。 \n无法从服务器获取新密钥。也许是你联系人的服务器出了问题? - 该联系人没有可用的密钥。 + 此联系人没有可用的密钥。 \n确保你们双方都有在线状态订阅。 出错了 正在从服务器获取历史记录 @@ -393,7 +393,7 @@ 启用所有账号 禁用所有账号 执行操作 - 没有从属关系 + 无从属关系 离线 已逐出 成员 @@ -476,7 +476,7 @@ %1$s离开了群聊 用户名 用户名 - 该用户名无效 + 此用户名无效 下载失败:服务器未找到 下载失败:文件未找到 下载失败:无法连接到服务器 @@ -516,8 +516,8 @@ 主机名 端口 服务器或 .onion 地址 - 该端口号无效 - 该主机名无效 + 此端口号无效 + 此主机名无效 已连接 %2$d 个账号中的 %1$d 个 %d 条消息 @@ -577,7 +577,7 @@ 你的设备不支持禁用电池优化 注册失败:稍后再试 注册失败:密码太弱 - 选择成员 + 选择参与者 正在创建群聊…… 再次邀请 禁用 @@ -790,7 +790,7 @@ 重要程度、声音、振动 视频压缩 查看媒体文件 - 成员 + 参与者 媒体浏览器 文件由于违反安全规定被删除。 视频质量 @@ -885,10 +885,10 @@ 任何人可以邀请别人。 XMPP 地址对管理员可见。 XMPP 地址对任何人可见。 - 此公开频道无成员。邀请你的联系人或使用共享按钮分享其 XMPP 地址。 - 此私密群聊无成员。 + 此公开频道无参与者。邀请你的联系人或使用共享按钮分享其 XMPP 地址。 + 此私密群聊无参与者。 管理权限 - 搜索成员 + 搜索参与者 文件过大 附加 发现频道 @@ -970,7 +970,7 @@ GPX 轨迹 无法更正消息 所有会话 - 该会话 + 此会话 你的头像 %s的头像 用 OMEMO 加密 @@ -982,7 +982,7 @@ 暂停音频播放 添加联系人、创建或加入群聊,或发现频道 - 查看 %1$d 位成员 + 查看 %1$d 位参与者 一些消息无法送达 @@ -1008,13 +1008,13 @@ 推送服务器 无(已停用) UnifiedPush 分发程序 - 将通过该账号接收推送消息。 + 将通过此账号接收推送消息。 用户选择的推送服务器,通过 XMPP 将消息推送到你的设备。 拒绝 来电 (%s) · %s 去电 (%s) · %s 去电 · %s - 频道发现功能使用第三方服务 <a href=https://search.jabber.network>search.jabber.network</a>。<br><br>使用此功能会发送你的 IP 地址和搜索词条到该服务。更多信息见 <a href=https://search.jabber.network/privacy>隐私政策</a>。 + 频道发现功能使用第三方服务 <a href=https://search.jabber.network>search.jabber.network</a>。<br><br>使用此功能会发送你的 IP 地址和搜索词条到此服务。更多信息见 <a href=https://search.jabber.network/privacy>隐私政策</a>。 无法从服务器删除账号 群聊 另存为群聊 From 7f278202c65ae2cf5c0e4398020f31300659230a Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Thu, 12 Oct 2023 00:45:47 +0000 Subject: [PATCH 165/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (51 of 51 strings) Translation: Conversations/App Store Metadata (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/zh_Hans/ --- fastlane/metadata/android/zh-CN/changelogs/390.txt | 2 +- fastlane/metadata/android/zh-CN/changelogs/42072.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fastlane/metadata/android/zh-CN/changelogs/390.txt b/fastlane/metadata/android/zh-CN/changelogs/390.txt index 2b6300e5f..5566010a2 100644 --- a/fastlane/metadata/android/zh-CN/changelogs/390.txt +++ b/fastlane/metadata/android/zh-CN/changelogs/390.txt @@ -1 +1 @@ -* 在接听者忙时提供语音留言服务 +* 在接听者忙时提供语音消息服务 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42072.txt b/fastlane/metadata/android/zh-CN/changelogs/42072.txt index e37ca41e6..481587e68 100644 --- a/fastlane/metadata/android/zh-CN/changelogs/42072.txt +++ b/fastlane/metadata/android/zh-CN/changelogs/42072.txt @@ -1,3 +1,3 @@ * 将 libwebrtc 依赖项提升到 M117 并提升 libvpx -* 回到 AAC 语音信息 +* 回到 AAC 语音消息 * 支持每个应用程序语言设置 From a40d244bf59478bb137dd60825dea5b1177f99bc Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 12 Oct 2023 11:59:21 +0200 Subject: [PATCH 166/402] remove unnecessary in resolver --- .../java/de/gultsch/minidns/DNSSocket.java | 12 ++++++++-- .../de/gultsch/minidns/NetworkDataSource.java | 2 +- .../siacs/conversations/utils/Resolver.java | 22 +++++++++++++------ 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/main/java/de/gultsch/minidns/DNSSocket.java b/src/main/java/de/gultsch/minidns/DNSSocket.java index 4b096e0b2..f69b6fb27 100644 --- a/src/main/java/de/gultsch/minidns/DNSSocket.java +++ b/src/main/java/de/gultsch/minidns/DNSSocket.java @@ -28,6 +28,8 @@ import java.util.Iterator; import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import javax.net.ssl.SSLPeerUnverifiedException; import javax.net.ssl.SSLSession; @@ -37,6 +39,7 @@ import javax.net.ssl.SSLSocketFactory; final class DNSSocket implements Closeable { private static final int CONNECT_TIMEOUT = 5_000; + public static final int QUERY_TIMEOUT = 5_000; private final Semaphore semaphore = new Semaphore(1); private final Map> inFlightQueries = new HashMap<>(); @@ -109,6 +112,7 @@ final class DNSSocket implements Closeable { new InetSocketAddress(dnsServer.inetAddress, dnsServer.port); final Socket socket = new Socket(); socket.connect(socketAddress, CONNECT_TIMEOUT); + socket.setSoTimeout(QUERY_TIMEOUT); return DNSSocket.of(socket); } @@ -120,9 +124,11 @@ final class DNSSocket implements Closeable { final SocketAddress socketAddress = new InetSocketAddress(dnsServer.inetAddress, dnsServer.port); sslSocket = (SSLSocket) factory.createSocket(dnsServer.inetAddress, dnsServer.port); - sslSocket.connect(socketAddress, 5_000); + sslSocket.connect(socketAddress, CONNECT_TIMEOUT); + sslSocket.setSoTimeout(QUERY_TIMEOUT); } else { sslSocket = (SSLSocket) factory.createSocket(dnsServer.hostname, dnsServer.port); + sslSocket.setSoTimeout(QUERY_TIMEOUT); final SSLSession session = sslSocket.getSession(); final Certificate[] peerCertificates = session.getPeerCertificates(); if (peerCertificates.length == 0 || !(peerCertificates[0] instanceof X509Certificate)) { @@ -138,7 +144,7 @@ final class DNSSocket implements Closeable { public DNSMessage query(final DNSMessage query) throws IOException, InterruptedException { try { - return queryAsync(query).get(); + return queryAsync(query).get(QUERY_TIMEOUT, TimeUnit.MILLISECONDS); } catch (final ExecutionException e) { final Throwable cause = e.getCause(); if (cause instanceof IOException) { @@ -146,6 +152,8 @@ final class DNSSocket implements Closeable { } else { throw new IOException(e); } + } catch (final TimeoutException e) { + throw new IOException(e); } } diff --git a/src/main/java/de/gultsch/minidns/NetworkDataSource.java b/src/main/java/de/gultsch/minidns/NetworkDataSource.java index 1ba56f3c0..93909891d 100644 --- a/src/main/java/de/gultsch/minidns/NetworkDataSource.java +++ b/src/main/java/de/gultsch/minidns/NetworkDataSource.java @@ -93,7 +93,7 @@ public class NetworkDataSource extends DNSDataSource { } catch (final IOException e) { ioExceptions.add(e); } catch (final InterruptedException e) { - return null; + throw new IOException(e); } } MultipleIoException.throwIfRequired(ioExceptions); diff --git a/src/main/java/eu/siacs/conversations/utils/Resolver.java b/src/main/java/eu/siacs/conversations/utils/Resolver.java index 444deda4a..d6d1adaf0 100644 --- a/src/main/java/eu/siacs/conversations/utils/Resolver.java +++ b/src/main/java/eu/siacs/conversations/utils/Resolver.java @@ -6,6 +6,8 @@ import android.util.Log; import androidx.annotation.NonNull; +import com.google.common.base.Throwables; + import java.io.IOException; import java.lang.reflect.Field; import java.net.Inet4Address; @@ -113,7 +115,7 @@ public class Resolver { return port == 443 || port == 5223; } - public static List resolve(String domain) { + public static List resolve(final String domain) { final List ipResults = fromIpAddress(domain); if (ipResults.size() > 0) { return ipResults; @@ -127,8 +129,10 @@ public class Resolver { synchronized (results) { results.addAll(list); } - } catch (Throwable throwable) { - Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + ": error resolving SRV record (direct TLS)", throwable); + } catch (final Throwable throwable) { + if (!(Throwables.getRootCause(throwable) instanceof InterruptedException)) { + Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + ": error resolving SRV record (direct TLS)", throwable); + } } }); threads[1] = new Thread(() -> { @@ -137,8 +141,10 @@ public class Resolver { synchronized (results) { results.addAll(list); } - } catch (Throwable throwable) { - Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + ": error resolving SRV record (STARTTLS)", throwable); + } catch (final Throwable throwable) { + if (!(Throwables.getRootCause(throwable) instanceof InterruptedException)) { + Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + ": error resolving SRV record (STARTTLS)", throwable); + } } }); threads[2] = new Thread(() -> { @@ -261,8 +267,10 @@ public class Resolver { results.addAll(resolveNoSrvRecords(cname.name, false)); } } - } catch (Throwable throwable) { - Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + "error resolving fallback records", throwable); + } catch (final Throwable throwable) { + if (!(Throwables.getRootCause(throwable) instanceof InterruptedException)) { + Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + "error resolving fallback records", throwable); + } } results.add(Result.createDefault(dnsName)); return results; From 5b2444ea139a4209920dac01505526971fbcd8ce Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 13 Oct 2023 08:29:23 +0200 Subject: [PATCH 167/402] implement see-other-host stream error --- .../siacs/conversations/entities/Account.java | 3 + .../java/eu/siacs/conversations/utils/IP.java | 12 ++++ .../siacs/conversations/utils/Resolver.java | 62 +++++++++++++++++++ .../conversations/xmpp/XmppConnection.java | 27 +++++++- .../xmpp/jingle/JingleRtpConnection.java | 4 +- src/main/res/values/strings.xml | 1 + 6 files changed, 105 insertions(+), 4 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index bfbe817cb..0fb748d88 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -787,6 +787,7 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable BIND_FAILURE, HOST_UNKNOWN, STREAM_ERROR, + SEE_OTHER_HOST, STREAM_OPENING_ERROR, POLICY_VIOLATION, PAYMENT_REQUIRED, @@ -874,6 +875,8 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable return R.string.account_status_stream_opening_error; case PAYMENT_REQUIRED: return R.string.payment_required; + case SEE_OTHER_HOST: + return R.string.reconnect_on_other_host; case MISSING_INTERNET_PERMISSION: return R.string.missing_internet_permission; case TEMPORARY_AUTH_FAILURE: diff --git a/src/main/java/eu/siacs/conversations/utils/IP.java b/src/main/java/eu/siacs/conversations/utils/IP.java index a7182e207..948f7537a 100644 --- a/src/main/java/eu/siacs/conversations/utils/IP.java +++ b/src/main/java/eu/siacs/conversations/utils/IP.java @@ -1,5 +1,7 @@ package eu.siacs.conversations.utils; +import com.google.common.net.InetAddresses; + import java.util.regex.Pattern; public class IP { @@ -27,4 +29,14 @@ public class IP { } } + public static String unwrapIPv6(final String host) { + if (host.length() > 2 && host.charAt(0) == '[' && host.charAt(host.length() - 1) == ']') { + final String ip = host.substring(1,host.length() -1); + if (InetAddresses.isInetAddress(ip)) { + return ip; + } + } + return host; + } + } diff --git a/src/main/java/eu/siacs/conversations/utils/Resolver.java b/src/main/java/eu/siacs/conversations/utils/Resolver.java index d6d1adaf0..915209413 100644 --- a/src/main/java/eu/siacs/conversations/utils/Resolver.java +++ b/src/main/java/eu/siacs/conversations/utils/Resolver.java @@ -6,7 +6,10 @@ import android.util.Log; import androidx.annotation.NonNull; +import com.google.common.base.Strings; import com.google.common.base.Throwables; +import com.google.common.net.InetAddresses; +import com.google.common.primitives.Ints; import java.io.IOException; import java.lang.reflect.Field; @@ -446,6 +449,65 @@ public class Resolver { contentValues.put(AUTHENTICATED, authenticated ? 1 : 0); return contentValues; } + + public Result seeOtherHost(final String seeOtherHost) { + final String hostname = seeOtherHost.trim(); + if (hostname.isEmpty()) { + return null; + } + final Result result = new Result(); + result.directTls = this.directTls; + final int portSegmentStart = hostname.lastIndexOf(':'); + if (hostname.charAt(hostname.length() - 1) != ']' + && portSegmentStart >= 0 + && hostname.length() >= portSegmentStart + 1) { + final String hostPart = hostname.substring(0, portSegmentStart); + final String portPart = hostname.substring(portSegmentStart + 1); + final Integer port = Ints.tryParse(portPart); + if (port == null || Strings.isNullOrEmpty(hostPart)) { + return null; + } + final String host = eu.siacs.conversations.utils.IP.unwrapIPv6(hostPart); + result.port = port; + if (InetAddresses.isInetAddress(host)) { + final InetAddress inetAddress; + try { + inetAddress = InetAddresses.forString(host); + } catch (final IllegalArgumentException e) { + return null; + } + result.ip = inetAddress; + } else { + if (hostPart.trim().isEmpty()) { + return null; + } + try { + result.hostname = DNSName.from(hostPart.trim()); + } catch (final Exception e) { + return null; + } + } + } else { + final String host = eu.siacs.conversations.utils.IP.unwrapIPv6(hostname); + if (InetAddresses.isInetAddress(host)) { + final InetAddress inetAddress; + try { + inetAddress = InetAddresses.forString(host); + } catch (final IllegalArgumentException e) { + return null; + } + result.ip = inetAddress; + } else { + try { + result.hostname = DNSName.from(hostname); + } catch (final Exception e) { + return null; + } + } + result.port = port; + } + return result; + } } } diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 93ab1ebf5..8a2b2e7cd 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -189,6 +189,8 @@ public class XmppConnection implements Runnable { private HashedToken.Mechanism hashTokenRequest; private HttpUrl redirectionUrl = null; private String verifiedHostname = null; + private Resolver.Result currentResolverResult; + private Resolver.Result seeOtherHostResolverResult; private volatile Thread mThread; private CountDownLatch mStreamCountDownLatch; @@ -360,7 +362,12 @@ public class XmppConnection implements Runnable { + storedBackupResult); } } - for (Iterator iterator = results.iterator(); + final Resolver.Result seeOtherHost = this.seeOtherHostResolverResult; + if (seeOtherHost != null) { + Log.d(Config.LOGTAG,account.getJid().asBareJid()+": injected see-other-host on position 0"); + results.add(0, seeOtherHost); + } + for (final Iterator iterator = results.iterator(); iterator.hasNext(); ) { final Resolver.Result result = iterator.next(); if (Thread.currentThread().isInterrupted()) { @@ -374,7 +381,6 @@ public class XmppConnection implements Runnable { features.encryptionEnabled = result.isDirectTls(); verifiedHostname = result.isAuthenticated() ? result.getHostname().toString() : null; - Log.d(Config.LOGTAG, "verified hostname " + verifiedHostname); final InetSocketAddress addr; if (result.getIp() != null) { addr = new InetSocketAddress(result.getIp(), result.getPort()); @@ -422,6 +428,8 @@ public class XmppConnection implements Runnable { mXmppConnectionService.databaseBackend.saveResolverResult( domain, result); } + this.currentResolverResult = result; + this.seeOtherHostResolverResult = null; break; // successfully connected to server that speaks xmpp } else { FileBackend.close(localSocket); @@ -2166,6 +2174,21 @@ public class XmppConnection implements Runnable { Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": policy violation. " + text); failPendingMessages(text); throw new StateChangingException(Account.State.POLICY_VIOLATION); + } else if (streamError.hasChild("see-other-host")) { + final String seeOtherHost = streamError.findChildContent("see-other-host"); + final Resolver.Result currentResolverResult = this.currentResolverResult; + if (Strings.isNullOrEmpty(seeOtherHost) || currentResolverResult == null) { + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": stream error " + streamError); + throw new StateChangingException(Account.State.STREAM_ERROR); + } + Log.d(Config.LOGTAG,account.getJid().asBareJid()+": see other host: "+seeOtherHost+" "+currentResolverResult); + final Resolver.Result seeOtherResult = currentResolverResult.seeOtherHost(seeOtherHost); + if (seeOtherResult != null) { + this.seeOtherHostResolverResult = seeOtherResult; + throw new StateChangingException(Account.State.SEE_OTHER_HOST); + } else { + throw new StateChangingException(Account.State.STREAM_ERROR); + } } else { Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": stream error " + streamError); throw new StateChangingException(Account.State.STREAM_ERROR); diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java index 2f26c7fc9..af6d219b0 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java @@ -553,13 +553,13 @@ public class JingleRtpConnection extends AbstractJingleConnection sendSessionTerminate(Reason.FAILED_APPLICATION, cause.getMessage()); return; } - processCandidates(receivedContentAccept.contents.entrySet()); - updateEndUserState(); Log.d( Config.LOGTAG, id.getAccount().getJid().asBareJid() + ": remote has accepted content-add " + ContentAddition.summary(receivedContentAccept)); + processCandidates(receivedContentAccept.contents.entrySet()); + updateEndUserState(); } private void receiveContentModify(final JinglePacket jinglePacket) { diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 4981128de..cb97f7afb 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -587,6 +587,7 @@ Web browser Console Payment required + Reconnect on other host Grant permission to use the Internet Me Contact asks for presence subscription From 894ff1918c7af74cc173298d20a2dcad54c03a2b Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 13 Oct 2023 08:36:15 +0200 Subject: [PATCH 168/402] update woodpecker syntax --- .woodpecker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index 2de87b707..affaf7110 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -1,4 +1,4 @@ -pipeline: +steps: build: image: codeberg.org/freeyourgadget/android-fdroid-tools:latest commands: From 9a922ffe5dc84a514a54b22ed4d35096d70bc6fe Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 13 Oct 2023 17:36:12 +0200 Subject: [PATCH 169/402] quietly ignore mediated invites from blocked contacts --- .../conversations/parser/MessageParser.java | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 0378c2927..2d1cbcf32 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -1097,22 +1097,26 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece this.inviter = inviter; } - public boolean execute(Account account) { - if (jid != null) { - Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, jid, true, false); - if (conversation.getMucOptions().online()) { - Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": received invite to " + jid + " but muc is considered to be online"); - mXmppConnectionService.mucSelfPingAndRejoin(conversation); - } else { - conversation.getMucOptions().setPassword(password); - mXmppConnectionService.databaseBackend.updateConversation(conversation); - final Contact contact = inviter != null ? account.getRoster().getContactFromContactList(inviter) : null; - mXmppConnectionService.joinMuc(conversation, contact != null && contact.mutualPresenceSubscription()); - mXmppConnectionService.updateConversationUi(); - } - return true; + public boolean execute(final Account account) { + if (this.jid == null) { + return false; } - return false; + final Contact contact = this.inviter != null ? account.getRoster().getContact(this.inviter) : null; + if (contact != null && contact.isBlocked()) { + Log.d(Config.LOGTAG,account.getJid().asBareJid()+": ignore invite from "+contact.getJid()+" because contact is blocked"); + return false; + } + final Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, jid, true, false); + if (conversation.getMucOptions().online()) { + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": received invite to " + jid + " but muc is considered to be online"); + mXmppConnectionService.mucSelfPingAndRejoin(conversation); + } else { + conversation.getMucOptions().setPassword(password); + mXmppConnectionService.databaseBackend.updateConversation(conversation); + mXmppConnectionService.joinMuc(conversation, contact != null && contact.showInContactList()); + mXmppConnectionService.updateConversationUi(); + } + return true; } } } From 73994bebd23660dada8a31707a76fb76f7208846 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 13 Oct 2023 22:14:56 +0200 Subject: [PATCH 170/402] support themable icons on Android 13 closes #44 --- .../res/drawable/ic_launcher_foreground.xml | 31 ++++++---------- .../res/drawable/ic_launcher_monochrome.xml | 13 +++++++ .../drawable-v24/ic_launcher_background.xml | 33 ++++++++++++++++++ .../res/mipmap-anydpi-v26/new_launcher.xml | 5 +-- .../mipmap-anydpi-v26/new_launcher_round.xml | 3 +- .../mipmap-hdpi/ic_launcher_background.png | Bin 1752 -> 0 bytes .../mipmap-mdpi/ic_launcher_background.png | Bin 1162 -> 0 bytes .../mipmap-xhdpi/ic_launcher_background.png | Bin 2499 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_background.png | Bin 3882 -> 0 bytes .../mipmap-xxxhdpi/ic_launcher_background.png | Bin 5359 -> 0 bytes .../res/drawable/ic_launcher_foreground.xml | 26 ++++++-------- .../res/drawable/ic_launcher_monochrome.xml | 13 +++++++ .../res/mipmap-anydpi-v26/new_launcher.xml | 5 --- .../mipmap-anydpi-v26/new_launcher_round.xml | 5 --- 14 files changed, 84 insertions(+), 50 deletions(-) create mode 100644 src/conversations/res/drawable/ic_launcher_monochrome.xml create mode 100644 src/main/res/drawable-v24/ic_launcher_background.xml rename src/{conversations => main}/res/mipmap-anydpi-v26/new_launcher.xml (51%) rename src/{conversations => main}/res/mipmap-anydpi-v26/new_launcher_round.xml (54%) delete mode 100644 src/main/res/mipmap-hdpi/ic_launcher_background.png delete mode 100644 src/main/res/mipmap-mdpi/ic_launcher_background.png delete mode 100644 src/main/res/mipmap-xhdpi/ic_launcher_background.png delete mode 100644 src/main/res/mipmap-xxhdpi/ic_launcher_background.png delete mode 100644 src/main/res/mipmap-xxxhdpi/ic_launcher_background.png create mode 100644 src/quicksy/res/drawable/ic_launcher_monochrome.xml delete mode 100644 src/quicksy/res/mipmap-anydpi-v26/new_launcher.xml delete mode 100644 src/quicksy/res/mipmap-anydpi-v26/new_launcher_round.xml diff --git a/src/conversations/res/drawable/ic_launcher_foreground.xml b/src/conversations/res/drawable/ic_launcher_foreground.xml index 07a7ee7eb..5851e5f2c 100644 --- a/src/conversations/res/drawable/ic_launcher_foreground.xml +++ b/src/conversations/res/drawable/ic_launcher_foreground.xml @@ -1,24 +1,13 @@ - - - + android:width="108dp" + android:height="108dp" + android:viewportWidth="1146.7721" + android:viewportHeight="1146.7721"> + + diff --git a/src/conversations/res/drawable/ic_launcher_monochrome.xml b/src/conversations/res/drawable/ic_launcher_monochrome.xml new file mode 100644 index 000000000..56895d605 --- /dev/null +++ b/src/conversations/res/drawable/ic_launcher_monochrome.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/src/main/res/drawable-v24/ic_launcher_background.xml b/src/main/res/drawable-v24/ic_launcher_background.xml new file mode 100644 index 000000000..ec3c58ad5 --- /dev/null +++ b/src/main/res/drawable-v24/ic_launcher_background.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + diff --git a/src/conversations/res/mipmap-anydpi-v26/new_launcher.xml b/src/main/res/mipmap-anydpi-v26/new_launcher.xml similarity index 51% rename from src/conversations/res/mipmap-anydpi-v26/new_launcher.xml rename to src/main/res/mipmap-anydpi-v26/new_launcher.xml index 6f2acb4f0..b070c763d 100644 --- a/src/conversations/res/mipmap-anydpi-v26/new_launcher.xml +++ b/src/main/res/mipmap-anydpi-v26/new_launcher.xml @@ -1,5 +1,6 @@ - - + + + \ No newline at end of file diff --git a/src/conversations/res/mipmap-anydpi-v26/new_launcher_round.xml b/src/main/res/mipmap-anydpi-v26/new_launcher_round.xml similarity index 54% rename from src/conversations/res/mipmap-anydpi-v26/new_launcher_round.xml rename to src/main/res/mipmap-anydpi-v26/new_launcher_round.xml index 6f2acb4f0..04091bd10 100644 --- a/src/conversations/res/mipmap-anydpi-v26/new_launcher_round.xml +++ b/src/main/res/mipmap-anydpi-v26/new_launcher_round.xml @@ -1,5 +1,6 @@ - + + \ No newline at end of file diff --git a/src/main/res/mipmap-hdpi/ic_launcher_background.png b/src/main/res/mipmap-hdpi/ic_launcher_background.png deleted file mode 100644 index 0e5a16390aae109be31f0e54e7236bc0d23ddf54..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1752 zcmah~`8(SO7*8UXbecqotf&w}wRNq6s`xsK5^=0ibRzYnYuQ+7R-~4%t6A%+TGuL- zxJT9^j;=$aVvf?*9CbX@F-L|9qKwv-?jP6>@B4m!`F!5b=Xu`ed4HhOPN`uIVjvKR znx}`Wzj79TEHqNtpRE(LArNGdr>j%o)v=X{CI5iaxb$%I7(IZdkHLRpOzvv60%J53 z!y`wl>MKc@9V11!1?`{u6ZS1M`$9f8X^urM1xgR#-JyBT2m`b+XS3Kw zJWK)~1L*OXcrE_EteWEz4FOQFF|pR`Y0IfpC*u}$ryn!Iz{j=>?QYYUq;NpzNUGd7dvC5`=e>=7F>%eHE$9}kvP3G$A;9|ihyM%qf`6G z+ud*O_z44_14AA+1ap4@I!9j}>TfpoK_doPE9FLX!MGgW3S7O7|b@ zE)%!`2-c}Pe?Alp%)nWj(X!yaZAlX*a7zrUT~Aq>9LNndwha*gqW9@YY}|+H6;Xl& z&g#(CP-_m2APoJ7^UMTd7)E-@#)Pv-4c#5W7~zgY#j=AAG@?rZksRaoXwyXA}t7&LKQ zgbjhyNoVQ;vQnF_kR##Vq~V%?qzCB~d1;p@|E4-$Gt{kr>ImY+L1SF?uQ&eieOA#? zb4`3c*gOw7%DtY6phiaFJ;0z*UCO!i3(y06O~qDj6gJvM&}ab$EkhFfAaA}&8v^01 zHnO%I)gh;?@4^=)bXe^xqYjlKLI~{_Cakt=yg6Z1?j;bXs7k#khsRmGGj!@iqYc3b zce6!ijVRKxstzuJvp})SKHjZGkupcF*hP)%kSlb$rsOZyErZcPl@w(n=Gn$J8&Q2i z4v-Og=MmD2XN9wGN;KPaRh3Fyq9VCpPA!KwrodTK_gluGJ8k1FryuF{%7`Fwd#V{J zK-CwF3AnrV5ElKu%5osjy6t(|J&Zcvsgv^SfNxgB8-bq*NaWm3(QExMH7_i9mk42X zwQq!ULzYs0LVd1jh;wPxd&`Cm>i^CCPEdvFq2vIc*g6hE6{rPNAW|u`aD5n3GBsD? z-HDd+UgMfn>f3GJhcoQ+R!AT*=GxhP7V3qX-iJL%$Ob#|ZHPkBv^5*UcA$GX!TRG% za&K5@g=tg1j-`89!218zPdFy=mtUs$IKeEJ-Gff^WM5@jDn=} z{jGGt#gTc$X(}WeGlV7MbnUNBT2`p^b~Jq-J)n~poB_lw8>U+EEamIWzm!sohg=<= zt#2O%J}z1FJ=5!K0ySy79P^Lc1UDxk15iBq^j)#>-Q*KIyTzl-c^)?t&!?T!+ZqaZ zMR@a-Ga2al$jhwx{tyF-8U^*HQKdZNe1T9q>o zwYFbZB=82A@Z#B6Q%=Au}Ihvmmj8i)ZE2Drj8F7#z#a{P8y#o)oxIMYK=%ewa8T&$h#B(uFe z!2Efxy(YMbSd(cj-;|FClZfNxO41V>Xt9P6Au-1q8(J}YFEmsnfv&1$=Pybw}Jl>ITexDxt zW!kp-l&896HZ1yna{r+jG{2!)wHGs8iI_IzUL;lcc8orcolHmYZ@sh*d#6?rPJO14 zAye8a1V`SV-Itj9CK&(V{m!b}xaGXl;BvtN!QlVD23kKtxZxO66nSr*s?wnRSP)M) Kn(ISnX7axdE(){& diff --git a/src/main/res/mipmap-mdpi/ic_launcher_background.png b/src/main/res/mipmap-mdpi/ic_launcher_background.png deleted file mode 100644 index 57edd5ca3b8225076c8a49743cbcb823d7ffe73d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1162 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 WMM;#w_Bwb6Mp&Cu$W>-uN&gSL?WEBF diff --git a/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png b/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png deleted file mode 100644 index b75f8bc457e06ea450ee9a26bcb094c94d38750c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5359 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 B!~p;R diff --git a/src/quicksy/res/drawable/ic_launcher_foreground.xml b/src/quicksy/res/drawable/ic_launcher_foreground.xml index 40af0ee17..276e138e3 100644 --- a/src/quicksy/res/drawable/ic_launcher_foreground.xml +++ b/src/quicksy/res/drawable/ic_launcher_foreground.xml @@ -1,19 +1,13 @@ - - + android:width="108dp" + android:height="108dp" + android:viewportWidth="49.41353" + android:viewportHeight="49.413532"> + + diff --git a/src/quicksy/res/drawable/ic_launcher_monochrome.xml b/src/quicksy/res/drawable/ic_launcher_monochrome.xml new file mode 100644 index 000000000..fefe300d5 --- /dev/null +++ b/src/quicksy/res/drawable/ic_launcher_monochrome.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/src/quicksy/res/mipmap-anydpi-v26/new_launcher.xml b/src/quicksy/res/mipmap-anydpi-v26/new_launcher.xml deleted file mode 100644 index 6f2acb4f0..000000000 --- a/src/quicksy/res/mipmap-anydpi-v26/new_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/quicksy/res/mipmap-anydpi-v26/new_launcher_round.xml b/src/quicksy/res/mipmap-anydpi-v26/new_launcher_round.xml deleted file mode 100644 index 6f2acb4f0..000000000 --- a/src/quicksy/res/mipmap-anydpi-v26/new_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file From 49b0550d9bd7d91ad194f19a2b48127ab73c2b50 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 14 Oct 2023 10:43:59 +0200 Subject: [PATCH 171/402] Do not export EventReceiver Conversations only listens for system events which do not need the receiver to be exported. --- src/main/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index aca21e2ed..1377cb257 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -98,7 +98,7 @@ + android:exported="false"> From ffde9336c72932578ce4fc1bd33561835d9b1f95 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Fri, 13 Oct 2023 10:04:33 +0000 Subject: [PATCH 172/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (969 of 969 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 208 ++++++++++++------------- 1 file changed, 104 insertions(+), 104 deletions(-) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index 5b56ecb70..1e1e92bff 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -1,12 +1,12 @@ 设置 - 新会话 + 新对话 管理账号 管理账号 - 关闭会话 + 关闭对话 联系人详情 - 群聊详情 + 群组聊天详情 频道详情 添加账号 编辑名称 @@ -20,8 +20,8 @@ 解封参与者 管理账号 设置 - 分享至会话 - 开始会话 + 分享至对话 + 开始对话 选择联系人 选择联系人 通过账号分享 @@ -30,10 +30,10 @@ 1 分钟前 %d 分钟前 - %d 个未读会话 + %d 个未读对话 - 正在发送…… - 解密消息中。请稍候…… + 正在发送… + 解密消息中。请稍候… OpenPGP 加密的消息 昵称已使用 无效的昵称 @@ -42,18 +42,18 @@ 群主 参与者 访客 - 你想从通讯录中移除%s吗?此联系人的会话不会被清除。 + 你想从联系人列表中移除%s吗?此联系人的对话不会被清除。 你想封禁 %s向你发送消息吗? 你想解封%s并允许他们向你发送消息吗? 封禁来自%s的所有联系人吗\? 解封来自%s的所有联系人吗? 联系人已封禁 已封禁 - 你想从书签中移除%s吗?此书签的会话将不会被清除。 + 你想从书签中移除%s吗?此书签的对话将不会被清除。 在服务器上注册新账号 在服务器上修改密码 - 分享至…… - 开始会话 + 分享至… + 开始对话 邀请联系人 邀请 联系人 @@ -75,22 +75,22 @@ 无法连接到多个账号 点击管理你的账号 发送文件 - 此联系人不在你的通讯录中,需要添加吗 \? + 此联系人不在你的联系人列表中,需要添加吗 \? 添加联系人 传递失败 准备发送图片 准备发送图片 - 分享文件中。请稍候…… + 分享文件中。请稍候… 清除历史记录 - 清除会话记录 - 你想删除此会话中的所有消息吗? + 清除对话历史记录 + 你想删除此对话中的所有消息吗? \n \n警告:这不会删除存储在其他设备或服务器上的那些消息的副本。 删除文件 你确定要删除此文件吗? \n \n警告:这不会删除存储在其他设备或服务器上的此文件的副本。 - 之后关闭此会话 + 之后关闭此对话 选择设备 发送未加密的消息 发送消息 @@ -106,8 +106,8 @@ 重启 安装 请安装 OpenKeychain - 正在提供…… - 正在等候…… + 正在提供… + 正在等候… 未找到 OpenPGP 密钥 由于你的联系人未公布其公钥,无法加密你的消息。 \n @@ -118,7 +118,7 @@ \n请通知你的联系人设置 OpenPGP。 常规 接收文件 - 自动接收小于此大小的文件…… + 自动接收小于此大小的文件… 附件 通知 振动 @@ -162,7 +162,7 @@ 未知 暂时禁用 在线 - 正在连接…… + 正在连接… 离线 未授权 服务器未找到 @@ -192,7 +192,7 @@ \n你的联系人将无法再向你发送 OpenPGP 加密消息。 OpenPGP 公钥已发布。 启用账号 - 你确定删除账号吗?删除账号会删除你的全部会话历史记录 + 你确定删除账号吗?删除账号会删除你的全部对话历史记录 录制音频 XMPP 地址 封禁 XMPP 地址 @@ -231,13 +231,13 @@ v\\OMEMO 指纹(消息来源) 其他设备 信任的 OMEMO 指纹 - 获取密钥中…… + 获取密钥中… 完成 解密 搜索 输入联系人 删除联系人 - 查看联系人详细信息 + 查看联系人详情 封禁联系人 解封联系人 新建 @@ -248,21 +248,21 @@ channel@conference.example.com 保存为书签 删除书签 - 解散群聊 + 解散群组聊天 解散频道 - 你确定要解散此群聊吗? + 你确定要解散此群组聊天吗? \n -\n警告:此群聊将在服务器上完全删除。 +\n警告:此群组聊天将在服务器上完全删除。 你确定要解散此公共频道吗? \n \n警告:此频道将在服务器上完全删除。 - 无法解散群聊 + 无法解散群组聊天 无法解散频道 - 编辑群聊主题 + 编辑群组聊天主题 主题 - 正在加入群聊…… + 正在加入群组聊天… 离开 - 联系人已添加你到通讯录 + 联系人已添加你到联系人列表 反向添加 %s 已阅读至此 %s 已阅读至此 @@ -270,7 +270,7 @@ 所有人都已阅读至此 发布 点击头像从图库中选择图片 - 正在发布…… + 正在发布… 服务器拒绝了你的发布请求 无法转换你的图片 不能将头像保存至磁盘 @@ -278,7 +278,7 @@ 你的服务器不支持发布头像 私聊 至%s - 与%s私聊 + 发送私人消息至%s 连接 此账号已存在 下一步 @@ -286,7 +286,7 @@ 跳过 关闭通知 启用 - 需要密码才能进入此群聊 + 群组聊天需要密码 输入密码 请先向你的联系人请求在线状态更新。 \n @@ -311,13 +311,13 @@ 同步书签 加入或离开多用户聊天时设置 “autojoin\" 标志,并回应其他客户端所做更改。 OMEMO 指纹已复制到剪贴板 - 你被此群聊封禁 - 此群聊仅限成员参与 + 你被此群组聊天封禁 + 此群组聊天仅限成员参与 资源限制 - 你被此群聊踢出 - 此群聊已被关闭 - 你已不在此群聊 - 由于技术原因你离开了此群聊 + 你被此群组聊天踢出 + 此群组聊天已被关闭 + 你已不在此群组聊天 + 由于技术原因你离开了此群组聊天 使用账号%s 托管于%s 正在 HTTP 主机上检查%s @@ -369,8 +369,8 @@ 动态标签 在联系人下方显示只读标签 启用通知 - 群聊服务器未找到 - 无法创建群聊 + 群组聊天服务器未找到 + 无法创建群组聊天 账号头像 复制 OMEMO 指纹到剪贴板 重新生成 OMEMO 密钥 @@ -383,7 +383,7 @@ 出错了 正在从服务器获取历史记录 服务器上没有更多历史记录 - 更新中…… + 正在更新… 密码已修改! 不能修改密码 修改密码 @@ -404,22 +404,22 @@ 撤销管理员权限 授予所有者权限 撤销所有者权限 - 从群聊中移除 + 从群组聊天中移除 从频道中移除 不能修改%s的从属关系 - 从群聊中封禁 + 从群组聊天中封禁 从频道中封禁 你正在尝试从公共频道中移除%s。唯一的办法就是永远封禁此用户。 立即封禁 不能修改%s的角色 - 私密群聊设置 - 公开频道设置 - 私密,仅限成员 + 私人群组聊天配置 + 公开频道配置 + 私人,仅限成员 使 XMPP 地址对任何人可见 使频道受到管理 你未参与 - 群聊设置修改成功! - 无法更改群聊设置 + 已修改群组聊天选项! + 无法更改群组聊天选项 从不 直至另行通知 稍后提醒 @@ -442,9 +442,9 @@ 正在发送%s 正在提供%s 隐藏离线联系人 - %s正在输入…… + %s正在输入… %s已停止输入 - %s正在输入…… + %s正在输入… %s已停止输入 输入通知 让对方知道你正在写消息 @@ -452,8 +452,8 @@ 显示位置 未找到可以显示位置的应用 位置 - 会话已关闭 - 离开私密群聊 + 对话已关闭 + 离开私人群组聊天 离开公开频道 不信任系统证书 所有证书必须手动批准 @@ -472,8 +472,8 @@ 最近使用 选择快捷操作 搜索联系人 - 发送私密消息 - %1$s离开了群聊 + 发送私人消息 + %1$s离开了群组聊天 用户名 用户名 此用户名无效 @@ -500,7 +500,7 @@ 无法解析证书 存档首选项 服务器端存档首选项 - 获取存档首选项。请稍候…… + 获取存档首选项。请稍候… 无法获取存档首选项 需要验证码 输入上图中的文字 @@ -530,7 +530,7 @@ 授予 %1$s 访问外部存储的权限 授予 %1$s 访问相机的权限 同步联系人 - %1$s想要访问通讯录的权限来将它与你的 XMPP 通讯录相匹配。 + %1$s想要访问通讯录的权限来将它与你的 XMPP 联系人列表相匹配。 \n这会显示你的联系人的完整姓名和头像。 \n \n%1$s只会读取你的通讯录并在本地进行匹配,不会将信息上传到你的服务器。 @@ -553,11 +553,11 @@ 必填 更正消息 发送更正后的消息 - 你已经安全地验证了此人指纹以确认信任。通过选择“完成”,你只是确认%s是此群聊的一部分。 + 你已经安全地验证了此人指纹以确认信任。通过选择“完成”,确认%s加入群组聊天。 你已经禁用了此账号 安全错误:文件访问无效! 未找到可以分享此链接的应用 - 分享链接…… + 分享链接… 同意并继续 在 conversations.im 上有创建账号的指南。 \n选择 conversations.im 作为提供者时,你只需提供完整的 XMPP 地址,就能与其他提供者的用户进行交流。 @@ -578,7 +578,7 @@ 注册失败:稍后再试 注册失败:密码太弱 选择参与者 - 正在创建群聊…… + 正在创建群组聊天… 再次邀请 禁用 @@ -625,10 +625,10 @@ 此设备已验证 复制指纹 你已验证了你拥有的所有 OMEMO 密钥 - 条形码不包含此次会话的指纹。 + 条形码不包含此次对话的指纹。 已验证的指纹 使用相机扫描联系人的条形码 - 请等待获取密钥 + 请稍候获取密钥 分享条形码 分享 XMPP URI 分享 HTTP 链接 @@ -639,8 +639,8 @@ 无效二维码 清理缓存文件夹(由相机应用使用) 清除缓存 - 清除私密存储 - 清除保存私密文件的存储(可从服务器重新下载) + 清除私人存储空间 + 清除保存文件的私人存储(可从服务器重新下载) 此链接的源头是可信的 点击链接后将会开始验证%1$s的 OMEMO 密钥。只有当你从仅%2$s才能发布此链接的可信来源点击此链接时,这才是安全的。 你将验证你自己账号的 OMEMO 密钥。只有当你从仅你才能发布此链接的可信来源点击此链接时,这才是安全的。 @@ -674,7 +674,7 @@ 消息加密中 由于本地保留期限设置,无法提取消息。 正在压缩视频 - 相应的会话已关闭。 + 相应的对话已关闭。 联系人已封禁。 来自陌生人的通知 收到陌生人的消息和电话时进行通知。 @@ -700,7 +700,7 @@ 复制到剪贴板 消息已复制到剪贴板 消息 - 禁止私信 + 私人消息被禁用 受保护的应用 为了在屏幕关闭时也能收到消息提醒,你需要将 Conversations 加入受保护的应用列表。 接受未知的证书? @@ -719,15 +719,15 @@ %1$s 无法发送加密消息到 %2$s。这可能是因为你的联系人使用了过期的服务器或者无法处理 OMEMO 的客户端。 无法获取设备列表 无法获取密钥 - 提示:某些情况下,可以将对方加入你的通讯录,以解决此问题。 - 你确定要禁用此会话的 OMEMO 加密吗? + 提示:某些情况下,可以将对方加入你的联系人列表,以解决此问题。 + 你确定要禁用此对话的 OMEMO 加密吗? \n这将允许服务器管理员阅读你的消息,但这可能是与使用过时客户端的用户进行交流的唯一方法。 立即禁用 草稿: OMEMO 加密 OMEMO 将始终用于一对一和私人群组聊天。 - OMEMO 将默认用于新会话。 - OMEMO 将必须为新会话明确打开。 + OMEMO 将默认用于新对话。 + OMEMO 将必须为新对话明确打开。 创建快捷方式 字体大小 应用内使用的相对字体大小。 @@ -749,27 +749,27 @@ 显示位置 分享 无法开始录制 - 请等待…… + 请稍候… 授权 %1$s 访问麦克风 搜索消息 GIF - 查看会话 + 查看对话 位置分享插件 使用共享位置插件代替内置地图 复制网址 复制 XMPP 地址 用于 S3 的 HTTP 文件分享 直接搜索 - 在“开始会话”屏幕上打开键盘并将光标放在搜索栏中 - 群聊头像 - 主机不支持群聊头像 - 只有所有者才能更改群聊头像 + 在“开始对话”屏幕上打开键盘并将光标放在搜索栏中 + 群组聊天头像 + 主机不支持群组聊天头像 + 只有所有者才能更改群组聊天头像 联系人名称 昵称 名称 提供名称是可选的 - 群聊名称 - 此群聊已被解散 + 群组聊天名称 + 此群组聊天已被解散 无法保存录制 前台服务 此通知类别用于显示 %1$s 正在运行的永久通知。 @@ -783,8 +783,8 @@ 正在进行的通话 未接来电 静音消息 - 此通知组用于显示不应触发任何声音的通知。 例如,在另一台设备上处于活动状态时(静默期)。 - 发送失败 + 此通知组用于显示不应触发任何声音的通知。 例如,在另一台设备上处于活跃状态时(静默期)。 + 传递失败 消息通知设置 来电通知设置 重要程度、声音、振动 @@ -800,11 +800,11 @@ 已取消 你已经在起草一条消息了。 功能未实现 - 无效国家代码 - 选择国家 + 无效的国家/地区代码 + 选择国家/地区 手机号 验证你的手机号 - Quicksy 将发送短信(运营商可能收费)验证你的电话号码。请输入你的国家代码和手机号: + Quicksy 将发送短信(运营商可能收费)验证你的电话号码。请输入你的国家/地区代码和手机号: 我们将验证这个电话号码

%s

,这样可以吗?或者你想编辑这个号码?
%s 不是有效的电话号码。 请输入你的手机号。 @@ -822,8 +822,8 @@ 你确定要取消注册程序吗? - 正在验证…… - 正在请求短信…… + 正在验证… + 正在请求短信… 你输入的 PIN 码有误。 我们发给你的 PIN 码已过期。 未知网络错误。 @@ -852,7 +852,7 @@ 此频道将公开你的 XMPP 地址 电子书 原始(未压缩) - 打开为…… + 打开为… Conversations 个人资料图片 选择账号 恢复备份 @@ -861,18 +861,18 @@ 请勿使用恢复备份功能尝试克隆(同时运行)安装。恢复备份仅适用于迁移或你丢失原始设备的情况。 无法恢复备份。 无法解密备份。密码是否正确? - 备份与恢复 + 备份 & 恢复 输入 XMPP 地址 - 创建群聊 + 创建群组聊天 加入公开频道 - 创建私密群聊 + 创建私人群组聊天 创建公开频道 频道名称 XMPP 地址 请提供频道名 请提供 XMPP 地址 这是一个 XMPP 地址。请提供一个名称。 - 创建公开频道…… + 创建公开频道… 频道已存在 你加入了一个已经存在的频道 无法保存频道配置 @@ -886,7 +886,7 @@ XMPP 地址对管理员可见。 XMPP 地址对任何人可见。 此公开频道无参与者。邀请你的联系人或使用共享按钮分享其 XMPP 地址。 - 此私密群聊无参与者。 + 此私人群组聊天无参与者。 管理权限 搜索参与者 文件过大 @@ -908,9 +908,9 @@ 账号已设置 请输入此账号的密码 无法执行此操作 - 加入公开频道…… + 加入公开频道… 共享应用程序未授予访问此文件的权限。 - + 群组聊天 & 频道 jabber.network 本地服务器 大多数用户应该选择“jabber.network”以从整个 XMPP 生态系统中获得更好的建议。 @@ -960,7 +960,7 @@ 语音通话 视频通话 帮助 - 切换到会话 + 切换到对话 麦克风不可用 你每次只能拨打一个电话。 返回正在进行的通话 @@ -969,8 +969,8 @@ 取消置顶 GPX 轨迹 无法更正消息 - 所有会话 - 此会话 + 所有对话 + 此对话 你的头像 %s的头像 用 OMEMO 加密 @@ -980,20 +980,20 @@ 录制语音邮件 播放音频 暂停音频播放 - 添加联系人、创建或加入群聊,或发现频道 + 添加联系人、创建或加入群组聊天,或发现频道 查看 %1$d 位参与者 - 一些消息无法送达 + 一些消息无法传递 - 送达失败 + 传递失败 更多选项 未找到应用程序 邀请到 Conversations 无法解析邀请 服务器不支持生成邀请 - 没有活动账号支持此功能 + 没有活跃账号支持此功能 已启动备份。一旦完成,你会收到通知。 无法启用视频。 纯文本文档 @@ -1016,9 +1016,9 @@ 去电 · %s 频道发现功能使用第三方服务 <a href=https://search.jabber.network>search.jabber.network</a>。<br><br>使用此功能会发送你的 IP 地址和搜索词条到此服务。更多信息见 <a href=https://search.jabber.network/privacy>隐私政策</a>。 无法从服务器删除账号 - 群聊 - 另存为群聊 - 搜索群聊 + 群组聊天 + 保存为群组聊天 + 搜索群组聊天 从服务器删除账号 不要尝试恢复你尚未自行创建的备份! 你正尝试导入过时的备份文件格式 From 6ab58fe1f7b5d1e437b9810871851d15d5ed33e8 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Fri, 13 Oct 2023 09:17:35 +0000 Subject: [PATCH 173/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (13 of 13 strings) Translation: Conversations/Android App (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-conversations/zh_Hans/ --- src/conversations/res/values-zh-rCN/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/conversations/res/values-zh-rCN/strings.xml b/src/conversations/res/values-zh-rCN/strings.xml index 4b2d740a2..3731ca170 100644 --- a/src/conversations/res/values-zh-rCN/strings.xml +++ b/src/conversations/res/values-zh-rCN/strings.xml @@ -3,7 +3,7 @@ 选择你的 XMPP 提供者 使用 conversations.im 创建新账号 - 你已经有一个 XMPP 账号了吗?如果你之前使用过其他的 XMPP 客户端,那么你已经拥有这种账号了。如果没有的话,你现在可以创建一个。 + 你已经有一个 XMPP 账号了吗?如果你已经在使用不同的 XMPP 客户端或者以前使用过 Conversations,那么你已经拥有这种账号了。如果没有的话,你现在可以创建一个。 \n提示:有些电子邮件服务也提供 XMPP 账号。 XMPP 是独立于提供者的即时消息网络。你可以将此客户端与任意 XMPP 服务器一同使用。 \n不过,你可以很容易地在 conversations.im 上创建一个账号;它是特别适合与“Conversations”一起使用的提供者。 @@ -16,5 +16,5 @@ 点击分享按钮向你的联系人发送加入 %1$s 的邀请。 如果你的联系人在附近,他们也可以扫描下面的代码来接受你的邀请。 加入 %1$s 和我聊天:%2$s - 分享邀请… + 分享邀请至…
\ No newline at end of file From 73f1c9386319d932d814c4f6775ab0104aee3d4e Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Fri, 13 Oct 2023 09:12:11 +0000 Subject: [PATCH 174/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (9 of 9 strings) Translation: Conversations/Android App (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-quicksy/zh_Hans/ --- src/quicksy/res/values-zh-rCN/strings.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/quicksy/res/values-zh-rCN/strings.xml b/src/quicksy/res/values-zh-rCN/strings.xml index a93ac4a09..751df629a 100644 --- a/src/quicksy/res/values-zh-rCN/strings.xml +++ b/src/quicksy/res/values-zh-rCN/strings.xml @@ -1,12 +1,12 @@ - 发现在其它设备上的活动后,Conversations保持安静的时间 - 通过发送堆栈跟踪,您可以帮助 Quicksy 的持续开发 - 让你的所有联系人知道你使用Quicksy的时间 - 为了在屏幕关闭时也能收到消息提醒,您需要将 Quicksy 加入受保护的应用列表。 + Quicksy 发现其他设备上的活动后保持安静的时间长度 + 通过发送堆栈跟踪,你可以帮助 Quicksy 的持续开发 + 让所有联系人知道你在使用 Quicksy + 为了在屏幕关闭时也能收到消息提醒,你需要将 Quicksy 加入受保护的应用列表。 Quicksy 个人资料图片 - Quicksy在您的国家无服务。 + Quicksy 在你所在的国家/地区无法使用。 无法验证服务器身份。 未知安全错误。 - 连接到服务器时超时。 + 连接服务器超时。 \ No newline at end of file From 1543dee6e6151ba835a60cc343181ea2118fda43 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Fri, 13 Oct 2023 08:56:41 +0000 Subject: [PATCH 175/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (2 of 2 strings) Translation: Conversations/App Store Metadata (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata-conversations/zh_Hans/ --- .../fastlane/metadata/android/zh-CN/full_description.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt b/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt index 6853d2e19..a3d6757a8 100644 --- a/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt +++ b/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt @@ -32,7 +32,7 @@ Conversations 适用于所有 XMPP 服务器。然而,XMPP是一种可扩展 * XEP-0163:个人事件协议对于头像 * XEP-0191:屏蔽指令可让你将垃圾邮件发送者列入黑名单或封禁的联系人中,而不会将其从通讯录中删除。 * XEP-0198:流管理允许 XMPP 在小规模网络中断和底层 TCP 连接发生变化时继续运行。 -* XEP-0280:消息抄送,可自动将你发送的消息同步到桌面客户端,因此你可以在一次会话中从手机客户端无缝切换到桌面客户端,然后再返回。 +* XEP-0280:消息抄送,可自动将你发送的消息同步到桌面客户端,因此你可以在一次对话中从手机客户端无缝切换到桌面客户端,然后再返回。 * XEP-0237:通讯录版本化主要是为了在移动连接不佳的情况下节省带宽 * XEP-0313:消息存档管理与服务器同步消息历史记录。传递 Conversations 离线时发送的消息。 * XEP-0352:客户端状态指示让服务器知道 Conversations 是否在后台。允许服务器保留不重要的数据包,从而节省带宽。 From 8c53f19458095d5a252dca2cf246b2841e4398a5 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Fri, 13 Oct 2023 11:08:00 +0000 Subject: [PATCH 176/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (51 of 51 strings) Translation: Conversations/App Store Metadata (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/zh_Hans/ --- fastlane/metadata/android/zh-CN/changelogs/349.txt | 2 +- fastlane/metadata/android/zh-CN/changelogs/398.txt | 4 ++-- fastlane/metadata/android/zh-CN/changelogs/42037.txt | 2 +- fastlane/metadata/android/zh-CN/changelogs/42068.txt | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fastlane/metadata/android/zh-CN/changelogs/349.txt b/fastlane/metadata/android/zh-CN/changelogs/349.txt index d5d84b8bc..836b1e8aa 100644 --- a/fastlane/metadata/android/zh-CN/changelogs/349.txt +++ b/fastlane/metadata/android/zh-CN/changelogs/349.txt @@ -1,4 +1,4 @@ * 引入专家设置在本地服务器上执行频道发现而不是 search.jabber.network -* 默认启用发送复选标记并删除设置 +* 默认启用传递复选标记并删除设置 * 默认启用“发送按钮指示状态”并删除设置 * 将备份和前台服务设置移至主屏幕 diff --git a/fastlane/metadata/android/zh-CN/changelogs/398.txt b/fastlane/metadata/android/zh-CN/changelogs/398.txt index c4bf43212..5a3df8a3f 100644 --- a/fastlane/metadata/android/zh-CN/changelogs/398.txt +++ b/fastlane/metadata/android/zh-CN/changelogs/398.txt @@ -1,4 +1,4 @@ -* 搜索个人会话 -* 消息发送失败时通知用户 +* 搜索个人对话 +* 消息传递失败时通知用户 * 重新启动时记住 Quicksy 用户的显示名称(昵称) * 如有必要,添加按钮以从通知中启动 Orbot(Tor) diff --git a/fastlane/metadata/android/zh-CN/changelogs/42037.txt b/fastlane/metadata/android/zh-CN/changelogs/42037.txt index b1a32f6ad..db6e59ceb 100644 --- a/fastlane/metadata/android/zh-CN/changelogs/42037.txt +++ b/fastlane/metadata/android/zh-CN/changelogs/42037.txt @@ -1,7 +1,7 @@ 版本2.10.9 * 进行音视频通话时请求蓝牙权限(如果你不使用蓝牙耳机可以拒绝) * 修复呼叫 Movim 时的错误 -* 修复群聊时显示错误头像的问题 +* 修复群组聊天的显示错误头像的问题 * 始终要求选择退出电池优化 * 在“x 个已连接账号”通知上设置仅本地标志 * 修复与 Google 地图共享位置插件的交互 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42068.txt b/fastlane/metadata/android/zh-CN/changelogs/42068.txt index b022e0fd2..3c7020ba0 100644 --- a/fastlane/metadata/android/zh-CN/changelogs/42068.txt +++ b/fastlane/metadata/android/zh-CN/changelogs/42068.txt @@ -1,2 +1,2 @@ -* 支持每个会话通知设置 +* 支持每个对话通知设置 * 在 Android 10 上使用 opus 发送语音消息 From 01053d1ad2d9d5b8594dcaca41f948580f118102 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Fri, 13 Oct 2023 14:03:53 +0000 Subject: [PATCH 177/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (2 of 2 strings) Translation: Conversations/App Store Metadata (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata-quicksy/zh_Hans/ --- .../fastlane/metadata/android/zh-CN/full_description.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quicksy/fastlane/metadata/android/zh-CN/full_description.txt b/src/quicksy/fastlane/metadata/android/zh-CN/full_description.txt index 8dd32119d..d98d310bc 100644 --- a/src/quicksy/fastlane/metadata/android/zh-CN/full_description.txt +++ b/src/quicksy/fastlane/metadata/android/zh-CN/full_description.txt @@ -2,7 +2,7 @@ Quicksy 是流行的 Jabber/XMPP 客户端 Conversations 的衍生产品,具 你只需用电话号码注册,Quicksy 就会自动—根据你通讯录中的电话号码—向你推荐可能的联系人。 -从本质上讲,Quicksy 是一个成熟的 Jabber 客户端,可让你与任何公共联合服务器上的任何用户进行交流。同样,只需将 +phonenumber@quicksy.im 添加到你的通讯录中,即可从外部联系 Quicksy 上的用户。 +从本质上讲,Quicksy 是一个成熟的 Jabber 客户端,可让你与任何公共联合服务器上的任何用户进行交流。同样,只需将 +phonenumber@quicksy.im 添加到你的联系人列表中,即可从外部联系 Quicksy 上的用户。 除了联系人同步之外,用户界面尽可能地接近 Conversations。这使得用户最终可以从 Quicksy 迁移到 Conversations,而无需重新学习应用程序的工作方式。 From b5e7a9e7f9dc98496adb93cbcf3494853a97c690 Mon Sep 17 00:00:00 2001 From: nautilusx Date: Fri, 13 Oct 2023 21:45:27 +0000 Subject: [PATCH 178/402] Translated using Weblate (German) Currently translated at 100.0% (970 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/de/ --- src/main/res/values-de/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-de/strings.xml b/src/main/res/values-de/strings.xml index 3c465681c..455d31803 100644 --- a/src/main/res/values-de/strings.xml +++ b/src/main/res/values-de/strings.xml @@ -1012,4 +1012,5 @@ Versuche nicht, Backups wiederherzustellen, die du nicht selbst erstellt hast! Du versuchst, ein veraltetes Sicherungsdateiformat zu importieren Hörbuch + Verbindung auf anderem Host wiederherstellen \ No newline at end of file From 67b10504e3e466b0d9bb8fffe71e0a67c8bf93e1 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Fri, 13 Oct 2023 23:24:27 +0000 Subject: [PATCH 179/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (970 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index 1e1e92bff..dda66f685 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -11,7 +11,7 @@ 添加账号 编辑名称 添加到通讯录 - 从通讯录中删除 + 从名册中删除 封禁联系人 解封联系人 封禁域名 @@ -205,8 +205,8 @@ XEP-0313:消息存档管理 XEP-0280:消息抄送 XEP-0352:客户端状态指示 - XEP-0191:屏蔽指令 - XEP-0237:通讯录版本管理 + XEP-0191:封禁指令 + XEP-0237:名册版本控制 XEP-0198:流管理 XEP-0215:发现外部服务 XEP-0163:个人事件协议(头像/OMEMO) @@ -1023,4 +1023,5 @@ 不要尝试恢复你尚未自行创建的备份! 你正尝试导入过时的备份文件格式 有声书 + 重新连接其他主机 \ No newline at end of file From 8edf835872c8df18f08f0e215b5462991847d46f Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Fri, 13 Oct 2023 23:55:48 +0000 Subject: [PATCH 180/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (13 of 13 strings) Translation: Conversations/Android App (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-conversations/zh_Hans/ --- src/conversations/res/values-zh-rCN/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conversations/res/values-zh-rCN/strings.xml b/src/conversations/res/values-zh-rCN/strings.xml index 3731ca170..ff37bb346 100644 --- a/src/conversations/res/values-zh-rCN/strings.xml +++ b/src/conversations/res/values-zh-rCN/strings.xml @@ -12,7 +12,7 @@ 你已受邀加入 %1$s。已为你选择了一个用户名。我们将指导你完成创建账号的过程。 \n你可以使用完整的 XMPP 地址来与其他提供者的用户进行交流。 你的服务器邀请 - 格式不正确的配置代码 + 配置代码格式不当 点击分享按钮向你的联系人发送加入 %1$s 的邀请。 如果你的联系人在附近,他们也可以扫描下面的代码来接受你的邀请。 加入 %1$s 和我聊天:%2$s From 26fbde560862e5a7d591bf47f9b238daaa0b0538 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Fri, 13 Oct 2023 23:52:47 +0000 Subject: [PATCH 181/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (2 of 2 strings) Translation: Conversations/App Store Metadata (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata-conversations/zh_Hans/ --- .../fastlane/metadata/android/zh-CN/full_description.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt b/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt index a3d6757a8..0f199930a 100644 --- a/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt +++ b/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt @@ -30,10 +30,10 @@ Conversations 适用于所有 XMPP 服务器。然而,XMPP是一种可扩展 * XEP-0065:SOCKS5字节流(or mod_proxy65)。如果双方都在防火墙(NAT)后面,将用于传输文件。 * XEP-0163:个人事件协议对于头像 -* XEP-0191:屏蔽指令可让你将垃圾邮件发送者列入黑名单或封禁的联系人中,而不会将其从通讯录中删除。 +* XEP-0191:封禁指令可让你将垃圾邮件发送者列入黑名单或封禁的联系人中,而不会将其从名册中删除。 * XEP-0198:流管理允许 XMPP 在小规模网络中断和底层 TCP 连接发生变化时继续运行。 * XEP-0280:消息抄送,可自动将你发送的消息同步到桌面客户端,因此你可以在一次对话中从手机客户端无缝切换到桌面客户端,然后再返回。 -* XEP-0237:通讯录版本化主要是为了在移动连接不佳的情况下节省带宽 +* XEP-0237:名册版本控制主要是为了在移动连接不佳的情况下节省带宽 * XEP-0313:消息存档管理与服务器同步消息历史记录。传递 Conversations 离线时发送的消息。 * XEP-0352:客户端状态指示让服务器知道 Conversations 是否在后台。允许服务器保留不重要的数据包,从而节省带宽。 * XEP-0363:通过 HTTP 文件上传功能,你可以在群聊中与离线联系人共享文件。需要在服务器上安装额外组件。 From 66415e3f7691c9014e935d3e4784f98db7ecaa55 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Fri, 13 Oct 2023 23:42:26 +0000 Subject: [PATCH 182/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (51 of 51 strings) Translation: Conversations/App Store Metadata (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/zh_Hans/ --- fastlane/metadata/android/zh-CN/changelogs/42014.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane/metadata/android/zh-CN/changelogs/42014.txt b/fastlane/metadata/android/zh-CN/changelogs/42014.txt index 11afbe025..4b1865a6a 100644 --- a/fastlane/metadata/android/zh-CN/changelogs/42014.txt +++ b/fastlane/metadata/android/zh-CN/changelogs/42014.txt @@ -1,2 +1,2 @@ * 始终验证域名。 没有用户覆盖 -* 支持通讯录预验证 +* 支持名册预验证 From 55551610eca145b538390c9fd24fdbd4d3a96269 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Sat, 14 Oct 2023 02:28:16 +0000 Subject: [PATCH 183/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (970 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index dda66f685..5543c6aff 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -135,7 +135,7 @@ 从不发送崩溃报告 通过发送堆栈跟踪,你可以为开发提供帮助 确认消息 - 让对方知道你收到并阅读了他们的消息 + 让联系人知道你已收到并阅读了他们的消息 防止截屏 在应用切换中隐藏应用程序内容并阻止截图 用户界面 @@ -253,7 +253,7 @@ 你确定要解散此群组聊天吗? \n \n警告:此群组聊天将在服务器上完全删除。 - 你确定要解散此公共频道吗? + 你确定要解散此公开频道吗? \n \n警告:此频道将在服务器上完全删除。 无法解散群组聊天 @@ -298,7 +298,7 @@ \n前往联系人详情以验证你订阅的在线状态。 安全 允许更正消息 - 允许对方发送后编辑消息 + 允许联系人发送后编辑消息 高级设置 请谨慎使用 关于%s @@ -409,7 +409,7 @@ 不能修改%s的从属关系 从群组聊天中封禁 从频道中封禁 - 你正在尝试从公共频道中移除%s。唯一的办法就是永远封禁此用户。 + 你正在尝试从公开频道中移除%s。唯一的办法就是永远封禁此用户。 立即封禁 不能修改%s的角色 私人群组聊天配置 @@ -447,7 +447,7 @@ %s正在输入… %s已停止输入 输入通知 - 让对方知道你正在写消息 + 让联系人知道你在给他们写消息 发送位置 显示位置 未找到可以显示位置的应用 @@ -533,7 +533,7 @@ %1$s想要访问通讯录的权限来将它与你的 XMPP 联系人列表相匹配。 \n这会显示你的联系人的完整姓名和头像。 \n -\n%1$s只会读取你的通讯录并在本地进行匹配,不会将信息上传到你的服务器。 +\n%1$s只会读取你的通讯录并在本地进行匹配,不会上传任何东西到你的服务器。
通知所有消息 仅在提及时通知 通知已禁用 @@ -610,7 +610,7 @@ 远程服务器未找到 远程服务器超时 无法更新账号 - 举报此 XMPP 地址发送垃圾信息。 + 举报此 XMPP 地址发送垃圾消息。 删除 OMEMO 身份 重新生成 OMEMO 密钥。所有联系人都需要再次验证。请将此作为最后的办法。 删除选择的密钥 From 01b44948c1f200f74123c045d09715948dfe6eb7 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 15 Oct 2023 08:48:09 +0200 Subject: [PATCH 184/402] support data extraction rules Data Extraction Rules have replaced Backup Content on Android 12 --- src/main/AndroidManifest.xml | 6 ++++-- src/main/res/xml/data_extraction_rules.xml | 11 +++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 src/main/res/xml/data_extraction_rules.xml diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 1377cb257..d7da25ccc 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -78,6 +78,7 @@ android:allowBackup="true" android:appCategory="social" android:fullBackupContent="@xml/backup_content" + android:dataExtractionRules="@xml/data_extraction_rules" android:hardwareAccelerated="true" android:icon="@mipmap/new_launcher" android:label="@string/app_name" @@ -88,7 +89,7 @@ android:theme="@style/ConversationsTheme" tools:replace="android:label" android:localeConfig="@xml/locales_config" - tools:targetApi="q"> + tools:targetApi="tiramisu"> - + diff --git a/src/main/res/xml/data_extraction_rules.xml b/src/main/res/xml/data_extraction_rules.xml new file mode 100644 index 000000000..54ba0d72b --- /dev/null +++ b/src/main/res/xml/data_extraction_rules.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file From 3350ea8b5bab0707d06d3ee4fa2df264e368b49b Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 15 Oct 2023 08:51:06 +0200 Subject: [PATCH 185/402] ensure we are in session accepted when processing content-modify --- .../siacs/conversations/xmpp/jingle/JingleRtpConnection.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java index af6d219b0..e080b2a35 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java @@ -563,7 +563,10 @@ public class JingleRtpConnection extends AbstractJingleConnection } private void receiveContentModify(final JinglePacket jinglePacket) { - // TODO check session accepted + if (this.state != State.SESSION_ACCEPTED) { + terminateWithOutOfOrder(jinglePacket); + return; + } final Map modification = Maps.transformEntries( jinglePacket.getJingleContents(), (key, value) -> value.getSenders()); From 1b49e6b3c178e8690bb7636c4029b371a41dcc20 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 15 Oct 2023 11:23:12 +0200 Subject: [PATCH 186/402] disable password edit unless unauthorized --- src/main/java/eu/siacs/conversations/entities/Account.java | 5 ++++- .../java/eu/siacs/conversations/ui/EditAccountActivity.java | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 0fb748d88..eb042a1a6 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -31,7 +31,6 @@ import eu.siacs.conversations.crypto.sasl.HashedToken; import eu.siacs.conversations.crypto.sasl.HashedTokenSha256; import eu.siacs.conversations.crypto.sasl.HashedTokenSha512; import eu.siacs.conversations.crypto.sasl.SaslMechanism; -import eu.siacs.conversations.crypto.sasl.ScramPlusMechanism; import eu.siacs.conversations.services.AvatarService; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.utils.UIHelper; @@ -328,6 +327,10 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable } } + public boolean unauthorized() { + return this.status == State.UNAUTHORIZED || this.lastErrorStatus == State.UNAUTHORIZED; + } + public State getLastErrorStatus() { return this.lastErrorStatus; } diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index b4812477f..e58a05729 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -1025,7 +1025,8 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat final boolean togglePassword = mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE) || !mAccount.isOptionSet(Account.OPTION_LOGGED_IN_SUCCESSFULLY); - final boolean editPassword = !mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE) || (!mAccount.isOptionSet(Account.OPTION_LOGGED_IN_SUCCESSFULLY) && QuickConversationsService.isConversations()) || mAccount.getLastErrorStatus() == Account.State.UNAUTHORIZED; + final boolean neverLoggedIn = !mAccount.isOptionSet(Account.OPTION_LOGGED_IN_SUCCESSFULLY) && QuickConversationsService.isConversations(); + final boolean editPassword = mAccount.unauthorized() || neverLoggedIn; this.binding.accountPasswordLayout.setPasswordVisibilityToggleEnabled(togglePassword); From 5da883730feee1d5f98385e4b6229a732bc3399b Mon Sep 17 00:00:00 2001 From: ghose Date: Sat, 14 Oct 2023 06:02:58 +0000 Subject: [PATCH 187/402] Translated using Weblate (Galician) Currently translated at 100.0% (970 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/gl/ --- src/main/res/values-gl/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-gl/strings.xml b/src/main/res/values-gl/strings.xml index 60281767b..1bbe45d5a 100644 --- a/src/main/res/values-gl/strings.xml +++ b/src/main/res/values-gl/strings.xml @@ -1015,4 +1015,5 @@ Non intentes restablecer unha copia de apoio que non tiveses creado ti! Estás intentando importar un ficheiro de apoio co formato antigo Audiolibro + Volver conectar noutro servidor \ No newline at end of file From 92a500bf11d86edfdc1c5b856666049e1458be9c Mon Sep 17 00:00:00 2001 From: SomeTr Date: Sat, 14 Oct 2023 12:33:42 +0000 Subject: [PATCH 188/402] Translated using Weblate (Ukrainian) Currently translated at 100.0% (970 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/uk/ --- src/main/res/values-uk/strings.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/res/values-uk/strings.xml b/src/main/res/values-uk/strings.xml index f192c50db..5cdbe7bb9 100644 --- a/src/main/res/values-uk/strings.xml +++ b/src/main/res/values-uk/strings.xml @@ -1030,7 +1030,7 @@ Пропущений виклик · %s Вхідний виклик (%s) · %s Вихідний виклик (%s) · %s - Повторне з\'єнання + Повторне з\'єднання Повторний виклик Повторний відеовиклик Проблема при перевірці @@ -1066,4 +1066,5 @@ Не намагайтеся відновити резервні копії, які створили не Ви! Ви намагаєтеся імпортувати файл резервної копії у застарілому форматі Аудіокнига + Відновити з\'єднання на іншому вузлі \ No newline at end of file From 451f102046ec635ede2d87d1d078d170e4521c2a Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Sat, 14 Oct 2023 12:39:24 +0000 Subject: [PATCH 189/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (970 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 174 ++++++++++++------------- 1 file changed, 87 insertions(+), 87 deletions(-) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index 5543c6aff..8ba8d8786 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -12,12 +12,12 @@ 编辑名称 添加到通讯录 从名册中删除 - 封禁联系人 - 解封联系人 - 封禁域名 - 解封域名 - 封禁参与者 - 解封参与者 + 屏蔽联系人 + 解除屏蔽联系人 + 屏蔽域名 + 解除屏蔽域名 + 屏蔽参与者 + 解除屏蔽参与者 管理账号 设置 分享至对话 @@ -25,7 +25,7 @@ 选择联系人 选择联系人 通过账号分享 - 封禁列表 + 屏蔽列表 刚才 1 分钟前 %d 分钟前 @@ -39,16 +39,16 @@ 无效的昵称 管理员 所有者 - 群主 + 主持人 参与者 访客 你想从联系人列表中移除%s吗?此联系人的对话不会被清除。 - 你想封禁 %s向你发送消息吗? - 你想解封%s并允许他们向你发送消息吗? - 封禁来自%s的所有联系人吗\? - 解封来自%s的所有联系人吗? - 联系人已封禁 - 已封禁 + 你想屏蔽%s向你发送消息吗? + 你想解除屏蔽%s并允许他们向你发送消息吗? + 屏蔽来自%s的所有联系人吗\? + 解除屏蔽来自%s的所有联系人吗? + 联系人已屏蔽 + 已屏蔽 你想从书签中移除%s吗?此书签的对话将不会被清除。 在服务器上注册新账号 在服务器上修改密码 @@ -63,8 +63,8 @@ 添加 编辑 删除 - 封禁 - 解封 + 屏蔽 + 解除屏蔽 保存 完成 %1$s已崩溃 @@ -74,7 +74,7 @@ 无法连接账号 无法连接到多个账号 点击管理你的账号 - 发送文件 + 附上文件 此联系人不在你的联系人列表中,需要添加吗 \? 添加联系人 传递失败 @@ -94,13 +94,13 @@ 选择设备 发送未加密的消息 发送消息 - 发消息给%s + 发送消息至%s 发送 OMEMO 加密消息 发送 v\\OMEMO 加密消息 发送 OpenPGP 加密消息 新昵称使用中 - 发送未加密 - 解密失败,也许你没有正确的私钥。 + 发送未加密的 + 解密失败。也许你没有正确的私钥。 OpenKeychain %1$s使用 <b>OpenKeychain</b>来加密和解密消息并管理你的公钥。<br><br>它在 GPLv3+ 许可证下授权并可在 F-Droid 和 Google Play 上获得。<br><br><small>(请稍后重新启动%1$s。)</small> 重启 @@ -127,8 +127,8 @@ 收到新消息时闪烁通知灯 铃声 通知铃声 - 新消息通知铃声 - 来电响铃 + 新消息的通知铃声 + 来电铃声 静默期 在你的其他设备上检测到活动之后,通知在此时间段内将被静音。 高级 @@ -140,7 +140,7 @@ 在应用切换中隐藏应用程序内容并阻止截图 用户界面 OpenKeychain 出现了一个错误。 - 错误的加密密钥。 + 加密密钥错误。 接受 出现了一个错误 错误 @@ -150,7 +150,7 @@ 请求在线状态更新 选择图片 拍摄图片 - 预先同意订阅请求 + 预先授予订阅请求 你所选的文件不是图片 无法转换图片文件 文件未找到 @@ -171,7 +171,7 @@ 用户名已使用 注册已完成 服务器不支持注册 - 无效的注册令牌 + 注册令牌无效 TLS 协商失败 域名无法验证 违反政策 @@ -195,7 +195,7 @@ 你确定删除账号吗?删除账号会删除你的全部对话历史记录 录制音频 XMPP 地址 - 封禁 XMPP 地址 + 屏蔽 XMPP 地址 username@example.com 密码 这不是有效的 XMPP 地址 @@ -205,15 +205,15 @@ XEP-0313:消息存档管理 XEP-0280:消息抄送 XEP-0352:客户端状态指示 - XEP-0191:封禁指令 + XEP-0191:屏蔽指令 XEP-0237:名册版本控制 XEP-0198:流管理 XEP-0215:发现外部服务 XEP-0163:个人事件协议(头像/OMEMO) XEP-0363:HTTP文件上传 XEP-0357:推送 - 有效 - 无效 + 可用 + 不可用 缺少公钥公布 最后上线于刚才 最后上线于 1 分钟前 @@ -238,11 +238,11 @@ 输入联系人 删除联系人 查看联系人详情 - 封禁联系人 - 解封联系人 + 屏蔽联系人 + 解除屏蔽联系人 新建 选择 - 联系人已存在 + 此联系人已存在 加入 channel@conference.example.com/nick channel@conference.example.com @@ -258,8 +258,8 @@ \n警告:此频道将在服务器上完全删除。
无法解散群组聊天 无法解散频道 - 编辑群组聊天主题 - 主题 + 编辑群组聊天话题 + 话题 正在加入群组聊天… 离开 联系人已添加你到联系人列表 @@ -297,10 +297,10 @@ \n \n前往联系人详情以验证你订阅的在线状态。
安全 - 允许更正消息 - 允许联系人发送后编辑消息 + 允许消息更正 + 允许你的联系人发送后编辑其消息 高级设置 - 请谨慎使用 + 请谨慎使用这些 关于%s 静默时段 开始时间 @@ -311,10 +311,10 @@ 同步书签 加入或离开多用户聊天时设置 “autojoin\" 标志,并回应其他客户端所做更改。 OMEMO 指纹已复制到剪贴板 - 你被此群组聊天封禁 + 你已被此群组聊天封禁 此群组聊天仅限成员参与 资源限制 - 你被此群组聊天踢出 + 你已被此群组聊天踢出 此群组聊天已被关闭 你已不在此群组聊天 由于技术原因你离开了此群组聊天 @@ -336,7 +336,7 @@ 网址 扫描二维码 显示二维码 - 显示封禁列表 + 显示屏蔽列表 账号详情 确认 重试 @@ -363,8 +363,8 @@ 无法分享文件 文件传输已取消 文件已经删除 - 未找到可以打开此文件的应用 - 未找到可以打开此链接的应用 + 未找到可以打开文件的应用 + 未找到可以打开链接的应用 未找到可以查看联系人的应用 动态标签 在联系人下方显示只读标签 @@ -395,7 +395,7 @@ 执行操作 无从属关系 离线 - 已逐出 + 被驱逐者 成员 高级模式 授予成员权限 @@ -409,7 +409,7 @@ 不能修改%s的从属关系 从群组聊天中封禁 从频道中封禁 - 你正在尝试从公开频道中移除%s。唯一的办法就是永远封禁此用户。 + 你正试图从公开频道中移除%s。唯一的办法就是永远封禁此用户。 立即封禁 不能修改%s的角色 私人群组聊天配置 @@ -479,7 +479,7 @@ 此用户名无效 下载失败:服务器未找到 下载失败:文件未找到 - 下载失败:无法连接到服务器 + 下载失败:无法连接到主机 下载失败:不能写入文件 下载失败:无效文件 Tor 网络不可用 @@ -491,8 +491,8 @@ 当设备锁定时显示为离开 静音模式时忙碌 当设备处于静音模式时显示为忙碌 - 将振动看作静音 - 当设备振动时显示为忙碌 + 将振动模式视为静音模式 + 当设备处于振动模式时显示为忙碌 扩展连接设置 设置账号时显示主机名和端口设置 xmpp.example.com @@ -523,15 +523,15 @@ %d 条消息 加载更多消息 - 文件已分享给%s - 图片已分享给%s - 图片已分享给%s - 文本已分享给%s + 文件已分享至%s + 图片已分享至%s + 图片已分享至%s + 文本已分享至%s 授予 %1$s 访问外部存储的权限 授予 %1$s 访问相机的权限 同步联系人 %1$s想要访问通讯录的权限来将它与你的 XMPP 联系人列表相匹配。 -\n这会显示你的联系人的完整姓名和头像。 +\n这会显示你的联系人的全名和头像。 \n \n%1$s只会读取你的通讯录并在本地进行匹配,不会上传任何东西到你的服务器。 通知所有消息 @@ -541,7 +541,7 @@ 图片压缩 提示:无论此设置如何,使用“选择文件”而不是“选择图片”会发送未压缩的单张图片。 总是 - 仅限大图 + 仅限大图片 已启用节电模式 你的设备正对 %1$s 实施强力电池优化,这可能导致通知延迟甚至消息丢失。\n建议禁用这些优化。 你的设备正对 %1$s 实施强力电池优化,这可能导致通知延迟甚至消息丢失。 @@ -556,8 +556,8 @@ 你已经安全地验证了此人指纹以确认信任。通过选择“完成”,确认%s加入群组聊天。 你已经禁用了此账号 安全错误:文件访问无效! - 未找到可以分享此链接的应用 - 分享链接… + 未找到可以分享 URI 的应用 + 分享 URI 至… 同意并继续 在 conversations.im 上有创建账号的指南。 \n选择 conversations.im 作为提供者时,你只需提供完整的 XMPP 地址,就能与其他提供者的用户进行交流。 @@ -670,17 +670,17 @@ %d 个月 自动删除消息 - 自动从此设备上删除超过配置时间段的消息。 + 自动从此设备上删除超过配置时限的消息。 消息加密中 由于本地保留期限设置,无法提取消息。 正在压缩视频 相应的对话已关闭。 - 联系人已封禁。 - 来自陌生人的通知 - 收到陌生人的消息和电话时进行通知。 + 联系人已屏蔽。 + 陌生人的通知 + 收到陌生人的消息和来电时进行通知。 收到陌生人发来的消息 - 封禁陌生人 - 封禁整个域名 + 屏蔽陌生人 + 屏蔽整个域名 当前在线 重试解密 会话失败 @@ -695,7 +695,7 @@ 通过 DNSSEC 验证主机名 包含主机名的服务器证书被认为是已验证的 证书不包含 XMPP 地址 - 一部分 + 部分 录制视频 复制到剪贴板 消息已复制到剪贴板 @@ -711,8 +711,8 @@ 证书详情: 仅一次 二维码扫描器需要访问摄像头 - 滚动到底部 - 发送消息后滚动到底部 + 滚动至底部 + 发送消息后向下滚屏 编辑状态消息 编辑状态消息 禁用加密 @@ -755,7 +755,7 @@ GIF 查看对话 位置分享插件 - 使用共享位置插件代替内置地图 + 使用分享位置插件代替内置地图 复制网址 复制 XMPP 地址 用于 S3 的 HTTP 文件分享 @@ -794,7 +794,7 @@ 媒体浏览器 文件由于违反安全规定被删除。 视频质量 - 画质越低意味着文件越小 + 质量越低,文件越小 中(360p) 高(720p) 已取消 @@ -825,7 +825,7 @@ 正在验证… 正在请求短信… 你输入的 PIN 码有误。 - 我们发给你的 PIN 码已过期。 + 我们发送给你的 PIN 码已过期。 未知网络错误。 未知服务器响应。 无法连接服务器。 @@ -841,10 +841,10 @@ 你使用的是过时版本的应用程序。 更新 此电话号码目前已在其他设备上登录。 - 请输入你的名字,以便让通讯录中没有你的人知道你是谁。 - 你的名字 - 输入你的名字 - 使用编辑按钮设置你的名字。 + 请输入你的名称,以便让通讯录中没有你的人知道你是谁。 + 你的名称 + 输入你的名称 + 使用编辑按钮设置你的名称。 拒绝请求 安装 Orbot 启动 Orbot @@ -885,7 +885,7 @@ 任何人可以邀请别人。 XMPP 地址对管理员可见。 XMPP 地址对任何人可见。 - 此公开频道无参与者。邀请你的联系人或使用共享按钮分享其 XMPP 地址。 + 此公开频道无参与者。邀请你的联系人或使用分享按钮分享其 XMPP 地址。 此私人群组聊天无参与者。 管理权限 搜索参与者 @@ -909,7 +909,7 @@ 请输入此账号的密码 无法执行此操作 加入公开频道… - 共享应用程序未授予访问此文件的权限。 + 分享应用程序未授予访问此文件的权限。 群组聊天 & 频道 jabber.network 本地服务器 @@ -920,22 +920,22 @@ 请启用一个账号 进行通话 来电 - 视频来电 + 视频通话来电 切换到视频通话? 添加额外轨道? 正在连接 已连接 重新连接 - 正在接通来电 - 正在结束来电 + 接受通话 + 结束通话 应答 忽略 发现设备中 - 正在响铃 + 响铃中 正忙 - 无法接通来电 + 无法连接通话 连接丢失 - 通话已撤销 + 已撤回通话 程序错误 验证问题 挂断 @@ -943,21 +943,21 @@ 正在进行的视频通话 重连通话 重连视频通话 - 禁用 Tor 以拨打电话 + 禁用 Tor 以进行通话 来电 - 错过的通话 · %s + 未接来电 · %s 去电 - 未接电话 + 未接来电 - %1$d 错过了来自 %2$s 的电话 + 来自 %2$s 的 %1$d 个未接来电 - %d 个未接电话 + %d 个未接来电 - %1$d 个未接电话,来自 %2$d 位联系人 + 来自 %2$d 位联系人的 %1$d 个未接来电 - 语音通话 + 音频通话 视频通话 帮助 切换到对话 @@ -1021,7 +1021,7 @@ 搜索群组聊天 从服务器删除账号 不要尝试恢复你尚未自行创建的备份! - 你正尝试导入过时的备份文件格式 + 你正试图导入过时的备份文件格式 有声书 重新连接其他主机 \ No newline at end of file From 98d36cbd7d53fe22a18faaa12a2670cf52617e43 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Sat, 14 Oct 2023 07:04:17 +0000 Subject: [PATCH 190/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (13 of 13 strings) Translation: Conversations/Android App (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-conversations/zh_Hans/ --- src/conversations/res/values-zh-rCN/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conversations/res/values-zh-rCN/strings.xml b/src/conversations/res/values-zh-rCN/strings.xml index ff37bb346..373f56f6f 100644 --- a/src/conversations/res/values-zh-rCN/strings.xml +++ b/src/conversations/res/values-zh-rCN/strings.xml @@ -4,7 +4,7 @@ 使用 conversations.im 创建新账号 你已经有一个 XMPP 账号了吗?如果你已经在使用不同的 XMPP 客户端或者以前使用过 Conversations,那么你已经拥有这种账号了。如果没有的话,你现在可以创建一个。 -\n提示:有些电子邮件服务也提供 XMPP 账号。 +\n提示:有些电子邮件提供者也提供 XMPP 账号。 XMPP 是独立于提供者的即时消息网络。你可以将此客户端与任意 XMPP 服务器一同使用。 \n不过,你可以很容易地在 conversations.im 上创建一个账号;它是特别适合与“Conversations”一起使用的提供者。 你已受邀加入 %1$s。我们将指导你完成创建账号的过程。 From 07032e2a80eb50b03062f5ad4211773f3cafde95 Mon Sep 17 00:00:00 2001 From: SomeTr Date: Sat, 14 Oct 2023 12:32:47 +0000 Subject: [PATCH 191/402] Translated using Weblate (Ukrainian) Currently translated at 100.0% (51 of 51 strings) Translation: Conversations/App Store Metadata (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/uk/ --- fastlane/metadata/android/uk/changelogs/42041.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane/metadata/android/uk/changelogs/42041.txt b/fastlane/metadata/android/uk/changelogs/42041.txt index 8138f1334..f0c963522 100644 --- a/fastlane/metadata/android/uk/changelogs/42041.txt +++ b/fastlane/metadata/android/uk/changelogs/42041.txt @@ -1,4 +1,4 @@ -* Реалізація Extensible SASL Profile, Bind 2.0 і Fast для швидшого повторного з'єнання +* Реалізація Extensible SASL Profile, Bind 2.0 і Fast для швидшого повторного з'єднання * Реалізація Channel Binding * Додано можливість перемикатися з голосового на відеовиклик * Додано можливість видаляти свою піктограму користувача From 7eef73c0b86d7bafcd9942572bc6155f4282ea2c Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Sat, 14 Oct 2023 12:42:40 +0000 Subject: [PATCH 192/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (2 of 2 strings) Translation: Conversations/App Store Metadata (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata-conversations/zh_Hans/ --- .../fastlane/metadata/android/zh-CN/full_description.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt b/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt index 0f199930a..e95c62219 100644 --- a/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt +++ b/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt @@ -30,10 +30,10 @@ Conversations 适用于所有 XMPP 服务器。然而,XMPP是一种可扩展 * XEP-0065:SOCKS5字节流(or mod_proxy65)。如果双方都在防火墙(NAT)后面,将用于传输文件。 * XEP-0163:个人事件协议对于头像 -* XEP-0191:封禁指令可让你将垃圾邮件发送者列入黑名单或封禁的联系人中,而不会将其从名册中删除。 +* XEP-0191:屏蔽指令可让你将垃圾邮件发送者列入黑名单或屏蔽的联系人中,而不会将其从名册中删除。 * XEP-0198:流管理允许 XMPP 在小规模网络中断和底层 TCP 连接发生变化时继续运行。 * XEP-0280:消息抄送,可自动将你发送的消息同步到桌面客户端,因此你可以在一次对话中从手机客户端无缝切换到桌面客户端,然后再返回。 * XEP-0237:名册版本控制主要是为了在移动连接不佳的情况下节省带宽 * XEP-0313:消息存档管理与服务器同步消息历史记录。传递 Conversations 离线时发送的消息。 * XEP-0352:客户端状态指示让服务器知道 Conversations 是否在后台。允许服务器保留不重要的数据包,从而节省带宽。 -* XEP-0363:通过 HTTP 文件上传功能,你可以在群聊中与离线联系人共享文件。需要在服务器上安装额外组件。 +* XEP-0363:通过 HTTP 文件上传功能,你可以在群聊中与离线联系人分享文件。需要在服务器上安装额外组件。 From fbf6ef962a41fc8b659167435fad5cba7332d897 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Sat, 14 Oct 2023 05:27:07 +0000 Subject: [PATCH 193/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (51 of 51 strings) Translation: Conversations/App Store Metadata (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/zh_Hans/ --- fastlane/metadata/android/zh-CN/changelogs/42037.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane/metadata/android/zh-CN/changelogs/42037.txt b/fastlane/metadata/android/zh-CN/changelogs/42037.txt index db6e59ceb..9d6b04e34 100644 --- a/fastlane/metadata/android/zh-CN/changelogs/42037.txt +++ b/fastlane/metadata/android/zh-CN/changelogs/42037.txt @@ -4,7 +4,7 @@ * 修复群组聊天的显示错误头像的问题 * 始终要求选择退出电池优化 * 在“x 个已连接账号”通知上设置仅本地标志 -* 修复与 Google 地图共享位置插件的交互 +* 修复与 Google 地图分享位置插件的交互 * 删除有关服务器费用的脚注 * 将文件存储在适合 Android 11 的位置 * 网络切换后尝试重新连接通话 From 8da46c1658a4cf4ea03cd21c2848858f8267cf5d Mon Sep 17 00:00:00 2001 From: SomeTr Date: Sun, 15 Oct 2023 18:44:18 +0000 Subject: [PATCH 194/402] Translated using Weblate (Catalan) Currently translated at 92.2% (895 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/ca/ --- src/main/res/values-ca/strings.xml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/res/values-ca/strings.xml b/src/main/res/values-ca/strings.xml index 3efec8a7b..8a2fe7b8a 100644 --- a/src/main/res/values-ca/strings.xml +++ b/src/main/res/values-ca/strings.xml @@ -31,10 +31,7 @@ fa %d mins %dconverses no llegides - - %d converses no llegides - enviant… Desxifrant el missatge. Espereu… @@ -108,7 +105,9 @@ No s\'ha trobat cap clau OpenPGP No es va poder xifrar el teu missatge perquè el teu contacte no està anunciant la seva clau pública.\n\n Si us plau, demana-li al seu contacte que configuri OpenPGP. No s\'ha trobat cap clau OpenPGP - No es pot encriptar el teu missatge perquè els teus contactes no anuncien les seves claus públiques. Si us plau, demana\'ls que configurin OpenPGP. + No es pot encriptar el teu missatge perquè els teus contactes no anuncien les seves claus públiques. +\n +\nSi us plau, demana\'ls que configurin OpenPGP. General Accepta els fitxers Accepta fitxers automàticament amb una mida menor a… @@ -931,4 +930,4 @@ que l\'administrador del servidor llegeixi els missatges, però pot ser l\'únic No es pot processar la invitació El servidor no admet la generació d\'invitacions Cap compte actiu admet aquesta funció - + \ No newline at end of file From 8ad1ad338ed9f0e60d49acc83a409e09427d034d Mon Sep 17 00:00:00 2001 From: gallegonovato Date: Mon, 16 Oct 2023 16:12:13 +0000 Subject: [PATCH 195/402] Translated using Weblate (Spanish) Currently translated at 100.0% (970 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/es/ --- src/main/res/values-es/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-es/strings.xml b/src/main/res/values-es/strings.xml index 35a07ad76..71c1d179f 100644 --- a/src/main/res/values-es/strings.xml +++ b/src/main/res/values-es/strings.xml @@ -1026,4 +1026,5 @@ ¡No intentes restaurar las copias de seguridad que no creaste tu mismo! Estás intentando importar un formato de copia de seguridad obsoleto Audiolibro + Reconectarse a otros hosts \ No newline at end of file From bd0c9602f3ea9402cea4692223c31ec22317ad8a Mon Sep 17 00:00:00 2001 From: random_r Date: Mon, 16 Oct 2023 12:15:04 +0000 Subject: [PATCH 196/402] Translated using Weblate (Italian) Currently translated at 100.0% (970 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/it/ --- src/main/res/values-it/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-it/strings.xml b/src/main/res/values-it/strings.xml index 07bc8d01b..7a3b623ec 100644 --- a/src/main/res/values-it/strings.xml +++ b/src/main/res/values-it/strings.xml @@ -1026,4 +1026,5 @@ Non tentare di ripristinare dei backup che non hai creato te stesso! Stai tentando di importare un formato di file di backup obsoleto Audiolibro + Riconnetti su altro host \ No newline at end of file From 664f9491a711fedd9d805fc0a1ac48d7592169dd Mon Sep 17 00:00:00 2001 From: SomeTr Date: Sun, 15 Oct 2023 18:42:38 +0000 Subject: [PATCH 197/402] Translated using Weblate (Turkish) Currently translated at 97.6% (947 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/tr/ --- src/main/res/values-tr-rTR/strings.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/res/values-tr-rTR/strings.xml b/src/main/res/values-tr-rTR/strings.xml index f4652e192..7107efeb8 100644 --- a/src/main/res/values-tr-rTR/strings.xml +++ b/src/main/res/values-tr-rTR/strings.xml @@ -148,7 +148,9 @@ Görüntü dosyası dönüştürülemedi. Dosya bulunamadı Genel G/Ç hatası. Depolama yeri kalmamış olabilir mi? - Bu görüntüyü seçmekte kullandığınız uygulama, dosyanın okunması için yeterli izinleri sağlayamadı. Görüntüyü seçmek için farklı bir dosya yöneticisi kullan. + Bu görüntüyü seçmekte kullandığınız uygulama, dosyanın okunması için yeterli izinleri sağlayamadı. +\n +\nGörüntüyü seçmek için farklı bir dosya yöneticisi kullan. Bu dosyayı paylaşmakta kullandığınız uygulama yeterince yetki sağlamamaktadır. Bilinmeyen Geçici olarak devre dışı From 6416df65b1763d345dc103be53af6e38039875da Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Mon, 16 Oct 2023 13:54:44 +0000 Subject: [PATCH 198/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (970 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 343 +++++++++++++------------ 1 file changed, 172 insertions(+), 171 deletions(-) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index 8ba8d8786..ec1aa9176 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -42,14 +42,14 @@ 主持人 参与者 访客 - 你想从联系人列表中移除%s吗?此联系人的对话不会被清除。 - 你想屏蔽%s向你发送消息吗? - 你想解除屏蔽%s并允许他们向你发送消息吗? - 屏蔽来自%s的所有联系人吗\? - 解除屏蔽来自%s的所有联系人吗? + 你想从联系人列表中移除 %s 吗?与此联系人的对话将不会被清除。 + 你想屏蔽 %s 向你发送消息吗? + 你想解除屏蔽 %s 并允许他们向你发送消息吗? + 屏蔽来自 %s 的所有联系人吗? + 解除屏蔽来自 %s 的所有联系人吗? 联系人已屏蔽 已屏蔽 - 你想从书签中移除%s吗?此书签的对话将不会被清除。 + 你想从书签中移除 %s 吗?与此书签的对话将不会被清除。 在服务器上注册新账号 在服务器上修改密码 分享至… @@ -67,19 +67,19 @@ 解除屏蔽 保存 完成 - %1$s已崩溃 - 用你的 XMPP 账号发送堆栈跟踪有助于%1$s的持续开发。 + %1$s 已崩溃 + 使用你的 XMPP 账号发送堆栈跟踪有助于 %1$s 的持续开发。 立即发送 不再询问 无法连接账号 无法连接到多个账号 点击管理你的账号 附上文件 - 此联系人不在你的联系人列表中,需要添加吗 \? + 此联系人不在你的联系人列表中,需要添加吗? 添加联系人 传递失败 - 准备发送图片 - 准备发送图片 + 正在准备发送图片 + 正在准备发送图片 分享文件中。请稍候… 清除历史记录 清除对话历史记录 @@ -94,7 +94,7 @@ 选择设备 发送未加密的消息 发送消息 - 发送消息至%s + 发送消息至 %s 发送 OMEMO 加密消息 发送 v\\OMEMO 加密消息 发送 OpenPGP 加密消息 @@ -102,12 +102,12 @@ 发送未加密的 解密失败。也许你没有正确的私钥。 OpenKeychain - %1$s使用 <b>OpenKeychain</b>来加密和解密消息并管理你的公钥。<br><br>它在 GPLv3+ 许可证下授权并可在 F-Droid 和 Google Play 上获得。<br><br><small>(请稍后重新启动%1$s。)</small> + %1$s 使用 <b>OpenKeychain</b>来加密和解密消息并管理你的公钥。<br><br>它在 GPLv3+ 许可证下授权并可在 F-Droid 和 Google Play 上获得。<br><br><small>(请稍后重新启动 %1$s。)</small> 重启 安装 请安装 OpenKeychain 正在提供… - 正在等候… + 正在等待… 未找到 OpenPGP 密钥 由于你的联系人未公布其公钥,无法加密你的消息。 \n @@ -129,15 +129,15 @@ 通知铃声 新消息的通知铃声 来电铃声 - 静默期 - 在你的其他设备上检测到活动之后,通知在此时间段内将被静音。 + 宽限期 + 在你的某个其他设备上检测到活动之后,通知被静音的时间长度。 高级 从不发送崩溃报告 - 通过发送堆栈跟踪,你可以为开发提供帮助 + 通过发送堆栈跟踪,你正在帮助开发 确认消息 - 让联系人知道你已收到并阅读了他们的消息 + 当你已收到并阅读了你的联系人的消息后,让他们知道 防止截屏 - 在应用切换中隐藏应用程序内容并阻止截图 + 在应用程序切换器中隐藏应用程序内容并屏蔽屏幕截图 用户界面 OpenKeychain 出现了一个错误。 加密密钥错误。 @@ -151,7 +151,7 @@ 选择图片 拍摄图片 预先授予订阅请求 - 你所选的文件不是图片 + 你所选的文件不是一张图片 无法转换图片文件 文件未找到 常规 I/O 错误。也许你的存储空间已用完? @@ -175,7 +175,7 @@ TLS 协商失败 域名无法验证 违反政策 - 服务器不兼容 + 不兼容的服务器 不兼容的客户端 流错误 流打开错误 @@ -188,19 +188,19 @@ 发布头像 发布 OpenPGP 公钥 移除 OpenPGP 公钥 - 你确定要从在线状态公布中移除 OpenPGP 公钥吗? + 你确定要从你的在线状态公布中移除你的 OpenPGP 公钥吗? \n你的联系人将无法再向你发送 OpenPGP 加密消息。 OpenPGP 公钥已发布。 启用账号 - 你确定删除账号吗?删除账号会删除你的全部对话历史记录 - 录制音频 + 你确定要删除你的账号吗?删除你的账号会擦除你的全部对话历史记录 + 录制语音 XMPP 地址 屏蔽 XMPP 地址 username@example.com 密码 这不是有效的 XMPP 地址 空间不足。图片过大 - 是否添加%s到你的通讯录? + 你想要添加 %s 到你的通讯录中吗? 服务器信息 XEP-0313:消息存档管理 XEP-0280:消息抄送 @@ -210,7 +210,7 @@ XEP-0198:流管理 XEP-0215:发现外部服务 XEP-0163:个人事件协议(头像/OMEMO) - XEP-0363:HTTP文件上传 + XEP-0363:HTTP 文件上传 XEP-0357:推送 可用 不可用 @@ -231,7 +231,7 @@ v\\OMEMO 指纹(消息来源) 其他设备 信任的 OMEMO 指纹 - 获取密钥中… + 正在获取密钥… 完成 解密 搜索 @@ -252,10 +252,10 @@ 解散频道 你确定要解散此群组聊天吗? \n -\n警告:此群组聊天将在服务器上完全删除。 +\n警告: 此群组聊天将在服务器上完全删除。 你确定要解散此公开频道吗? \n -\n警告:此频道将在服务器上完全删除。 +\n警告: 此频道将在服务器上完全删除。 无法解散群组聊天 无法解散频道 编辑群组聊天话题 @@ -266,25 +266,25 @@ 反向添加 %s 已阅读至此 %s 已阅读至此 - %1$s和其他%2$d人都已阅读至此 - 所有人都已阅读至此 + %1$s 和其他 %2$d 人已阅读至此 + 每个人都已阅读至此 发布 点击头像从图库中选择图片 正在发布… - 服务器拒绝了你的发布请求 + 服务器拒绝发布你的头像 无法转换你的图片 - 不能将头像保存至磁盘 + 无法将头像保存至磁盘 (或长按恢复默认) 你的服务器不支持发布头像 私聊 - 至%s - 发送私人消息至%s + 至 %s + 发送私人消息至 %s 连接 此账号已存在 下一步 会话已建立 跳过 - 关闭通知 + 禁用通知 启用 群组聊天需要密码 输入密码 @@ -293,23 +293,23 @@ \n这将被用来判断你的联系人正在使用的聊天应用 立即请求 忽略 - 警告:在没有相互更新在线状态的情况下发送将会出现未知问题。 + 警告: 在没有相互更新在线状态的情况下发送此消息将会出现未知问题。 \n -\n前往联系人详情以验证你订阅的在线状态。 +\n前往“联系人详情”以验证你的在线状态订阅。 安全 允许消息更正 允许你的联系人发送后编辑其消息 - 高级设置 + 专家设置 请谨慎使用这些 - 关于%s - 静默时段 + 关于 %s + 安静时间 开始时间 结束时间 - 启用静默时段 - 静默时段通知将被静音 + 启用安静时间 + 在安静时间内,通知将被静音 其他 同步书签 - 加入或离开多用户聊天时设置 “autojoin\" 标志,并回应其他客户端所做更改。 + 在进入或离开多用户聊天时设置 “autojoin\" 标志,并回应其他客户端所做的修改。 OMEMO 指纹已复制到剪贴板 你已被此群组聊天封禁 此群组聊天仅限成员参与 @@ -318,12 +318,12 @@ 此群组聊天已被关闭 你已不在此群组聊天 由于技术原因你离开了此群组聊天 - 使用账号%s - 托管于%s - 正在 HTTP 主机上检查%s + 正在使用账号 %s + 托管于 %s + 正在 HTTP 主机上检查 %s 你未连接。稍后再试 - 检查%s的大小 - 在%2$s上检查%1$s的大小 + 检查 %s 的大小 + 在 %2$s 上检查 %1$s 的大小 消息选项 引用 粘贴为引用 @@ -339,26 +339,26 @@ 显示屏蔽列表 账号详情 确认 - 重试 + 再试一次 前台服务 - 防止操作系统中断连接 + 防止操作系统中断你的连接 创建备份 - 备份文件将存储在%s + 备份文件将存储在 %s 创建备份文件中 - 备份已创建 - 此备份文件已存储在%s - 正在恢复备份 - 备份已恢复 - 别忘了启用账号。 + 你的备份已创建 + 此备份文件已存储在 %s + 恢复备份中 + 你的备份已恢复 + 不要忘记启用此账号。 选择文件 - 接收%1$s(已完成%2$d%%) - 下载%s - 删除%s + 正在接收 %1$s(%2$d%% 已完成) + 下载 %s + 删除 %s 文件 - 打开%s - 正在发送(已完成%1$d%%) - 准备分享文件 - 可以下载%s + 打开 %s + 正在发送(%1$d%% 已完成) + 正在准备分享文件 + %s 可供下载 取消传输 无法分享文件 文件传输已取消 @@ -375,9 +375,9 @@ 复制 OMEMO 指纹到剪贴板 重新生成 OMEMO 密钥 清除设备 - 你确定要从 OMEMO 公布中清除所有其他设备吗?下次设备连接时,它们会重新公布自己,但可能不会收到在此期间发送的消息。 + 你确定要从 OMEMO 公布中清除所有其他设备吗?下次你的设备连接时,它们将会重新公布自己,但可能不会收到在此期间发送的消息。 此联系人没有可用的密钥。 -\n无法从服务器获取新密钥。也许是你联系人的服务器出了问题? +\n无法从服务器获取新密钥。也许是你的联系人的服务器出了问题?
此联系人没有可用的密钥。 \n确保你们双方都有在线状态订阅。 出错了 @@ -385,7 +385,7 @@ 服务器上没有更多历史记录 正在更新… 密码已修改! - 不能修改密码 + 无法修改密码 修改密码 当前密码 新密码 @@ -406,20 +406,20 @@ 撤销所有者权限 从群组聊天中移除 从频道中移除 - 不能修改%s的从属关系 + 无法修改 %s 的从属关系 从群组聊天中封禁 从频道中封禁 - 你正试图从公开频道中移除%s。唯一的办法就是永远封禁此用户。 + 你正试图从公开频道中移除 %s。唯一的办法就是永远封禁此用户。 立即封禁 - 不能修改%s的角色 + 无法修改 %s 的角色 私人群组聊天配置 公开频道配置 私人,仅限成员 使 XMPP 地址对任何人可见 - 使频道受到管理 + 对频道进行管理 你未参与 已修改群组聊天选项! - 无法更改群组聊天选项 + 无法修改群组聊天选项 从不 直至另行通知 稍后提醒 @@ -429,25 +429,25 @@ Enter 即发送 使用 Enter 键发送消息。即使禁用此选项,你始终可以使用 Ctrl+Enter 发送消息。 显示 Enter 键 - 将表情键更改为 Enter 键 + 将表情符号键更改为 Enter 键 音频 视频 图片 - 矢量图 + 矢量图形 多媒体文件 PDF 文档 - Android App + Android 应用程序 联系人 头像已经发布! - 正在发送%s - 正在提供%s + 正在发送 %s + 正在提供 %s 隐藏离线联系人 - %s正在输入… - %s已停止输入 - %s正在输入… - %s已停止输入 + %s 正在输入… + %s 已停止输入 + %s 正在输入… + %s 已停止输入 输入通知 - 让联系人知道你在给他们写消息 + 当你正在给你的联系人写消息时,让他们知道 发送位置 显示位置 未找到可以显示位置的应用 @@ -455,13 +455,13 @@ 对话已关闭 离开私人群组聊天 离开公开频道 - 不信任系统证书 + 不信任系统证书颁发机构 所有证书必须手动批准 移除证书 删除手动批准的证书 没有手动批准的证书 移除证书 - 删除已选 + 删除选中内容 取消 %d 个证书已被删除 @@ -473,14 +473,14 @@ 选择快捷操作 搜索联系人 发送私人消息 - %1$s离开了群组聊天 + %1$s 已离开群组聊天 用户名 用户名 此用户名无效 下载失败:服务器未找到 下载失败:文件未找到 下载失败:无法连接到主机 - 下载失败:不能写入文件 + 下载失败:无法写入文件 下载失败:无效文件 Tor 网络不可用 绑定失败 @@ -496,19 +496,19 @@ 扩展连接设置 设置账号时显示主机名和端口设置 xmpp.example.com - 用证书登录 + 使用证书登录 无法解析证书 存档首选项 服务器端存档首选项 - 获取存档首选项。请稍候… + 获取存档首选项中。请稍候… 无法获取存档首选项 需要验证码 输入上图中的文字 不受信任的证书链 XMPP 地址与证书不匹配 - 更新证书 + 续订证书 获取 OMEMO 密钥时出错! - 通过证书验证 OMEMO 密钥! + 已通过证书验证 OMEMO 密钥! 你的设备不支持选择客户端证书! 连接 通过 Tor 连接 @@ -523,58 +523,59 @@ %d 条消息 加载更多消息 - 文件已分享至%s - 图片已分享至%s - 图片已分享至%s - 文本已分享至%s + 文件已分享至 %s + 图片已分享至 %s + 图片已分享至 %s + 文本已分享至 %s 授予 %1$s 访问外部存储的权限 授予 %1$s 访问相机的权限 - 同步联系人 - %1$s想要访问通讯录的权限来将它与你的 XMPP 联系人列表相匹配。 -\n这会显示你的联系人的全名和头像。 + 与联系人同步 + %1$s 想要访问你的通讯录的权限来将它与你的 XMPP 联系人列表相匹配。 +\n这将会显示你的联系人的全名和头像。 \n -\n%1$s只会读取你的通讯录并在本地进行匹配,不会上传任何东西到你的服务器。 +\n%1$s 将只会读取你的通讯录并在本地进行匹配,不会上传任何东西到你的服务器。 通知所有消息 仅在提及时通知 通知已禁用 通知已暂停 图片压缩 提示:无论此设置如何,使用“选择文件”而不是“选择图片”会发送未压缩的单张图片。 - 总是 + 始终 仅限大图片 - 已启用节电模式 - 你的设备正对 %1$s 实施强力电池优化,这可能导致通知延迟甚至消息丢失。\n建议禁用这些优化。 - 你的设备正对 %1$s 实施强力电池优化,这可能导致通知延迟甚至消息丢失。 + 电池优化已启用 + 你的设备正对 %1$s 实施强力电池优化,这可能会导致通知延迟甚至消息丢失。 +\n建议禁用它们。 + 你的设备正对 %1$s 实施强力电池优化,这可能会导致通知延迟甚至消息丢失。 \n -\n你将被请求禁用这些优化。 +\n你现在将被要求禁用它们。 禁用 所选区域太大 (没有启用的账号) - 必填 + 此字段是必需的 更正消息 发送更正后的消息 - 你已经安全地验证了此人指纹以确认信任。通过选择“完成”,确认%s加入群组聊天。 + 你已经安全地验证了此人的指纹以确认信任。通过选择“完成”,你只是在确认 %s 是此群组聊天的一部分。 你已经禁用了此账号 安全错误:文件访问无效! 未找到可以分享 URI 的应用 分享 URI 至… 同意并继续 - 在 conversations.im 上有创建账号的指南。 + 在 conversations.im 上创建账号的指南已设置。 \n选择 conversations.im 作为提供者时,你只需提供完整的 XMPP 地址,就能与其他提供者的用户进行交流。 你的完整 XMPP 地址将是:%s 创建账号 使用我自己的提供者 - 输入你的用户名 + 选择你的用户名 手动管理可用性 - 在编辑状态消息时设置你的可用时间。 + 当编辑你的状态消息时设置你的可用时间。 状态消息 随时可聊 在线 离开 不在 忙碌 - 安全密码已生成 - 你的设备不支持禁用电池优化 + 已生成一个安全密码 + 你的设备不支持选择退出电池优化 注册失败:稍后再试 注册失败:密码太弱 选择参与者 @@ -585,13 +586,13 @@ 广播使用 - 让联系人知道你在使用 Conversations + 当你使用 Conversations 时,让你的联系人知道 隐私 主题 - 选择主题色彩 + 选择主题颜色 自动 - 明亮 - 灰暗 + 浅色 + 深色 绿色背景 对收到的消息使用绿色背景 无法连接到 OpenKeychain @@ -606,43 +607,43 @@ 联系人请求在线状态订阅 允许 - 无权访问%s + 没有权限访问 %s 远程服务器未找到 远程服务器超时 无法更新账号 举报此 XMPP 地址发送垃圾消息。 删除 OMEMO 身份 - 重新生成 OMEMO 密钥。所有联系人都需要再次验证。请将此作为最后的办法。 - 删除选择的密钥 - 你需要连接才能发布头像。 + 重新生成你的 OMEMO 密钥。你的所有联系人将不得不再次验证你的身份。只有在万不得已的情况下才会使用这种方法。 + 删除选定的密钥 + 你需要连接网络才能发布你的头像。 显示出错消息 出错消息 省流量模式已启用 你的操作系统正限制 %1$s 在后台时访问互联网。要接收新消息通知,你应当在“省流量模式”处于启用状态时允许 %1$s 不受限制的访问。 -\n%1$s 在可能的时候仍会试图节省数据。 +\n%1$s 仍将在可能的情况下努力节省数据。 你的设备不支持对 %1$s 禁用省流量模式。 无法创建临时文件 此设备已验证 复制指纹 你已验证了你拥有的所有 OMEMO 密钥 - 条形码不包含此次对话的指纹。 + 条码中不包含此对话的指纹。 已验证的指纹 - 使用相机扫描联系人的条形码 + 使用相机扫描联系人的条码 请稍候获取密钥 - 分享条形码 - 分享 XMPP URI - 分享 HTTP 链接 + 分享为条码 + 分享为 XMPP URI + 分享为 HTTP 链接 验证前盲目信任 - 自动信任陌生人的设备,但对于已验证的联系人,提示手动确认新设备。 + 信任来自未经验证的联系人的新设备,但对于已验证的联系人,提示手动确认新设备。 盲目信任的 OMEMO 密钥,表示它们可能是其他人或者某人可能冒充别人发送消息。 不信任的 - 无效二维码 + 二维码无效 清理缓存文件夹(由相机应用使用) 清除缓存 清除私人存储空间 - 清除保存文件的私人存储(可从服务器重新下载) + 清理保存文件的私人存储(它们可以从服务器重新下载) 此链接的源头是可信的 - 点击链接后将会开始验证%1$s的 OMEMO 密钥。只有当你从仅%2$s才能发布此链接的可信来源点击此链接时,这才是安全的。 + 点击链接后将会开始验证 %1$s 的 OMEMO 密钥。只有当你从仅 %2$s 才能发布此链接的可信来源点击此链接时,这才是安全的。 你将验证你自己账号的 OMEMO 密钥。只有当你从仅你才能发布此链接的可信来源点击此链接时,这才是安全的。 继续 验证 OMEMO 密钥 @@ -650,7 +651,7 @@ 隐藏不活跃设备 不再信任设备 你确认要移除此设备的验证吗? -\n此设备及从其发送的消息将会被标识为不可信。 +\n此设备和来自它的消息将会被标记为“不信任的”。
%d 秒 @@ -672,13 +673,13 @@ 自动删除消息 自动从此设备上删除超过配置时限的消息。 消息加密中 - 由于本地保留期限设置,无法提取消息。 + 由于本地保留期限设置,无法获取消息。 正在压缩视频 相应的对话已关闭。 联系人已屏蔽。 陌生人的通知 收到陌生人的消息和来电时进行通知。 - 收到陌生人发来的消息 + 收到了陌生人发来的消息 屏蔽陌生人 屏蔽整个域名 当前在线 @@ -704,13 +705,13 @@ 受保护的应用 为了在屏幕关闭时也能收到消息提醒,你需要将 Conversations 加入受保护的应用列表。 接受未知的证书? - 服务器证书未由已知证书机构签发。 + 此服务器证书不是由已知的证书颁发机构签发的。 接受不匹配的服务器名称? 由于“%s”,服务器无法验证。证书仅对此有效: 你仍要连接吗? 证书详情: 仅一次 - 二维码扫描器需要访问摄像头 + 二维码扫描器需要访问相机 滚动至底部 发送消息后向下滚屏 编辑状态消息 @@ -726,8 +727,8 @@ 草稿: OMEMO 加密 OMEMO 将始终用于一对一和私人群组聊天。 - OMEMO 将默认用于新对话。 - OMEMO 将必须为新对话明确打开。 + 默认情况下,新对话将使用 OMEMO。 + 对于新对话,必须明确地打开 OMEMO。 创建快捷方式 字体大小 应用内使用的相对字体大小。 @@ -750,11 +751,11 @@ 分享 无法开始录制 请稍候… - 授权 %1$s 访问麦克风 + 授予 %1$s 访问麦克风的权限 搜索消息 GIF 查看对话 - 位置分享插件 + 分享位置插件 使用分享位置插件代替内置地图 复制网址 复制 XMPP 地址 @@ -775,7 +776,7 @@ 此通知类别用于显示 %1$s 正在运行的永久通知。 状态信息 连接问题 - 此通知类别用于显示账号连接问题通知。 + 此通知类别用于在连接到账号时出现问题时显示通知。 消息 通话 消息 @@ -783,11 +784,11 @@ 正在进行的通话 未接来电 静音消息 - 此通知组用于显示不应触发任何声音的通知。 例如,在另一台设备上处于活跃状态时(静默期)。 + 此通知组用于显示不应触发任何声音的通知。 例如,在另一台设备上处于活跃状态时(宽限期)。 传递失败 消息通知设置 来电通知设置 - 重要程度、声音、振动 + 重要性、声音、振动 视频压缩 查看媒体文件 参与者 @@ -804,17 +805,17 @@ 选择国家/地区 手机号 验证你的手机号 - Quicksy 将发送短信(运营商可能收费)验证你的电话号码。请输入你的国家/地区代码和手机号: + Quicksy 将发送短信(运营商可能收费)来验证你的电话号码。请输入你的国家/地区代码和电话号码: 我们将验证这个电话号码

%s

,这样可以吗?或者你想编辑这个号码?
%s 不是有效的电话号码。 - 请输入你的手机号。 - 搜索国家 - 验证%s + 请输入你的电话号码。 + 搜索国家/地区 + 验证 %s 我们已向你发送短信 %s 我们已经向你发送了另一条带有 6 位数验证码的短信。 请在下方输入 6 位数的 PIN 码。 重新发送短信 - 重发短信 (%s) + 重新发送短信 (%s) 请稍候 (%s) 返回 已自动从剪贴板粘贴可能的 PIN 码。 @@ -828,9 +829,9 @@ 我们发送给你的 PIN 码已过期。 未知网络错误。 未知服务器响应。 - 无法连接服务器。 + 无法连接到服务器。 无法建立安全连接。 - 找不到服务器。 + 无法找到服务器。 处理你的请求时出了问题。 用户输入无效 暂时无法连接。请稍候再试。 @@ -857,7 +858,7 @@ 选择账号 恢复备份 恢复 - 输入你的%s账号的密码以恢复备份。 + 输入你的 %s 账号的密码以恢复备份。 请勿使用恢复备份功能尝试克隆(同时运行)安装。恢复备份仅适用于迁移或你丢失原始设备的情况。 无法恢复备份。 无法解密备份。密码是否正确? @@ -872,9 +873,9 @@ 请提供频道名 请提供 XMPP 地址 这是一个 XMPP 地址。请提供一个名称。 - 创建公开频道… - 频道已存在 - 你加入了一个已经存在的频道 + 正在创建公开频道… + 此频道已存在 + 你已加入现有频道 无法保存频道配置 允许任何人编辑话题 允许任何人邀请别人 @@ -885,15 +886,15 @@ 任何人可以邀请别人。 XMPP 地址对管理员可见。 XMPP 地址对任何人可见。 - 此公开频道无参与者。邀请你的联系人或使用分享按钮分享其 XMPP 地址。 + 此公开频道无参与者。邀请你的联系人或使用分享按钮分发其 XMPP 地址。 此私人群组聊天无参与者。 管理权限 搜索参与者 - 文件过大 + 文件太大 附加 发现频道 搜索频道 - 可能侵犯隐私! + 可能会侵犯隐私! 我已有账号 添加已有账号 注册新账号 @@ -905,7 +906,7 @@ 事件 打开备份 选择的文件不是 Conversations 备份文件 - 账号已设置 + 此账号已设置 请输入此账号的密码 无法执行此操作 加入公开频道… @@ -913,7 +914,7 @@ 群组聊天 & 频道 jabber.network 本地服务器 - 大多数用户应该选择“jabber.network”以从整个 XMPP 生态系统中获得更好的建议。 + 大多数用户应该选择“jabber.network”以便从整个公共 XMPP 生态系统中获得更好的建议。 频道发现方法 备份 关于 @@ -925,7 +926,7 @@ 添加额外轨道? 正在连接 已连接 - 重新连接 + 正在重新连接 接受通话 结束通话 应答 @@ -941,8 +942,8 @@ 挂断 正在进行的通话 正在进行的视频通话 - 重连通话 - 重连视频通话 + 正在重新连接通话 + 正在重新连接视频通话 禁用 Tor 以进行通话 来电 未接来电 · %s @@ -961,7 +962,7 @@ 视频通话 帮助 切换到对话 - 麦克风不可用 + 你的麦克风不可用 你每次只能拨打一个电话。 返回正在进行的通话 无法切换摄像头 @@ -972,15 +973,15 @@ 所有对话 此对话 你的头像 - %s的头像 + %s 的头像 用 OMEMO 加密 用 OpenPGP 加密 未加密 退出 - 录制语音邮件 + 录制语音留言 播放音频 - 暂停音频播放 - 添加联系人、创建或加入群组聊天,或发现频道 + 暂停音频 + 添加联系人,创建或加入群组聊天,或发现频道 查看 %1$d 位参与者 @@ -990,14 +991,14 @@ 传递失败 更多选项 未找到应用程序 - 邀请到 Conversations + 邀请至 Conversations 无法解析邀请 服务器不支持生成邀请 没有活跃账号支持此功能 - 已启动备份。一旦完成,你会收到通知。 + 备份已开始。完成后你会收到通知。 无法启用视频。 纯文本文档 - 不支持注册账号 + 不支持账号注册 未找到 XMPP 地址 验证暂时失败 删除头像 @@ -1008,13 +1009,13 @@ 推送服务器 无(已停用) UnifiedPush 分发程序 - 将通过此账号接收推送消息。 - 用户选择的推送服务器,通过 XMPP 将消息推送到你的设备。 + 接收推送消息的账号。 + 用户选择的推送服务器,通过 XMPP 将推送消息转送至你的设备。 拒绝 来电 (%s) · %s 去电 (%s) · %s 去电 · %s - 频道发现功能使用第三方服务 <a href=https://search.jabber.network>search.jabber.network</a>。<br><br>使用此功能会发送你的 IP 地址和搜索词条到此服务。更多信息见 <a href=https://search.jabber.network/privacy>隐私政策</a>。 + 频道发现功能使用第三方服务 <a href=https://search.jabber.network>search.jabber.network</a>。<br><br>使用此功能会将你的 IP 地址和搜索词条传输到此服务。更多信息,请参阅他们的 <a href=https://search.jabber.network/privacy>隐私政策</a>。 无法从服务器删除账号 群组聊天 保存为群组聊天 @@ -1022,6 +1023,6 @@ 从服务器删除账号 不要尝试恢复你尚未自行创建的备份! 你正试图导入过时的备份文件格式 - 有声书 + 有声读物 重新连接其他主机 \ No newline at end of file From 57ad9d21cb85baac7ebc2408d31add55719ec7d2 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Sun, 15 Oct 2023 23:43:06 +0000 Subject: [PATCH 199/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (9 of 9 strings) Translation: Conversations/Android App (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-quicksy/zh_Hans/ --- src/quicksy/res/values-zh-rCN/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quicksy/res/values-zh-rCN/strings.xml b/src/quicksy/res/values-zh-rCN/strings.xml index 751df629a..4b8cb43ae 100644 --- a/src/quicksy/res/values-zh-rCN/strings.xml +++ b/src/quicksy/res/values-zh-rCN/strings.xml @@ -2,7 +2,7 @@ Quicksy 发现其他设备上的活动后保持安静的时间长度 通过发送堆栈跟踪,你可以帮助 Quicksy 的持续开发 - 让所有联系人知道你在使用 Quicksy + 当你使用 Quicksy 时,让你的所有联系人知道 为了在屏幕关闭时也能收到消息提醒,你需要将 Quicksy 加入受保护的应用列表。 Quicksy 个人资料图片 Quicksy 在你所在的国家/地区无法使用。 From 8f75e2f1e4d02fac784955f813a0c044941d5d8e Mon Sep 17 00:00:00 2001 From: licaon-kter Date: Tue, 17 Oct 2023 08:32:39 +0000 Subject: [PATCH 200/402] Translated using Weblate (Romanian) Currently translated at 100.0% (970 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/ro/ --- src/main/res/values-ro-rRO/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-ro-rRO/strings.xml b/src/main/res/values-ro-rRO/strings.xml index 5b8de225e..72f71c7e7 100644 --- a/src/main/res/values-ro-rRO/strings.xml +++ b/src/main/res/values-ro-rRO/strings.xml @@ -1034,4 +1034,5 @@ Nu încercați să restaurați copii de rezervă pe care nu le-ați creat personal! Încercați să importați un fișier copie de rezervă format vechi Carte audio + Reconectat pe altă gazdă \ No newline at end of file From b7e68a20b9315ebc62aab354fc030186b0c9a731 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Tue, 17 Oct 2023 12:54:41 +0000 Subject: [PATCH 201/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (970 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 250 ++++++++++++------------- 1 file changed, 125 insertions(+), 125 deletions(-) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index ec1aa9176..c0561084f 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -42,14 +42,14 @@ 主持人 参与者 访客 - 你想从联系人列表中移除 %s 吗?与此联系人的对话将不会被清除。 - 你想屏蔽 %s 向你发送消息吗? - 你想解除屏蔽 %s 并允许他们向你发送消息吗? + 您想从联系人列表中移除 %s 吗?与此联系人的对话将不会被清除。 + 您想屏蔽 %s 向您发送消息吗? + 您想解除屏蔽 %s 并允许他们向您发送消息吗? 屏蔽来自 %s 的所有联系人吗? 解除屏蔽来自 %s 的所有联系人吗? 联系人已屏蔽 已屏蔽 - 你想从书签中移除 %s 吗?与此书签的对话将不会被清除。 + 您想从书签中移除 %s 吗?与此书签的对话将不会被清除。 在服务器上注册新账号 在服务器上修改密码 分享至… @@ -68,14 +68,14 @@ 保存 完成 %1$s 已崩溃 - 使用你的 XMPP 账号发送堆栈跟踪有助于 %1$s 的持续开发。 + 使用您的 XMPP 账号发送堆栈跟踪有助于 %1$s 的持续开发。 立即发送 不再询问 无法连接账号 无法连接到多个账号 - 点击管理你的账号 + 点击管理您的账号 附上文件 - 此联系人不在你的联系人列表中,需要添加吗? + 此联系人不在您的联系人列表中,需要添加吗? 添加联系人 传递失败 正在准备发送图片 @@ -83,13 +83,13 @@ 分享文件中。请稍候… 清除历史记录 清除对话历史记录 - 你想删除此对话中的所有消息吗? + 您想删除此对话中的所有消息吗? \n -\n警告:这不会删除存储在其他设备或服务器上的那些消息的副本。 +\n警告: 这将不会影响存储在其他设备或服务器上的消息。 删除文件 - 你确定要删除此文件吗? + 您确定要删除此文件吗? \n -\n警告:这不会删除存储在其他设备或服务器上的此文件的副本。 +\n警告: 这将不会删除存储在其他设备或服务器上的此文件的副本。 之后关闭此对话 选择设备 发送未加密的消息 @@ -100,22 +100,22 @@ 发送 OpenPGP 加密消息 新昵称使用中 发送未加密的 - 解密失败。也许你没有正确的私钥。 + 解密失败。也许您没有正确的私钥。 OpenKeychain - %1$s 使用 <b>OpenKeychain</b>来加密和解密消息并管理你的公钥。<br><br>它在 GPLv3+ 许可证下授权并可在 F-Droid 和 Google Play 上获得。<br><br><small>(请稍后重新启动 %1$s。)</small> + %1$s 使用 <b>OpenKeychain</b>来加密和解密消息并管理您的公钥。<br><br>它在 GPLv3+ 许可证下授权并可在 F-Droid 和 Google Play 上获得。<br><br><small>(请稍后重新启动 %1$s。)</small> 重启 安装 请安装 OpenKeychain 正在提供… 正在等待… 未找到 OpenPGP 密钥 - 由于你的联系人未公布其公钥,无法加密你的消息。 + 由于您的联系人未公布其公钥,无法加密您的消息。 \n -\n请通知你的联系人设置 OpenPGP。 +\n请通知您的联系人设置 OpenPGP。 未找到 OpenPGP 密钥 - 由于你的联系人未公布其公钥,无法加密你的消息。 + 由于您的联系人未公布其公钥,无法加密您的消息。 \n -\n请通知你的联系人设置 OpenPGP。 +\n请通知您的联系人设置 OpenPGP。 常规 接收文件 自动接收小于此大小的文件… @@ -130,12 +130,12 @@ 新消息的通知铃声 来电铃声 宽限期 - 在你的某个其他设备上检测到活动之后,通知被静音的时间长度。 + 在您的某个其他设备上检测到活动之后,通知被静音的时间长度。 高级 从不发送崩溃报告 - 通过发送堆栈跟踪,你正在帮助开发 + 通过发送堆栈跟踪,您正在帮助开发 确认消息 - 当你已收到并阅读了你的联系人的消息后,让他们知道 + 当您已收到并阅读了您的联系人的消息后,让他们知道 防止截屏 在应用程序切换器中隐藏应用程序内容并屏蔽屏幕截图 用户界面 @@ -144,21 +144,21 @@ 接受 出现了一个错误 错误 - 你的账号 + 您的账号 发送在线状态更新 接收在线状态更新 请求在线状态更新 选择图片 拍摄图片 预先授予订阅请求 - 你所选的文件不是一张图片 + 您所选的文件不是一张图片 无法转换图片文件 文件未找到 - 常规 I/O 错误。也许你的存储空间已用完? - 你用来选择图片的应用没有提供读取文件的足够权限。 + 常规 I/O 错误。也许您的存储空间已用完? + 您用来选择图片的应用没有提供读取文件的足够权限。 \n \n使用不同的文件管理器来选择图片. - 你用来分享此文件的应用程序没有提供足够的权限。 + 您用来分享此文件的应用程序没有提供足够的权限。 未知 暂时禁用 在线 @@ -188,11 +188,11 @@ 发布头像 发布 OpenPGP 公钥 移除 OpenPGP 公钥 - 你确定要从你的在线状态公布中移除你的 OpenPGP 公钥吗? -\n你的联系人将无法再向你发送 OpenPGP 加密消息。 + 您确定要从您的在线状态公布中移除您的 OpenPGP 公钥吗? +\n您的联系人将无法再向您发送 OpenPGP 加密消息。 OpenPGP 公钥已发布。 启用账号 - 你确定要删除你的账号吗?删除你的账号会擦除你的全部对话历史记录 + 您确定要删除您的账号吗?删除您的账号会擦除您的全部对话历史记录 录制语音 XMPP 地址 屏蔽 XMPP 地址 @@ -200,7 +200,7 @@ 密码 这不是有效的 XMPP 地址 空间不足。图片过大 - 你想要添加 %s 到你的通讯录中吗? + 您想要添加 %s 到您的通讯录中吗? 服务器信息 XEP-0313:消息存档管理 XEP-0280:消息抄送 @@ -209,7 +209,7 @@ XEP-0237:名册版本控制 XEP-0198:流管理 XEP-0215:发现外部服务 - XEP-0163:个人事件协议(头像/OMEMO) + XEP-0163:个人事件协议(头像 / OMEMO) XEP-0363:HTTP 文件上传 XEP-0357:推送 可用 @@ -250,10 +250,10 @@ 删除书签 解散群组聊天 解散频道 - 你确定要解散此群组聊天吗? + 您确定要解散此群组聊天吗? \n \n警告: 此群组聊天将在服务器上完全删除。 - 你确定要解散此公开频道吗? + 您确定要解散此公开频道吗? \n \n警告: 此频道将在服务器上完全删除。 无法解散群组聊天 @@ -262,8 +262,8 @@ 话题 正在加入群组聊天… 离开 - 联系人已添加你到联系人列表 - 反向添加 + 联系人已添加您到联系人列表 + 添加对方 %s 已阅读至此 %s 已阅读至此 %1$s 和其他 %2$d 人已阅读至此 @@ -271,11 +271,11 @@ 发布 点击头像从图库中选择图片 正在发布… - 服务器拒绝发布你的头像 - 无法转换你的图片 + 服务器拒绝发布您的头像 + 无法转换您的图片 无法将头像保存至磁盘 (或长按恢复默认) - 你的服务器不支持发布头像 + 您的服务器不支持发布头像 私聊 至 %s 发送私人消息至 %s @@ -288,17 +288,17 @@ 启用 群组聊天需要密码 输入密码 - 请先向你的联系人请求在线状态更新。 + 请先向您的联系人请求在线状态更新。 \n -\n这将被用来判断你的联系人正在使用的聊天应用 +\n这将被用来判断您的联系人正在使用的聊天应用 立即请求 忽略 警告: 在没有相互更新在线状态的情况下发送此消息将会出现未知问题。 \n -\n前往“联系人详情”以验证你的在线状态订阅。 +\n前往“联系人详情”以验证您的在线状态订阅。 安全 允许消息更正 - 允许你的联系人发送后编辑其消息 + 允许您的联系人发送后编辑其消息 专家设置 请谨慎使用这些 关于 %s @@ -311,17 +311,17 @@ 同步书签 在进入或离开多用户聊天时设置 “autojoin\" 标志,并回应其他客户端所做的修改。 OMEMO 指纹已复制到剪贴板 - 你已被此群组聊天封禁 + 您已被此群组聊天封禁 此群组聊天仅限成员参与 资源限制 - 你已被此群组聊天踢出 + 您已被此群组聊天踢出 此群组聊天已被关闭 - 你已不在此群组聊天 - 由于技术原因你离开了此群组聊天 + 您已不在此群组聊天 + 由于技术原因您离开了此群组聊天 正在使用账号 %s 托管于 %s 正在 HTTP 主机上检查 %s - 你未连接。稍后再试 + 您未连接。稍后再试 检查 %s 的大小 在 %2$s 上检查 %1$s 的大小 消息选项 @@ -341,14 +341,14 @@ 确认 再试一次 前台服务 - 防止操作系统中断你的连接 + 防止操作系统中断您的连接 创建备份 备份文件将存储在 %s 创建备份文件中 - 你的备份已创建 + 您的备份已创建 此备份文件已存储在 %s 恢复备份中 - 你的备份已恢复 + 您的备份已恢复 不要忘记启用此账号。 选择文件 正在接收 %1$s(%2$d%% 已完成) @@ -362,7 +362,7 @@ 取消传输 无法分享文件 文件传输已取消 - 文件已经删除 + 文件已删除 未找到可以打开文件的应用 未找到可以打开链接的应用 未找到可以查看联系人的应用 @@ -375,11 +375,11 @@ 复制 OMEMO 指纹到剪贴板 重新生成 OMEMO 密钥 清除设备 - 你确定要从 OMEMO 公布中清除所有其他设备吗?下次你的设备连接时,它们将会重新公布自己,但可能不会收到在此期间发送的消息。 + 您确定要从 OMEMO 公布中清除所有其他设备吗?下次您的设备连接时,它们将会重新公布自己,但可能不会收到在此期间发送的消息。 此联系人没有可用的密钥。 -\n无法从服务器获取新密钥。也许是你的联系人的服务器出了问题? +\n无法从服务器获取新密钥。也许是您的联系人的服务器出了问题? 此联系人没有可用的密钥。 -\n确保你们双方都有在线状态订阅。 +\n确保双方都有在线状态订阅。 出错了 正在从服务器获取历史记录 服务器上没有更多历史记录 @@ -409,7 +409,7 @@ 无法修改 %s 的从属关系 从群组聊天中封禁 从频道中封禁 - 你正试图从公开频道中移除 %s。唯一的办法就是永远封禁此用户。 + 您正试图从公开频道中移除 %s。唯一的办法就是永远封禁此用户。 立即封禁 无法修改 %s 的角色 私人群组聊天配置 @@ -417,7 +417,7 @@ 私人,仅限成员 使 XMPP 地址对任何人可见 对频道进行管理 - 你未参与 + 您未参与 已修改群组聊天选项! 无法修改群组聊天选项 从不 @@ -427,7 +427,7 @@ 标记为已读 输入 Enter 即发送 - 使用 Enter 键发送消息。即使禁用此选项,你始终可以使用 Ctrl+Enter 发送消息。 + 使用 Enter 键发送消息。即使禁用此选项,您始终可以使用 Ctrl+Enter 发送消息。 显示 Enter 键 将表情符号键更改为 Enter 键 音频 @@ -438,7 +438,7 @@ PDF 文档 Android 应用程序 联系人 - 头像已经发布! + 头像已发布! 正在发送 %s 正在提供 %s 隐藏离线联系人 @@ -447,7 +447,7 @@ %s 正在输入… %s 已停止输入 输入通知 - 当你正在给你的联系人写消息时,让他们知道 + 当您正在给您的联系人写消息时,让他们知道 发送位置 显示位置 未找到可以显示位置的应用 @@ -509,7 +509,7 @@ 续订证书 获取 OMEMO 密钥时出错! 已通过证书验证 OMEMO 密钥! - 你的设备不支持选择客户端证书! + 您的设备不支持选择客户端证书! 连接 通过 Tor 连接 通过 Tor 网络传输所有连接。需要 Orbot @@ -530,10 +530,10 @@ 授予 %1$s 访问外部存储的权限 授予 %1$s 访问相机的权限 与联系人同步 - %1$s 想要访问你的通讯录的权限来将它与你的 XMPP 联系人列表相匹配。 -\n这将会显示你的联系人的全名和头像。 + %1$s 想要访问您的通讯录的权限来将它与您的 XMPP 联系人列表相匹配。 +\n这将会显示您的联系人的全名和头像。 \n -\n%1$s 将只会读取你的通讯录并在本地进行匹配,不会上传任何东西到你的服务器。 +\n%1$s 将只会读取您的通讯录并在本地进行匹配,不会上传任何东西到您的服务器。 通知所有消息 仅在提及时通知 通知已禁用 @@ -543,31 +543,31 @@ 始终 仅限大图片 电池优化已启用 - 你的设备正对 %1$s 实施强力电池优化,这可能会导致通知延迟甚至消息丢失。 + 您的设备正对 %1$s 实施强力电池优化,这可能会导致通知延迟甚至消息丢失。 \n建议禁用它们。 - 你的设备正对 %1$s 实施强力电池优化,这可能会导致通知延迟甚至消息丢失。 + 您的设备正对 %1$s 实施强力电池优化,这可能会导致通知延迟甚至消息丢失。 \n -\n你现在将被要求禁用它们。 +\n您现在将被要求禁用它们。 禁用 所选区域太大 (没有启用的账号) 此字段是必需的 更正消息 发送更正后的消息 - 你已经安全地验证了此人的指纹以确认信任。通过选择“完成”,你只是在确认 %s 是此群组聊天的一部分。 - 你已经禁用了此账号 + 您已经安全地验证了此人的指纹以确认信任。通过选择“完成”,您只是在确认 %s 是此群组聊天的一部分。 + 您已禁用了此账号 安全错误:文件访问无效! 未找到可以分享 URI 的应用 分享 URI 至… 同意并继续 在 conversations.im 上创建账号的指南已设置。 -\n选择 conversations.im 作为提供者时,你只需提供完整的 XMPP 地址,就能与其他提供者的用户进行交流。 - 你的完整 XMPP 地址将是:%s +\n当选择 conversations.im 作为提供者时,您将能够通过向来自其他提供者的用户提供您的完整 XMPP 地址来与他们进行交流。 + 您的完整 XMPP 地址将是:%s 创建账号 使用我自己的提供者 - 选择你的用户名 + 选择您的用户名 手动管理可用性 - 当编辑你的状态消息时设置你的可用时间。 + 当编辑您的状态消息时设置您的可用时间。 状态消息 随时可聊 在线 @@ -575,7 +575,7 @@ 不在 忙碌 已生成一个安全密码 - 你的设备不支持选择退出电池优化 + 您的设备不支持选择退出电池优化 注册失败:稍后再试 注册失败:密码太弱 选择参与者 @@ -586,7 +586,7 @@ 广播使用 - 当你使用 Conversations 时,让你的联系人知道 + 当您使用 Conversations 时,让您的联系人知道 隐私 主题 选择主题颜色 @@ -613,19 +613,19 @@ 无法更新账号 举报此 XMPP 地址发送垃圾消息。 删除 OMEMO 身份 - 重新生成你的 OMEMO 密钥。你的所有联系人将不得不再次验证你的身份。只有在万不得已的情况下才会使用这种方法。 + 重新生成您的 OMEMO 密钥。您的所有联系人将不得不再次验证您的身份。只有在万不得已的情况下才会使用这种方法。 删除选定的密钥 - 你需要连接网络才能发布你的头像。 + 您需要连接网络才能发布您的头像。 显示出错消息 出错消息 省流量模式已启用 - 你的操作系统正限制 %1$s 在后台时访问互联网。要接收新消息通知,你应当在“省流量模式”处于启用状态时允许 %1$s 不受限制的访问。 + 您的操作系统正限制 %1$s 在后台时访问互联网。要接收新消息通知,您应当在“省流量模式”处于启用状态时允许 %1$s 不受限制的访问。 \n%1$s 仍将在可能的情况下努力节省数据。 - 你的设备不支持对 %1$s 禁用省流量模式。 + 您的设备不支持对 %1$s 禁用省流量模式。 无法创建临时文件 此设备已验证 复制指纹 - 你已验证了你拥有的所有 OMEMO 密钥 + 您已验证了您拥有的所有 OMEMO 密钥 条码中不包含此对话的指纹。 已验证的指纹 使用相机扫描联系人的条码 @@ -642,15 +642,15 @@ 清除缓存 清除私人存储空间 清理保存文件的私人存储(它们可以从服务器重新下载) - 此链接的源头是可信的 - 点击链接后将会开始验证 %1$s 的 OMEMO 密钥。只有当你从仅 %2$s 才能发布此链接的可信来源点击此链接时,这才是安全的。 - 你将验证你自己账号的 OMEMO 密钥。只有当你从仅你才能发布此链接的可信来源点击此链接时,这才是安全的。 + 我从一个可信来源收到此链接 + 点击链接后,您即将验证 %1$s 的 OMEMO 密钥。只有当您从一个可信来源(只有 %2$s 可以发布此链接)收到此链接时,这才是安全的。 + 您即将验证您自己账号的 OMEMO 密钥。只有当您从一个可信来源(只有您可以发布此链接)收到此链接时,这才是安全的。 继续 验证 OMEMO 密钥 显示不活跃设备 隐藏不活跃设备 不再信任设备 - 你确认要移除此设备的验证吗? + 您确定要移除此设备的验证吗? \n此设备和来自它的消息将会被标记为“不信任的”。 %d 秒 @@ -703,12 +703,12 @@ 消息 私人消息被禁用 受保护的应用 - 为了在屏幕关闭时也能收到消息提醒,你需要将 Conversations 加入受保护的应用列表。 + 为了在屏幕关闭时也能收到消息提醒,您需要将 Conversations 加入受保护的应用列表。 接受未知的证书? 此服务器证书不是由已知的证书颁发机构签发的。 接受不匹配的服务器名称? 由于“%s”,服务器无法验证。证书仅对此有效: - 你仍要连接吗? + 您仍要连接吗? 证书详情: 仅一次 二维码扫描器需要访问相机 @@ -717,12 +717,12 @@ 编辑状态消息 编辑状态消息 禁用加密 - %1$s 无法发送加密消息到 %2$s。这可能是因为你的联系人使用了过期的服务器或者无法处理 OMEMO 的客户端。 + %1$s 无法发送加密消息到 %2$s。这可能是因为您的联系人使用了过期的服务器或者无法处理 OMEMO 的客户端。 无法获取设备列表 无法获取密钥 - 提示:某些情况下,可以将对方加入你的联系人列表,以解决此问题。 - 你确定要禁用此对话的 OMEMO 加密吗? -\n这将允许服务器管理员阅读你的消息,但这可能是与使用过时客户端的用户进行交流的唯一方法。 + 提示:某些情况下,可以将对方加入您的联系人列表,以解决此问题。 + 您确定要禁用此对话的 OMEMO 加密吗? +\n这将允许服务器管理员阅读您的消息,但这可能是与使用过时客户端的用户进行交流的唯一方法。 立即禁用 草稿: OMEMO 加密 @@ -799,58 +799,58 @@ 中(360p) 高(720p) 已取消 - 你已经在起草一条消息了。 + 您已经在起草一条消息了。 功能未实现 无效的国家/地区代码 选择国家/地区 - 手机号 - 验证你的手机号 - Quicksy 将发送短信(运营商可能收费)来验证你的电话号码。请输入你的国家/地区代码和电话号码: - 我们将验证这个电话号码

%s

,这样可以吗?或者你想编辑这个号码?
+ 电话号码 + 验证您的电话号码 + Quicksy 将发送短信(运营商可能收费)来验证您的电话号码。请输入您的国家/地区代码和电话号码: + 我们将验证这个电话号码

%s

,这样可以吗?或者您想编辑这个号码?
%s 不是有效的电话号码。 - 请输入你的电话号码。 + 请输入您的电话号码。 搜索国家/地区 验证 %s - 我们已向你发送短信 %s - 我们已经向你发送了另一条带有 6 位数验证码的短信。 + 我们已向您发送短信 %s + 我们已经向您发送了另一条带有 6 位数验证码的短信。 请在下方输入 6 位数的 PIN 码。 重新发送短信 重新发送短信 (%s) 请稍候 (%s) 返回 已自动从剪贴板粘贴可能的 PIN 码。 - 请输入你的 6 位数 PIN 码。 - 你确定要取消注册程序吗? + 请输入您的 6 位数 PIN 码。 + 您确定要取消注册程序吗? 正在验证… 正在请求短信… - 你输入的 PIN 码有误。 - 我们发送给你的 PIN 码已过期。 + 您输入的 PIN 码有误。 + 我们发送给您的 PIN 码已过期。 未知网络错误。 未知服务器响应。 无法连接到服务器。 无法建立安全连接。 无法找到服务器。 - 处理你的请求时出了问题。 + 处理您的请求时出了问题。 用户输入无效 暂时无法连接。请稍候再试。 无网络连接。 请在 %s 后重试 - 你被限制速率 + 您被限制速率 尝试次数过多 - 你使用的是过时版本的应用程序。 + 您使用的是过时版本的应用程序。 更新 此电话号码目前已在其他设备上登录。 - 请输入你的名称,以便让通讯录中没有你的人知道你是谁。 - 你的名称 - 输入你的名称 - 使用编辑按钮设置你的名称。 + 请输入您的名称,以便让通讯录中没有您的人知道您是谁。 + 您的名称 + 输入您的名称 + 使用编辑按钮设置您的名称。 拒绝请求 安装 Orbot 启动 Orbot 未安装应用商店。 - 此频道将公开你的 XMPP 地址 + 此频道将公开您的 XMPP 地址 电子书 原始(未压缩) 打开为… @@ -858,8 +858,8 @@ 选择账号 恢复备份 恢复 - 输入你的 %s 账号的密码以恢复备份。 - 请勿使用恢复备份功能尝试克隆(同时运行)安装。恢复备份仅适用于迁移或你丢失原始设备的情况。 + 输入您的 %s 账号的密码以恢复备份。 + 请勿使用恢复备份功能尝试克隆(同时运行)安装。恢复备份仅适用于迁移或您丢失原始设备的情况。 无法恢复备份。 无法解密备份。密码是否正确? 备份 & 恢复 @@ -875,7 +875,7 @@ 这是一个 XMPP 地址。请提供一个名称。 正在创建公开频道… 此频道已存在 - 你已加入现有频道 + 您已加入现有频道 无法保存频道配置 允许任何人编辑话题 允许任何人邀请别人 @@ -886,7 +886,7 @@ 任何人可以邀请别人。 XMPP 地址对管理员可见。 XMPP 地址对任何人可见。 - 此公开频道无参与者。邀请你的联系人或使用分享按钮分发其 XMPP 地址。 + 此公开频道无参与者。邀请您的联系人或使用分享按钮分发其 XMPP 地址。 此私人群组聊天无参与者。 管理权限 搜索参与者 @@ -898,9 +898,9 @@ 我已有账号 添加已有账号 注册新账号 - 这好像是一个域名地址 - 仍然添加 - 这好像是一个频道地址 + 这看起来像一个域名地址 + 无论如何都要添加 + 这看起来像一个频道地址 分享备份文件 Conversations 备份 事件 @@ -921,7 +921,7 @@ 请启用一个账号 进行通话 来电 - 视频通话来电 + 视频来电 切换到视频通话? 添加额外轨道? 正在连接 @@ -962,9 +962,9 @@ 视频通话 帮助 切换到对话 - 你的麦克风不可用 - 你每次只能拨打一个电话。 - 返回正在进行的通话 + 您的麦克风不可用 + 您每次只能拨打一个电话。 + 返回到正在进行的通话 无法切换摄像头 置顶 取消置顶 @@ -972,7 +972,7 @@ 无法更正消息 所有对话 此对话 - 你的头像 + 您的头像 %s 的头像 用 OMEMO 加密 用 OpenPGP 加密 @@ -995,7 +995,7 @@ 无法解析邀请 服务器不支持生成邀请 没有活跃账号支持此功能 - 备份已开始。完成后你会收到通知。 + 备份已开始。完成后您会收到通知。 无法启用视频。 纯文本文档 不支持账号注册 @@ -1010,19 +1010,19 @@ 无(已停用) UnifiedPush 分发程序 接收推送消息的账号。 - 用户选择的推送服务器,通过 XMPP 将推送消息转送至你的设备。 + 用户选择的推送服务器,通过 XMPP 将推送消息转送至您的设备。 拒绝 来电 (%s) · %s 去电 (%s) · %s 去电 · %s - 频道发现功能使用第三方服务 <a href=https://search.jabber.network>search.jabber.network</a>。<br><br>使用此功能会将你的 IP 地址和搜索词条传输到此服务。更多信息,请参阅他们的 <a href=https://search.jabber.network/privacy>隐私政策</a>。 + 频道发现使用称为 <a href=https://search.jabber.network>search.jabber.network</a> 的第三方服务。<br><br>使用此功能会将您的 IP 地址和搜索词传输到此服务。请参阅他们的 <a href=https://search.jabber.network/privacy>隐私政策</a> 以获取更多信息。 无法从服务器删除账号 群组聊天 保存为群组聊天 搜索群组聊天 从服务器删除账号 - 不要尝试恢复你尚未自行创建的备份! - 你正试图导入过时的备份文件格式 + 不要尝试恢复您尚未自行创建的备份! + 您正试图导入过时的备份文件格式 有声读物 重新连接其他主机 \ No newline at end of file From 55637836ccd37c0ac8f144d71dce933401a0fecf Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Tue, 17 Oct 2023 14:17:15 +0000 Subject: [PATCH 202/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (13 of 13 strings) Translation: Conversations/Android App (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-conversations/zh_Hans/ --- .../res/values-zh-rCN/strings.xml | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/conversations/res/values-zh-rCN/strings.xml b/src/conversations/res/values-zh-rCN/strings.xml index 373f56f6f..79c582529 100644 --- a/src/conversations/res/values-zh-rCN/strings.xml +++ b/src/conversations/res/values-zh-rCN/strings.xml @@ -1,20 +1,20 @@ - 选择你的 XMPP 提供者 + 选择您的 XMPP 提供者 使用 conversations.im 创建新账号 - 你已经有一个 XMPP 账号了吗?如果你已经在使用不同的 XMPP 客户端或者以前使用过 Conversations,那么你已经拥有这种账号了。如果没有的话,你现在可以创建一个。 -\n提示:有些电子邮件提供者也提供 XMPP 账号。 - XMPP 是独立于提供者的即时消息网络。你可以将此客户端与任意 XMPP 服务器一同使用。 -\n不过,你可以很容易地在 conversations.im 上创建一个账号;它是特别适合与“Conversations”一起使用的提供者。 - 你已受邀加入 %1$s。我们将指导你完成创建账号的过程。 -\n使用 %1$s 作为提供者时,你可以通过你的完整 XMPP 地址与其他提供者的用户进行交流。 - 你已受邀加入 %1$s。已为你选择了一个用户名。我们将指导你完成创建账号的过程。 -\n你可以使用完整的 XMPP 地址来与其他提供者的用户进行交流。 - 你的服务器邀请 + 您已经有一个 XMPP 账号了吗?如果您已经在使用不同的 XMPP 客户端或者以前使用过 Conversations,那么您已经拥有这种账号了。如果没有的话,您现在可以创建一个。 +\n提示:一些电子邮件提供者也提供 XMPP 账号。 + XMPP 是独立于提供者的即时通讯网络。您可以将此客户端与您选择的任何 XMPP 服务器一起使用。 +\n不过,为了您的方便,我们让您可以轻松地在 conversations.im 上创建一个账号;这是一个特别适合与 Conversations 一起使用的提供者。 + 您已受邀加入 %1$s。我们将指导您完成创建账号的过程。 +\n当选择 %1$s 作为提供者时,您将能够通过向来自其他提供者的用户提供您的完整 XMPP 地址来与他们进行交流。 + 您已受邀加入 %1$s。已为您选择了一个用户名。我们将指导您完成创建账号的过程。 +\n您将能够通过向来自其他提供者的用户提供您的完整 XMPP 地址来与他们进行交流。 + 您的服务器邀请 配置代码格式不当 - 点击分享按钮向你的联系人发送加入 %1$s 的邀请。 - 如果你的联系人在附近,他们也可以扫描下面的代码来接受你的邀请。 + 点击分享按钮向您的联系人发送加入 %1$s 的邀请。 + 如果您的联系人在附近,他们也可以扫描下面的代码来接受您的邀请。 加入 %1$s 和我聊天:%2$s 分享邀请至… \ No newline at end of file From c30bc10ce2d2ead1817f280ed1ea646f7b1f2ad4 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Tue, 17 Oct 2023 12:54:41 +0000 Subject: [PATCH 203/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (9 of 9 strings) Translation: Conversations/Android App (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-quicksy/zh_Hans/ --- src/quicksy/res/values-zh-rCN/strings.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/quicksy/res/values-zh-rCN/strings.xml b/src/quicksy/res/values-zh-rCN/strings.xml index 4b8cb43ae..81608a938 100644 --- a/src/quicksy/res/values-zh-rCN/strings.xml +++ b/src/quicksy/res/values-zh-rCN/strings.xml @@ -1,11 +1,11 @@ Quicksy 发现其他设备上的活动后保持安静的时间长度 - 通过发送堆栈跟踪,你可以帮助 Quicksy 的持续开发 - 当你使用 Quicksy 时,让你的所有联系人知道 - 为了在屏幕关闭时也能收到消息提醒,你需要将 Quicksy 加入受保护的应用列表。 + 通过发送堆栈跟踪,您可以帮助 Quicksy 的持续开发 + 当您使用 Quicksy 时,让您的所有联系人知道 + 为了在屏幕关闭时也能收到消息提醒,您需要将 Quicksy 加入受保护的应用列表。 Quicksy 个人资料图片 - Quicksy 在你所在的国家/地区无法使用。 + Quicksy 在您所在的国家/地区无法使用。 无法验证服务器身份。 未知安全错误。 连接服务器超时。 From 4fec00f842375ad5fb0453b20e4dbe677539bc29 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Tue, 17 Oct 2023 12:54:41 +0000 Subject: [PATCH 204/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (2 of 2 strings) Translation: Conversations/App Store Metadata (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata-conversations/zh_Hans/ --- .../metadata/android/zh-CN/full_description.txt | 12 ++++++------ .../metadata/android/zh-CN/short_description.txt | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt b/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt index e95c62219..0c51b9c16 100644 --- a/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt +++ b/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt @@ -13,27 +13,27 @@ * 发送和接收图片 * 加密音视频通话(DTLS-SRTP) * 直观的用户界面,遵循 Android 设计准则 -* 为你的联系人添加图片/头像 +* 为您的联系人添加图片 / 头像 * 与桌面客户端同步 * 群聊(支持书签功能) * 通讯录集成 -* 多账号/统一收件箱 +* 多账号 / 统一收件箱 * 对电池寿命的影响非常小 Conversations 使在免费的 conversations.im 服务器上创建账号变得非常简单。不过,Conversations 也适用于任何其他 XMPP 服务器。许多 XMPP 服务器都是由志愿者免费运行的。 XMPP 功能: -Conversations 适用于所有 XMPP 服务器。然而,XMPP是一种可扩展的协议。这些扩展也在所谓的 XEP 中进行了标准化。Conversations 支持其中的几项功能,使整体用户体验更好。你当前的 XMPP 服务器可能不支持这些扩展。因此,要想最大限度地利用 Conversations 功能,你应该考虑切换到一个支持 Conversations 功能的 XMPP 服务器,或者为你和你的朋友运行自己的 XMPP 服务器(这更好)。 +Conversations 适用于所有 XMPP 服务器。然而,XMPP是一种可扩展的协议。这些扩展也在所谓的 XEP 中进行了标准化。Conversations 支持其中的几项功能,使整体用户体验更好。您当前的 XMPP 服务器可能不支持这些扩展。因此,要想最大限度地利用 Conversations 功能,您应该考虑切换到一个支持 Conversations 功能的 XMPP 服务器,或者为您和您的朋友运行自己的 XMPP 服务器(这更好)。 到目前为止,这些 XEP 是: * XEP-0065:SOCKS5字节流(or mod_proxy65)。如果双方都在防火墙(NAT)后面,将用于传输文件。 * XEP-0163:个人事件协议对于头像 -* XEP-0191:屏蔽指令可让你将垃圾邮件发送者列入黑名单或屏蔽的联系人中,而不会将其从名册中删除。 +* XEP-0191:屏蔽指令可让您将垃圾邮件发送者列入黑名单或屏蔽的联系人中,而不会将其从名册中删除。 * XEP-0198:流管理允许 XMPP 在小规模网络中断和底层 TCP 连接发生变化时继续运行。 -* XEP-0280:消息抄送,可自动将你发送的消息同步到桌面客户端,因此你可以在一次对话中从手机客户端无缝切换到桌面客户端,然后再返回。 +* XEP-0280:消息抄送,可自动将您发送的消息同步到桌面客户端,因此您可以在一次对话中从手机客户端无缝切换到桌面客户端,然后再返回。 * XEP-0237:名册版本控制主要是为了在移动连接不佳的情况下节省带宽 * XEP-0313:消息存档管理与服务器同步消息历史记录。传递 Conversations 离线时发送的消息。 * XEP-0352:客户端状态指示让服务器知道 Conversations 是否在后台。允许服务器保留不重要的数据包,从而节省带宽。 -* XEP-0363:通过 HTTP 文件上传功能,你可以在群聊中与离线联系人分享文件。需要在服务器上安装额外组件。 +* XEP-0363:通过 HTTP 文件上传功能,您可以在群聊中与离线联系人分享文件。需要在服务器上安装额外组件。 diff --git a/src/conversations/fastlane/metadata/android/zh-CN/short_description.txt b/src/conversations/fastlane/metadata/android/zh-CN/short_description.txt index ced555912..29442956d 100644 --- a/src/conversations/fastlane/metadata/android/zh-CN/short_description.txt +++ b/src/conversations/fastlane/metadata/android/zh-CN/short_description.txt @@ -1 +1 @@ -为你的移动设备提供加密、易用的 XMPP 即时信使 +为您的移动设备提供加密、易用的 XMPP 即时信使 From 173c438cb890bd25a2ab1318c2a95618d4af0e0a Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Tue, 17 Oct 2023 12:54:41 +0000 Subject: [PATCH 205/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (51 of 51 strings) Translation: Conversations/App Store Metadata (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/zh_Hans/ --- fastlane/metadata/android/zh-CN/changelogs/390.txt | 2 +- fastlane/metadata/android/zh-CN/changelogs/42012.txt | 2 +- fastlane/metadata/android/zh-CN/changelogs/42037.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fastlane/metadata/android/zh-CN/changelogs/390.txt b/fastlane/metadata/android/zh-CN/changelogs/390.txt index 5566010a2..ee78f954d 100644 --- a/fastlane/metadata/android/zh-CN/changelogs/390.txt +++ b/fastlane/metadata/android/zh-CN/changelogs/390.txt @@ -1 +1 @@ -* 在接听者忙时提供语音消息服务 +* 在接听者忙时提供录制语音消息服务 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42012.txt b/fastlane/metadata/android/zh-CN/changelogs/42012.txt index ac5dd6eee..9c15d9ceb 100644 --- a/fastlane/metadata/android/zh-CN/changelogs/42012.txt +++ b/fastlane/metadata/android/zh-CN/changelogs/42012.txt @@ -1 +1 @@ -* 修复不信任系统证书的用户的 HTTP 上传/下载问题 +* 修复不信任系统证书颁发机构的用户的 HTTP 上传/下载问题 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42037.txt b/fastlane/metadata/android/zh-CN/changelogs/42037.txt index 9d6b04e34..468ddaa52 100644 --- a/fastlane/metadata/android/zh-CN/changelogs/42037.txt +++ b/fastlane/metadata/android/zh-CN/changelogs/42037.txt @@ -1,5 +1,5 @@ 版本2.10.9 -* 进行音视频通话时请求蓝牙权限(如果你不使用蓝牙耳机可以拒绝) +* 进行音视频通话时请求蓝牙权限(如果您不使用蓝牙耳机可以拒绝) * 修复呼叫 Movim 时的错误 * 修复群组聊天的显示错误头像的问题 * 始终要求选择退出电池优化 From fda6693b6df22e13d14de7a7b2930b69e23e325a Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Tue, 17 Oct 2023 12:54:41 +0000 Subject: [PATCH 206/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (2 of 2 strings) Translation: Conversations/App Store Metadata (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata-quicksy/zh_Hans/ --- .../fastlane/metadata/android/zh-CN/full_description.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/quicksy/fastlane/metadata/android/zh-CN/full_description.txt b/src/quicksy/fastlane/metadata/android/zh-CN/full_description.txt index d98d310bc..327e085df 100644 --- a/src/quicksy/fastlane/metadata/android/zh-CN/full_description.txt +++ b/src/quicksy/fastlane/metadata/android/zh-CN/full_description.txt @@ -1,14 +1,14 @@ Quicksy 是流行的 Jabber/XMPP 客户端 Conversations 的衍生产品,具有自动发现联系人的功能。 -你只需用电话号码注册,Quicksy 就会自动—根据你通讯录中的电话号码—向你推荐可能的联系人。 +您只需用电话号码注册,Quicksy 就会自动—根据您通讯录中的电话号码—向您推荐可能的联系人。 -从本质上讲,Quicksy 是一个成熟的 Jabber 客户端,可让你与任何公共联合服务器上的任何用户进行交流。同样,只需将 +phonenumber@quicksy.im 添加到你的联系人列表中,即可从外部联系 Quicksy 上的用户。 +从本质上讲,Quicksy 是一个成熟的 Jabber 客户端,可让您与任何公共联合服务器上的任何用户进行交流。同样,只需将 +phonenumber@quicksy.im 添加到您的联系人列表中,即可从外部联系 Quicksy 上的用户。 除了联系人同步之外,用户界面尽可能地接近 Conversations。这使得用户最终可以从 Quicksy 迁移到 Conversations,而无需重新学习应用程序的工作方式。 建议的联系人包括其他 Quicksy 用户和在 Quicksy 目录中输入 Jabber ID 的普通 Jabber/XMPP 用户。(https://quicksy.im/#get-listed)。 -注意:要在 Quicksy 中输入(https://quicksy.im/enter/)你的 Jabber ID +注意:要在 Quicksy 中输入(https://quicksy.im/enter/)您的 Jabber ID 目录一次性注册费用是必需的。 请阅读隐私政策(https://quicksy.im/#privacy),了解更多信息。 From 063f30ded2f8222264959fd895edba45916fe407 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 17 Oct 2023 07:22:22 +0200 Subject: [PATCH 207/402] ignore outgoing invite outgoing, mediated invites are of type=normal and can end up in MAM. We want to ignore those if they get mirrored back to us --- .../generator/MessageGenerator.java | 4 ++-- .../conversations/parser/MessageParser.java | 21 ++++++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java index 4b055e158..4e99ab086 100644 --- a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java @@ -194,8 +194,8 @@ public class MessageGenerator extends AbstractGenerator { return packet; } - public MessagePacket invite(Conversation conversation, Jid contact) { - MessagePacket packet = new MessagePacket(); + public MessagePacket invite(final Conversation conversation, final Jid contact) { + final MessagePacket packet = new MessagePacket(); packet.setTo(conversation.getJid().asBareJid()); packet.setFrom(conversation.getAccount().getJid()); Element x = new Element("x"); diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 2d1cbcf32..97910f3bb 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -170,14 +170,19 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece return null; } - private Invite extractInvite(Element message) { + private Invite extractInvite(final Element message) { final Element mucUser = message.findChild("x", Namespace.MUC_USER); if (mucUser != null) { - Element invite = mucUser.findChild("invite"); + final Element invite = mucUser.findChild("invite"); if (invite != null) { - String password = mucUser.findChildContent("password"); - Jid from = InvalidJid.getNullForInvalid(invite.getAttributeAsJid("from")); - Jid room = InvalidJid.getNullForInvalid(message.getAttributeAsJid("from")); + final String password = mucUser.findChildContent("password"); + final Jid from = InvalidJid.getNullForInvalid(invite.getAttributeAsJid("from")); + final Jid to = InvalidJid.getNullForInvalid(invite.getAttributeAsJid("to")); + if (to != null && from == null) { + Log.d(Config.LOGTAG,"do not parse outgoing mediated invite "+message); + return null; + } + final Jid room = InvalidJid.getNullForInvalid(message.getAttributeAsJid("from")); if (room == null) { return null; } @@ -454,8 +459,10 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece final Invite invite = extractInvite(packet); if (invite != null) { - if (isTypeGroupChat) { - Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": ignoring invite to " + invite.jid + " because type=groupchat"); + if (invite.jid.asBareJid().equals(account.getJid().asBareJid())) { + Log.d(Config.LOGTAG,account.getJid().asBareJid()+": ignore invite to "+invite.jid+" because it matches account"); + } else if (isTypeGroupChat) { + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": ignoring invite to " + invite.jid + " because it was received as group chat"); } else if (invite.direct && (mucUserElement != null || invite.inviter == null || mXmppConnectionService.isMuc(account, invite.inviter))) { Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": ignoring direct invite to " + invite.jid + " because it was received in MUC"); } else { From 8631c2f9f9efa61f3128828def6eeabea02aecbc Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 17 Oct 2023 07:27:01 +0200 Subject: [PATCH 208/402] version bump to 2.12.12 + changelog --- CHANGELOG.md | 6 ++++++ build.gradle | 4 ++-- fastlane/metadata/android/en-US/changelogs/42074.txt | 3 +++ 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/42074.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e3277f71..a105ca8b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +### Version 2.12.12 + +* Support Private DNS (DNS over TLS) +* Support themed launcher icon +* Fix rare permission issue when sharing files on Android 11+ + ### Version 2.12.11 * Bump libwebrtc dependency to M117 and bump libvpx diff --git a/build.gradle b/build.gradle index c54b90f33..a358e937d 100644 --- a/build.gradle +++ b/build.gradle @@ -95,8 +95,8 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 33 - versionCode 42072 - versionName "2.12.11" + versionCode 42074 + versionName "2.12.12" archivesBaseName += "-$versionName" applicationId "eu.siacs.conversations" resValue "string", "applicationId", applicationId diff --git a/fastlane/metadata/android/en-US/changelogs/42074.txt b/fastlane/metadata/android/en-US/changelogs/42074.txt new file mode 100644 index 000000000..6b19df3eb --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/42074.txt @@ -0,0 +1,3 @@ +* Support Private DNS (DNS over TLS) +* Support themed launcher icon +* Fix rare permission issue when sharing files on Android 11+ From f944fa0c96c2114225b67b9543d8b41f42bb32b7 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 18 Oct 2023 18:43:33 +0200 Subject: [PATCH 209/402] add -beta to version name --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a358e937d..559053252 100644 --- a/build.gradle +++ b/build.gradle @@ -96,7 +96,7 @@ android { minSdkVersion 21 targetSdkVersion 33 versionCode 42074 - versionName "2.12.12" + versionName "2.12.12-beta" archivesBaseName += "-$versionName" applicationId "eu.siacs.conversations" resValue "string", "applicationId", applicationId From 71ebca40e869e24f6fbe7a7c18e4907613c76d28 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 19 Oct 2023 18:11:08 +0200 Subject: [PATCH 210/402] =?UTF-8?q?add=20=C4=B7=20as=20irregular=20unicode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eu/siacs/conversations/utils/IrregularUnicodeDetector.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/eu/siacs/conversations/utils/IrregularUnicodeDetector.java b/src/main/java/eu/siacs/conversations/utils/IrregularUnicodeDetector.java index 1c94225b1..04573ef4c 100644 --- a/src/main/java/eu/siacs/conversations/utils/IrregularUnicodeDetector.java +++ b/src/main/java/eu/siacs/conversations/utils/IrregularUnicodeDetector.java @@ -60,7 +60,7 @@ public class IrregularUnicodeDetector { private static final Map NORMALIZATION_MAP; private static final LruCache CACHE = new LruCache<>(4096); - private static final List AMBIGUOUS_CYRILLIC = Arrays.asList("а","г","е","ѕ","і","ј","ԛ","о","р","с","у","х"); + private static final List AMBIGUOUS_CYRILLIC = Arrays.asList("а","г","е","ѕ","і","ј","ķ","ԛ","о","р","с","у","х"); static { Map temp = new HashMap<>(); From d1f4fbd9defc135766e02e1c4a9c4b989d72fa51 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 19 Oct 2023 20:51:19 +0200 Subject: [PATCH 211/402] add connect timeout to DoT --- src/main/java/de/gultsch/minidns/DNSSocket.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/de/gultsch/minidns/DNSSocket.java b/src/main/java/de/gultsch/minidns/DNSSocket.java index f69b6fb27..a3403115a 100644 --- a/src/main/java/de/gultsch/minidns/DNSSocket.java +++ b/src/main/java/de/gultsch/minidns/DNSSocket.java @@ -38,7 +38,6 @@ import javax.net.ssl.SSLSocketFactory; final class DNSSocket implements Closeable { - private static final int CONNECT_TIMEOUT = 5_000; public static final int QUERY_TIMEOUT = 5_000; private final Semaphore semaphore = new Semaphore(1); @@ -111,7 +110,7 @@ final class DNSSocket implements Closeable { final SocketAddress socketAddress = new InetSocketAddress(dnsServer.inetAddress, dnsServer.port); final Socket socket = new Socket(); - socket.connect(socketAddress, CONNECT_TIMEOUT); + socket.connect(socketAddress, QUERY_TIMEOUT / 2); socket.setSoTimeout(QUERY_TIMEOUT); return DNSSocket.of(socket); } @@ -119,16 +118,18 @@ final class DNSSocket implements Closeable { private static DNSSocket connectTlsSocket(final DNSServer dnsServer) throws IOException { Preconditions.checkArgument(dnsServer.uniqueTransport() == Transport.TLS); final SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); - final SSLSocket sslSocket; + final SSLSocket sslSocket = (SSLSocket) factory.createSocket(); if (Strings.isNullOrEmpty(dnsServer.hostname)) { final SocketAddress socketAddress = new InetSocketAddress(dnsServer.inetAddress, dnsServer.port); - sslSocket = (SSLSocket) factory.createSocket(dnsServer.inetAddress, dnsServer.port); - sslSocket.connect(socketAddress, CONNECT_TIMEOUT); + sslSocket.connect(socketAddress, QUERY_TIMEOUT / 2); sslSocket.setSoTimeout(QUERY_TIMEOUT); + sslSocket.startHandshake(); } else { - sslSocket = (SSLSocket) factory.createSocket(dnsServer.hostname, dnsServer.port); + final SocketAddress socketAddress = new InetSocketAddress(dnsServer.hostname, dnsServer.port); + sslSocket.connect(socketAddress, QUERY_TIMEOUT / 2); sslSocket.setSoTimeout(QUERY_TIMEOUT); + sslSocket.startHandshake(); final SSLSession session = sslSocket.getSession(); final Certificate[] peerCertificates = session.getPeerCertificates(); if (peerCertificates.length == 0 || !(peerCertificates[0] instanceof X509Certificate)) { From d042924afe2b13bf41dbce64fb574924fdd9b1a1 Mon Sep 17 00:00:00 2001 From: Eryk Michalak Date: Tue, 17 Oct 2023 21:42:34 +0000 Subject: [PATCH 212/402] Translated using Weblate (Polish) Currently translated at 100.0% (970 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/pl/ --- src/main/res/values-pl/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/res/values-pl/strings.xml b/src/main/res/values-pl/strings.xml index 3d2557561..48c160035 100644 --- a/src/main/res/values-pl/strings.xml +++ b/src/main/res/values-pl/strings.xml @@ -1045,4 +1045,5 @@ Nie próbuj przywracać kopii zapasowych, których nie utworzono samodzielnie! Próbujesz zaimportować plik kopii zapasowej o przestarzałym formacie Audiobook + Połącz się ponownie na innym hoście \ No newline at end of file From c420b6a3b112ac8f18a0dd0ddd611fa951eca47e Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Wed, 18 Oct 2023 01:10:00 +0000 Subject: [PATCH 213/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (970 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 114 ++++++++++++------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index c0561084f..69c84dd5d 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -11,7 +11,7 @@ 添加账号 编辑名称 添加到通讯录 - 从名册中删除 + 从通讯录删除 屏蔽联系人 解除屏蔽联系人 屏蔽域名 @@ -49,7 +49,7 @@ 解除屏蔽来自 %s 的所有联系人吗? 联系人已屏蔽 已屏蔽 - 您想从书签中移除 %s 吗?与此书签的对话将不会被清除。 + 您想从书签中移除 %s 吗?与此书签相关的对话将不会被清除。 在服务器上注册新账号 在服务器上修改密码 分享至… @@ -71,9 +71,9 @@ 使用您的 XMPP 账号发送堆栈跟踪有助于 %1$s 的持续开发。 立即发送 不再询问 - 无法连接账号 + 无法连接到账号 无法连接到多个账号 - 点击管理您的账号 + 点击以管理您的账号 附上文件 此联系人不在您的联系人列表中,需要添加吗? 添加联系人 @@ -90,7 +90,7 @@ 您确定要删除此文件吗? \n \n警告: 这将不会删除存储在其他设备或服务器上的此文件的副本。 - 之后关闭此对话 + 稍后关闭此对话 选择设备 发送未加密的消息 发送消息 @@ -103,7 +103,7 @@ 解密失败。也许您没有正确的私钥。 OpenKeychain %1$s 使用 <b>OpenKeychain</b>来加密和解密消息并管理您的公钥。<br><br>它在 GPLv3+ 许可证下授权并可在 F-Droid 和 Google Play 上获得。<br><br><small>(请稍后重新启动 %1$s。)</small> - 重启 + 重新启动 安装 请安装 OpenKeychain 正在提供… @@ -133,7 +133,7 @@ 在您的某个其他设备上检测到活动之后,通知被静音的时间长度。 高级 从不发送崩溃报告 - 通过发送堆栈跟踪,您正在帮助开发 + 通过发送堆栈跟踪,您可以帮助进一步的开发 确认消息 当您已收到并阅读了您的联系人的消息后,让他们知道 防止截屏 @@ -155,9 +155,9 @@ 无法转换图片文件 文件未找到 常规 I/O 错误。也许您的存储空间已用完? - 您用来选择图片的应用没有提供读取文件的足够权限。 + 您用来选择此图片的应用程序没有提供足够的权限来读取文件。 \n -\n使用不同的文件管理器来选择图片. +\n使用不同的文件管理器来选择图片 您用来分享此文件的应用程序没有提供足够的权限。 未知 暂时禁用 @@ -188,27 +188,27 @@ 发布头像 发布 OpenPGP 公钥 移除 OpenPGP 公钥 - 您确定要从您的在线状态公布中移除您的 OpenPGP 公钥吗? + 您确定要从在线状态公布中移除您的 OpenPGP 公钥吗? \n您的联系人将无法再向您发送 OpenPGP 加密消息。 OpenPGP 公钥已发布。 启用账号 - 您确定要删除您的账号吗?删除您的账号会擦除您的全部对话历史记录 + 您确定要删除您的账号吗?删除账号会擦除您的全部对话历史记录 录制语音 XMPP 地址 屏蔽 XMPP 地址 username@example.com 密码 这不是有效的 XMPP 地址 - 空间不足。图片过大 + 空间不足。图片太大 您想要添加 %s 到您的通讯录中吗? 服务器信息 XEP-0313:消息存档管理 XEP-0280:消息抄送 XEP-0352:客户端状态指示 XEP-0191:屏蔽指令 - XEP-0237:名册版本控制 + XEP-0237:通讯录版本控制 XEP-0198:流管理 - XEP-0215:发现外部服务 + XEP-0215:外部服务发现 XEP-0163:个人事件协议(头像 / OMEMO) XEP-0363:HTTP 文件上传 XEP-0357:推送 @@ -230,7 +230,7 @@ OMEMO 指纹(消息来源) v\\OMEMO 指纹(消息来源) 其他设备 - 信任的 OMEMO 指纹 + 信任 OMEMO 指纹 正在获取密钥… 完成 解密 @@ -290,10 +290,10 @@ 输入密码 请先向您的联系人请求在线状态更新。 \n -\n这将被用来判断您的联系人正在使用的聊天应用 +\n这将被用来判断您的联系人正在使用的聊天应用程序 立即请求 忽略 - 警告: 在没有相互更新在线状态的情况下发送此消息将会出现未知问题。 + 警告: 在没有彼此更新在线状态的情况下发送此消息将会出现未知问题。 \n \n前往“联系人详情”以验证您的在线状态订阅。 安全 @@ -316,7 +316,7 @@ 资源限制 您已被此群组聊天踢出 此群组聊天已被关闭 - 您已不在此群组聊天 + 您已不在此群组聊天中 由于技术原因您离开了此群组聊天 正在使用账号 %s 托管于 %s @@ -363,9 +363,9 @@ 无法分享文件 文件传输已取消 文件已删除 - 未找到可以打开文件的应用 - 未找到可以打开链接的应用 - 未找到可以查看联系人的应用 + 未找到可以打开文件的应用程序 + 未找到可以打开链接的应用程序 + 未找到可以查看联系人的应用程序 动态标签 在联系人下方显示只读标签 启用通知 @@ -380,7 +380,7 @@ \n无法从服务器获取新密钥。也许是您的联系人的服务器出了问题? 此联系人没有可用的密钥。 \n确保双方都有在线状态订阅。 - 出错了 + 出了点问题 正在从服务器获取历史记录 服务器上没有更多历史记录 正在更新… @@ -416,7 +416,7 @@ 公开频道配置 私人,仅限成员 使 XMPP 地址对任何人可见 - 对频道进行管理 + 对频道进行审核 您未参与 已修改群组聊天选项! 无法修改群组聊天选项 @@ -429,7 +429,7 @@ Enter 即发送 使用 Enter 键发送消息。即使禁用此选项,您始终可以使用 Ctrl+Enter 发送消息。 显示 Enter 键 - 将表情符号键更改为 Enter 键 + 将表情符号键替换为 Enter 键 音频 视频 图片 @@ -450,7 +450,7 @@ 当您正在给您的联系人写消息时,让他们知道 发送位置 显示位置 - 未找到可以显示位置的应用 + 未找到可以显示位置的应用程序 位置 对话已关闭 离开私人群组聊天 @@ -464,7 +464,7 @@ 删除选中内容 取消 - %d 个证书已被删除 + %d 个证书已删除 以快捷操作替代“发送”按钮 快捷操作 @@ -473,7 +473,7 @@ 选择快捷操作 搜索联系人 发送私人消息 - %1$s 已离开群组聊天 + %1$s 已离开此群组聊天 用户名 用户名 此用户名无效 @@ -486,7 +486,7 @@ 绑定失败 服务器不能为域名做出响应 损坏 - 可用性 + 可用时间 当设备锁定时离开 当设备锁定时显示为离开 静音模式时忙碌 @@ -504,12 +504,12 @@ 无法获取存档首选项 需要验证码 输入上图中的文字 - 不受信任的证书链 + 不信任的证书链 XMPP 地址与证书不匹配 续订证书 获取 OMEMO 密钥时出错! 已通过证书验证 OMEMO 密钥! - 您的设备不支持选择客户端证书! + 您的设备不支持客户端证书选择! 连接 通过 Tor 连接 通过 Tor 网络传输所有连接。需要 Orbot @@ -557,17 +557,17 @@ 您已经安全地验证了此人的指纹以确认信任。通过选择“完成”,您只是在确认 %s 是此群组聊天的一部分。 您已禁用了此账号 安全错误:文件访问无效! - 未找到可以分享 URI 的应用 + 未找到可以分享 URI 的应用程序 分享 URI 至… 同意并继续 在 conversations.im 上创建账号的指南已设置。 -\n当选择 conversations.im 作为提供者时,您将能够通过向来自其他提供者的用户提供您的完整 XMPP 地址来与他们进行交流。 +\n当选择 conversations.im 作为提供者时,通过向其他提供者的用户提供您的完整 XMPP 地址,您将能够与他们进行交流。
您的完整 XMPP 地址将是:%s 创建账号 使用我自己的提供者 选择您的用户名 - 手动管理可用性 - 当编辑您的状态消息时设置您的可用时间。 + 手动管理可用时间 + 在编辑状态消息时,设置您的可用时间。 状态消息 随时可聊 在线 @@ -615,7 +615,7 @@ 删除 OMEMO 身份 重新生成您的 OMEMO 密钥。您的所有联系人将不得不再次验证您的身份。只有在万不得已的情况下才会使用这种方法。 删除选定的密钥 - 您需要连接网络才能发布您的头像。 + 您需要连接到网络才能发布您的头像。 显示出错消息 出错消息 省流量模式已启用 @@ -623,14 +623,14 @@ \n%1$s 仍将在可能的情况下努力节省数据。
您的设备不支持对 %1$s 禁用省流量模式。 无法创建临时文件 - 此设备已验证 + 此设备已通过验证 复制指纹 您已验证了您拥有的所有 OMEMO 密钥 - 条码中不包含此对话的指纹。 + 二维码中不包含此对话的指纹。 已验证的指纹 - 使用相机扫描联系人的条码 + 使用相机扫描联系人的二维码 请稍候获取密钥 - 分享为条码 + 分享为二维码 分享为 XMPP URI 分享为 HTTP 链接 验证前盲目信任 @@ -638,10 +638,10 @@ 盲目信任的 OMEMO 密钥,表示它们可能是其他人或者某人可能冒充别人发送消息。 不信任的 二维码无效 - 清理缓存文件夹(由相机应用使用) + 清除缓存文件夹(由相机应用使用) 清除缓存 清除私人存储空间 - 清理保存文件的私人存储(它们可以从服务器重新下载) + 清除保存文件的私人存储(它们可以从服务器重新下载) 我从一个可信来源收到此链接 点击链接后,您即将验证 %1$s 的 OMEMO 密钥。只有当您从一个可信来源(只有 %2$s 可以发布此链接)收到此链接时,这才是安全的。 您即将验证您自己账号的 OMEMO 密钥。只有当您从一个可信来源(只有您可以发布此链接)收到此链接时,这才是安全的。 @@ -672,7 +672,7 @@ 自动删除消息 自动从此设备上删除超过配置时限的消息。 - 消息加密中 + 正在加密消息 由于本地保留期限设置,无法获取消息。 正在压缩视频 相应的对话已关闭。 @@ -688,7 +688,7 @@ 已降级的 SASL 机制 服务器要求在网站上注册 打开网站 - 未找到可以打开网站的应用 + 未找到可以打开网站的应用程序 顶部通知 显示顶部通知 今天 @@ -702,11 +702,11 @@ 消息已复制到剪贴板 消息 私人消息被禁用 - 受保护的应用 - 为了在屏幕关闭时也能收到消息提醒,您需要将 Conversations 加入受保护的应用列表。 - 接受未知的证书? + 受保护的应用程序 + 为了继续接收通知,即使在屏幕关闭的情况下也是如此,您需要将 Conversations 加入受保护的应用程序列表。 + 是否接受未知证书? 此服务器证书不是由已知的证书颁发机构签发的。 - 接受不匹配的服务器名称? + 是否接受不匹配的服务器名称? 由于“%s”,服务器无法验证。证书仅对此有效: 您仍要连接吗? 证书详情: @@ -720,7 +720,7 @@ %1$s 无法发送加密消息到 %2$s。这可能是因为您的联系人使用了过期的服务器或者无法处理 OMEMO 的客户端。 无法获取设备列表 无法获取密钥 - 提示:某些情况下,可以将对方加入您的联系人列表,以解决此问题。 + 提示:某些情况下,可以通过彼此添加到联系人列表中来解决此问题。 您确定要禁用此对话的 OMEMO 加密吗? \n这将允许服务器管理员阅读您的消息,但这可能是与使用过时客户端的用户进行交流的唯一方法。 立即禁用 @@ -731,7 +731,7 @@ 对于新对话,必须明确地打开 OMEMO。 创建快捷方式 字体大小 - 应用内使用的相对字体大小。 + 应用程序中使用的相对字体大小。 默认开启 默认关闭 @@ -773,10 +773,10 @@ 此群组聊天已被解散 无法保存录制 前台服务 - 此通知类别用于显示 %1$s 正在运行的永久通知。 + 此通知类别用于显示永久通知,指示 %1$s 正在运行。 状态信息 连接问题 - 此通知类别用于在连接到账号时出现问题时显示通知。 + 此通知类别用于在连接账号出现问题时显示通知。 消息 通话 消息 @@ -834,7 +834,7 @@ 无法找到服务器。 处理您的请求时出了问题。 用户输入无效 - 暂时无法连接。请稍候再试。 + 暂时不可用。请稍后再试。 无网络连接。 请在 %s 后重试 您被限制速率 @@ -905,7 +905,7 @@ Conversations 备份 事件 打开备份 - 选择的文件不是 Conversations 备份文件 + 您所选的文件不是一个 Conversations 备份文件 此账号已设置 请输入此账号的密码 无法执行此操作 @@ -927,8 +927,8 @@ 正在连接 已连接 正在重新连接 - 接受通话 - 结束通话 + 正在接受通话 + 正在结束通话 应答 忽略 发现设备中 @@ -937,7 +937,7 @@ 无法连接通话 连接丢失 已撤回通话 - 程序错误 + 应用程序错误 验证问题 挂断 正在进行的通话 @@ -981,7 +981,7 @@ 录制语音留言 播放音频 暂停音频 - 添加联系人,创建或加入群组聊天,或发现频道 + 添加联系人、创建或加入群组聊天、或发现频道 查看 %1$d 位参与者 From 73a5c4df55eb3d703fbc3374704ff5d79264aec5 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Wed, 18 Oct 2023 00:42:50 +0000 Subject: [PATCH 214/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (13 of 13 strings) Translation: Conversations/Android App (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-conversations/zh_Hans/ --- src/conversations/res/values-zh-rCN/strings.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/conversations/res/values-zh-rCN/strings.xml b/src/conversations/res/values-zh-rCN/strings.xml index 79c582529..0f3ecc4a0 100644 --- a/src/conversations/res/values-zh-rCN/strings.xml +++ b/src/conversations/res/values-zh-rCN/strings.xml @@ -3,18 +3,18 @@ 选择您的 XMPP 提供者 使用 conversations.im 创建新账号 - 您已经有一个 XMPP 账号了吗?如果您已经在使用不同的 XMPP 客户端或者以前使用过 Conversations,那么您已经拥有这种账号了。如果没有的话,您现在可以创建一个。 + 您已经有一个 XMPP 账号了吗?如果您已经在使用一个不同的 XMPP 客户端或者以前使用过 Conversations,那么您已经拥有这种账号了。如果没有的话,您现在可以创建一个新的 XMPP 账号。 \n提示:一些电子邮件提供者也提供 XMPP 账号。 - XMPP 是独立于提供者的即时通讯网络。您可以将此客户端与您选择的任何 XMPP 服务器一起使用。 -\n不过,为了您的方便,我们让您可以轻松地在 conversations.im 上创建一个账号;这是一个特别适合与 Conversations 一起使用的提供者。 + XMPP 是一个独立于提供者的即时通讯网络。您可以将此客户端与您选择的任何 XMPP 服务器一起使用。 +\n不过,为了您的方便,我们让您可以轻松地在 conversations.im 上创建一个账号;一个特别适合与 Conversations 一起使用的提供者。 您已受邀加入 %1$s。我们将指导您完成创建账号的过程。 -\n当选择 %1$s 作为提供者时,您将能够通过向来自其他提供者的用户提供您的完整 XMPP 地址来与他们进行交流。 +\n当选择 %1$s 作为提供者时,通过向其他提供者的用户提供您的完整 XMPP 地址,您将能够与他们进行交流。 您已受邀加入 %1$s。已为您选择了一个用户名。我们将指导您完成创建账号的过程。 -\n您将能够通过向来自其他提供者的用户提供您的完整 XMPP 地址来与他们进行交流。 +\n通过向其他提供者的用户提供您的完整 XMPP 地址,您将能够与他们进行交流。
您的服务器邀请 配置代码格式不当 点击分享按钮向您的联系人发送加入 %1$s 的邀请。 - 如果您的联系人在附近,他们也可以扫描下面的代码来接受您的邀请。 + 如果您的联系人在附近,他们也可以扫描下方二维码来接受您的邀请。 加入 %1$s 和我聊天:%2$s 分享邀请至… \ No newline at end of file From af933da91df0c9f178e191f0aec0b3fd716ca3e4 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Tue, 17 Oct 2023 23:02:40 +0000 Subject: [PATCH 215/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (9 of 9 strings) Translation: Conversations/Android App (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-quicksy/zh_Hans/ --- src/quicksy/res/values-zh-rCN/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/quicksy/res/values-zh-rCN/strings.xml b/src/quicksy/res/values-zh-rCN/strings.xml index 81608a938..98e243f8b 100644 --- a/src/quicksy/res/values-zh-rCN/strings.xml +++ b/src/quicksy/res/values-zh-rCN/strings.xml @@ -1,12 +1,12 @@ Quicksy 发现其他设备上的活动后保持安静的时间长度 - 通过发送堆栈跟踪,您可以帮助 Quicksy 的持续开发 + 通过发送堆栈跟踪,您正在帮助 Quicksy 的持续开发 当您使用 Quicksy 时,让您的所有联系人知道 - 为了在屏幕关闭时也能收到消息提醒,您需要将 Quicksy 加入受保护的应用列表。 + 为了继续接收通知,即使在屏幕关闭的情况下也是如此,您需要将 Quicksy 加入受保护的应用程序列表。 Quicksy 个人资料图片 Quicksy 在您所在的国家/地区无法使用。 无法验证服务器身份。 未知安全错误。 - 连接服务器超时。 + 连接到服务器时超时。 \ No newline at end of file From 61b1e6bbe4ee5741797f63013b98c1f9f09da9a0 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Wed, 18 Oct 2023 15:04:06 +0000 Subject: [PATCH 216/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (2 of 2 strings) Translation: Conversations/App Store Metadata (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata-conversations/zh_Hans/ --- .../metadata/android/zh-CN/full_description.txt | 10 +++++----- .../metadata/android/zh-CN/short_description.txt | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt b/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt index 0c51b9c16..b733788c5 100644 --- a/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt +++ b/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt @@ -1,10 +1,10 @@ -易于使用、性能可靠、省电。内置支持图片、群组聊天和 e2e 加密功能。 +易于使用、性能可靠、电池友好。内置支持图片、群组聊天和 e2e 加密功能。 设计原则: * 在不牺牲安全性和隐私性的前提下,尽可能美观易用 * 依托现有的、成熟的协议 -* 不需要 Google 账号或特定的 Google 云信息服务(GCM) +* 不需要 Google 账号或特定的 Google 云通讯服务(GCM) * 要求尽可能少的权限 特点: @@ -24,16 +24,16 @@ Conversations 使在免费的 conversations.im 服务器上创建账号变得非 XMPP 功能: -Conversations 适用于所有 XMPP 服务器。然而,XMPP是一种可扩展的协议。这些扩展也在所谓的 XEP 中进行了标准化。Conversations 支持其中的几项功能,使整体用户体验更好。您当前的 XMPP 服务器可能不支持这些扩展。因此,要想最大限度地利用 Conversations 功能,您应该考虑切换到一个支持 Conversations 功能的 XMPP 服务器,或者为您和您的朋友运行自己的 XMPP 服务器(这更好)。 +Conversations 适用于所有 XMPP 服务器。然而,XMPP是一种可扩展的协议。这些扩展也在所谓的 XEP 中进行了标准化。Conversations 支持其中的几项功能,使整体用户体验更好。有一种可能性是您当前的 XMPP 服务器不支持这些扩展。因此,要想充分使用 Conversations 的功能,您应该考虑切换到具有以下功能的 XMPP 服务器,甚至有更好的方式,或者为您和您的朋友运行自己的 XMPP 服务器。 到目前为止,这些 XEP 是: * XEP-0065:SOCKS5字节流(or mod_proxy65)。如果双方都在防火墙(NAT)后面,将用于传输文件。 * XEP-0163:个人事件协议对于头像 -* XEP-0191:屏蔽指令可让您将垃圾邮件发送者列入黑名单或屏蔽的联系人中,而不会将其从名册中删除。 +* XEP-0191:屏蔽指令可让您将垃圾邮件发送者列入黑名单或屏蔽的联系人中,而不会将其从通讯录中删除。 * XEP-0198:流管理允许 XMPP 在小规模网络中断和底层 TCP 连接发生变化时继续运行。 * XEP-0280:消息抄送,可自动将您发送的消息同步到桌面客户端,因此您可以在一次对话中从手机客户端无缝切换到桌面客户端,然后再返回。 -* XEP-0237:名册版本控制主要是为了在移动连接不佳的情况下节省带宽 +* XEP-0237:通讯录版本控制主要是为了在移动连接不佳的情况下节省带宽 * XEP-0313:消息存档管理与服务器同步消息历史记录。传递 Conversations 离线时发送的消息。 * XEP-0352:客户端状态指示让服务器知道 Conversations 是否在后台。允许服务器保留不重要的数据包,从而节省带宽。 * XEP-0363:通过 HTTP 文件上传功能,您可以在群聊中与离线联系人分享文件。需要在服务器上安装额外组件。 diff --git a/src/conversations/fastlane/metadata/android/zh-CN/short_description.txt b/src/conversations/fastlane/metadata/android/zh-CN/short_description.txt index 29442956d..28659cd56 100644 --- a/src/conversations/fastlane/metadata/android/zh-CN/short_description.txt +++ b/src/conversations/fastlane/metadata/android/zh-CN/short_description.txt @@ -1 +1 @@ -为您的移动设备提供加密、易用的 XMPP 即时信使 +加密、易于使用的 XMPP 即时信使,适用于您的移动设备 From fecf81285bb2d7ace6c88efb7a92b091d2218df9 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Wed, 18 Oct 2023 04:15:37 +0000 Subject: [PATCH 217/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (51 of 51 strings) Translation: Conversations/App Store Metadata (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/zh_Hans/ --- fastlane/metadata/android/zh-CN/changelogs/42014.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane/metadata/android/zh-CN/changelogs/42014.txt b/fastlane/metadata/android/zh-CN/changelogs/42014.txt index 4b1865a6a..11afbe025 100644 --- a/fastlane/metadata/android/zh-CN/changelogs/42014.txt +++ b/fastlane/metadata/android/zh-CN/changelogs/42014.txt @@ -1,2 +1,2 @@ * 始终验证域名。 没有用户覆盖 -* 支持名册预验证 +* 支持通讯录预验证 From 8d264fdce406b657cd03ac746d3ba2157d97d2a1 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Wed, 18 Oct 2023 00:29:09 +0000 Subject: [PATCH 218/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (2 of 2 strings) Translation: Conversations/App Store Metadata (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata-quicksy/zh_Hans/ --- .../fastlane/metadata/android/zh-CN/full_description.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/quicksy/fastlane/metadata/android/zh-CN/full_description.txt b/src/quicksy/fastlane/metadata/android/zh-CN/full_description.txt index 327e085df..4f154352f 100644 --- a/src/quicksy/fastlane/metadata/android/zh-CN/full_description.txt +++ b/src/quicksy/fastlane/metadata/android/zh-CN/full_description.txt @@ -1,12 +1,12 @@ -Quicksy 是流行的 Jabber/XMPP 客户端 Conversations 的衍生产品,具有自动发现联系人的功能。 +Quicksy 是一个流行的 Jabber/XMPP 客户端 Conversations 的衍生品,具有自动发现联系人的功能。 您只需用电话号码注册,Quicksy 就会自动—根据您通讯录中的电话号码—向您推荐可能的联系人。 从本质上讲,Quicksy 是一个成熟的 Jabber 客户端,可让您与任何公共联合服务器上的任何用户进行交流。同样,只需将 +phonenumber@quicksy.im 添加到您的联系人列表中,即可从外部联系 Quicksy 上的用户。 -除了联系人同步之外,用户界面尽可能地接近 Conversations。这使得用户最终可以从 Quicksy 迁移到 Conversations,而无需重新学习应用程序的工作方式。 +除了联系人同步之外,用户界面尽可能地接近 Conversations。这使得用户最终可以从 Quicksy 迁移到 Conversations,而无需重新了解应用程序的工作方式。 -建议的联系人包括其他 Quicksy 用户和在 Quicksy 目录中输入 Jabber ID 的普通 Jabber/XMPP 用户。(https://quicksy.im/#get-listed)。 +建议的联系人包括其他 Quicksy 用户和在 Quicksy 目录中输入 Jabber ID 的普通 Jabber/XMPP 用户(https://quicksy.im/#get-listed)。 注意:要在 Quicksy 中输入(https://quicksy.im/enter/)您的 Jabber ID 目录一次性注册费用是必需的。 From c37036e67ad415c266ef2c13d539f0c0c48998e0 Mon Sep 17 00:00:00 2001 From: 0que <0que@users.noreply.translate.codeberg.org> Date: Thu, 19 Oct 2023 06:25:08 +0000 Subject: [PATCH 219/402] Translated using Weblate (Russian) Currently translated at 99.8% (969 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/ru/ --- src/main/res/values-ru/strings.xml | 33 +++++++++++++++++++----------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/main/res/values-ru/strings.xml b/src/main/res/values-ru/strings.xml index 0d7689596..6da979c15 100644 --- a/src/main/res/values-ru/strings.xml +++ b/src/main/res/values-ru/strings.xml @@ -8,7 +8,7 @@ Сведения о контакте Подробности конференции Сведения о канале - Добавить аккаунт + Добавить учётную запись Редактировать контакт Добавить в адресную книгу Удалить из списка @@ -53,7 +53,7 @@ Контакт заблокирован Заблокирован Вы хотите удалить %s из избранного? Беседы, связанные с данной закладкой, будут сохранены. - Создать новый аккаунт на сервере + Создать новую учётную запись на сервере Изменить пароль на сервере Поделиться с Начать беседу @@ -139,7 +139,7 @@ Принять Произошла ошибка Ошибка - Ваш аккаунт + Ваша учётная запись Отправлять присутствие Получать присутствие Запрашивать присутствие @@ -183,7 +183,7 @@ Вы действительно хотите удалить ваш OpenPGP публичный ключ из опубликованных?\nВаши собеседники не смогут больше отправлять вам зашифрованные OpenPGP сообщения. Публичный ключ OpenPGP опубликован. Включить аккаунт - Вы уверены, что хотите удалить свой аккаунт\? Это удалит все истории диалогов + Вы точно хотите удалить свою учётную запись\? Это удалит все истории диалогов Запись голоса XMPP-адрес Заблокировать XMPP-адрес @@ -267,7 +267,7 @@ отправить %s Приватное сообщение %s Подключиться - Аккаунт уже существует + Эта учётная запись уже существует Далее Сеанс установлен Пропустить @@ -329,7 +329,7 @@ Файлы резервной копии сохранены в %s Восстановление из резервной копии Восстановление из резервной копии выполнено - Не забудьте включить аккаунт + Не забудьте включить учётную запись. Выбрать файл %1$s загружается (%2$d%% выполнено) Загрузить %s @@ -526,12 +526,12 @@ Ваше устройство использует агрессивную оптимизацию энергопотребления %1$s, что может привести к задержке уведомлений и даже потере сообщений.\nСейчас появится предложение её отключить. Запретить Выбранная область слишком большая - (Нет активных аккаунтов) + (Нет активированных учётных записей) Незаполненное поле Исправить сообщение Отправить исправленное сообщение Вы уже подтвердили, что электронный отпечаток принадлежит этому человеку. Выбрав \"Готово\", вы только подтвердите, что %s является участником конференции. - Вы отключили этот аккаунт + Вы отключили эту учётную запись Ошибка безопасности: недействительный доступ к файлу Не найдено приложения для передачи URI Отправить URI… @@ -883,9 +883,9 @@ Найти каналы Поиск каналов Возможно нарушение конфиденциальности! - У меня уже есть аккаунт + У меня уже есть учётная запись Добавить существующий аккаунт - Зарегистрировать новую учетную запись + Создать новую учетную запись Это похоже на имя домена Добавить все равно Это похоже на адрес канала @@ -930,7 +930,7 @@ Входящий вызов Пропущенный вызов · %s Исходящий вызов - Пропущен вызов + Пропущенный вызов Аудиовызов Видеовызов Помощь @@ -989,7 +989,7 @@ Продолжить Сервер уведомлений Распределитель UnifiedPush - Пропущенные звонки + Пропущенные вызовы Переподключение Адрес XMPP не найден Учётная запись XMPP @@ -1028,4 +1028,13 @@ %1$d пропущенных вызовов от %2$s %1$d пропущенных вызовов от %2$s + Переподключиться на другой сервер + Вы попытались импортировать резервную копию в устаревшем формате + + %1$d пропущенный вызов от %2$d контакта + %1$d пропущенных вызова от %2$d контактов + %1$d пропущенных вызовов от %2$d контактов + %1$d пропущенных вызовов от %2$d контактов + + Аудиокнига \ No newline at end of file From eed71c44dee071eb8910c57c3ccb456da531958e Mon Sep 17 00:00:00 2001 From: SomeTr Date: Thu, 19 Oct 2023 19:04:06 +0000 Subject: [PATCH 220/402] Translated using Weblate (Ukrainian) Currently translated at 100.0% (970 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/uk/ --- src/main/res/values-uk/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/res/values-uk/strings.xml b/src/main/res/values-uk/strings.xml index 5cdbe7bb9..a3044180f 100644 --- a/src/main/res/values-uk/strings.xml +++ b/src/main/res/values-uk/strings.xml @@ -122,7 +122,7 @@ Звук сповіщень Звук сповіщень для нових повідомлень Час до блокування - Час, протягом якого сповіщення вимикнені після виявлення активності на іншому пристрої. + Час, протягом якого сповіщення вимкнені після виявлення активності на іншому пристрої. Розширені Не надсилати звіти про збої Надсилаючи траси стеку викликів, Ви допомагаєте розробляти застосунок From 5d52d205e8f9ecb77805db1415d19d651499f00f Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Thu, 19 Oct 2023 05:28:00 +0000 Subject: [PATCH 221/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (970 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 112 ++++++++++++------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index 69c84dd5d..1623d3efa 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -11,7 +11,7 @@ 添加账号 编辑名称 添加到通讯录 - 从通讯录删除 + 从联系人列表删除 屏蔽联系人 解除屏蔽联系人 屏蔽域名 @@ -35,21 +35,21 @@ 正在发送… 解密消息中。请稍候… OpenPGP 加密的消息 - 昵称已使用 + 此昵称已在使用中 无效的昵称 管理员 所有者 主持人 参与者 访客 - 您想从联系人列表中移除 %s 吗?与此联系人的对话将不会被清除。 + 您想从联系人列表中移除 %s 吗?与此联系人的对话将不会被移除。 您想屏蔽 %s 向您发送消息吗? 您想解除屏蔽 %s 并允许他们向您发送消息吗? 屏蔽来自 %s 的所有联系人吗? 解除屏蔽来自 %s 的所有联系人吗? 联系人已屏蔽 已屏蔽 - 您想从书签中移除 %s 吗?与此书签相关的对话将不会被清除。 + 您想从书签中移除 %s 吗?与此书签相关的对话将不会被移除。 在服务器上注册新账号 在服务器上修改密码 分享至… @@ -90,7 +90,7 @@ 您确定要删除此文件吗? \n \n警告: 这将不会删除存储在其他设备或服务器上的此文件的副本。 - 稍后关闭此对话 + 之后关闭此对话 选择设备 发送未加密的消息 发送消息 @@ -98,11 +98,11 @@ 发送 OMEMO 加密消息 发送 v\\OMEMO 加密消息 发送 OpenPGP 加密消息 - 新昵称使用中 + 正在使用新昵称 发送未加密的 解密失败。也许您没有正确的私钥。 OpenKeychain - %1$s 使用 <b>OpenKeychain</b>来加密和解密消息并管理您的公钥。<br><br>它在 GPLv3+ 许可证下授权并可在 F-Droid 和 Google Play 上获得。<br><br><small>(请稍后重新启动 %1$s。)</small> + %1$s 使用 <b>OpenKeychain</b>来加密和解密消息并管理您的公钥。<br><br>它在 GPLv3+ 许可证下授权并可在 F-Droid 和 Google Play 上获得。<br><br><small>(请之后重新启动 %1$s。)</small> 重新启动 安装 请安装 OpenKeychain @@ -133,7 +133,7 @@ 在您的某个其他设备上检测到活动之后,通知被静音的时间长度。 高级 从不发送崩溃报告 - 通过发送堆栈跟踪,您可以帮助进一步的开发 + 通过发送堆栈跟踪,您正在帮助此应用程序的开发 确认消息 当您已收到并阅读了您的联系人的消息后,让他们知道 防止截屏 @@ -150,7 +150,7 @@ 请求在线状态更新 选择图片 拍摄图片 - 预先授予订阅请求 + 预先同意订阅请求 您所选的文件不是一张图片 无法转换图片文件 文件未找到 @@ -206,13 +206,13 @@ XEP-0280:消息抄送 XEP-0352:客户端状态指示 XEP-0191:屏蔽指令 - XEP-0237:通讯录版本控制 + XEP-0237:花名册版本控制 XEP-0198:流管理 XEP-0215:外部服务发现 - XEP-0163:个人事件协议(头像 / OMEMO) + XEP-0163:个人事件协议(头像/OMEMO) XEP-0363:HTTP 文件上传 XEP-0357:推送 - 可用 + 可用的 不可用 缺少公钥公布 最后上线于刚才 @@ -227,8 +227,8 @@ OpenPGP 密钥 ID OMEMO 指纹 v\\OMEMO 指纹 - OMEMO 指纹(消息来源) - v\\OMEMO 指纹(消息来源) + OMEMO 指纹(消息来源) + v\\OMEMO 指纹(消息来源) 其他设备 信任 OMEMO 指纹 正在获取密钥… @@ -252,10 +252,10 @@ 解散频道 您确定要解散此群组聊天吗? \n -\n警告: 此群组聊天将在服务器上完全删除。 +\n警告: 此群组聊天将在服务器上被完全移除。
您确定要解散此公开频道吗? \n -\n警告: 此频道将在服务器上完全删除。 +\n警告: 此频道将在服务器上被完全移除。
无法解散群组聊天 无法解散频道 编辑群组聊天话题 @@ -271,10 +271,10 @@ 发布 点击头像从图库中选择图片 正在发布… - 服务器拒绝发布您的头像 + 服务器拒绝了您的发布 无法转换您的图片 无法将头像保存至磁盘 - (或长按恢复默认) + (或长按恢复默认) 您的服务器不支持发布头像 私聊 至 %s @@ -293,9 +293,9 @@ \n这将被用来判断您的联系人正在使用的聊天应用程序
立即请求 忽略 - 警告: 在没有彼此更新在线状态的情况下发送此消息将会出现未知问题。 + 警告: 在双方没有更新在线状态的情况下发送此消息将会出现未知问题。 \n -\n前往“联系人详情”以验证您的在线状态订阅。 +\n请前往“联系人详情”以验证您的在线状态订阅。 安全 允许消息更正 允许您的联系人发送后编辑其消息 @@ -317,7 +317,7 @@ 您已被此群组聊天踢出 此群组聊天已被关闭 您已不在此群组聊天中 - 由于技术原因您离开了此群组聊天 + 由于技术原因,您离开了此群组聊天 正在使用账号 %s 托管于 %s 正在 HTTP 主机上检查 %s @@ -351,12 +351,12 @@ 您的备份已恢复 不要忘记启用此账号。 选择文件 - 正在接收 %1$s(%2$d%% 已完成) + 正在接收 %1$s (%2$d%% 已完成) 下载 %s 删除 %s 文件 打开 %s - 正在发送(%1$d%% 已完成) + 正在发送 (%1$d%% 已完成) 正在准备分享文件 %s 可供下载 取消传输 @@ -461,7 +461,7 @@ 删除手动批准的证书 没有手动批准的证书 移除证书 - 删除选中内容 + 删除选定内容 取消 %d 个证书已删除 @@ -485,8 +485,8 @@ Tor 网络不可用 绑定失败 服务器不能为域名做出响应 - 损坏 - 可用时间 + 损坏的 + 可用性 当设备锁定时离开 当设备锁定时显示为离开 静音模式时忙碌 @@ -550,7 +550,7 @@ \n您现在将被要求禁用它们。
禁用 所选区域太大 - (没有启用的账号) + (没有启用的账号) 此字段是必需的 更正消息 发送更正后的消息 @@ -566,13 +566,13 @@ 创建账号 使用我自己的提供者 选择您的用户名 - 手动管理可用时间 - 在编辑状态消息时,设置您的可用时间。 + 手动管理可用性 + 在编辑状态消息时,设置您的可用性,指示您的在线状态。 状态消息 - 随时可聊 + 有空聊天 在线 离开 - 不在 + 没空 忙碌 已生成一个安全密码 您的设备不支持选择退出电池优化 @@ -638,13 +638,13 @@ 盲目信任的 OMEMO 密钥,表示它们可能是其他人或者某人可能冒充别人发送消息。 不信任的 二维码无效 - 清除缓存文件夹(由相机应用使用) - 清除缓存 - 清除私人存储空间 - 清除保存文件的私人存储(它们可以从服务器重新下载) + 清理缓存文件夹(由相机应用使用) + 清理缓存 + 清理私人存储空间 + 清理保存文件的私人存储(它们可以从服务器重新下载) 我从一个可信来源收到此链接 - 点击链接后,您即将验证 %1$s 的 OMEMO 密钥。只有当您从一个可信来源(只有 %2$s 可以发布此链接)收到此链接时,这才是安全的。 - 您即将验证您自己账号的 OMEMO 密钥。只有当您从一个可信来源(只有您可以发布此链接)收到此链接时,这才是安全的。 + 点击链接后,您即将验证 %1$s 的 OMEMO 密钥。只有当您从一个可信来源(只有 %2$s 可以发布此链接)收到此链接时,这才是安全的。 + 您即将验证您自己账号的 OMEMO 密钥。只有当您从一个可信来源(只有您可以发布此链接)收到此链接时,这才是安全的。 继续 验证 OMEMO 密钥 显示不活跃设备 @@ -696,7 +696,7 @@ 通过 DNSSEC 验证主机名 包含主机名的服务器证书被认为是已验证的 证书不包含 XMPP 地址 - 部分 + 部分的 录制视频 复制到剪贴板 消息已复制到剪贴板 @@ -717,10 +717,10 @@ 编辑状态消息 编辑状态消息 禁用加密 - %1$s 无法发送加密消息到 %2$s。这可能是因为您的联系人使用了过期的服务器或者无法处理 OMEMO 的客户端。 + %1$s 无法发送加密消息到 %2$s。这可能是因为您的联系人使用了过时的服务器或者无法处理 OMEMO 的客户端。 无法获取设备列表 无法获取密钥 - 提示:某些情况下,可以通过彼此添加到联系人列表中来解决此问题。 + 提示:某些情况下,可以通过双方添加到联系人列表中来解决此问题。 您确定要禁用此对话的 OMEMO 加密吗? \n这将允许服务器管理员阅读您的消息,但这可能是与使用过时客户端的用户进行交流的唯一方法。 立即禁用 @@ -773,7 +773,7 @@ 此群组聊天已被解散 无法保存录制 前台服务 - 此通知类别用于显示永久通知,指示 %1$s 正在运行。 + 此通知类别用于显示永久通知,表明 %1$s 正在运行。 状态信息 连接问题 此通知类别用于在连接账号出现问题时显示通知。 @@ -784,7 +784,7 @@ 正在进行的通话 未接来电 静音消息 - 此通知组用于显示不应触发任何声音的通知。 例如,在另一台设备上处于活跃状态时(宽限期)。 + 此通知组用于显示不应触发任何声音的通知。 例如,在另一台设备上处于活跃状态时(宽限期)。 传递失败 消息通知设置 来电通知设置 @@ -796,7 +796,7 @@ 文件由于违反安全规定被删除。 视频质量 质量越低,文件越小 - 中(360p) + 中(360p) 高(720p) 已取消 您已经在起草一条消息了。 @@ -805,13 +805,13 @@ 选择国家/地区 电话号码 验证您的电话号码 - Quicksy 将发送短信(运营商可能收费)来验证您的电话号码。请输入您的国家/地区代码和电话号码: + Quicksy 将发送短信(运营商可能收费)来验证您的电话号码。请输入您的国家/地区代码和电话号码: 我们将验证这个电话号码

%s

,这样可以吗?或者您想编辑这个号码?
%s 不是有效的电话号码。 请输入您的电话号码。 搜索国家/地区 验证 %s - 我们已向您发送短信 %s + 我们已向您发送短信至 %s 我们已经向您发送了另一条带有 6 位数验证码的短信。 请在下方输入 6 位数的 PIN 码。 重新发送短信 @@ -820,7 +820,7 @@ 返回 已自动从剪贴板粘贴可能的 PIN 码。 请输入您的 6 位数 PIN 码。 - 您确定要取消注册程序吗? + 您确定要中止注册程序吗? 正在验证… @@ -839,9 +839,9 @@ 请在 %s 后重试 您被限制速率 尝试次数过多 - 您使用的是过时版本的应用程序。 + 您正在使用此应用程序的过时版本。 更新 - 此电话号码目前已在其他设备上登录。 + 此电话号码目前已在另一台设备上登录。 请输入您的名称,以便让通讯录中没有您的人知道您是谁。 您的名称 输入您的名称 @@ -852,14 +852,14 @@ 未安装应用商店。 此频道将公开您的 XMPP 地址 电子书 - 原始(未压缩) + 原始(未压缩) 打开为… Conversations 个人资料图片 选择账号 恢复备份 恢复 - 输入您的 %s 账号的密码以恢复备份。 - 请勿使用恢复备份功能尝试克隆(同时运行)安装。恢复备份仅适用于迁移或您丢失原始设备的情况。 + 请输入您的 %s 账号的密码以恢复备份。 + 请勿使用恢复备份功能尝试克隆(同时运行)安装。恢复备份仅适用于迁移或您丢失原始设备的情况。 无法恢复备份。 无法解密备份。密码是否正确? 备份 & 恢复 @@ -906,7 +906,7 @@ 事件 打开备份 您所选的文件不是一个 Conversations 备份文件 - 此账号已设置 + 此账号已完成设置 请输入此账号的密码 无法执行此操作 加入公开频道… @@ -1007,7 +1007,7 @@ 拒绝视频切换请求 XMPP 账号 推送服务器 - 无(已停用) + 无(已停用) UnifiedPush 分发程序 接收推送消息的账号。 用户选择的推送服务器,通过 XMPP 将推送消息转送至您的设备。 @@ -1020,9 +1020,9 @@ 群组聊天 保存为群组聊天 搜索群组聊天 - 从服务器删除账号 - 不要尝试恢复您尚未自行创建的备份! - 您正试图导入过时的备份文件格式 + 从服务器移除账号 + 请勿尝试恢复您尚未自行创建的备份! + 您正尝试导入过时的备份文件格式 有声读物 重新连接其他主机 \ No newline at end of file From 072d68c0bafc35ff94b7b044e2c6d7a5ea8d64ef Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Thu, 19 Oct 2023 05:06:26 +0000 Subject: [PATCH 222/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (9 of 9 strings) Translation: Conversations/Android App (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-quicksy/zh_Hans/ --- src/quicksy/res/values-zh-rCN/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quicksy/res/values-zh-rCN/strings.xml b/src/quicksy/res/values-zh-rCN/strings.xml index 98e243f8b..648119c1c 100644 --- a/src/quicksy/res/values-zh-rCN/strings.xml +++ b/src/quicksy/res/values-zh-rCN/strings.xml @@ -1,6 +1,6 @@ - Quicksy 发现其他设备上的活动后保持安静的时间长度 + Quicksy 发现另一台设备上的活动后保持安静的时间长度 通过发送堆栈跟踪,您正在帮助 Quicksy 的持续开发 当您使用 Quicksy 时,让您的所有联系人知道 为了继续接收通知,即使在屏幕关闭的情况下也是如此,您需要将 Quicksy 加入受保护的应用程序列表。 From 17e8e4cff7d4a605cfad01ec16096fa3ad56ddbf Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Fri, 20 Oct 2023 00:55:31 +0000 Subject: [PATCH 223/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (2 of 2 strings) Translation: Conversations/App Store Metadata (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata-conversations/zh_Hans/ --- .../metadata/android/zh-CN/full_description.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt b/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt index b733788c5..b9bcb2bc9 100644 --- a/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt +++ b/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt @@ -24,16 +24,16 @@ Conversations 使在免费的 conversations.im 服务器上创建账号变得非 XMPP 功能: -Conversations 适用于所有 XMPP 服务器。然而,XMPP是一种可扩展的协议。这些扩展也在所谓的 XEP 中进行了标准化。Conversations 支持其中的几项功能,使整体用户体验更好。有一种可能性是您当前的 XMPP 服务器不支持这些扩展。因此,要想充分使用 Conversations 的功能,您应该考虑切换到具有以下功能的 XMPP 服务器,甚至有更好的方式,或者为您和您的朋友运行自己的 XMPP 服务器。 +Conversations 适用于所有 XMPP 服务器。然而,XMPP是一种可扩展的协议。这些扩展在所谓的 XEP 中也是标准化的。Conversations 支持其中的一些扩展,以使整体用户体验更好。有一种可能是您当前的 XMPP 服务器不支持这些扩展。因此,要想充分使用 Conversations 的功能,您应该考虑切换到支持这些扩展的 XMPP 服务器,甚至有更好的方式,或者为您和您的朋友运行自己的 XMPP 服务器。 到目前为止,这些 XEP 是: -* XEP-0065:SOCKS5字节流(or mod_proxy65)。如果双方都在防火墙(NAT)后面,将用于传输文件。 +* XEP-0065:SOCKS5 字节流(or mod_proxy65)。如果双方都在防火墙(NAT)后面,将用于传输文件。 * XEP-0163:个人事件协议对于头像 -* XEP-0191:屏蔽指令可让您将垃圾邮件发送者列入黑名单或屏蔽的联系人中,而不会将其从通讯录中删除。 +* XEP-0191:屏蔽指令可让您将垃圾邮件发送者列入黑名单或屏蔽的联系人中,而不会将其从花名册中删除。 * XEP-0198:流管理允许 XMPP 在小规模网络中断和底层 TCP 连接发生变化时继续运行。 * XEP-0280:消息抄送,可自动将您发送的消息同步到桌面客户端,因此您可以在一次对话中从手机客户端无缝切换到桌面客户端,然后再返回。 -* XEP-0237:通讯录版本控制主要是为了在移动连接不佳的情况下节省带宽 -* XEP-0313:消息存档管理与服务器同步消息历史记录。传递 Conversations 离线时发送的消息。 +* XEP-0237:花名册版本控制主要是为了在移动连接不佳的情况下节省带宽 +* XEP-0313:消息存档管理与服务器同步消息历史记录。补发 Conversations 离线时发送的消息。 * XEP-0352:客户端状态指示让服务器知道 Conversations 是否在后台。允许服务器保留不重要的数据包,从而节省带宽。 * XEP-0363:通过 HTTP 文件上传功能,您可以在群聊中与离线联系人分享文件。需要在服务器上安装额外组件。 From a3b2b24b11b50ea0a1f00d69aecf1954cbdb23b6 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Fri, 20 Oct 2023 00:54:30 +0000 Subject: [PATCH 224/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (51 of 51 strings) Translation: Conversations/App Store Metadata (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/zh_Hans/ --- fastlane/metadata/android/zh-CN/changelogs/349.txt | 4 ++-- fastlane/metadata/android/zh-CN/changelogs/393.txt | 2 +- fastlane/metadata/android/zh-CN/changelogs/42014.txt | 2 +- fastlane/metadata/android/zh-CN/changelogs/42037.txt | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fastlane/metadata/android/zh-CN/changelogs/349.txt b/fastlane/metadata/android/zh-CN/changelogs/349.txt index 836b1e8aa..689259e2b 100644 --- a/fastlane/metadata/android/zh-CN/changelogs/349.txt +++ b/fastlane/metadata/android/zh-CN/changelogs/349.txt @@ -1,4 +1,4 @@ * 引入专家设置在本地服务器上执行频道发现而不是 search.jabber.network -* 默认启用传递复选标记并删除设置 -* 默认启用“发送按钮指示状态”并删除设置 +* 默认启用传递复选标记并移除设置 +* 默认启用“发送按钮指示状态”并移除设置 * 将备份和前台服务设置移至主屏幕 diff --git a/fastlane/metadata/android/zh-CN/changelogs/393.txt b/fastlane/metadata/android/zh-CN/changelogs/393.txt index f432818ff..1d903fe6c 100644 --- a/fastlane/metadata/android/zh-CN/changelogs/393.txt +++ b/fastlane/metadata/android/zh-CN/changelogs/393.txt @@ -1,3 +1,3 @@ * 如果音频/视频通话失败则显示帮助按钮 * 修复了一些恼人的崩溃问题 -* 修复了带有裸 JID 的 Jingle 连接(文件传输 + 通话) +* 修复了带有纯 JID 的 Jingle 连接(文件传输 + 通话) diff --git a/fastlane/metadata/android/zh-CN/changelogs/42014.txt b/fastlane/metadata/android/zh-CN/changelogs/42014.txt index 11afbe025..937c7f8cc 100644 --- a/fastlane/metadata/android/zh-CN/changelogs/42014.txt +++ b/fastlane/metadata/android/zh-CN/changelogs/42014.txt @@ -1,2 +1,2 @@ * 始终验证域名。 没有用户覆盖 -* 支持通讯录预验证 +* 支持花名册预验证 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42037.txt b/fastlane/metadata/android/zh-CN/changelogs/42037.txt index 468ddaa52..bde374945 100644 --- a/fastlane/metadata/android/zh-CN/changelogs/42037.txt +++ b/fastlane/metadata/android/zh-CN/changelogs/42037.txt @@ -5,7 +5,7 @@ * 始终要求选择退出电池优化 * 在“x 个已连接账号”通知上设置仅本地标志 * 修复与 Google 地图分享位置插件的交互 -* 删除有关服务器费用的脚注 +* 移除有关服务器费用的脚注 * 将文件存储在适合 Android 11 的位置 * 网络切换后尝试重新连接通话 * 在来电屏幕中显示来电者JID和帐户JID From a5f51d69e1e419dc50ee04f1e0e9b86393eecd73 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 20 Oct 2023 10:33:22 +0200 Subject: [PATCH 225/402] version bump to 2.12.12-beta.2 --- build.gradle | 4 ++-- .../android/en-US/changelogs/{42074.txt => 42075.txt} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename fastlane/metadata/android/en-US/changelogs/{42074.txt => 42075.txt} (100%) diff --git a/build.gradle b/build.gradle index 559053252..ff78ec7e1 100644 --- a/build.gradle +++ b/build.gradle @@ -95,8 +95,8 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 33 - versionCode 42074 - versionName "2.12.12-beta" + versionCode 42075 + versionName "2.12.12-beta.2" archivesBaseName += "-$versionName" applicationId "eu.siacs.conversations" resValue "string", "applicationId", applicationId diff --git a/fastlane/metadata/android/en-US/changelogs/42074.txt b/fastlane/metadata/android/en-US/changelogs/42075.txt similarity index 100% rename from fastlane/metadata/android/en-US/changelogs/42074.txt rename to fastlane/metadata/android/en-US/changelogs/42075.txt From 822f3f4d22437c60cc64d3e8ee2a7f17343ee00e Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 21 Oct 2023 14:21:29 +0200 Subject: [PATCH 226/402] consider going from unique or exporter to endpoint a downgrade --- .../conversations/crypto/sasl/ChannelBinding.java | 10 ++++++++++ .../crypto/sasl/ChannelBindingMechanism.java | 9 +++++++++ .../siacs/conversations/crypto/sasl/ScramSha1Plus.java | 2 +- .../conversations/crypto/sasl/ScramSha256Plus.java | 2 +- .../conversations/crypto/sasl/ScramSha512Plus.java | 2 +- 5 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/crypto/sasl/ChannelBinding.java b/src/main/java/eu/siacs/conversations/crypto/sasl/ChannelBinding.java index 216f3d7f8..2eb5e39fb 100644 --- a/src/main/java/eu/siacs/conversations/crypto/sasl/ChannelBinding.java +++ b/src/main/java/eu/siacs/conversations/crypto/sasl/ChannelBinding.java @@ -117,4 +117,14 @@ public enum ChannelBinding { throw new AssertionError("Missing short name for " + channelBinding); } } + + public static int priority(final ChannelBinding channelBinding) { + if (Arrays.asList(TLS_EXPORTER,TLS_UNIQUE).contains(channelBinding)) { + return 2; + } else if (channelBinding == ChannelBinding.TLS_SERVER_END_POINT) { + return 1; + } else { + return 0; + } + } } diff --git a/src/main/java/eu/siacs/conversations/crypto/sasl/ChannelBindingMechanism.java b/src/main/java/eu/siacs/conversations/crypto/sasl/ChannelBindingMechanism.java index b94210a60..7343eb86e 100644 --- a/src/main/java/eu/siacs/conversations/crypto/sasl/ChannelBindingMechanism.java +++ b/src/main/java/eu/siacs/conversations/crypto/sasl/ChannelBindingMechanism.java @@ -97,4 +97,13 @@ public interface ChannelBindingMechanism { messageDigest.update(encodedCertificate); return messageDigest.digest(); } + + static int getPriority(final SaslMechanism mechanism) { + if (mechanism instanceof ChannelBindingMechanism) { + final ChannelBindingMechanism channelBindingMechanism = (ChannelBindingMechanism) mechanism; + return ChannelBinding.priority(channelBindingMechanism.getChannelBinding()); + } else { + return 0; + } + } } diff --git a/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha1Plus.java b/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha1Plus.java index 2ca27570f..4490d7621 100644 --- a/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha1Plus.java +++ b/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha1Plus.java @@ -27,7 +27,7 @@ public class ScramSha1Plus extends ScramPlusMechanism { @Override public int getPriority() { - return 35; // higher than SCRAM-SHA512 (30) + return 35 + ChannelBinding.priority(this.channelBinding); // higher than SCRAM-SHA512 (30) } @Override diff --git a/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha256Plus.java b/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha256Plus.java index 4db33a2fa..eafc86fbc 100644 --- a/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha256Plus.java +++ b/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha256Plus.java @@ -27,7 +27,7 @@ public class ScramSha256Plus extends ScramPlusMechanism { @Override public int getPriority() { - return 40; + return 40 + ChannelBinding.priority(this.channelBinding); } @Override diff --git a/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha512Plus.java b/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha512Plus.java index 5d8461973..d110e7708 100644 --- a/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha512Plus.java +++ b/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha512Plus.java @@ -27,7 +27,7 @@ public class ScramSha512Plus extends ScramPlusMechanism { @Override public int getPriority() { - return 45; + return 45 + ChannelBinding.priority(this.channelBinding); } @Override From c44f4b102a9933e935fb45e4c207051fff2bf1d0 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 21 Oct 2023 14:22:38 +0200 Subject: [PATCH 227/402] do not accept fast token w/o channel binding for channel bound login --- .../siacs/conversations/xmpp/XmppConnection.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 8a2b2e7cd..7ba266794 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -65,6 +65,7 @@ import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.XmppDomainVerifier; import eu.siacs.conversations.crypto.axolotl.AxolotlService; import eu.siacs.conversations.crypto.sasl.ChannelBinding; +import eu.siacs.conversations.crypto.sasl.ChannelBindingMechanism; import eu.siacs.conversations.crypto.sasl.HashedToken; import eu.siacs.conversations.crypto.sasl.SaslMechanism; import eu.siacs.conversations.entities.Account; @@ -826,10 +827,15 @@ public class XmppConnection implements Runnable { tokenMechanism = null; } if (tokenMechanism != null && !Strings.isNullOrEmpty(token)) { - this.account.setFastToken(tokenMechanism, token); - Log.d( - Config.LOGTAG, - account.getJid().asBareJid() + ": storing hashed token " + tokenMechanism); + if (ChannelBinding.priority(tokenMechanism.channelBinding) >= ChannelBindingMechanism.getPriority(currentSaslMechanism)) { + this.account.setFastToken(tokenMechanism, token); + Log.d( + Config.LOGTAG, + account.getJid().asBareJid() + ": storing hashed token " + tokenMechanism); + } else { + Log.d(Config.LOGTAG,account.getJid().asBareJid()+": not accepting hashed token "+ tokenMechanism.name()+" for log in mechanism "+currentSaslMechanism.getMechanism()); + this.account.resetFastToken(); + } } else if (this.hashTokenRequest != null) { Log.w( Config.LOGTAG, From 284934148eb2944d5ba0a79fc26fd8b1da10bfcb Mon Sep 17 00:00:00 2001 From: ghose Date: Fri, 20 Oct 2023 06:36:22 +0000 Subject: [PATCH 228/402] Translated using Weblate (Galician) Currently translated at 100.0% (970 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/gl/ --- src/main/res/values-gl/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/res/values-gl/strings.xml b/src/main/res/values-gl/strings.xml index 1bbe45d5a..367b6e487 100644 --- a/src/main/res/values-gl/strings.xml +++ b/src/main/res/values-gl/strings.xml @@ -909,7 +909,7 @@ Chamada entrante Videochamada entrante Cambiar a unha chamada de vídeo? - Engadir pistas adicionais? + Engadir rutas adicionais\? Conectando Conectado Reconectando From f524163b56965db3b6b1f4278b31ff3203ae6f1a Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Sat, 21 Oct 2023 05:13:39 +0000 Subject: [PATCH 229/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (970 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 342 ++++++++++++------------- 1 file changed, 171 insertions(+), 171 deletions(-) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index 1623d3efa..90f3a9325 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -6,7 +6,7 @@ 管理账号 关闭对话 联系人详情 - 群组聊天详情 + 群聊详情 频道详情 添加账号 编辑名称 @@ -42,14 +42,14 @@ 主持人 参与者 访客 - 您想从联系人列表中移除 %s 吗?与此联系人的对话将不会被移除。 - 您想屏蔽 %s 向您发送消息吗? - 您想解除屏蔽 %s 并允许他们向您发送消息吗? - 屏蔽来自 %s 的所有联系人吗? - 解除屏蔽来自 %s 的所有联系人吗? + 是否从联系人列表中移除 %s?与此联系人的对话将不会移除。 + 是否屏蔽 %s 向您发送消息? + 是否解除屏蔽 %s 并允许他们向您发送消息? + 是否屏蔽来自 %s 的所有联系人? + 是否解除屏蔽来自 %s 的所有联系人? 联系人已屏蔽 已屏蔽 - 您想从书签中移除 %s 吗?与此书签相关的对话将不会被移除。 + 是否从书签中移除 %s?与此书签相关的对话将不会移除。 在服务器上注册新账号 在服务器上修改密码 分享至… @@ -73,9 +73,9 @@ 不再询问 无法连接到账号 无法连接到多个账号 - 点击以管理您的账号 - 附上文件 - 此联系人不在您的联系人列表中,需要添加吗? + 点击即可管理账号 + 附加文件 + 此联系人不在您的联系人列表中,是否添加? 添加联系人 传递失败 正在准备发送图片 @@ -83,37 +83,37 @@ 分享文件中。请稍候… 清除历史记录 清除对话历史记录 - 您想删除此对话中的所有消息吗? + 是否删除此对话中的所有消息? \n -\n警告: 这将不会影响存储在其他设备或服务器上的消息。 +\n警告: 这将不会影响存储在其他设备或服务器上的消息。 删除文件 - 您确定要删除此文件吗? + 是否删除此文件? \n -\n警告: 这将不会删除存储在其他设备或服务器上的此文件的副本。 +\n警告: 这将不会删除存储在其他设备或服务器上的此文件的副本。 之后关闭此对话 选择设备 发送未加密的消息 发送消息 发送消息至 %s - 发送 OMEMO 加密消息 - 发送 v\\OMEMO 加密消息 - 发送 OpenPGP 加密消息 + 发送 OMEMO 加密的消息 + 发送 v\\OMEMO 加密的消息 + 发送 OpenPGP 加密的消息 正在使用新昵称 发送未加密的 解密失败。也许您没有正确的私钥。 OpenKeychain - %1$s 使用 <b>OpenKeychain</b>来加密和解密消息并管理您的公钥。<br><br>它在 GPLv3+ 许可证下授权并可在 F-Droid 和 Google Play 上获得。<br><br><small>(请之后重新启动 %1$s。)</small> + %1$s 使用 <b>OpenKeychain</b> 来加密和解密消息并管理您的公钥。<br><br>它在 GPLv3+ 许可证下授权并可在 F-Droid 和 Google Play 上获得。<br><br><small>(请之后重新启动 %1$s。)</small> 重新启动 安装 请安装 OpenKeychain 正在提供… 正在等待… 未找到 OpenPGP 密钥 - 由于您的联系人未公布其公钥,无法加密您的消息。 + 无法加密消息,因为您的联系人未公布其公钥。 \n \n请通知您的联系人设置 OpenPGP。 未找到 OpenPGP 密钥 - 由于您的联系人未公布其公钥,无法加密您的消息。 + 无法加密消息,因为您的联系人未公布其公钥。 \n \n请通知您的联系人设置 OpenPGP。 常规 @@ -130,7 +130,7 @@ 新消息的通知铃声 来电铃声 宽限期 - 在您的某个其他设备上检测到活动之后,通知被静音的时间长度。 + 在您的某个其他设备上检测到活动之后,通知会静音的时间长度。 高级 从不发送崩溃报告 通过发送堆栈跟踪,您正在帮助此应用程序的开发 @@ -139,10 +139,10 @@ 防止截屏 在应用程序切换器中隐藏应用程序内容并屏蔽屏幕截图 用户界面 - OpenKeychain 出现了一个错误。 + OpenKeychain 出现了错误。 加密密钥错误。 接受 - 出现了一个错误 + 出现了错误 错误 您的账号 发送在线状态更新 @@ -151,14 +151,14 @@ 选择图片 拍摄图片 预先同意订阅请求 - 您所选的文件不是一张图片 + 所选的文件不是图片 无法转换图片文件 文件未找到 - 常规 I/O 错误。也许您的存储空间已用完? - 您用来选择此图片的应用程序没有提供足够的权限来读取文件。 + 常规 I/O 错误。也许存储空间已用完? + 用来选择此图片的应用程序没有提供足够的权限来读取文件。 \n \n使用不同的文件管理器来选择图片 - 您用来分享此文件的应用程序没有提供足够的权限。 + 用来分享此文件的应用程序没有提供足够的权限。 未知 暂时禁用 在线 @@ -168,7 +168,7 @@ 服务器未找到 未连接 注册失败 - 用户名已使用 + 此用户名已在使用中 注册已完成 服务器不支持注册 注册令牌无效 @@ -179,7 +179,7 @@ 不兼容的客户端 流错误 流打开错误 - 未加密 + 未加密的 OTR OpenPGP OMEMO @@ -188,11 +188,11 @@ 发布头像 发布 OpenPGP 公钥 移除 OpenPGP 公钥 - 您确定要从在线状态公布中移除您的 OpenPGP 公钥吗? + 是否从在线状态公布中移除您的 OpenPGP 公钥? \n您的联系人将无法再向您发送 OpenPGP 加密消息。 OpenPGP 公钥已发布。 启用账号 - 您确定要删除您的账号吗?删除账号会擦除您的全部对话历史记录 + 是否删除账号?删除账号会擦除您的全部对话历史记录 录制语音 XMPP 地址 屏蔽 XMPP 地址 @@ -200,18 +200,18 @@ 密码 这不是有效的 XMPP 地址 空间不足。图片太大 - 您想要添加 %s 到您的通讯录中吗? + 是否添加 %s 到您的通讯录中? 服务器信息 - XEP-0313:消息存档管理 - XEP-0280:消息抄送 - XEP-0352:客户端状态指示 - XEP-0191:屏蔽指令 - XEP-0237:花名册版本控制 - XEP-0198:流管理 - XEP-0215:外部服务发现 - XEP-0163:个人事件协议(头像/OMEMO) - XEP-0363:HTTP 文件上传 - XEP-0357:推送 + XEP-0313: 消息存档管理 + XEP-0280: 消息抄送 + XEP-0352: 客户端状态指示 + XEP-0191: 屏蔽指令 + XEP-0237: 花名册版本控制 + XEP-0198: 流管理 + XEP-0215: 外部服务发现 + XEP-0163: 个人事件协议(头像/OMEMO) + XEP-0363: HTTP 文件上传 + XEP-0357: 推送 可用的 不可用 缺少公钥公布 @@ -222,7 +222,7 @@ 最后上线于 %d 小时前 最后上线于 1 天前 最后上线于 %d 天前 - 加密消息。请安装 OpenKeychain 以解密。 + 加密的消息。请安装 OpenKeychain 以解密。 发现新的 OpenPGP 加密消息 OpenPGP 密钥 ID OMEMO 指纹 @@ -248,32 +248,32 @@ channel@conference.example.com 保存为书签 删除书签 - 解散群组聊天 + 解散群聊 解散频道 - 您确定要解散此群组聊天吗? + 是否解散此群聊? \n -\n警告: 此群组聊天将在服务器上被完全移除。 - 您确定要解散此公开频道吗? +\n警告: 群聊将在服务器上完全移除。 + 是否解散此公开频道? \n -\n警告: 此频道将在服务器上被完全移除。 - 无法解散群组聊天 +\n警告: 频道将在服务器上完全移除。 + 无法解散群聊 无法解散频道 - 编辑群组聊天话题 + 编辑群聊话题 话题 - 正在加入群组聊天… + 正在加入群聊… 离开 - 联系人已添加您到联系人列表 + 联系人已将您添加到联系人列表 添加对方 %s 已阅读至此 %s 已阅读至此 %1$s 和其他 %2$d 人已阅读至此 每个人都已阅读至此 发布 - 点击头像从图库中选择图片 + 点击头像即可从图库中选择图片 正在发布… 服务器拒绝了您的发布 - 无法转换您的图片 - 无法将头像保存至磁盘 + 无法转换图片 + 无法将头像保存到磁盘 (或长按恢复默认) 您的服务器不支持发布头像 私聊 @@ -286,38 +286,38 @@ 跳过 禁用通知 启用 - 群组聊天需要密码 + 需要密码才能进入此群聊 输入密码 请先向您的联系人请求在线状态更新。 \n -\n这将被用来判断您的联系人正在使用的聊天应用程序 +\n这将用于确定您的联系人正在使用的聊天应用程序 立即请求 忽略 - 警告: 在双方没有更新在线状态的情况下发送此消息将会出现未知问题。 + 警告: 在双方没有更新在线状态的情况下发送此消息将会出现未知问题。 \n -\n请前往“联系人详情”以验证您的在线状态订阅。 +\n前往“联系人详情”以验证在线状态订阅。 安全 允许消息更正 允许您的联系人发送后编辑其消息 专家设置 - 请谨慎使用这些 + 请谨慎设置这些 关于 %s 安静时间 开始时间 结束时间 启用安静时间 - 在安静时间内,通知将被静音 + 在安静时间内,将会静音通知 其他 同步书签 - 在进入或离开多用户聊天时设置 “autojoin\" 标志,并回应其他客户端所做的修改。 + 在进入或离开多用户聊天时设置 “autojoin\" 标志,并回应其他客户端所做的改变。 OMEMO 指纹已复制到剪贴板 - 您已被此群组聊天封禁 - 此群组聊天仅限成员参与 + 此群聊已将您封禁了 + 此群聊仅限成员参与 资源限制 - 您已被此群组聊天踢出 - 此群组聊天已被关闭 - 您已不在此群组聊天中 - 由于技术原因,您离开了此群组聊天 + 此群聊已将您踢出了 + 此群聊已关闭 + 您已不在群聊中 + 由于技术原因,您离开了群聊 正在使用账号 %s 托管于 %s 正在 HTTP 主机上检查 %s @@ -341,14 +341,14 @@ 确认 再试一次 前台服务 - 防止操作系统中断您的连接 + 防止操作系统中断连接 创建备份 备份文件将存储在 %s 创建备份文件中 - 您的备份已创建 + 备份已创建 此备份文件已存储在 %s 恢复备份中 - 您的备份已恢复 + 备份已恢复 不要忘记启用此账号。 选择文件 正在接收 %1$s (%2$d%% 已完成) @@ -369,20 +369,20 @@ 动态标签 在联系人下方显示只读标签 启用通知 - 群组聊天服务器未找到 - 无法创建群组聊天 + 群聊服务器未找到 + 无法创建群聊 账号头像 复制 OMEMO 指纹到剪贴板 重新生成 OMEMO 密钥 清除设备 - 您确定要从 OMEMO 公布中清除所有其他设备吗?下次您的设备连接时,它们将会重新公布自己,但可能不会收到在此期间发送的消息。 + 是否从 OMEMO 公布中清除所有其他设备?下次连接时,设备将会重新公布,但可能不会收到在此期间发送的消息。 此联系人没有可用的密钥。 \n无法从服务器获取新密钥。也许是您的联系人的服务器出了问题? 此联系人没有可用的密钥。 \n确保双方都有在线状态订阅。 出了点问题 - 正在从服务器获取历史记录 - 服务器上没有更多历史记录 + 正在从服务器获取消息历史记录 + 服务器上没有更多消息历史记录 正在更新… 密码已修改! 无法修改密码 @@ -404,22 +404,22 @@ 撤销管理员权限 授予所有者权限 撤销所有者权限 - 从群组聊天中移除 + 从群聊中移除 从频道中移除 - 无法修改 %s 的从属关系 - 从群组聊天中封禁 + 无法更改 %s 的从属关系 + 从群聊中封禁 从频道中封禁 您正试图从公开频道中移除 %s。唯一的办法就是永远封禁此用户。 立即封禁 - 无法修改 %s 的角色 - 私人群组聊天配置 + 无法更改 %s 的角色 + 私人群聊配置 公开频道配置 私人,仅限成员 使 XMPP 地址对任何人可见 对频道进行审核 - 您未参与 - 已修改群组聊天选项! - 无法修改群组聊天选项 + 您没有参与 + 群聊选项修改成功! + 无法修改群聊选项 从不 直至另行通知 稍后提醒 @@ -441,7 +441,7 @@ 头像已发布! 正在发送 %s 正在提供 %s - 隐藏离线联系人 + 隐藏离线的联系人 %s 正在输入… %s 已停止输入 %s 正在输入… @@ -453,7 +453,7 @@ 未找到可以显示位置的应用程序 位置 对话已关闭 - 离开私人群组聊天 + 离开私人群聊 离开公开频道 不信任系统证书颁发机构 所有证书必须手动批准 @@ -461,7 +461,7 @@ 删除手动批准的证书 没有手动批准的证书 移除证书 - 删除选定内容 + 删除所选证书 取消 %d 个证书已删除 @@ -473,30 +473,30 @@ 选择快捷操作 搜索联系人 发送私人消息 - %1$s 已离开此群组聊天 + %1$s 离开了群聊 用户名 用户名 此用户名无效 - 下载失败:服务器未找到 - 下载失败:文件未找到 - 下载失败:无法连接到主机 - 下载失败:无法写入文件 - 下载失败:无效文件 + 下载失败: 服务器未找到 + 下载失败: 文件未找到 + 下载失败: 无法连接到主机 + 下载失败: 无法写入文件 + 下载失败: 无效文件 Tor 网络不可用 绑定失败 服务器不能为域名做出响应 损坏的 可用性 - 当设备锁定时离开 - 当设备锁定时显示为离开 + 设备锁定时离开 + 当设备锁定时,在线状态显示为“暂时离开” 静音模式时忙碌 - 当设备处于静音模式时显示为忙碌 + 当设备处于静音模式时,在线状态显示为“请勿打扰” 将振动模式视为静音模式 - 当设备处于振动模式时显示为忙碌 + 当设备处于振动模式时,在线状态显示为“请勿打扰” 扩展连接设置 设置账号时显示主机名和端口设置 xmpp.example.com - 使用证书登录 + 用证书登录 无法解析证书 存档首选项 服务器端存档首选项 @@ -523,10 +523,10 @@ %d 条消息 加载更多消息 - 文件已分享至 %s - 图片已分享至 %s - 图片已分享至 %s - 文本已分享至 %s + 文件已分享给 %s + 图片已分享给 %s + 图片已分享给 %s + 文本已分享给 %s 授予 %1$s 访问外部存储的权限 授予 %1$s 访问相机的权限 与联系人同步 @@ -539,7 +539,7 @@ 通知已禁用 通知已暂停 图片压缩 - 提示:无论此设置如何,使用“选择文件”而不是“选择图片”会发送未压缩的单张图片。 + 提示:无论此设置如何,使用“选择文件”会发送未压缩的图片。 始终 仅限大图片 电池优化已启用 @@ -547,39 +547,39 @@ \n建议禁用它们。 您的设备正对 %1$s 实施强力电池优化,这可能会导致通知延迟甚至消息丢失。 \n -\n您现在将被要求禁用它们。 +\n现在将要求您禁用它们。 禁用 所选区域太大 (没有启用的账号) 此字段是必需的 更正消息 发送更正后的消息 - 您已经安全地验证了此人的指纹以确认信任。通过选择“完成”,您只是在确认 %s 是此群组聊天的一部分。 + 您已经安全地验证了此用户的指纹以确认信任。通过选择“完成”以确认 %s 加入群聊。 您已禁用了此账号 - 安全错误:文件访问无效! + 安全错误: 文件访问无效! 未找到可以分享 URI 的应用程序 分享 URI 至… 同意并继续 在 conversations.im 上创建账号的指南已设置。 \n当选择 conversations.im 作为提供者时,通过向其他提供者的用户提供您的完整 XMPP 地址,您将能够与他们进行交流。 - 您的完整 XMPP 地址将是:%s + 您的完整 XMPP 地址将是: %s 创建账号 使用我自己的提供者 选择您的用户名 手动管理可用性 - 在编辑状态消息时,设置您的可用性,指示您的在线状态。 - 状态消息 - 有空聊天 - 在线 - 离开 - 没空 - 忙碌 - 已生成一个安全密码 + 在编辑状态信息时,设置您的可用性,指示您的在线状态。 + 状态信息 + 和我聊天吧 + 在线中 + 暂时离开 + 离开很久 + 请勿打扰 + 安全密码已生成 您的设备不支持选择退出电池优化 - 注册失败:稍后再试 - 注册失败:密码太弱 + 注册失败: 稍后再试 + 注册失败: 密码太弱 选择参与者 - 正在创建群组聊天… + 正在创建群聊… 再次邀请 禁用 @@ -600,7 +600,7 @@ 电脑 手机 平板 - 浏览器 + Web 浏览器 控制台 需要付款 授予使用互联网的权限 @@ -613,9 +613,9 @@ 无法更新账号 举报此 XMPP 地址发送垃圾消息。 删除 OMEMO 身份 - 重新生成您的 OMEMO 密钥。您的所有联系人将不得不再次验证您的身份。只有在万不得已的情况下才会使用这种方法。 - 删除选定的密钥 - 您需要连接到网络才能发布您的头像。 + 重新生成您的 OMEMO 密钥。您的所有联系人将必须再次验证您。只有在万不得已的情况下才这样做。 + 删除所选的密钥 + 需要连接到网络才能发布头像。 显示出错消息 出错消息 省流量模式已启用 @@ -629,7 +629,7 @@ 二维码中不包含此对话的指纹。 已验证的指纹 使用相机扫描联系人的二维码 - 请稍候获取密钥 + 正在获取密钥,请稍候 分享为二维码 分享为 XMPP URI 分享为 HTTP 链接 @@ -642,16 +642,16 @@ 清理缓存 清理私人存储空间 清理保存文件的私人存储(它们可以从服务器重新下载) - 我从一个可信来源收到此链接 - 点击链接后,您即将验证 %1$s 的 OMEMO 密钥。只有当您从一个可信来源(只有 %2$s 可以发布此链接)收到此链接时,这才是安全的。 - 您即将验证您自己账号的 OMEMO 密钥。只有当您从一个可信来源(只有您可以发布此链接)收到此链接时,这才是安全的。 + 我从可信来源收到此链接 + 点击链接后,您将验证 %1$s 的 OMEMO 密钥。只有当您从可信来源(只有 %2$s 可以发布此链接)收到此链接时,这才是安全的。 + 您将验证自己账号的 OMEMO 密钥。只有当您从可信来源(只有您可以发布此链接)收到此链接时,这才是安全的。 继续 验证 OMEMO 密钥 - 显示不活跃设备 - 隐藏不活跃设备 + 显示不活跃的设备 + 隐藏不活跃的设备 不再信任设备 - 您确定要移除此设备的验证吗? -\n此设备和来自它的消息将会被标记为“不信任的”。 + 是否移除此设备的验证? +\n此设备和来自它的消息将会标记为“不信任的”。 %d 秒 @@ -694,41 +694,41 @@ 今天 昨天 通过 DNSSEC 验证主机名 - 包含主机名的服务器证书被认为是已验证的 + 将包含主机名的服务器证书视为是已验证的 证书不包含 XMPP 地址 部分的 录制视频 复制到剪贴板 消息已复制到剪贴板 消息 - 私人消息被禁用 + 已禁用私人消息 受保护的应用程序 为了继续接收通知,即使在屏幕关闭的情况下也是如此,您需要将 Conversations 加入受保护的应用程序列表。 是否接受未知证书? 此服务器证书不是由已知的证书颁发机构签发的。 是否接受不匹配的服务器名称? 由于“%s”,服务器无法验证。证书仅对此有效: - 您仍要连接吗? + 是否仍要连接? 证书详情: 仅一次 二维码扫描器需要访问相机 滚动至底部 发送消息后向下滚屏 - 编辑状态消息 - 编辑状态消息 + 编辑状态信息 + 编辑状态信息 禁用加密 %1$s 无法发送加密消息到 %2$s。这可能是因为您的联系人使用了过时的服务器或者无法处理 OMEMO 的客户端。 无法获取设备列表 无法获取密钥 提示:某些情况下,可以通过双方添加到联系人列表中来解决此问题。 - 您确定要禁用此对话的 OMEMO 加密吗? + 是否禁用此对话的 OMEMO 加密? \n这将允许服务器管理员阅读您的消息,但这可能是与使用过时客户端的用户进行交流的唯一方法。 立即禁用 草稿: OMEMO 加密 - OMEMO 将始终用于一对一和私人群组聊天。 - 默认情况下,新对话将使用 OMEMO。 - 对于新对话,必须明确地打开 OMEMO。 + OMEMO 加密将始终用于一对一和私人群组聊天。 + 默认情况下,新对话将使用 OMEMO 加密。 + 对于新对话,必须明确地打开 OMEMO 加密。 创建快捷方式 字体大小 应用程序中使用的相对字体大小。 @@ -762,15 +762,15 @@ 用于 S3 的 HTTP 文件分享 直接搜索 在“开始对话”屏幕上打开键盘并将光标放在搜索栏中 - 群组聊天头像 - 主机不支持群组聊天头像 - 只有所有者才能更改群组聊天头像 + 群聊头像 + 主机不支持群聊头像 + 只有所有者才能更改群聊头像 联系人名称 昵称 名称 提供名称是可选的 - 群组聊天名称 - 此群组聊天已被解散 + 群聊名称 + 此群聊已解散 无法保存录制 前台服务 此通知类别用于显示永久通知,表明 %1$s 正在运行。 @@ -793,11 +793,11 @@ 查看媒体文件 参与者 媒体浏览器 - 文件由于违反安全规定被删除。 + 由于违反安全规定,文件已删除。 视频质量 质量越低,文件越小 - 中(360p) - 高(720p) + 中 (360p) + 高 (720p) 已取消 您已经在起草一条消息了。 功能未实现 @@ -806,7 +806,7 @@ 电话号码 验证您的电话号码 Quicksy 将发送短信(运营商可能收费)来验证您的电话号码。请输入您的国家/地区代码和电话号码: - 我们将验证这个电话号码

%s

,这样可以吗?或者您想编辑这个号码?
+ 我们将验证这个电话号码

%s

可以吗?还是要编辑号码?
%s 不是有效的电话号码。 请输入您的电话号码。 搜索国家/地区 @@ -820,7 +820,7 @@ 返回 已自动从剪贴板粘贴可能的 PIN 码。 请输入您的 6 位数 PIN 码。 - 您确定要中止注册程序吗? + 是否中止注册程序? 正在验证… @@ -834,15 +834,15 @@ 无法找到服务器。 处理您的请求时出了问题。 用户输入无效 - 暂时不可用。请稍后再试。 + 暂时不可用。稍后再试。 无网络连接。 请在 %s 后重试 - 您被限制速率 + 您的速率受到限制 尝试次数过多 您正在使用此应用程序的过时版本。 更新 此电话号码目前已在另一台设备上登录。 - 请输入您的名称,以便让通讯录中没有您的人知道您是谁。 + 请输入名称,以便让通讯录中没有您的人知道您是谁。 您的名称 输入您的名称 使用编辑按钮设置您的名称。 @@ -858,21 +858,21 @@ 选择账号 恢复备份 恢复 - 请输入您的 %s 账号的密码以恢复备份。 + 输入 %s 账号的密码以恢复备份。 请勿使用恢复备份功能尝试克隆(同时运行)安装。恢复备份仅适用于迁移或您丢失原始设备的情况。 无法恢复备份。 无法解密备份。密码是否正确? 备份 & 恢复 输入 XMPP 地址 - 创建群组聊天 + 创建群聊 加入公开频道 - 创建私人群组聊天 + 创建私人群聊 创建公开频道 频道名称 XMPP 地址 请提供频道名 请提供 XMPP 地址 - 这是一个 XMPP 地址。请提供一个名称。 + 这是 XMPP 地址。请提供名称。 正在创建公开频道… 此频道已存在 您已加入现有频道 @@ -887,7 +887,7 @@ XMPP 地址对管理员可见。 XMPP 地址对任何人可见。 此公开频道无参与者。邀请您的联系人或使用分享按钮分发其 XMPP 地址。 - 此私人群组聊天无参与者。 + 此私人群聊无参与者。 管理权限 搜索参与者 文件太大 @@ -898,32 +898,32 @@ 我已有账号 添加已有账号 注册新账号 - 这看起来像一个域名地址 + 这看起来像是域名地址 无论如何都要添加 - 这看起来像一个频道地址 + 这看起来像是频道地址 分享备份文件 Conversations 备份 事件 打开备份 - 您所选的文件不是一个 Conversations 备份文件 + 您所选的文件不是 Conversations 备份文件 此账号已完成设置 请输入此账号的密码 无法执行此操作 加入公开频道… 分享应用程序未授予访问此文件的权限。 - 群组聊天 & 频道 + 群聊 & 频道 jabber.network 本地服务器 大多数用户应该选择“jabber.network”以便从整个公共 XMPP 生态系统中获得更好的建议。 频道发现方法 备份 关于 - 请启用一个账号 + 请启用账号 进行通话 来电 视频来电 - 切换到视频通话? - 添加额外轨道? + 是否切换到视频通话? + 是否添加额外轨道? 正在连接 已连接 正在重新连接 @@ -963,7 +963,7 @@ 帮助 切换到对话 您的麦克风不可用 - 您每次只能拨打一个电话。 + 一次只能打一通电话。 返回到正在进行的通话 无法切换摄像头 置顶 @@ -981,7 +981,7 @@ 录制语音留言 播放音频 暂停音频 - 添加联系人、创建或加入群组聊天、或发现频道 + 添加联系人、创建或加入群聊、或发现频道 查看 %1$d 位参与者 @@ -995,14 +995,14 @@ 无法解析邀请 服务器不支持生成邀请 没有活跃账号支持此功能 - 备份已开始。完成后您会收到通知。 + 备份已开始。一旦完成,您将会收到通知。 无法启用视频。 纯文本文档 不支持账号注册 未找到 XMPP 地址 验证暂时失败 删除头像 - 使用 Tor 时通话被禁用 + 使用 Tor 时,已禁用通话 切换到视频 拒绝视频切换请求 XMPP 账号 @@ -1017,9 +1017,9 @@ 去电 · %s 频道发现使用称为 <a href=https://search.jabber.network>search.jabber.network</a> 的第三方服务。<br><br>使用此功能会将您的 IP 地址和搜索词传输到此服务。请参阅他们的 <a href=https://search.jabber.network/privacy>隐私政策</a> 以获取更多信息。 无法从服务器删除账号 - 群组聊天 - 保存为群组聊天 - 搜索群组聊天 + 群聊 + 保存为群聊 + 搜索群聊 从服务器移除账号 请勿尝试恢复您尚未自行创建的备份! 您正尝试导入过时的备份文件格式 From 39465a9f72aaac98b259d0ab5c0432cdbbb3ec24 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Fri, 20 Oct 2023 23:37:32 +0000 Subject: [PATCH 230/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (13 of 13 strings) Translation: Conversations/Android App (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-conversations/zh_Hans/ --- .../res/values-zh-rCN/strings.xml | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/conversations/res/values-zh-rCN/strings.xml b/src/conversations/res/values-zh-rCN/strings.xml index 0f3ecc4a0..09929cb2c 100644 --- a/src/conversations/res/values-zh-rCN/strings.xml +++ b/src/conversations/res/values-zh-rCN/strings.xml @@ -3,18 +3,18 @@ 选择您的 XMPP 提供者 使用 conversations.im 创建新账号 - 您已经有一个 XMPP 账号了吗?如果您已经在使用一个不同的 XMPP 客户端或者以前使用过 Conversations,那么您已经拥有这种账号了。如果没有的话,您现在可以创建一个新的 XMPP 账号。 -\n提示:一些电子邮件提供者也提供 XMPP 账号。 - XMPP 是一个独立于提供者的即时通讯网络。您可以将此客户端与您选择的任何 XMPP 服务器一起使用。 -\n不过,为了您的方便,我们让您可以轻松地在 conversations.im 上创建一个账号;一个特别适合与 Conversations 一起使用的提供者。 + 您已经有 XMPP 账号了吗?如果您已经在使用不同的 XMPP 客户端或者之前使用过 Conversations,那么您已经拥有这种账号了。如果没有的话,您可以立即创建一个。 +\n提示:一些电子邮件服务也提供 XMPP 账号。 + XMPP 是独立于提供者的即时通讯网络。您可以将此客户端与您选择的任何 XMPP 服务器一起使用。 +\n不过,您可以轻松地在 conversations.im 上创建账号;它特别适合与 Conversations 一起使用。 您已受邀加入 %1$s。我们将指导您完成创建账号的过程。 -\n当选择 %1$s 作为提供者时,通过向其他提供者的用户提供您的完整 XMPP 地址,您将能够与他们进行交流。 - 您已受邀加入 %1$s。已为您选择了一个用户名。我们将指导您完成创建账号的过程。 -\n通过向其他提供者的用户提供您的完整 XMPP 地址,您将能够与他们进行交流。 +\n当选择 %1$s 作为提供者时,通过向其他 XMPP 用户提供您的完整地址,就能和他们交流。
+ 您已受邀加入 %1$s。已经为您选择了用户名。我们将指导您完成创建账号的过程。 +\n通过向其他 XMPP 用户提供您的完整地址,就能和他们交流。 您的服务器邀请 - 配置代码格式不当 - 点击分享按钮向您的联系人发送加入 %1$s 的邀请。 - 如果您的联系人在附近,他们也可以扫描下方二维码来接受您的邀请。 + 配置代码格式不正确 + 点击分享按钮,向您的联系人发送加入 %1$s 的邀请。 + 如果您的联系人在附近,他们也可以扫描下方二维码接受您的邀请。 加入 %1$s 和我聊天:%2$s 分享邀请至…
\ No newline at end of file From 0ae15f3482dccf8ea2b83e4c8de7513e864ae1ad Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Sat, 21 Oct 2023 00:20:28 +0000 Subject: [PATCH 231/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (9 of 9 strings) Translation: Conversations/Android App (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-quicksy/zh_Hans/ --- src/quicksy/res/values-zh-rCN/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quicksy/res/values-zh-rCN/strings.xml b/src/quicksy/res/values-zh-rCN/strings.xml index 648119c1c..1a17048d8 100644 --- a/src/quicksy/res/values-zh-rCN/strings.xml +++ b/src/quicksy/res/values-zh-rCN/strings.xml @@ -7,6 +7,6 @@ Quicksy 个人资料图片 Quicksy 在您所在的国家/地区无法使用。 无法验证服务器身份。 - 未知安全错误。 + 未知的安全错误。 连接到服务器时超时。 \ No newline at end of file From 3239a986773592343d22800519306cf5159be1bc Mon Sep 17 00:00:00 2001 From: random_r Date: Fri, 20 Oct 2023 15:48:31 +0000 Subject: [PATCH 232/402] Translated using Weblate (Italian) Currently translated at 100.0% (52 of 52 strings) Translation: Conversations/App Store Metadata (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/it/ --- fastlane/metadata/android/it-IT/changelogs/42074.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 fastlane/metadata/android/it-IT/changelogs/42074.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/42074.txt b/fastlane/metadata/android/it-IT/changelogs/42074.txt new file mode 100644 index 000000000..675715118 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42074.txt @@ -0,0 +1,3 @@ +* Supporto per DNS Privato (DNS over TLS) +* Supporto per icona del launcher a tema +* Risolto un raro problema di autorizzazione durante la condivisione di file su Android 11+ From 1fda935463fe13c041dcad9dad1ad73ef1e3c1ea Mon Sep 17 00:00:00 2001 From: nautilusx Date: Fri, 20 Oct 2023 08:51:05 +0000 Subject: [PATCH 233/402] Translated using Weblate (German) Currently translated at 100.0% (52 of 52 strings) Translation: Conversations/App Store Metadata (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/de/ --- fastlane/metadata/android/de-DE/changelogs/42074.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 fastlane/metadata/android/de-DE/changelogs/42074.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/42074.txt b/fastlane/metadata/android/de-DE/changelogs/42074.txt new file mode 100644 index 000000000..ad343db66 --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/42074.txt @@ -0,0 +1,3 @@ +* Unterstützung von Private DNS (DNS über TLS) +* Unterstützung für designbasiertes Startsymbol +* Behebt ein seltenes Berechtigungsproblem beim Teilen von Dateien unter Android 11+ From 15dd4b75a1cc3a2da9f90df844adab0f41077011 Mon Sep 17 00:00:00 2001 From: ghose Date: Fri, 20 Oct 2023 06:34:24 +0000 Subject: [PATCH 234/402] Translated using Weblate (Galician) Currently translated at 30.7% (16 of 52 strings) Translation: Conversations/App Store Metadata (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/gl/ --- fastlane/metadata/android/gl-ES/changelogs/42074.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 fastlane/metadata/android/gl-ES/changelogs/42074.txt diff --git a/fastlane/metadata/android/gl-ES/changelogs/42074.txt b/fastlane/metadata/android/gl-ES/changelogs/42074.txt new file mode 100644 index 000000000..6729e251d --- /dev/null +++ b/fastlane/metadata/android/gl-ES/changelogs/42074.txt @@ -0,0 +1,3 @@ +* Soport para DNS Privado (DNS sobre TLS) +* Soporte para personalizar a icona de inicio +* Arranxamos un raro problema de permisos ao compartir ficheiros en Android 11+ From b36e4822876fdc24588fd80e143469eb92e4b414 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Fri, 20 Oct 2023 08:56:31 +0000 Subject: [PATCH 235/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (2 of 2 strings) Translation: Conversations/App Store Metadata (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata-conversations/zh_Hans/ --- .../metadata/android/zh-CN/full_description.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt b/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt index b9bcb2bc9..8296d6e2d 100644 --- a/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt +++ b/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt @@ -3,32 +3,32 @@ 设计原则: * 在不牺牲安全性和隐私性的前提下,尽可能美观易用 -* 依托现有的、成熟的协议 -* 不需要 Google 账号或特定的 Google 云通讯服务(GCM) +* 依赖现有的、成熟的协议 +* 不需要 Google 账号或特定的 Google 云通讯服务 (GCM) * 要求尽可能少的权限 特点: * 使用 OMEMOOpenPGP 进行端对端加密 * 发送和接收图片 -* 加密音视频通话(DTLS-SRTP) +* 加密音视频通话 (DTLS-SRTP) * 直观的用户界面,遵循 Android 设计准则 -* 为您的联系人添加图片 / 头像 +* 为您的联系人添加图片/头像 * 与桌面客户端同步 -* 群聊(支持书签功能) +* 群聊(支持书签功能) * 通讯录集成 -* 多账号 / 统一收件箱 +* 多账号/统一收件箱 * 对电池寿命的影响非常小 Conversations 使在免费的 conversations.im 服务器上创建账号变得非常简单。不过,Conversations 也适用于任何其他 XMPP 服务器。许多 XMPP 服务器都是由志愿者免费运行的。 XMPP 功能: -Conversations 适用于所有 XMPP 服务器。然而,XMPP是一种可扩展的协议。这些扩展在所谓的 XEP 中也是标准化的。Conversations 支持其中的一些扩展,以使整体用户体验更好。有一种可能是您当前的 XMPP 服务器不支持这些扩展。因此,要想充分使用 Conversations 的功能,您应该考虑切换到支持这些扩展的 XMPP 服务器,甚至有更好的方式,或者为您和您的朋友运行自己的 XMPP 服务器。 +Conversations 适用于所有 XMPP 服务器。然而,XMPP 是一种可扩展的协议。这些扩展在所谓的 XEP 中也是标准化的。Conversations 支持其中的一些扩展,以使整体用户体验更好。有一种可能是您当前的 XMPP 服务器不支持这些扩展。因此,要想充分使用 Conversations 的功能,您应该考虑切换到支持这些扩展的 XMPP 服务器,甚至有更好的方式,或者为您和您的朋友运行自己的 XMPP 服务器。 到目前为止,这些 XEP 是: -* XEP-0065:SOCKS5 字节流(or mod_proxy65)。如果双方都在防火墙(NAT)后面,将用于传输文件。 +* XEP-0065:SOCKS5 字节流 (or mod_proxy65)。如果双方都在防火墙 (NAT) 后面,将用于传输文件。 * XEP-0163:个人事件协议对于头像 * XEP-0191:屏蔽指令可让您将垃圾邮件发送者列入黑名单或屏蔽的联系人中,而不会将其从花名册中删除。 * XEP-0198:流管理允许 XMPP 在小规模网络中断和底层 TCP 连接发生变化时继续运行。 From 2ea01c0be1ad57f88730a98fc3fb429869bf814b Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Fri, 20 Oct 2023 07:36:14 +0000 Subject: [PATCH 236/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (52 of 52 strings) Translation: Conversations/App Store Metadata (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/zh_Hans/ --- fastlane/metadata/android/zh-CN/changelogs/42074.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42074.txt diff --git a/fastlane/metadata/android/zh-CN/changelogs/42074.txt b/fastlane/metadata/android/zh-CN/changelogs/42074.txt new file mode 100644 index 000000000..12acff938 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42074.txt @@ -0,0 +1,3 @@ +* 支持私人 DNS(DNS over TLS) +* 支持主题启动器图标 +* 修复在 Android 11+ 分享文件时罕见的权限问题 From 89c59909b5de366602090297c8204754bf852ab1 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Fri, 20 Oct 2023 08:58:36 +0000 Subject: [PATCH 237/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (2 of 2 strings) Translation: Conversations/App Store Metadata (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata-quicksy/zh_Hans/ --- .../fastlane/metadata/android/zh-CN/full_description.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/quicksy/fastlane/metadata/android/zh-CN/full_description.txt b/src/quicksy/fastlane/metadata/android/zh-CN/full_description.txt index 4f154352f..a8aa68753 100644 --- a/src/quicksy/fastlane/metadata/android/zh-CN/full_description.txt +++ b/src/quicksy/fastlane/metadata/android/zh-CN/full_description.txt @@ -6,9 +6,9 @@ Quicksy 是一个流行的 Jabber/XMPP 客户端 Conversations 的衍生品, 除了联系人同步之外,用户界面尽可能地接近 Conversations。这使得用户最终可以从 Quicksy 迁移到 Conversations,而无需重新了解应用程序的工作方式。 -建议的联系人包括其他 Quicksy 用户和在 Quicksy 目录中输入 Jabber ID 的普通 Jabber/XMPP 用户(https://quicksy.im/#get-listed)。 +建议的联系人包括其他 Quicksy 用户和在 Quicksy 目录中输入 Jabber ID 的普通 Jabber/XMPP 用户 (https://quicksy.im/#get-listed)。 -注意:要在 Quicksy 中输入(https://quicksy.im/enter/)您的 Jabber ID +注意:要在 Quicksy 中输入 (https://quicksy.im/enter/) 您的 Jabber ID 目录一次性注册费用是必需的。 -请阅读隐私政策(https://quicksy.im/#privacy),了解更多信息。 +请阅读隐私政策 (https://quicksy.im/#privacy) ,了解更多信息。 From 68eb17d4003c20a2efcae2c279ae1dfcec73f6a0 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 23 Oct 2023 11:21:42 +0200 Subject: [PATCH 238/402] create missed call notification when device is busy --- .../services/NotificationService.java | 24 ++++++++++++++ .../xmpp/jingle/JingleConnectionManager.java | 32 ++++++++++++++++--- 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java index 44d21bed6..ce3f43857 100644 --- a/src/main/java/eu/siacs/conversations/services/NotificationService.java +++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java @@ -773,6 +773,25 @@ public class NotificationService { } } + public void clearMissedCall(final Message message) { + synchronized (mMissedCalls) { + final Iterator> iterator = mMissedCalls.entrySet().iterator(); + while (iterator.hasNext()) { + final Map.Entry entry = iterator.next(); + final Conversational conversational = entry.getKey(); + final MissedCallsInfo missedCallsInfo = entry.getValue(); + if (conversational.getUuid().equals(message.getConversation().getUuid())) { + if (missedCallsInfo.removeMissedCall()) { + cancel(conversational.getUuid(), MISSED_CALL_NOTIFICATION_ID); + Log.d(Config.LOGTAG,conversational.getAccount().getJid().asBareJid()+": dismissed missed call because call was picked up on other device"); + iterator.remove(); + } + } + } + updateMissedCallNotifications(null); + } + } + public void clearMissedCalls() { synchronized (mMissedCalls) { for (final Conversational conversation : mMissedCalls.keySet()) { @@ -1943,6 +1962,11 @@ public class NotificationService { lastTime = time; } + public boolean removeMissedCall() { + --numberOfCalls; + return numberOfCalls <= 0; + } + public int getNumberOfCalls() { return numberOfCalls; } diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java index 1a55b9a96..6f044cb56 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java @@ -100,7 +100,8 @@ public class JingleConnectionManager extends AbstractConnectionManager { this.terminatedSessions.asMap().containsKey(PersistableSessionId.of(id)); final boolean stranger = isWithStrangerAndStrangerNotificationsAreOff(account, id.with); - if (isBusy() || sessionEnded || stranger) { + final boolean busy = isBusy(); + if (busy || sessionEnded || stranger) { Log.d( Config.LOGTAG, id.account.getJid().asBareJid() @@ -117,6 +118,15 @@ public class JingleConnectionManager extends AbstractConnectionManager { sessionTermination.setTo(id.with); sessionTermination.setReason(Reason.BUSY, null); mXmppConnectionService.sendIqPacket(account, sessionTermination, null); + if (busy || stranger) { + writeLogMissedIncoming( + account, + id.with, + id.sessionId, + null, + System.currentTimeMillis(), + stranger); + } return; } connection = new JingleRtpConnection(this, id, from); @@ -329,6 +339,7 @@ public class JingleConnectionManager extends AbstractConnectionManager { Config.LOGTAG, id.account.getJid().asBareJid() + ": updated previous busy because call got picked up by another device"); + mXmppConnectionService.getNotificationService().clearMissedCall(previousBusy); return; } } @@ -400,7 +411,12 @@ public class JingleConnectionManager extends AbstractConnectionManager { isWithStrangerAndStrangerNotificationsAreOff(account, id.with); if (isBusy() || stranger) { writeLogMissedIncoming( - account, id.with.asBareJid(), id.sessionId, serverMsgId, timestamp); + account, + id.with.asBareJid(), + id.sessionId, + serverMsgId, + timestamp, + stranger); if (stranger) { Log.d( Config.LOGTAG, @@ -544,10 +560,11 @@ public class JingleConnectionManager extends AbstractConnectionManager { private void writeLogMissedIncoming( final Account account, - Jid with, + final Jid with, final String sessionId, - String serverMsgId, - long timestamp) { + final String serverMsgId, + final long timestamp, + final boolean stranger) { final Conversation conversation = mXmppConnectionService.findOrCreateConversation( account, with.asBareJid(), false, false); @@ -557,7 +574,12 @@ public class JingleConnectionManager extends AbstractConnectionManager { message.setBody(new RtpSessionStatus(false, 0).toString()); message.setServerMsgId(serverMsgId); message.setTime(timestamp); + message.setCounterpart(with); writeMessage(message); + if (stranger) { + return; + } + mXmppConnectionService.getNotificationService().pushMissedCallNow(message); } private void writeMessage(final Message message) { From 55a77c083fee51b12baf62156e19e01eb7120e2a Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 23 Oct 2023 14:40:40 +0200 Subject: [PATCH 239/402] store SSLSocket after starttls to fix channel binding mechanism detection --- .../eu/siacs/conversations/xmpp/XmppConnection.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 7ba266794..402cd1ba2 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -1260,8 +1260,9 @@ public class XmppConnection implements Runnable { tagReader.readTag(); final Socket socket = this.socket; final SSLSocket sslSocket = upgradeSocketToTls(socket); - tagReader.setInputStream(sslSocket.getInputStream()); - tagWriter.setOutputStream(sslSocket.getOutputStream()); + this.socket = sslSocket; + this.tagReader.setInputStream(sslSocket.getInputStream()); + this.tagWriter.setOutputStream(sslSocket.getOutputStream()); Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": TLS connection established"); final boolean quickStart; try { @@ -2218,9 +2219,13 @@ public class XmppConnection implements Runnable { private boolean establishStream(final SSLSockets.Version sslVersion) throws IOException, InterruptedException { - final SaslMechanism quickStartMechanism = - SaslMechanism.ensureAvailable(account.getQuickStartMechanism(), sslVersion); final boolean secureConnection = sslVersion != SSLSockets.Version.NONE; + final SaslMechanism quickStartMechanism; + if (secureConnection) { + quickStartMechanism = SaslMechanism.ensureAvailable(account.getQuickStartMechanism(), sslVersion); + } else { + quickStartMechanism = null; + } if (secureConnection && Config.QUICKSTART_ENABLED && quickStartMechanism != null From 97acd164229a933496fad457741d11afe8a18ac2 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 24 Oct 2023 18:53:14 +0200 Subject: [PATCH 240/402] keep cache of DNS messages --- .../de/gultsch/minidns/AndroidDNSClient.java | 80 ++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/gultsch/minidns/AndroidDNSClient.java b/src/main/java/de/gultsch/minidns/AndroidDNSClient.java index 194ad23bd..d47430339 100644 --- a/src/main/java/de/gultsch/minidns/AndroidDNSClient.java +++ b/src/main/java/de/gultsch/minidns/AndroidDNSClient.java @@ -5,18 +5,30 @@ import android.net.ConnectivityManager; import android.net.LinkProperties; import android.net.Network; import android.os.Build; +import android.util.Log; +import androidx.collection.LruCache; + +import com.google.common.base.Objects; import com.google.common.base.Strings; +import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import de.measite.minidns.AbstractDNSClient; import de.measite.minidns.DNSMessage; +import eu.siacs.conversations.Config; + import java.io.IOException; import java.net.InetAddress; +import java.time.Duration; +import java.util.Collections; import java.util.List; public class AndroidDNSClient extends AbstractDNSClient { + + private static final LruCache QUERY_CACHE = + new LruCache<>(1024); private final Context context; private final NetworkDataSource networkDataSource = new NetworkDataSource(); private boolean askForDnssec = false; @@ -56,6 +68,8 @@ public class AndroidDNSClient extends AbstractDNSClient { protected DNSMessage query(final DNSMessage.Builder queryBuilder) throws IOException { final DNSMessage question = newQuestion(queryBuilder).build(); for (final DNSServer dnsServer : getDNSServers()) { + final QuestionServerTuple cacheKey = new QuestionServerTuple(dnsServer, question); + final DNSMessage cachedResponse = queryCache(cacheKey); final DNSMessage response = this.networkDataSource.query(question, dnsServer); if (response == null) { continue; @@ -67,7 +81,7 @@ public class AndroidDNSClient extends AbstractDNSClient { default: continue; } - + cacheQuery(cacheKey, response); return response; } return null; @@ -120,4 +134,68 @@ public class AndroidDNSClient extends AbstractDNSClient { } return connectivityManager.getAllNetworks(); } + + private DNSMessage queryCache(final QuestionServerTuple key) { + final DNSMessage cachedResponse; + synchronized (QUERY_CACHE) { + cachedResponse = QUERY_CACHE.get(key); + if (cachedResponse == null) { + return null; + } + final long expiresIn = expiresIn(cachedResponse); + if (expiresIn < 0) { + QUERY_CACHE.remove(key); + return null; + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + Log.d( + Config.LOGTAG, + "DNS query came from cache. expires in " + Duration.ofMillis(expiresIn)); + } + } + return cachedResponse; + } + + private void cacheQuery(final QuestionServerTuple key, final DNSMessage response) { + if (response.receiveTimestamp <= 0) { + return; + } + synchronized (QUERY_CACHE) { + QUERY_CACHE.put(key, response); + } + } + + private static long expiresAt(final DNSMessage dnsMessage) { + return dnsMessage.receiveTimestamp + + (Collections.min(Collections2.transform(dnsMessage.answerSection, d -> d.ttl)) + * 1000L); + } + + private static long expiresIn(final DNSMessage dnsMessage) { + return expiresAt(dnsMessage) - System.currentTimeMillis(); + } + + private static class QuestionServerTuple { + private final DNSServer dnsServer; + private final DNSMessage question; + + private QuestionServerTuple(final DNSServer dnsServer, final DNSMessage question) { + this.dnsServer = dnsServer; + this.question = question.asNormalizedVersion(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + QuestionServerTuple that = (QuestionServerTuple) o; + return Objects.equal(dnsServer, that.dnsServer) + && Objects.equal(question, that.question); + } + + @Override + public int hashCode() { + return Objects.hashCode(dnsServer, question); + } + } } From 1da9d42065d712ca68d44a0386f8477181ac103c Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 24 Oct 2023 19:16:47 +0200 Subject: [PATCH 241/402] retrieve DNS response from cache --- src/main/java/de/gultsch/minidns/AndroidDNSClient.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/de/gultsch/minidns/AndroidDNSClient.java b/src/main/java/de/gultsch/minidns/AndroidDNSClient.java index d47430339..047799815 100644 --- a/src/main/java/de/gultsch/minidns/AndroidDNSClient.java +++ b/src/main/java/de/gultsch/minidns/AndroidDNSClient.java @@ -70,6 +70,9 @@ public class AndroidDNSClient extends AbstractDNSClient { for (final DNSServer dnsServer : getDNSServers()) { final QuestionServerTuple cacheKey = new QuestionServerTuple(dnsServer, question); final DNSMessage cachedResponse = queryCache(cacheKey); + if (cachedResponse != null) { + return cachedResponse; + } final DNSMessage response = this.networkDataSource.query(question, dnsServer); if (response == null) { continue; From 6d519cd447614f9b2ae24806c4dc0a0221aa3e17 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 24 Oct 2023 21:05:35 +0200 Subject: [PATCH 242/402] pick proper TTL for non existent DNS entries --- .../de/gultsch/minidns/AndroidDNSClient.java | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/main/java/de/gultsch/minidns/AndroidDNSClient.java b/src/main/java/de/gultsch/minidns/AndroidDNSClient.java index 047799815..2c3731871 100644 --- a/src/main/java/de/gultsch/minidns/AndroidDNSClient.java +++ b/src/main/java/de/gultsch/minidns/AndroidDNSClient.java @@ -16,6 +16,8 @@ import com.google.common.collect.ImmutableList; import de.measite.minidns.AbstractDNSClient; import de.measite.minidns.DNSMessage; +import de.measite.minidns.Record; +import de.measite.minidns.record.Data; import eu.siacs.conversations.Config; @@ -27,6 +29,8 @@ import java.util.List; public class AndroidDNSClient extends AbstractDNSClient { + private static final long DNS_MAX_TTL = 86_400L; + private static final LruCache QUERY_CACHE = new LruCache<>(1024); private final Context context; @@ -168,10 +172,23 @@ public class AndroidDNSClient extends AbstractDNSClient { } } + private static long ttl(final DNSMessage dnsMessage) { + final List> answerSection = dnsMessage.answerSection; + if (answerSection == null || answerSection.isEmpty()) { + final List> authoritySection = dnsMessage.authoritySection; + if (authoritySection == null || authoritySection.isEmpty()) { + return 0; + } else { + return Collections.min(Collections2.transform(authoritySection, d -> d.ttl)); + } + + } else { + return Collections.min(Collections2.transform(answerSection, d -> d.ttl)); + } + } + private static long expiresAt(final DNSMessage dnsMessage) { - return dnsMessage.receiveTimestamp - + (Collections.min(Collections2.transform(dnsMessage.answerSection, d -> d.ttl)) - * 1000L); + return dnsMessage.receiveTimestamp + (Math.min(DNS_MAX_TTL, ttl(dnsMessage)) * 1000L); } private static long expiresIn(final DNSMessage dnsMessage) { From ce051e32b15003f1a172eaee7008829d5637ce7d Mon Sep 17 00:00:00 2001 From: SomeTr Date: Sun, 22 Oct 2023 08:52:07 +0000 Subject: [PATCH 243/402] Translated using Weblate (Ukrainian) Currently translated at 100.0% (970 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/uk/ --- src/main/res/values-uk/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/res/values-uk/strings.xml b/src/main/res/values-uk/strings.xml index a3044180f..6d4c194dc 100644 --- a/src/main/res/values-uk/strings.xml +++ b/src/main/res/values-uk/strings.xml @@ -828,7 +828,7 @@ Не знайдено застосунку для пошуку й встановлення нових застосунків. Цей канал опублікує Вашу адресу XMPP Електронна книга - Оригінал (не стиснений) + Оригінал (нестиснений) Відкрити… Зображення профілю для Conversations Виберіть обліковий запис @@ -977,7 +977,7 @@ Обліковий запис XMPP Пошук каналів використовує сторонній сервіс <a href=https://search.jabber.network>search.jabber.network</a>.<br><br>Використання цієї функції передає Вашу IP-адресу та пошукові запити цьому сервісу. Перегляньте їхню <a href=https://search.jabber.network/privacy>Політику конфіденційності</a>, щоб отримати більше інформації. Вихідний виклик · %s - %1$s використовує <b>OpenKeychain</b> для шифрування повідомлень і керування публічними ключами.<br><br>OpenKeychain поширюється на умовах ліцензії GPLv3+ і доступний для завантаження на F-Droid та Google Play.<br><br><small>(Після встановлення необхідно перезапустити %1$s.)</small> + %1$s використовує <b>OpenKeychain</b> для шифрування/дешифрування повідомлень і керування публічними ключами.<br><br>OpenKeychain поширюється на умовах ліцензії GPLv3+ і доступний для завантаження на F-Droid та Google Play.<br><br><small>(Після встановлення необхідно перезапустити %1$s.)</small> Додатково Не вдалося увімкнути відео. Жоден з активних облікових записів не підтримує цієї функції From 20b1cb2bd787b6a3d0dc80871c6474a577cc922b Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Tue, 24 Oct 2023 00:21:42 +0000 Subject: [PATCH 244/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (970 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 270 ++++++++++++------------- 1 file changed, 135 insertions(+), 135 deletions(-) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index 90f3a9325..153247ef8 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -42,14 +42,14 @@ 主持人 参与者 访客 - 是否从联系人列表中移除 %s?与此联系人的对话将不会移除。 - 是否屏蔽 %s 向您发送消息? - 是否解除屏蔽 %s 并允许他们向您发送消息? - 是否屏蔽来自 %s 的所有联系人? - 是否解除屏蔽来自 %s 的所有联系人? + 是否从联系人列表中移除 %s\? 将不会移除与对方的对话。 + 是否屏蔽 %s 向您发送消息\? + 是否解除屏蔽 %s 并允许对方向您发送消息\? + 屏蔽来自 %s 的所有联系人\? + 解除屏蔽来自 %s 的所有联系人\? 联系人已屏蔽 已屏蔽 - 是否从书签中移除 %s?与此书签相关的对话将不会移除。 + 是否从书签中移除 %s\? 将不会移除与此书签相关的对话。 在服务器上注册新账号 在服务器上修改密码 分享至… @@ -75,21 +75,21 @@ 无法连接到多个账号 点击即可管理账号 附加文件 - 此联系人不在您的联系人列表中,是否添加? + 对方不在您的联系人列表中,是否添加\? 添加联系人 传递失败 正在准备发送图片 正在准备发送图片 分享文件中。请稍候… - 清除历史记录 - 清除对话历史记录 - 是否删除此对话中的所有消息? + 清空历史记录 + 清空对话历史记录 + 是否要删除此对话中的所有消息\? \n -\n警告: 这将不会影响存储在其他设备或服务器上的消息。 +\n警告: 将不会影响存储在其他设备或服务器上的消息。 删除文件 - 是否删除此文件? + 是否确定要删除此文件\? \n -\n警告: 这将不会删除存储在其他设备或服务器上的此文件的副本。 +\n警告: 将不会删除存储在其他设备或服务器上的此文件的副本。 之后关闭此对话 选择设备 发送未加密的消息 @@ -109,13 +109,13 @@ 正在提供… 正在等待… 未找到 OpenPGP 密钥 - 无法加密消息,因为您的联系人未公布其公钥。 + 无法加密消息,因为对方未公布其公钥。 \n -\n请通知您的联系人设置 OpenPGP。 +\n请通知对方设置 OpenPGP。 未找到 OpenPGP 密钥 - 无法加密消息,因为您的联系人未公布其公钥。 + 无法加密消息,因为对方未公布其公钥。 \n -\n请通知您的联系人设置 OpenPGP。 +\n请通知对方设置 OpenPGP。 常规 接收文件 自动接收小于此大小的文件… @@ -129,15 +129,15 @@ 通知铃声 新消息的通知铃声 来电铃声 - 宽限期 - 在您的某个其他设备上检测到活动之后,通知会静音的时间长度。 + 通知宽限期 + 在您的某个其他设备上检测到活动之后,通知静音的时间长度。 高级 从不发送崩溃报告 - 通过发送堆栈跟踪,您正在帮助此应用程序的开发 + 通过发送堆栈跟踪,您正在帮助此应用的开发 确认消息 - 当您已收到并阅读了您的联系人的消息后,让他们知道 + 让对方知道您已收到并阅读了其消息 防止截屏 - 在应用程序切换器中隐藏应用程序内容并屏蔽屏幕截图 + 在应用切换器中隐藏应用内容并阻止屏幕截图 用户界面 OpenKeychain 出现了错误。 加密密钥错误。 @@ -150,15 +150,15 @@ 请求在线状态更新 选择图片 拍摄图片 - 预先同意订阅请求 + 预先同意状态请求 所选的文件不是图片 无法转换图片文件 文件未找到 - 常规 I/O 错误。也许存储空间已用完? - 用来选择此图片的应用程序没有提供足够的权限来读取文件。 + 常规 I/O 错误。也许存储空间已用完\? + 用来选择图片的应用没有提供读取文件的足够权限。 \n \n使用不同的文件管理器来选择图片 - 用来分享此文件的应用程序没有提供足够的权限。 + 用来分享此文件的应用没有提供足够的权限。 未知 暂时禁用 在线 @@ -188,11 +188,11 @@ 发布头像 发布 OpenPGP 公钥 移除 OpenPGP 公钥 - 是否从在线状态公布中移除您的 OpenPGP 公钥? -\n您的联系人将无法再向您发送 OpenPGP 加密消息。 + 是否确定要从在线状态公布中移除 OpenPGP 公钥\? +\n对方将无法再向您发送 OpenPGP 加密消息。 OpenPGP 公钥已发布。 启用账号 - 是否删除账号?删除账号会擦除您的全部对话历史记录 + 是否确定要删除账号\? 删除账号会擦除您的全部对话历史记录 录制语音 XMPP 地址 屏蔽 XMPP 地址 @@ -200,7 +200,7 @@ 密码 这不是有效的 XMPP 地址 空间不足。图片太大 - 是否添加 %s 到您的通讯录中? + 是否要添加 %s 到您的通讯录中\? 服务器信息 XEP-0313: 消息存档管理 XEP-0280: 消息抄送 @@ -212,8 +212,8 @@ XEP-0163: 个人事件协议(头像/OMEMO) XEP-0363: HTTP 文件上传 XEP-0357: 推送 - 可用的 - 不可用 + 有效 + 无效 缺少公钥公布 最后上线于刚才 最后上线于 1 分钟前 @@ -250,19 +250,19 @@ 删除书签 解散群聊 解散频道 - 是否解散此群聊? + 是否确定要解散此群聊\? \n -\n警告: 群聊将在服务器上完全移除。 - 是否解散此公开频道? +\n警告: 将在服务器上完全移除群聊。 + 是否确定要解散此公开频道\? \n -\n警告: 频道将在服务器上完全移除。 +\n警告: 将在服务器上完全移除频道。 无法解散群聊 无法解散频道 编辑群聊话题 话题 正在加入群聊… 离开 - 联系人已将您添加到联系人列表 + 对方已将您添加到联系人列表 添加对方 %s 已阅读至此 %s 已阅读至此 @@ -288,17 +288,17 @@ 启用 需要密码才能进入此群聊 输入密码 - 请先向您的联系人请求在线状态更新。 + 请先向对方请求在线状态更新。 \n -\n这将用于确定您的联系人正在使用的聊天应用程序 +\n这将用于确定对方正在使用的聊天应用 立即请求 忽略 警告: 在双方没有更新在线状态的情况下发送此消息将会出现未知问题。 \n -\n前往“联系人详情”以验证在线状态订阅。 +\n前往“联系人详情”以验证在线状态请求。 安全 允许消息更正 - 允许您的联系人发送后编辑其消息 + 允许对方发送后编辑其消息 专家设置 请谨慎设置这些 关于 %s @@ -306,10 +306,10 @@ 开始时间 结束时间 启用安静时间 - 在安静时间内,将会静音通知 + 通知将在安静时间静音 其他 同步书签 - 在进入或离开多用户聊天时设置 “autojoin\" 标志,并回应其他客户端所做的改变。 + 在进入或离开多用户聊天时设置“自动加入”标志,并回应其他客户端所做的改变。 OMEMO 指纹已复制到剪贴板 此群聊已将您封禁了 此群聊仅限成员参与 @@ -333,7 +333,7 @@ 已复制 URL 到剪贴板 已复制 XMPP 地址到剪贴板 已复制错误消息到剪贴板 - 网址 + web 地址 扫描二维码 显示二维码 显示屏蔽列表 @@ -344,11 +344,11 @@ 防止操作系统中断连接 创建备份 备份文件将存储在 %s - 创建备份文件中 - 备份已创建 + 正在创建备份文件 + 已创建备份 此备份文件已存储在 %s - 恢复备份中 - 备份已恢复 + 正在恢复备份 + 已恢复备份 不要忘记启用此账号。 选择文件 正在接收 %1$s (%2$d%% 已完成) @@ -363,9 +363,9 @@ 无法分享文件 文件传输已取消 文件已删除 - 未找到可以打开文件的应用程序 - 未找到可以打开链接的应用程序 - 未找到可以查看联系人的应用程序 + 未找到可以打开文件的应用 + 未找到可以打开链接的应用 + 未找到可以查看联系人的应用 动态标签 在联系人下方显示只读标签 启用通知 @@ -375,16 +375,16 @@ 复制 OMEMO 指纹到剪贴板 重新生成 OMEMO 密钥 清除设备 - 是否从 OMEMO 公布中清除所有其他设备?下次连接时,设备将会重新公布,但可能不会收到在此期间发送的消息。 - 此联系人没有可用的密钥。 -\n无法从服务器获取新密钥。也许是您的联系人的服务器出了问题? - 此联系人没有可用的密钥。 -\n确保双方都有在线状态订阅。 - 出了点问题 - 正在从服务器获取消息历史记录 - 服务器上没有更多消息历史记录 + 是否确定要从 OMEMO 公布中清除所有其他设备\? 下次连接时,设备将会重新公布,但可能不会收到在此期间发送的消息。 + 对方没有可用的密钥。 +\n无法从服务器获取新密钥。也许是对方的服务器出了问题\? + 对方没有可用的密钥。 +\n确保双方都请求在线状态。 + 出了问题 + 正在从服务器获取历史记录 + 服务器上没有更多历史记录 正在更新… - 密码已修改! + 密码已修改! 无法修改密码 修改密码 当前密码 @@ -418,7 +418,7 @@ 使 XMPP 地址对任何人可见 对频道进行审核 您没有参与 - 群聊选项修改成功! + 群聊选项修改成功! 无法修改群聊选项 从不 直至另行通知 @@ -436,9 +436,9 @@ 矢量图形 多媒体文件 PDF 文档 - Android 应用程序 + Android 应用 联系人 - 头像已发布! + 已发布头像! 正在发送 %s 正在提供 %s 隐藏离线的联系人 @@ -447,10 +447,10 @@ %s 正在输入… %s 已停止输入 输入通知 - 当您正在给您的联系人写消息时,让他们知道 + 让对方知道您正在输入 发送位置 显示位置 - 未找到可以显示位置的应用程序 + 未找到可以显示位置的应用 位置 对话已关闭 离开私人群聊 @@ -461,7 +461,7 @@ 删除手动批准的证书 没有手动批准的证书 移除证书 - 删除所选证书 + 删除所选 取消 %d 个证书已删除 @@ -482,17 +482,17 @@ 下载失败: 无法连接到主机 下载失败: 无法写入文件 下载失败: 无效文件 - Tor 网络不可用 + Tor 网络无法使用 绑定失败 服务器不能为域名做出响应 - 损坏的 - 可用性 + 损坏 + 在线状态 设备锁定时离开 - 当设备锁定时,在线状态显示为“暂时离开” + 当设备锁定时显示为“离开” 静音模式时忙碌 - 当设备处于静音模式时,在线状态显示为“请勿打扰” + 当设备处于静音模式时显示为“忙碌” 将振动模式视为静音模式 - 当设备处于振动模式时,在线状态显示为“请勿打扰” + 当设备处于振动模式时显示为“忙碌” 扩展连接设置 设置账号时显示主机名和端口设置 xmpp.example.com @@ -507,9 +507,9 @@ 不信任的证书链 XMPP 地址与证书不匹配 续订证书 - 获取 OMEMO 密钥时出错! - 已通过证书验证 OMEMO 密钥! - 您的设备不支持客户端证书选择! + 获取 OMEMO 密钥时出错! + 已通过证书验证 OMEMO 密钥! + 您的设备不支持客户端证书选择! 连接 通过 Tor 连接 通过 Tor 网络传输所有连接。需要 Orbot @@ -530,16 +530,16 @@ 授予 %1$s 访问外部存储的权限 授予 %1$s 访问相机的权限 与联系人同步 - %1$s 想要访问您的通讯录的权限来将它与您的 XMPP 联系人列表相匹配。 -\n这将会显示您的联系人的全名和头像。 + %1$s 想要访问通讯录权限来将它与您的 XMPP 联系人列表相匹配。 +\n这将会显示联系人的全名和头像。 \n -\n%1$s 将只会读取您的通讯录并在本地进行匹配,不会上传任何东西到您的服务器。 +\n%1$s 将只会读取您的通讯录并在本地进行匹配,不会上传任何东西到服务器。 通知所有消息 仅在提及时通知 通知已禁用 通知已暂停 图片压缩 - 提示:无论此设置如何,使用“选择文件”会发送未压缩的图片。 + 提示: 无论此设置如何,使用“选择文件”会发送未压缩的图片。 始终 仅限大图片 电池优化已启用 @@ -556,25 +556,25 @@ 发送更正后的消息 您已经安全地验证了此用户的指纹以确认信任。通过选择“完成”以确认 %s 加入群聊。 您已禁用了此账号 - 安全错误: 文件访问无效! - 未找到可以分享 URI 的应用程序 + 安全错误: 文件访问无效! + 未找到可以分享 URI 的应用 分享 URI 至… 同意并继续 在 conversations.im 上创建账号的指南已设置。 -\n当选择 conversations.im 作为提供者时,通过向其他提供者的用户提供您的完整 XMPP 地址,您将能够与他们进行交流。 +\n当选择 conversations.im 作为提供者时,通过向其他 XMPP 用户提供您的完整地址,就能和对方交流。
您的完整 XMPP 地址将是: %s 创建账号 使用我自己的提供者 选择您的用户名 - 手动管理可用性 - 在编辑状态信息时,设置您的可用性,指示您的在线状态。 + 手动更改在线状态 + 在编辑状态信息时,设置您的在线状态。 状态信息 - 和我聊天吧 - 在线中 - 暂时离开 - 离开很久 - 请勿打扰 - 安全密码已生成 + 有空聊天 + 在线 + 离开 + 没空 + 忙碌 + 已生成安全密码 您的设备不支持选择退出电池优化 注册失败: 稍后再试 注册失败: 密码太弱 @@ -586,7 +586,7 @@ 广播使用 - 当您使用 Conversations 时,让您的联系人知道 + 让您的联系人知道您何时使用 Conversations 隐私 主题 选择主题颜色 @@ -605,7 +605,7 @@ 需要付款 授予使用互联网的权限 - 联系人请求在线状态订阅 + 对方请求获取在线状态 允许 没有权限访问 %s 远程服务器未找到 @@ -613,13 +613,13 @@ 无法更新账号 举报此 XMPP 地址发送垃圾消息。 删除 OMEMO 身份 - 重新生成您的 OMEMO 密钥。您的所有联系人将必须再次验证您。只有在万不得已的情况下才这样做。 + 重新生成 OMEMO 密钥。您的所有联系人将必须再次验证您。只有在万不得已的情况下才这样做。 删除所选的密钥 需要连接到网络才能发布头像。 显示出错消息 出错消息 省流量模式已启用 - 您的操作系统正限制 %1$s 在后台时访问互联网。要接收新消息通知,您应当在“省流量模式”处于启用状态时允许 %1$s 不受限制的访问。 + 您的操作系统正限制 %1$s 在后台时访问互联网。要接收新消息通知,您应当在“省流量模式”开启时允许 %1$s 无限制访问。 \n%1$s 仍将在可能的情况下努力节省数据。 您的设备不支持对 %1$s 禁用省流量模式。 无法创建临时文件 @@ -650,8 +650,8 @@ 显示不活跃的设备 隐藏不活跃的设备 不再信任设备 - 是否移除此设备的验证? -\n此设备和来自它的消息将会标记为“不信任的”。 + 是否确定要移除此设备的验证\? +\n将此设备及其消息标记为“不信任的”。 %d 秒 @@ -688,7 +688,7 @@ 已降级的 SASL 机制 服务器要求在网站上注册 打开网站 - 未找到可以打开网站的应用程序 + 未找到可以打开网站的应用 顶部通知 显示顶部通知 今天 @@ -696,20 +696,20 @@ 通过 DNSSEC 验证主机名 将包含主机名的服务器证书视为是已验证的 证书不包含 XMPP 地址 - 部分的 + 部分 录制视频 复制到剪贴板 消息已复制到剪贴板 消息 已禁用私人消息 - 受保护的应用程序 - 为了继续接收通知,即使在屏幕关闭的情况下也是如此,您需要将 Conversations 加入受保护的应用程序列表。 - 是否接受未知证书? + 受保护的应用 + 为了在屏幕关闭时也能收到消息提醒,您需要将 Conversations 加入受保护的应用列表。 + 接受未知的证书\? 此服务器证书不是由已知的证书颁发机构签发的。 - 是否接受不匹配的服务器名称? - 由于“%s”,服务器无法验证。证书仅对此有效: - 是否仍要连接? - 证书详情: + 接受不匹配的服务器名称\? + 由于\"%s\",服务器无法验证。证书仅对此有效: + 是否仍要连接\? + 证书详情: 仅一次 二维码扫描器需要访问相机 滚动至底部 @@ -717,21 +717,21 @@ 编辑状态信息 编辑状态信息 禁用加密 - %1$s 无法发送加密消息到 %2$s。这可能是因为您的联系人使用了过时的服务器或者无法处理 OMEMO 的客户端。 + %1$s 无法发送加密消息到 %2$s。这可能是由于对方使用了过时的服务器或者无法处理 OMEMO 的客户端。 无法获取设备列表 无法获取密钥 - 提示:某些情况下,可以通过双方添加到联系人列表中来解决此问题。 - 是否禁用此对话的 OMEMO 加密? + 提示: 某些情况下,可以通过双方添加到联系人列表来解决此问题。 + 是否确定要禁用此对话的 OMEMO 加密\? \n这将允许服务器管理员阅读您的消息,但这可能是与使用过时客户端的用户进行交流的唯一方法。 立即禁用 - 草稿: + 草稿: OMEMO 加密 - OMEMO 加密将始终用于一对一和私人群组聊天。 + OMEMO 加密将始终用于一对一聊天和私人群聊。 默认情况下,新对话将使用 OMEMO 加密。 对于新对话,必须明确地打开 OMEMO 加密。 创建快捷方式 字体大小 - 应用程序中使用的相对字体大小。 + 应用内使用的相对字体大小。 默认开启 默认关闭 @@ -757,7 +757,7 @@ 查看对话 分享位置插件 使用分享位置插件代替内置地图 - 复制网址 + 复制 web 地址 复制 XMPP 地址 用于 S3 的 HTTP 文件分享 直接搜索 @@ -769,7 +769,7 @@ 昵称 名称 提供名称是可选的 - 群聊名称 + 群聊名 此群聊已解散 无法保存录制 前台服务 @@ -784,7 +784,7 @@ 正在进行的通话 未接来电 静音消息 - 此通知组用于显示不应触发任何声音的通知。 例如,在另一台设备上处于活跃状态时(宽限期)。 + 此通知组用于显示不应触发任何声音的通知。 例如,在另一台设备上处于活跃状态时(通知宽限期)。 传递失败 消息通知设置 来电通知设置 @@ -805,8 +805,8 @@ 选择国家/地区 电话号码 验证您的电话号码 - Quicksy 将发送短信(运营商可能收费)来验证您的电话号码。请输入您的国家/地区代码和电话号码: - 我们将验证这个电话号码

%s

可以吗?还是要编辑号码?
+ Quicksy 将发送短信(运营商可能收费)来验证电话号码。请输入您的国家/地区代码和电话号码: + 我们将验证这个电话号码

%s

可以吗\? 是否编辑号码\?
%s 不是有效的电话号码。 请输入您的电话号码。 搜索国家/地区 @@ -820,7 +820,7 @@ 返回 已自动从剪贴板粘贴可能的 PIN 码。 请输入您的 6 位数 PIN 码。 - 是否中止注册程序? + 是否确定要中止注册程序\? 正在验证… @@ -834,12 +834,12 @@ 无法找到服务器。 处理您的请求时出了问题。 用户输入无效 - 暂时不可用。稍后再试。 + 暂时无法使用。稍后再试。 无网络连接。 请在 %s 后重试 您的速率受到限制 尝试次数过多 - 您正在使用此应用程序的过时版本。 + 您正在使用此应用的过时版本。 更新 此电话号码目前已在另一台设备上登录。 请输入名称,以便让通讯录中没有您的人知道您是谁。 @@ -861,21 +861,21 @@ 输入 %s 账号的密码以恢复备份。 请勿使用恢复备份功能尝试克隆(同时运行)安装。恢复备份仅适用于迁移或您丢失原始设备的情况。 无法恢复备份。 - 无法解密备份。密码是否正确? + 无法解密备份。密码是否正确\? 备份 & 恢复 输入 XMPP 地址 创建群聊 加入公开频道 创建私人群聊 创建公开频道 - 频道名称 + 频道名 XMPP 地址 请提供频道名 请提供 XMPP 地址 这是 XMPP 地址。请提供名称。 正在创建公开频道… 此频道已存在 - 您已加入现有频道 + 您已加入现有的频道 无法保存频道配置 允许任何人编辑话题 允许任何人邀请别人 @@ -894,9 +894,9 @@ 附加 发现频道 搜索频道 - 可能会侵犯隐私! + 可能会侵犯隐私! 我已有账号 - 添加已有账号 + 添加现有的账号 注册新账号 这看起来像是域名地址 无论如何都要添加 @@ -910,11 +910,11 @@ 请输入此账号的密码 无法执行此操作 加入公开频道… - 分享应用程序未授予访问此文件的权限。 + 分享应用未授予访问此文件的权限。 群聊 & 频道 jabber.network 本地服务器 - 大多数用户应该选择“jabber.network”以便从整个公共 XMPP 生态系统中获得更好的建议。 + 大多数用户应该选择 \"jabber.network\" 以便从整个公共 XMPP 生态系统中获得更好的建议。 频道发现方法 备份 关于 @@ -922,8 +922,8 @@ 进行通话 来电 视频来电 - 是否切换到视频通话? - 是否添加额外轨道? + 切换到视频通话\? + 添加额外轨道\? 正在连接 已连接 正在重新连接 @@ -931,13 +931,13 @@ 正在结束通话 应答 忽略 - 发现设备中 - 响铃中 - 正忙 + 正在发现设备 + 正在响铃 + 占线 无法连接通话 连接丢失 已撤回通话 - 应用程序错误 + 应用错误 验证问题 挂断 正在进行的通话 @@ -962,7 +962,7 @@ 视频通话 帮助 切换到对话 - 您的麦克风不可用 + 您的麦克风无法使用 一次只能打一通电话。 返回到正在进行的通话 无法切换摄像头 @@ -1015,13 +1015,13 @@ 来电 (%s) · %s 去电 (%s) · %s 去电 · %s - 频道发现使用称为 <a href=https://search.jabber.network>search.jabber.network</a> 的第三方服务。<br><br>使用此功能会将您的 IP 地址和搜索词传输到此服务。请参阅他们的 <a href=https://search.jabber.network/privacy>隐私政策</a> 以获取更多信息。 + 频道发现使用称为 <a href=https://search.jabber.network>search.jabber.network</a> 的第三方服务。<br><br>使用此功能会将您的 IP 地址和搜索词传输到此服务。请参阅其 <a href=https://search.jabber.network/privacy>隐私政策</a> 以获取更多信息。 无法从服务器删除账号 群聊 保存为群聊 搜索群聊 从服务器移除账号 - 请勿尝试恢复您尚未自行创建的备份! + 请勿尝试恢复您尚未自行创建的备份! 您正尝试导入过时的备份文件格式 有声读物 重新连接其他主机 From 6855069810a1f4addf9e17f780336f08d6eb4c37 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Sun, 22 Oct 2023 00:49:13 +0000 Subject: [PATCH 245/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (13 of 13 strings) Translation: Conversations/Android App (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-conversations/zh_Hans/ --- .../res/values-zh-rCN/strings.xml | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/conversations/res/values-zh-rCN/strings.xml b/src/conversations/res/values-zh-rCN/strings.xml index 09929cb2c..dd59cd45c 100644 --- a/src/conversations/res/values-zh-rCN/strings.xml +++ b/src/conversations/res/values-zh-rCN/strings.xml @@ -3,18 +3,18 @@ 选择您的 XMPP 提供者 使用 conversations.im 创建新账号 - 您已经有 XMPP 账号了吗?如果您已经在使用不同的 XMPP 客户端或者之前使用过 Conversations,那么您已经拥有这种账号了。如果没有的话,您可以立即创建一个。 -\n提示:一些电子邮件服务也提供 XMPP 账号。 - XMPP 是独立于提供者的即时通讯网络。您可以将此客户端与您选择的任何 XMPP 服务器一起使用。 -\n不过,您可以轻松地在 conversations.im 上创建账号;它特别适合与 Conversations 一起使用。 - 您已受邀加入 %1$s。我们将指导您完成创建账号的过程。 -\n当选择 %1$s 作为提供者时,通过向其他 XMPP 用户提供您的完整地址,就能和他们交流。 - 您已受邀加入 %1$s。已经为您选择了用户名。我们将指导您完成创建账号的过程。 -\n通过向其他 XMPP 用户提供您的完整地址,就能和他们交流。 + 您已经有 XMPP 账号了吗\? 如果您之前使用过 Conversations 或其他 XMPP 客户端,那么您已经有这种账号了。如果没有,您可以立即创建一个。 +\n提示: 一些电子邮件服务也提供 XMPP 账号。 + XMPP 是独立于提供者的即时通讯网络。您选择的任何 XMPP 服务器都可以使用此客户端。 +\n不过,您可以轻松地在 conversations.im 上创建账号;特别适合与 Conversations 使用的提供者。 + 您已受邀加入 %1$s。我们将指导您创建账号。 +\n当选择 %1$s 作为提供者时,通过向其他 XMPP 用户提供您的完整地址,就能和对方交流。 + 您已受邀加入 %1$s。已为您选择了用户名。我们将指导您创建账号。 +\n通过向其他 XMPP 用户提供您的完整地址,就能和对方交流。 您的服务器邀请 配置代码格式不正确 点击分享按钮,向您的联系人发送加入 %1$s 的邀请。 - 如果您的联系人在附近,他们也可以扫描下方二维码接受您的邀请。 - 加入 %1$s 和我聊天:%2$s + 如果您的联系人在附近,对方也可以扫描下方二维码接受您的邀请。 + 加入 %1$s 和我聊天: %2$s 分享邀请至… \ No newline at end of file From 07c934b8f64a19ed6ebe6465de3a1d708787ab93 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Mon, 23 Oct 2023 06:18:47 +0000 Subject: [PATCH 246/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (9 of 9 strings) Translation: Conversations/Android App (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-quicksy/zh_Hans/ --- src/quicksy/res/values-zh-rCN/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/quicksy/res/values-zh-rCN/strings.xml b/src/quicksy/res/values-zh-rCN/strings.xml index 1a17048d8..1d146191e 100644 --- a/src/quicksy/res/values-zh-rCN/strings.xml +++ b/src/quicksy/res/values-zh-rCN/strings.xml @@ -2,8 +2,8 @@ Quicksy 发现另一台设备上的活动后保持安静的时间长度 通过发送堆栈跟踪,您正在帮助 Quicksy 的持续开发 - 当您使用 Quicksy 时,让您的所有联系人知道 - 为了继续接收通知,即使在屏幕关闭的情况下也是如此,您需要将 Quicksy 加入受保护的应用程序列表。 + 让您的所有联系人知道您何时使用 Quicksy + 为了在屏幕关闭时也能收到消息提醒,您需要将 Quicksy 加入受保护的应用列表。 Quicksy 个人资料图片 Quicksy 在您所在的国家/地区无法使用。 无法验证服务器身份。 From 5bd7be82ad1bf3e5766bbde46f042a41a914fb43 Mon Sep 17 00:00:00 2001 From: random_r Date: Mon, 23 Oct 2023 09:47:46 +0000 Subject: [PATCH 247/402] Translated using Weblate (Italian) Currently translated at 100.0% (52 of 52 strings) Translation: Conversations/App Store Metadata (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/it/ --- fastlane/metadata/android/it-IT/changelogs/42075.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 fastlane/metadata/android/it-IT/changelogs/42075.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/42075.txt b/fastlane/metadata/android/it-IT/changelogs/42075.txt new file mode 100644 index 000000000..675715118 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/42075.txt @@ -0,0 +1,3 @@ +* Supporto per DNS Privato (DNS over TLS) +* Supporto per icona del launcher a tema +* Risolto un raro problema di autorizzazione durante la condivisione di file su Android 11+ From 1017a49f2a8888fa1f57b7f849fcaee17b40adb0 Mon Sep 17 00:00:00 2001 From: nautilusx Date: Sat, 21 Oct 2023 10:20:52 +0000 Subject: [PATCH 248/402] Translated using Weblate (German) Currently translated at 100.0% (52 of 52 strings) Translation: Conversations/App Store Metadata (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/de/ --- fastlane/metadata/android/de-DE/changelogs/42075.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 fastlane/metadata/android/de-DE/changelogs/42075.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/42075.txt b/fastlane/metadata/android/de-DE/changelogs/42075.txt new file mode 100644 index 000000000..61579ecd3 --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/42075.txt @@ -0,0 +1,3 @@ +* Unterstützung von Private DNS (DNS über TLS) +* Unterstützung von designbezogenem Startsymbol +* Behebt ein seltenes Berechtigungsproblem beim Teilen von Dateien unter Android 11+ From 6e6bc40199204e04f2ea0c13cc3c8e1f59b1b9b6 Mon Sep 17 00:00:00 2001 From: SomeTr Date: Sat, 21 Oct 2023 13:17:09 +0000 Subject: [PATCH 249/402] Translated using Weblate (Ukrainian) Currently translated at 100.0% (52 of 52 strings) Translation: Conversations/App Store Metadata (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/uk/ --- fastlane/metadata/android/uk/changelogs/42075.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 fastlane/metadata/android/uk/changelogs/42075.txt diff --git a/fastlane/metadata/android/uk/changelogs/42075.txt b/fastlane/metadata/android/uk/changelogs/42075.txt new file mode 100644 index 000000000..db6654491 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/42075.txt @@ -0,0 +1,3 @@ +* Підтримка приватної DNS (DNS over TLS) +* Підтримка тематичного значка додатка в лаунчері +* Виправлено рідкісну проблему з дозволами під час обміну файлами на Android 11 і новіших From bb98ed503b86a5e0594c9581f9d793ad259cae5b Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Mon, 23 Oct 2023 04:25:41 +0000 Subject: [PATCH 250/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (2 of 2 strings) Translation: Conversations/App Store Metadata (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata-conversations/zh_Hans/ --- .../fastlane/metadata/android/zh-CN/full_description.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt b/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt index 8296d6e2d..f19e2cd87 100644 --- a/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt +++ b/src/conversations/fastlane/metadata/android/zh-CN/full_description.txt @@ -3,7 +3,7 @@ 设计原则: * 在不牺牲安全性和隐私性的前提下,尽可能美观易用 -* 依赖现有的、成熟的协议 +* 依赖现有的、完善的协议 * 不需要 Google 账号或特定的 Google 云通讯服务 (GCM) * 要求尽可能少的权限 From 1dd23585c57f8e8a08dc2b80336785a5015818f7 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Sun, 22 Oct 2023 03:11:22 +0000 Subject: [PATCH 251/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (52 of 52 strings) Translation: Conversations/App Store Metadata (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/zh_Hans/ --- fastlane/metadata/android/zh-CN/changelogs/42075.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 fastlane/metadata/android/zh-CN/changelogs/42075.txt diff --git a/fastlane/metadata/android/zh-CN/changelogs/42075.txt b/fastlane/metadata/android/zh-CN/changelogs/42075.txt new file mode 100644 index 000000000..dfe357cc5 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/42075.txt @@ -0,0 +1,3 @@ +* 支持私人 DNS (DNS over TLS) +* 支持主题启动器图标 +* 修复在 Android 11+ 上分享文件时罕见的权限问题 From fb75d4cf28f48ef80966f665a5f8387ea4ee2a1f Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Tue, 24 Oct 2023 15:23:32 +0000 Subject: [PATCH 252/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (970 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 46 +++++++++++++------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index 153247ef8..56ac705db 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -129,8 +129,8 @@ 通知铃声 新消息的通知铃声 来电铃声 - 通知宽限期 - 在您的某个其他设备上检测到活动之后,通知静音的时间长度。 + 静默期 + 在您的某个其他设备上检测到活动之后,通知被静音的时间长度。 高级 从不发送崩溃报告 通过发送堆栈跟踪,您正在帮助此应用的开发 @@ -150,15 +150,15 @@ 请求在线状态更新 选择图片 拍摄图片 - 预先同意状态请求 + 预先同意订阅请求 所选的文件不是图片 无法转换图片文件 文件未找到 常规 I/O 错误。也许存储空间已用完\? - 用来选择图片的应用没有提供读取文件的足够权限。 + 用来选择图片的应用未提供读取文件的足够权限。 \n \n使用不同的文件管理器来选择图片 - 用来分享此文件的应用没有提供足够的权限。 + 用来分享此文件的应用未提供足够的权限。 未知 暂时禁用 在线 @@ -293,20 +293,20 @@ \n这将用于确定对方正在使用的聊天应用 立即请求 忽略 - 警告: 在双方没有更新在线状态的情况下发送此消息将会出现未知问题。 + 警告: 在双方未更新在线状态的情况下发送此消息将会出现未知问题。 \n -\n前往“联系人详情”以验证在线状态请求。 +\n前往“联系人详情”以验证在线状态订阅。 安全 允许消息更正 允许对方发送后编辑其消息 专家设置 请谨慎设置这些 关于 %s - 安静时间 + 免打扰时间 开始时间 结束时间 - 启用安静时间 - 通知将在安静时间静音 + 启用免打扰时间 + 通知将在免打扰时间内静音 其他 同步书签 在进入或离开多用户聊天时设置“自动加入”标志,并回应其他客户端所做的改变。 @@ -349,7 +349,7 @@ 此备份文件已存储在 %s 正在恢复备份 已恢复备份 - 不要忘记启用此账号。 + 不要忘记启用账号。 选择文件 正在接收 %1$s (%2$d%% 已完成) 下载 %s @@ -379,7 +379,7 @@ 对方没有可用的密钥。 \n无法从服务器获取新密钥。也许是对方的服务器出了问题\? 对方没有可用的密钥。 -\n确保双方都请求在线状态。 +\n确保双方都有在线状态订阅。
出了问题 正在从服务器获取历史记录 服务器上没有更多历史记录 @@ -417,7 +417,7 @@ 私人,仅限成员 使 XMPP 地址对任何人可见 对频道进行审核 - 您没有参与 + 您未参与 群聊选项修改成功! 无法修改群聊选项 从不 @@ -482,7 +482,7 @@ 下载失败: 无法连接到主机 下载失败: 无法写入文件 下载失败: 无效文件 - Tor 网络无法使用 + Tor 网络不可用 绑定失败 服务器不能为域名做出响应 损坏 @@ -605,7 +605,7 @@ 需要付款 授予使用互联网的权限 - 对方请求获取在线状态 + 对方请求在线状态订阅 允许 没有权限访问 %s 远程服务器未找到 @@ -613,7 +613,7 @@ 无法更新账号 举报此 XMPP 地址发送垃圾消息。 删除 OMEMO 身份 - 重新生成 OMEMO 密钥。您的所有联系人将必须再次验证您。只有在万不得已的情况下才这样做。 + 重新生成 OMEMO 密钥。您的所有联系人将必须再次验证您。仅将此作为最后的方法。 删除所选的密钥 需要连接到网络才能发布头像。 显示出错消息 @@ -628,7 +628,7 @@ 您已验证了您拥有的所有 OMEMO 密钥 二维码中不包含此对话的指纹。 已验证的指纹 - 使用相机扫描联系人的二维码 + 使用相机扫描对方二维码 正在获取密钥,请稍候 分享为二维码 分享为 XMPP URI @@ -770,7 +770,7 @@ 名称 提供名称是可选的 群聊名 - 此群聊已解散 + 已解散此群聊 无法保存录制 前台服务 此通知类别用于显示永久通知,表明 %1$s 正在运行。 @@ -784,7 +784,7 @@ 正在进行的通话 未接来电 静音消息 - 此通知组用于显示不应触发任何声音的通知。 例如,在另一台设备上处于活跃状态时(通知宽限期)。 + 此通知组用于显示不应触发任何声音的通知。 例如,在另一台设备上处于活跃状态时(静默期)。 传递失败 消息通知设置 来电通知设置 @@ -819,7 +819,7 @@ 请稍候 (%s) 返回 已自动从剪贴板粘贴可能的 PIN 码。 - 请输入您的 6 位数 PIN 码。 + 请输入您的 6 位数字 PIN 码。 是否确定要中止注册程序\? @@ -834,7 +834,7 @@ 无法找到服务器。 处理您的请求时出了问题。 用户输入无效 - 暂时无法使用。稍后再试。 + 暂时不可用。稍后再试。 无网络连接。 请在 %s 后重试 您的速率受到限制 @@ -896,7 +896,7 @@ 搜索频道 可能会侵犯隐私! 我已有账号 - 添加现有的账号 + 添加已有账号 注册新账号 这看起来像是域名地址 无论如何都要添加 @@ -935,7 +935,7 @@ 正在响铃 占线 无法连接通话 - 连接丢失 + 连接已中断 已撤回通话 应用错误 验证问题 From f6c9df00de1ac492c9d168a3208bac3a8c1c0443 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 25 Oct 2023 09:40:25 +0200 Subject: [PATCH 253/402] run account deletion callback on ui thread --- .../siacs/conversations/ui/XmppActivity.java | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java index c6a6bc630..cebb8c22f 100644 --- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java @@ -317,22 +317,24 @@ public abstract class XmppActivity extends ActionBarActivity { button.setText(R.string.please_wait); button.setEnabled(false); xmppConnectionService.unregisterAccount(account, result -> { - if (result) { - dialog.dismiss(); - if (postDelete != null) { - postDelete.run(); + runOnUiThread(()->{ + if (result) { + dialog.dismiss(); + if (postDelete != null) { + postDelete.run(); + } + if (xmppConnectionService.getAccounts().size() == 0 && Config.MAGIC_CREATE_DOMAIN != null) { + final Intent intent = SignupUtils.getSignUpIntent(this); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + startActivity(intent); + } + } else { + deleteFromServer.setEnabled(true); + button.setText(R.string.delete); + button.setEnabled(true); + Toast.makeText(this,R.string.could_not_delete_account_from_server,Toast.LENGTH_LONG).show(); } - if (xmppConnectionService.getAccounts().size() == 0 && Config.MAGIC_CREATE_DOMAIN != null) { - final Intent intent = SignupUtils.getSignUpIntent(this); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); - startActivity(intent); - } - } else { - deleteFromServer.setEnabled(true); - button.setText(R.string.delete); - button.setEnabled(true); - Toast.makeText(this,R.string.could_not_delete_account_from_server,Toast.LENGTH_LONG).show(); - } + }); }); } else { Toast.makeText(this,R.string.not_connected_try_again,Toast.LENGTH_LONG).show(); From c178910e4d0bc39325c9c06109d90239dbb3a90a Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 25 Oct 2023 09:59:14 +0200 Subject: [PATCH 254/402] version bump to 2.12.12-beta.3 --- build.gradle | 4 ++-- .../android/de-DE/changelogs/{42075.txt => 42076.txt} | 0 .../android/en-US/changelogs/{42075.txt => 42076.txt} | 0 .../android/it-IT/changelogs/{42075.txt => 42076.txt} | 0 .../metadata/android/uk/changelogs/{42075.txt => 42076.txt} | 0 .../android/zh-CN/changelogs/{42075.txt => 42076.txt} | 0 6 files changed, 2 insertions(+), 2 deletions(-) rename fastlane/metadata/android/de-DE/changelogs/{42075.txt => 42076.txt} (100%) rename fastlane/metadata/android/en-US/changelogs/{42075.txt => 42076.txt} (100%) rename fastlane/metadata/android/it-IT/changelogs/{42075.txt => 42076.txt} (100%) rename fastlane/metadata/android/uk/changelogs/{42075.txt => 42076.txt} (100%) rename fastlane/metadata/android/zh-CN/changelogs/{42075.txt => 42076.txt} (100%) diff --git a/build.gradle b/build.gradle index ff78ec7e1..d0a51faa9 100644 --- a/build.gradle +++ b/build.gradle @@ -95,8 +95,8 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 33 - versionCode 42075 - versionName "2.12.12-beta.2" + versionCode 42076 + versionName "2.12.12-beta.3" archivesBaseName += "-$versionName" applicationId "eu.siacs.conversations" resValue "string", "applicationId", applicationId diff --git a/fastlane/metadata/android/de-DE/changelogs/42075.txt b/fastlane/metadata/android/de-DE/changelogs/42076.txt similarity index 100% rename from fastlane/metadata/android/de-DE/changelogs/42075.txt rename to fastlane/metadata/android/de-DE/changelogs/42076.txt diff --git a/fastlane/metadata/android/en-US/changelogs/42075.txt b/fastlane/metadata/android/en-US/changelogs/42076.txt similarity index 100% rename from fastlane/metadata/android/en-US/changelogs/42075.txt rename to fastlane/metadata/android/en-US/changelogs/42076.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/42075.txt b/fastlane/metadata/android/it-IT/changelogs/42076.txt similarity index 100% rename from fastlane/metadata/android/it-IT/changelogs/42075.txt rename to fastlane/metadata/android/it-IT/changelogs/42076.txt diff --git a/fastlane/metadata/android/uk/changelogs/42075.txt b/fastlane/metadata/android/uk/changelogs/42076.txt similarity index 100% rename from fastlane/metadata/android/uk/changelogs/42075.txt rename to fastlane/metadata/android/uk/changelogs/42076.txt diff --git a/fastlane/metadata/android/zh-CN/changelogs/42075.txt b/fastlane/metadata/android/zh-CN/changelogs/42076.txt similarity index 100% rename from fastlane/metadata/android/zh-CN/changelogs/42075.txt rename to fastlane/metadata/android/zh-CN/changelogs/42076.txt From 981dc2df6dd80bd552df9d8b107930b69c45dce5 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 26 Oct 2023 09:38:24 +0200 Subject: [PATCH 255/402] fix RtpSessionActivity not asking for permissions --- src/main/java/eu/siacs/conversations/utils/PermissionUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/eu/siacs/conversations/utils/PermissionUtils.java b/src/main/java/eu/siacs/conversations/utils/PermissionUtils.java index dd74dc57c..004676156 100644 --- a/src/main/java/eu/siacs/conversations/utils/PermissionUtils.java +++ b/src/main/java/eu/siacs/conversations/utils/PermissionUtils.java @@ -72,7 +72,7 @@ public class PermissionUtils { public static boolean hasPermission( final Activity activity, final List permissions, final int requestCode) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { final ImmutableList.Builder missingPermissions = new ImmutableList.Builder<>(); for (final String permission : permissions) { if (ActivityCompat.checkSelfPermission(activity, permission) From 28455ac9d5cddd87682b90a94128c449f64d9df8 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Thu, 26 Oct 2023 02:52:01 +0000 Subject: [PATCH 256/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (970 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 172 ++++++++++++------------- 1 file changed, 86 insertions(+), 86 deletions(-) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index 56ac705db..bead6755d 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -42,14 +42,14 @@ 主持人 参与者 访客 - 是否从联系人列表中移除 %s\? 将不会移除与对方的对话。 - 是否屏蔽 %s 向您发送消息\? - 是否解除屏蔽 %s 并允许对方向您发送消息\? - 屏蔽来自 %s 的所有联系人\? - 解除屏蔽来自 %s 的所有联系人\? + 是否从联系人列表中移除 %s?将不会移除与对方的对话。 + 是否屏蔽 %s 向您发送消息? + 是否解除屏蔽 %s 并允许对方向您发送消息? + 屏蔽来自 %s 的所有联系人? + 解除屏蔽来自 %s 的所有联系人? 联系人已屏蔽 已屏蔽 - 是否从书签中移除 %s\? 将不会移除与此书签相关的对话。 + 是否从书签中移除 %s?将不会移除与此书签相关的对话。 在服务器上注册新账号 在服务器上修改密码 分享至… @@ -68,14 +68,14 @@ 保存 完成 %1$s 已崩溃 - 使用您的 XMPP 账号发送堆栈跟踪有助于 %1$s 的持续开发。 + 使用 XMPP 账号发送堆栈跟踪有助于 %1$s 的持续开发。 立即发送 不再询问 无法连接到账号 无法连接到多个账号 点击即可管理账号 附加文件 - 对方不在您的联系人列表中,是否添加\? + 对方不在您的联系人列表中,是否添加? 添加联系人 传递失败 正在准备发送图片 @@ -83,13 +83,13 @@ 分享文件中。请稍候… 清空历史记录 清空对话历史记录 - 是否要删除此对话中的所有消息\? + 是否要删除此对话中的所有消息? \n -\n警告: 将不会影响存储在其他设备或服务器上的消息。 +\n警告:将不会影响存储在其他设备或服务器上的消息。 删除文件 - 是否确定要删除此文件\? + 是否确定要删除此文件? \n -\n警告: 将不会删除存储在其他设备或服务器上的此文件的副本。 +\n警告:将不会删除存储在其他设备或服务器上的此文件的副本。 之后关闭此对话 选择设备 发送未加密的消息 @@ -102,7 +102,7 @@ 发送未加密的 解密失败。也许您没有正确的私钥。 OpenKeychain - %1$s 使用 <b>OpenKeychain</b> 来加密和解密消息并管理您的公钥。<br><br>它在 GPLv3+ 许可证下授权并可在 F-Droid 和 Google Play 上获得。<br><br><small>(请之后重新启动 %1$s。)</small> + %1$s 使用 <b>OpenKeychain</b> 来加密和解密消息并管理公钥。<br><br>它在 GPLv3+ 许可证下授权并可在 F-Droid 和 Google Play 上获得。<br><br><small>(请之后重新启动 %1$s。)</small> 重新启动 安装 请安装 OpenKeychain @@ -130,14 +130,14 @@ 新消息的通知铃声 来电铃声 静默期 - 在您的某个其他设备上检测到活动之后,通知被静音的时间长度。 + 在其他设备上检测到活动之后,通知在此期间静音。 高级 从不发送崩溃报告 通过发送堆栈跟踪,您正在帮助此应用的开发 确认消息 让对方知道您已收到并阅读了其消息 防止截屏 - 在应用切换器中隐藏应用内容并阻止屏幕截图 + 在切换应用时隐藏应用内容并阻止屏幕截图 用户界面 OpenKeychain 出现了错误。 加密密钥错误。 @@ -154,10 +154,10 @@ 所选的文件不是图片 无法转换图片文件 文件未找到 - 常规 I/O 错误。也许存储空间已用完\? + 常规 I/O 错误。也许存储空间已用完? 用来选择图片的应用未提供读取文件的足够权限。 \n -\n使用不同的文件管理器来选择图片 +\n使用其他文件管理器选择图片 用来分享此文件的应用未提供足够的权限。 未知 暂时禁用 @@ -188,11 +188,11 @@ 发布头像 发布 OpenPGP 公钥 移除 OpenPGP 公钥 - 是否确定要从在线状态公布中移除 OpenPGP 公钥\? + 是否确定要从在线状态公布中移除 OpenPGP 公钥? \n对方将无法再向您发送 OpenPGP 加密消息。 OpenPGP 公钥已发布。 启用账号 - 是否确定要删除账号\? 删除账号会擦除您的全部对话历史记录 + 是否确定要删除账号?删除账号会擦除您的全部对话历史记录 录制语音 XMPP 地址 屏蔽 XMPP 地址 @@ -200,18 +200,18 @@ 密码 这不是有效的 XMPP 地址 空间不足。图片太大 - 是否要添加 %s 到您的通讯录中\? + 是否要添加 %s 到您的通讯录中? 服务器信息 - XEP-0313: 消息存档管理 - XEP-0280: 消息抄送 - XEP-0352: 客户端状态指示 - XEP-0191: 屏蔽指令 - XEP-0237: 花名册版本控制 - XEP-0198: 流管理 - XEP-0215: 外部服务发现 - XEP-0163: 个人事件协议(头像/OMEMO) - XEP-0363: HTTP 文件上传 - XEP-0357: 推送 + XEP-0313:消息存档管理 + XEP-0280:消息抄送 + XEP-0352:客户端状态指示 + XEP-0191:屏蔽指令 + XEP-0237:花名册版本控制 + XEP-0198:流管理 + XEP-0215:外部服务发现 + XEP-0163:个人事件协议(头像/OMEMO) + XEP-0363:HTTP 文件上传 + XEP-0357:推送 有效 无效 缺少公钥公布 @@ -250,12 +250,12 @@ 删除书签 解散群聊 解散频道 - 是否确定要解散此群聊\? + 是否确定要解散此群聊? \n -\n警告: 将在服务器上完全移除群聊。 - 是否确定要解散此公开频道\? +\n警告:将在服务器上完全移除群聊。 + 是否确定要解散此公开频道? \n -\n警告: 将在服务器上完全移除频道。 +\n警告:将在服务器上完全移除频道。 无法解散群聊 无法解散频道 编辑群聊话题 @@ -275,7 +275,7 @@ 无法转换图片 无法将头像保存到磁盘 (或长按恢复默认) - 您的服务器不支持发布头像 + 服务器不支持发布头像 私聊 至 %s 发送私人消息至 %s @@ -293,7 +293,7 @@ \n这将用于确定对方正在使用的聊天应用 立即请求 忽略 - 警告: 在双方未更新在线状态的情况下发送此消息将会出现未知问题。 + 警告:在双方未更新在线状态的情况下发送此消息将会出现未知问题。 \n \n前往“联系人详情”以验证在线状态订阅。 安全 @@ -375,16 +375,16 @@ 复制 OMEMO 指纹到剪贴板 重新生成 OMEMO 密钥 清除设备 - 是否确定要从 OMEMO 公布中清除所有其他设备\? 下次连接时,设备将会重新公布,但可能不会收到在此期间发送的消息。 + 是否确定要从 OMEMO 公布中清除所有其他设备?下次连接时,设备将会重新公布,但可能不会收到在此期间发送的消息。 对方没有可用的密钥。 -\n无法从服务器获取新密钥。也许是对方的服务器出了问题\? +\n无法从服务器获取新密钥。也许是对方的服务器出了问题? 对方没有可用的密钥。 \n确保双方都有在线状态订阅。 出了问题 正在从服务器获取历史记录 服务器上没有更多历史记录 正在更新… - 密码已修改! + 密码已修改! 无法修改密码 修改密码 当前密码 @@ -418,7 +418,7 @@ 使 XMPP 地址对任何人可见 对频道进行审核 您未参与 - 群聊选项修改成功! + 群聊选项修改成功! 无法修改群聊选项 从不 直至另行通知 @@ -438,7 +438,7 @@ PDF 文档 Android 应用 联系人 - 已发布头像! + 已发布头像! 正在发送 %s 正在提供 %s 隐藏离线的联系人 @@ -477,11 +477,11 @@ 用户名 用户名 此用户名无效 - 下载失败: 服务器未找到 - 下载失败: 文件未找到 - 下载失败: 无法连接到主机 - 下载失败: 无法写入文件 - 下载失败: 无效文件 + 下载失败:服务器未找到 + 下载失败:文件未找到 + 下载失败:无法连接到主机 + 下载失败:无法写入文件 + 下载失败:无效文件 Tor 网络不可用 绑定失败 服务器不能为域名做出响应 @@ -507,9 +507,9 @@ 不信任的证书链 XMPP 地址与证书不匹配 续订证书 - 获取 OMEMO 密钥时出错! - 已通过证书验证 OMEMO 密钥! - 您的设备不支持客户端证书选择! + 获取 OMEMO 密钥时出错! + 已通过证书验证 OMEMO 密钥! + 设备不支持客户端证书选择! 连接 通过 Tor 连接 通过 Tor 网络传输所有连接。需要 Orbot @@ -530,22 +530,22 @@ 授予 %1$s 访问外部存储的权限 授予 %1$s 访问相机的权限 与联系人同步 - %1$s 想要访问通讯录权限来将它与您的 XMPP 联系人列表相匹配。 + %1$s 想要访问通讯录权限来将它与 XMPP 联系人列表相匹配。 \n这将会显示联系人的全名和头像。 \n -\n%1$s 将只会读取您的通讯录并在本地进行匹配,不会上传任何东西到服务器。 +\n%1$s 将只会读取通讯录并在本地匹配,不会上传任何东西到服务器。 通知所有消息 仅在提及时通知 通知已禁用 通知已暂停 图片压缩 - 提示: 无论此设置如何,使用“选择文件”会发送未压缩的图片。 + 提示:无论此设置如何,使用“选择文件”会发送未压缩的图片。 始终 仅限大图片 电池优化已启用 - 您的设备正对 %1$s 实施强力电池优化,这可能会导致通知延迟甚至消息丢失。 + 设备正对 %1$s 实施强力电池优化,这可能会导致通知延迟甚至消息丢失。 \n建议禁用它们。 - 您的设备正对 %1$s 实施强力电池优化,这可能会导致通知延迟甚至消息丢失。 + 设备正对 %1$s 实施强力电池优化,这可能会导致通知延迟甚至消息丢失。 \n \n现在将要求您禁用它们。 禁用 @@ -556,18 +556,18 @@ 发送更正后的消息 您已经安全地验证了此用户的指纹以确认信任。通过选择“完成”以确认 %s 加入群聊。 您已禁用了此账号 - 安全错误: 文件访问无效! + 安全错误:文件访问无效! 未找到可以分享 URI 的应用 分享 URI 至… 同意并继续 在 conversations.im 上创建账号的指南已设置。 \n当选择 conversations.im 作为提供者时,通过向其他 XMPP 用户提供您的完整地址,就能和对方交流。 - 您的完整 XMPP 地址将是: %s + 您的完整 XMPP 地址将是:%s 创建账号 使用我自己的提供者 选择您的用户名 手动更改在线状态 - 在编辑状态信息时,设置您的在线状态。 + 在编辑状态信息时,让对方知道您是否可以聊天。 状态信息 有空聊天 在线 @@ -575,9 +575,9 @@ 没空 忙碌 已生成安全密码 - 您的设备不支持选择退出电池优化 - 注册失败: 稍后再试 - 注册失败: 密码太弱 + 设备不支持选择退出电池优化 + 注册失败:稍后再试 + 注册失败:密码太弱 选择参与者 正在创建群聊… 再次邀请 @@ -586,7 +586,7 @@ 广播使用 - 让您的联系人知道您何时使用 Conversations + 让对方知道您使用 Conversations 的时间 隐私 主题 选择主题颜色 @@ -613,7 +613,7 @@ 无法更新账号 举报此 XMPP 地址发送垃圾消息。 删除 OMEMO 身份 - 重新生成 OMEMO 密钥。您的所有联系人将必须再次验证您。仅将此作为最后的方法。 + 重新生成 OMEMO 密钥。对方将必须再次验证您。仅将此作为最后的方法。 删除所选的密钥 需要连接到网络才能发布头像。 显示出错消息 @@ -621,7 +621,7 @@ 省流量模式已启用 您的操作系统正限制 %1$s 在后台时访问互联网。要接收新消息通知,您应当在“省流量模式”开启时允许 %1$s 无限制访问。 \n%1$s 仍将在可能的情况下努力节省数据。 - 您的设备不支持对 %1$s 禁用省流量模式。 + 设备不支持对 %1$s 禁用省流量模式。 无法创建临时文件 此设备已通过验证 复制指纹 @@ -650,7 +650,7 @@ 显示不活跃的设备 隐藏不活跃的设备 不再信任设备 - 是否确定要移除此设备的验证\? + 是否确定要移除此设备的验证? \n将此设备及其消息标记为“不信任的”。 %d 秒 @@ -678,7 +678,7 @@ 相应的对话已关闭。 联系人已屏蔽。 陌生人的通知 - 收到陌生人的消息和来电时进行通知。 + 收到陌生人的消息和来电时通知。 收到了陌生人发来的消息 屏蔽陌生人 屏蔽整个域名 @@ -704,12 +704,12 @@ 已禁用私人消息 受保护的应用 为了在屏幕关闭时也能收到消息提醒,您需要将 Conversations 加入受保护的应用列表。 - 接受未知的证书\? + 接受未知的证书? 此服务器证书不是由已知的证书颁发机构签发的。 - 接受不匹配的服务器名称\? - 由于\"%s\",服务器无法验证。证书仅对此有效: - 是否仍要连接\? - 证书详情: + 接受不匹配的服务器名称? + 由于\"%s\",服务器无法验证。证书仅对此有效: + 是否仍要连接? + 证书详情: 仅一次 二维码扫描器需要访问相机 滚动至底部 @@ -720,11 +720,11 @@ %1$s 无法发送加密消息到 %2$s。这可能是由于对方使用了过时的服务器或者无法处理 OMEMO 的客户端。 无法获取设备列表 无法获取密钥 - 提示: 某些情况下,可以通过双方添加到联系人列表来解决此问题。 - 是否确定要禁用此对话的 OMEMO 加密\? -\n这将允许服务器管理员阅读您的消息,但这可能是与使用过时客户端的用户进行交流的唯一方法。 + 提示:某些情况下,可以通过双方添加到联系人列表来解决此问题。 + 是否确定要禁用此对话的 OMEMO 加密? +\n这将允许服务器管理员阅读您的消息,但这可能是与使用过时客户端的用户交流的唯一方法。 立即禁用 - 草稿: + 草稿: OMEMO 加密 OMEMO 加密将始终用于一对一聊天和私人群聊。 默认情况下,新对话将使用 OMEMO 加密。 @@ -805,8 +805,8 @@ 选择国家/地区 电话号码 验证您的电话号码 - Quicksy 将发送短信(运营商可能收费)来验证电话号码。请输入您的国家/地区代码和电话号码: - 我们将验证这个电话号码

%s

可以吗\? 是否编辑号码\?
+ Quicksy 将发送短信(运营商可能收费)来验证电话号码。请输入您的国家/地区代码和电话号码: + 我们将验证这个电话号码

%s

可以吗?是否编辑号码?
%s 不是有效的电话号码。 请输入您的电话号码。 搜索国家/地区 @@ -820,7 +820,7 @@ 返回 已自动从剪贴板粘贴可能的 PIN 码。 请输入您的 6 位数字 PIN 码。 - 是否确定要中止注册程序\? + 是否确定要中止注册程序? 正在验证… @@ -845,7 +845,7 @@ 请输入名称,以便让通讯录中没有您的人知道您是谁。 您的名称 输入您的名称 - 使用编辑按钮设置您的名称。 + 使用编辑按钮设置名称。 拒绝请求 安装 Orbot 启动 Orbot @@ -861,7 +861,7 @@ 输入 %s 账号的密码以恢复备份。 请勿使用恢复备份功能尝试克隆(同时运行)安装。恢复备份仅适用于迁移或您丢失原始设备的情况。 无法恢复备份。 - 无法解密备份。密码是否正确\? + 无法解密备份。密码是否正确? 备份 & 恢复 输入 XMPP 地址 创建群聊 @@ -886,7 +886,7 @@ 任何人可以邀请别人。 XMPP 地址对管理员可见。 XMPP 地址对任何人可见。 - 此公开频道无参与者。邀请您的联系人或使用分享按钮分发其 XMPP 地址。 + 此公开频道无参与者。邀请联系人或使用分享按钮分发其 XMPP 地址。 此私人群聊无参与者。 管理权限 搜索参与者 @@ -894,7 +894,7 @@ 附加 发现频道 搜索频道 - 可能会侵犯隐私! + 可能会侵犯隐私! 我已有账号 添加已有账号 注册新账号 @@ -922,8 +922,8 @@ 进行通话 来电 视频来电 - 切换到视频通话\? - 添加额外轨道\? + 切换到视频通话? + 添加额外轨道? 正在连接 已连接 正在重新连接 @@ -962,7 +962,7 @@ 视频通话 帮助 切换到对话 - 您的麦克风无法使用 + 麦克风无法使用 一次只能打一通电话。 返回到正在进行的通话 无法切换摄像头 @@ -1010,7 +1010,7 @@ 无(已停用) UnifiedPush 分发程序 接收推送消息的账号。 - 用户选择的推送服务器,通过 XMPP 将推送消息转送至您的设备。 + 用户选择的推送服务器,通过 XMPP 将推送消息转送至设备。 拒绝 来电 (%s) · %s 去电 (%s) · %s @@ -1021,7 +1021,7 @@ 保存为群聊 搜索群聊 从服务器移除账号 - 请勿尝试恢复您尚未自行创建的备份! + 请勿尝试恢复您尚未自行创建的备份! 您正尝试导入过时的备份文件格式 有声读物 重新连接其他主机 From 2a8eafa624aad71186fb86b38872ea053d2c01b2 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Thu, 26 Oct 2023 05:11:32 +0000 Subject: [PATCH 257/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (13 of 13 strings) Translation: Conversations/Android App (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-conversations/zh_Hans/ --- src/conversations/res/values-zh-rCN/strings.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/conversations/res/values-zh-rCN/strings.xml b/src/conversations/res/values-zh-rCN/strings.xml index dd59cd45c..ddd19704d 100644 --- a/src/conversations/res/values-zh-rCN/strings.xml +++ b/src/conversations/res/values-zh-rCN/strings.xml @@ -3,8 +3,8 @@ 选择您的 XMPP 提供者 使用 conversations.im 创建新账号 - 您已经有 XMPP 账号了吗\? 如果您之前使用过 Conversations 或其他 XMPP 客户端,那么您已经有这种账号了。如果没有,您可以立即创建一个。 -\n提示: 一些电子邮件服务也提供 XMPP 账号。 + 您已经有 XMPP 账号了吗?如果您之前使用过 Conversations 或其他 XMPP 客户端,那么您已经有这种账号了。如果没有,您可以立即创建一个。 +\n提示:一些电子邮件服务也提供 XMPP 账号。 XMPP 是独立于提供者的即时通讯网络。您选择的任何 XMPP 服务器都可以使用此客户端。 \n不过,您可以轻松地在 conversations.im 上创建账号;特别适合与 Conversations 使用的提供者。 您已受邀加入 %1$s。我们将指导您创建账号。 @@ -14,7 +14,7 @@ 您的服务器邀请 配置代码格式不正确 点击分享按钮,向您的联系人发送加入 %1$s 的邀请。 - 如果您的联系人在附近,对方也可以扫描下方二维码接受您的邀请。 - 加入 %1$s 和我聊天: %2$s + 如果您的联系人在附近,对方也可以扫描下方二维码接受邀请。 + 加入 %1$s 和我聊天:%2$s 分享邀请至… \ No newline at end of file From 3e13ac1b05b9d506c9e2a26c27566b0ddb95d6cf Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Thu, 26 Oct 2023 03:58:49 +0000 Subject: [PATCH 258/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (9 of 9 strings) Translation: Conversations/Android App (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-quicksy/zh_Hans/ --- src/quicksy/res/values-zh-rCN/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/quicksy/res/values-zh-rCN/strings.xml b/src/quicksy/res/values-zh-rCN/strings.xml index 1d146191e..7bbb85c6c 100644 --- a/src/quicksy/res/values-zh-rCN/strings.xml +++ b/src/quicksy/res/values-zh-rCN/strings.xml @@ -1,8 +1,8 @@ - Quicksy 发现另一台设备上的活动后保持安静的时间长度 + Quicksy 发现另一台设备上的活动后在此期间保持安静 通过发送堆栈跟踪,您正在帮助 Quicksy 的持续开发 - 让您的所有联系人知道您何时使用 Quicksy + 让对方知道您使用 Quicksy 的时间 为了在屏幕关闭时也能收到消息提醒,您需要将 Quicksy 加入受保护的应用列表。 Quicksy 个人资料图片 Quicksy 在您所在的国家/地区无法使用。 From 7337c804bfe7693376511489589d469f1d969689 Mon Sep 17 00:00:00 2001 From: SomeTr Date: Fri, 27 Oct 2023 15:50:41 +0000 Subject: [PATCH 259/402] Translated using Weblate (Catalan) Currently translated at 92.1% (894 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/ca/ --- src/main/res/values-ca/strings.xml | 38 +++++++++++++++++------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/main/res/values-ca/strings.xml b/src/main/res/values-ca/strings.xml index 8a2fe7b8a..d57c9a0cc 100644 --- a/src/main/res/values-ca/strings.xml +++ b/src/main/res/values-ca/strings.xml @@ -84,7 +84,9 @@ Neteja l\'historial de la conversa Vols esborrar tots els missatges d\'aquesta conversa?\n\n Advertiment: Això no influirà en els missatges emmagatzemats en altres dispositius o servidors. Eliminar fitxer - Estàs segur que vols esborrar aquest fitxer?\n\n Advertiment: Això no eliminarà les còpies d\'aquest fitxer que estiguin emmagatzemades en altres dispositius o servidors. + Estàs segur que vols esborrar aquest fitxer\? +\n +\nAdvertiment: Això no eliminarà les còpies d\'aquest fitxer que estiguin emmagatzemades en altres dispositius o servidors. Tanca aquesta conversa després Tria el dispositiu Envia un missatge no xifrat @@ -143,8 +145,10 @@ El fitxer triat no és una imatge No es va poder convertir l\'arxiu d\'imatge No s\'ha trobat el fitxer - Error d\'E/S general. Pot ser que us hagueu quedat sense espai d\'emmagatzematge. - L\'aplicació que vas usar per a seleccionar aquesta imatge no va proporcionar suficients permisos per a llegir l\'arxiu.\n\nUtilitza un gestor d\'arxius diferent per a triar una imatge. + Error d\'E/S general. Pot ser que us hagueu quedat sense espai d\'emmagatzematge\? + L\'aplicació que vas usar per a seleccionar aquesta imatge no va proporcionar suficients permisos per a llegir l\'arxiu. +\n +\nUtilitza un gestor d\'arxius diferent per a triar una imatge. Desconegut Inhabilitat temporalment En línia @@ -265,7 +269,9 @@ Habilita El xat de grup requereix contrasenya Introduïu la contrasenya - Si us plau, sol·liciti primer les actualitzacions de presència al seu contacte.\n\nAixò s\'usarà per a determinar quina aplicació de xat està usant el teu contacte. + Si us plau, sol·liciti primer les actualitzacions de presència al seu contacte. +\n +\nAixò s\'usarà per a determinar quina aplicació de xat està usant el teu contacte. Sol·licita ara Ignora Advertiment:: Enviar això sense actualitzacions de presència mútua podria causar problemes inesperats.\n\n Vagi a \"Dades de contacte\" per a verificar les seves subscripcions de presència. @@ -351,8 +357,8 @@ Alguna cosa ha anat malament Anar a cercar la història als servidors No hi ha més histories al servidor - Actualitzant - Contrasenya canviada + Actualitzant… + Contrasenya canviada! No s\'ha pogut canviar la contrasenya Cambiar contrasenya Contrasenya actual @@ -360,7 +366,7 @@ La contrasenya no pot estar buida Habilitar tots els comptes Deshabilitar tots els comptes - Realitzar l\'acció amb… + Realitzar l\'acció amb Cap afiliació Fora de línia Outcast @@ -386,7 +392,7 @@ Fer que les direccions XMPP siguin visibles per a qualsevol Fer que el canal sigui moderat No esteu participant - S\'han modificat les opcions de xat en grup. + S\'han modificat les opcions de xat en grup! No s\'han pogut modificar les opcions de xat de grup Mai Fins nou avís @@ -471,9 +477,9 @@ Cadena de certificats no fiable La direcció XMPP no coincideix amb el certificat Renova el certificat - S\'ha produït un error en obtenir la clau OMEMO!. + S\'ha produït un error en obtenir la clau OMEMO! Clau OMEMO verificada amb certificat! - El vostre dispositiu no admet la selecció de certificats de client. + El vostre dispositiu no admet la selecció de certificats de client! Connexió Connectar mitjançant Tor Tunelar totes les connexions a través de la xarxa Tor. Requereix Orbot @@ -772,8 +778,8 @@ que l\'administrador del servidor llegeixi els missatges, però pot ser l\'únic Està segur que vol avortar el procediment de registre? Si No - Verificant... - Sol·licitud de SMS... + Verificant… + Sol·licitud de SMS… El pin que has introduït és incorrecte. El pin que li hem enviat ha caducat. Error de xarxa desconegut. @@ -802,7 +808,7 @@ que l\'administrador del servidor llegeixi els missatges, però pot ser l\'únic Aquest canal farà pública la seva adreça XMPP Llibre electrònic Original (sense comprimir) - Obrir amb... + Obrir amb… Foto de perfil de Conversations Triï el compte Restaurar còpia de seguretat @@ -822,7 +828,7 @@ que l\'administrador del servidor llegeixi els missatges, però pot ser l\'únic Indiqui un nom per al canal Indiqui una direcció XMPP Aquesta és una direcció XMPP. Si us plau, proporcioni un nom. - Creant un canal públic... + Creant un canal públic… Aquest canal ja existeix T\'has unit a un canal existent No s\'ha pogut guardar la configuració del canal @@ -843,7 +849,7 @@ que l\'administrador del servidor llegeixi els missatges, però pot ser l\'únic Adjuntar Descobreix canals Buscar canals - Possible violació de la privacitat. + Possible violació de la privacitat! Ja tinc un compte Afegir compte existent Registrar un nou compte @@ -858,7 +864,7 @@ que l\'administrador del servidor llegeixi els missatges, però pot ser l\'únic Aquest compte ja està configurada Si us plau, introdueixi la contrasenya d\'aquest compte No s\'ha pogut realitzar aquesta acció - Unir-se al canal públic... + Unir-se al canal públic… L\'aplicació per a compartir no va donar permís per a accedir a aquest arxiu. jabber.network From c5af91a4f74e6a92588191a5af9a1f9f3df79a31 Mon Sep 17 00:00:00 2001 From: SomeTr Date: Fri, 27 Oct 2023 14:01:34 +0000 Subject: [PATCH 260/402] Translated using Weblate (Turkish) Currently translated at 97.5% (946 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/tr/ --- src/main/res/values-tr-rTR/strings.xml | 119 ++++++++++++++----------- 1 file changed, 65 insertions(+), 54 deletions(-) diff --git a/src/main/res/values-tr-rTR/strings.xml b/src/main/res/values-tr-rTR/strings.xml index 7107efeb8..511981d15 100644 --- a/src/main/res/values-tr-rTR/strings.xml +++ b/src/main/res/values-tr-rTR/strings.xml @@ -53,7 +53,7 @@ %s kişisini yer imlerinden çıkarmak ister misiniz? Bu yer imi ile kayıtlı konuşmalar silinmeyecektir. Sunucuda yeni bir hesap oluştur Sunucudaki şifreni değiştir - Paylaş... + Paylaş… Konuşma başlat Kişi davet et Davet et @@ -73,18 +73,20 @@ Şimdi gönder Bir daha sorma Hesaba bağlanılamadı - Birden fazla hesaba bağlanılamadı. - Hesaplarınızı yönetmek için dokununuz. + Birden fazla hesaba bağlanılamadı + Hesaplarınızı yönetmek için dokununuz Dosya ekle Eksik olan bu kişiyi listenize eklemek ister misiniz? Kişi ekle ulaştırılamadı - Görüntü gönderilmeye hazırlanılıyor. - Görüntüler gönderilmeye hazırlanılıyor. - Dosyalar Paylaşılıyor. Lütfen bekleyin... + Görüntü gönderilmeye hazırlanılıyor + Görüntüler gönderilmeye hazırlanılıyor + Dosyalar Paylaşılıyor. Lütfen bekleyin… Geçmişi sil Konuşma geçmişini sil - Bu konuşmadaki tüm mesajları silmek istiyor musunuz? \n\nUyarı: Bu eylem, diğer aygıt ve sunucularda kayıtlı mesajları etkilemeyecektir. + Bu konuşmadaki tüm mesajları silmek istiyor musunuz\? +\n +\nUyarı: Bu eylem, diğer aygıt ve sunucularda kayıtlı mesajları etkilemeyecektir. Dosyayı sil Bu dosyayı silmek istediğinizden emin misiniz? \n\nUyarı: Bu eylem, bu dosyanın diğer aygıt ve sunucularda kayıtlı kopyalarını silmeyecektir. Devamında bu konuşmayı kapat @@ -99,7 +101,7 @@ Şifrelenmemiş gönder Deşifre edilemedi. Uygun bir özel anahtarınız olmayabilir. OpenKeychain - OpenKeychain kullanmaktadır. \n\nlt GPLv3+ altında lisanslıdır ve F-Droid ve Google Play\'de mevcuttur. \n\n

(Lütfen devamında %1$s\'ı yeniden başlatın.)]]>
+ %1$s mesajları şifrelemek, deşifre etmek ve genel anahtarlarınızı yönetmek için <b>OpenKeychain</b> kullanmaktadır.<br><br>lt GPLv3+ altında lisanslıdır ve F-Droid ve Google Play\'de mevcuttur.<br><br><small>(Lütfen devamında %1$s\'ı yeniden başlatın.)</small> Yeniden başlat Kur Lütfen OpenKeychain’i kur @@ -126,7 +128,7 @@ Cihazlarınızın birinde faaliyet tespit edilmesinden sonra zaman hatırlatmalarının susturulma uzunluğu. Gelişmiş Asla çöküş raporu gönderme - Yığın izi göndererek gelişime yardımcı oluyorsunuz. + Yığın izi göndererek gelişime yardımcı oluyorsunuz İletileri onayla Onların iletilerini aldığınızda ve okuduğunuzda, kişilerinizin bunu bilmesini sağlayın Ekran görüntülerini engelle @@ -145,7 +147,7 @@ Resim çek Abonelik isteğini peşinen kabul et Seçtiğiniz dosya bir görüntü dosyası değil - Görüntü dosyası dönüştürülemedi. + Görüntü dosyası dönüştürülemedi Dosya bulunamadı Genel G/Ç hatası. Depolama yeri kalmamış olabilir mi? Bu görüntüyü seçmekte kullandığınız uygulama, dosyanın okunması için yeterli izinleri sağlayamadı. @@ -163,7 +165,7 @@ Hesap oluşturulamadı Kullanıcı adı kullanılıyor Hesap oluşturuldu - Hesap, sunucu tarafından desteklenmiyor. + Hesap, sunucu tarafından desteklenmiyor Geçersiz hesak simgesi TLS uzlaşması başarısız Alan adı doğrulanamıyor @@ -191,7 +193,7 @@ kullanıcıadı@ornek.com parola Bu geçerli bir XMPP adresi değil - Yetersiz bellek. Görüntü çok büyük. + Yetersiz bellek. Görüntü çok büyük %s kişisini listenize eklemek ister misiniz? Sunucu bilgisi XEP-0313: MAM @@ -243,12 +245,14 @@ Grup konuşmasını yoket Kanalı yoket Bu grup konuşmasını yoketmek istediğinizden emin misiniz?\n\nUyarı: Grup konuşması sunucudan tamamen kaldırlacaktır. - Bu genel kanalı yoketmek istediğnizden emin misiniz?\n\nUyarı: Kanal sunucudan tamamen kaldırılacaktır. + Bu genel kanalı yoketmek istediğnizden emin misiniz\? +\n +\nUyarı: Kanal sunucudan tamamen kaldırılacaktır. Grup konuşması yokedilemedi Kanal yokedilemedi Grup konuşma konusunu düzenle Başlık - Grup konuşmasına bağlanılıyor... + Grup konuşmasına bağlanılıyor… Ayrıl Kişi sizi listesine ekledi Siz de ekleyin @@ -263,7 +267,7 @@ Resminiz dönüştürülemedi vatar diske kaydedilemedi (Veya varsayılan değerlere dönmek için uzun süre basılı tutun) - Sunucunuz avatarların tanıtılmasını desteklemiyor. + Sunucunuz avatarların tanıtılmasını desteklemiyor fısıldandı %s kişisine %s kişisine özel ileti gönder @@ -276,7 +280,9 @@ Etkinleştir Grup konuşması şifre talep ediyor Parolayı gir - Lütfen bağlantınızdan önce çevrim içi durum bildirimi talep edin. \n\nBu, bağlantınızın hangi konuşma uygulamasını kullandığını belirlemekte kullanılacak. + Lütfen bağlantınızdan önce çevrim içi durum bildirimi talep edin. +\n +\nBu, bağlantınızın hangi konuşma uygulamasını kullandığını belirlemekte kullanılacak. Şimdi iste Yok say Uyarı: Bu mesajı karşılıklı çevrim içi durum bildirimleri olmadan göndermek, beklenmeyen problemlere neden olabilir. \n\n Çevrim içi durum aboneliklerini doğrulamak için \"Kişi Bilgileri\" kısmına gidin. @@ -332,7 +338,7 @@ Yedekleme dosyaları %s\'da depolandı Yedekleme yükleniyor Yedekleminiz yüklendi - Hesabı etkinleştirmeyi unutmayın + Hesabı etkinleştirmeyi unutmayın. Dosya seç %1$s alıyor/(%2$d%% tamamlandı) %s indir @@ -360,7 +366,8 @@ Aygıtları sil OMEMO bildirimindeki diğer aygıtların hepsini silmek istediğinizden emin misiniz? Aygıtlarınız yeniden bağlandıklarında kendilerini yeniden bildirecekler ama bu süre zarfındaki iletileri alamayabilirler. Bu kişi için kullanılabilecek bir anahtar bulunmuyor.\nSunucudan yeni anahtarlar alınamıyor. Belki bağlantınızın sunucusunda bir sorun vardır? - Bu kişi için kullanılabilir bir anahtar yok.\İkinizin de çevrim içi durum aboneliği oldudğundan emin olun. + Bu kişi için kullanılabilir bir anahtar yok. +\nİkinizin de çevrim içi durum aboneliği oldudğundan emin olun. Bir şeyler ters gitti Sunucudan geçmiş alınıyor Sunucuda başka geçmiş kalmadı @@ -482,7 +489,7 @@ Sertifika çözümlenemedi Arşivleme tercihleri Sunucu tarafı arşivleme tercihleri - Arşivleme tercihleri alınıyor. Lütfen bekleyin... + Arşivleme tercihleri alınıyor. Lütfen bekleyin… Arşivleme tercihleri alınamadı CAPTCHA gerekli Resimdeki yazıyı girin @@ -513,7 +520,10 @@ %1$s\'ın harici depolama erişimine izin ver %1$s\'ın kamera erişimine izin ver Kişilerle senkronize et - %1$s XMPP listenizi telefon rehberinizle eşleştirmek için izin istiyor. Böylelikle, tüm rehberinizindeki kişilerin tam adları ve avatarlarını görebileceksiniz. \n\n%1$s kişilerinizi sunucunuza yüklemeyecek olup, sadece cihazınız üzerinden eşleştirme yapacaktır. + %1$s XMPP listenizi telefon rehberinizle eşleştirmek için izin istiyor. +\nBöylelikle, tüm rehberinizindeki kişilerin tam adları ve avatarlarını görebileceksiniz. +\n +\n%1$s kişilerinizi sunucunuza yüklemeyecek olup, sadece cihazınız üzerinden eşleştirme yapacaktır. Tüm iletilerde uyar Yalnızca bahsedilğinde haber ver Uyarılar devre dışı @@ -535,7 +545,7 @@ Bu hesabı devre dışı bıraktınız Güvenlik hatası: Geçersiz dosya erişimi! URL paylaşacak uygulama bulunamadı - URI paylaş ile... + URI paylaş ile… Kabul et ve devam et Conversations\'da hesap kurulum için bir rehber hazırlanmıştır.¹\nConversations.im\'i bir sağlayıcı olarak seçtikten sonra başka sağlayıcılar kullanan kullanıcılarla onlara tam XMPP adresinizi vererek iletişim kurabilirsiniz. Tam XMPP adresiniz %s olacak @@ -555,7 +565,7 @@ Hesap oluşturulamadı: Sonra yeniden deneyin Kayıt Başarısız: Parola çok zayıf Katılımcıları seç - Grup konuşması oluşturuluyor... + Grup konuşması oluşturuluyor… Yeniden davet et Devre dışı bırak Kısa @@ -625,7 +635,8 @@ Aktif olmayanları göster Aktif olmayanları sakla Güvensiz aygıt - Bu cihazın doğrulamasını kaldırmak istediğinizden emin misiniz\? Bu cihaz ve cihazdan gelen mesajlar güvenilmez olarak işaretlenecektir. + Bu cihazın doğrulamasını kaldırmak istediğinizden emin misiniz\? +\nBu cihaz ve cihazdan gelen mesajlar güvenilmez olarak işaretlenecektir. %d saniye %d saniye @@ -655,7 +666,7 @@ İletiyi şifrelemek Yerel saklama süresi nedeniyle ileti getirilmiyor. Video sıkıştırılıyor - Konuşma sonlandı + Konuşma sonlandı. Kişi engellendi. Yabancılardan bildirimler Yabancılardan alınan ileti ve aramaları bildir. @@ -716,8 +727,8 @@ Küçük Orta Büyük - İleti bu cihaz için şifrelenmedi - OMEMO mesajı çözümlenemedi + İleti bu cihaz için şifrelenmedi. + OMEMO mesajı çözümlenemedi. geri al Konum paylaşımı devre dışı bırakıldı Konumu sabitle @@ -729,7 +740,7 @@ Konumu göster Paylaş Kayıt başlatılamadı - Lütfen bekleyin... + Lütfen bekleyin… %1$s\'ın mikrofon erişimine izin ver İleti ara GIF @@ -755,7 +766,7 @@ Bu bildirim kategorisi %1$s\'ın çalıştığını sürekli belirtmekte kullanmaktadır. Durum bilgisi Bağlantı Sorunları - Bu bildirim kategorisi, bir hesaba bağlanmakta sorun olduğunu belirtmekte kullanılır + Bu bildirim kategorisi, bir hesaba bağlanmakta sorun olduğunu belirtmekte kullanılır. İletiler Aramalar İletiler @@ -763,7 +774,7 @@ Yapılan aramalar Cevapsız aramalar Sessiz iletiler - Bu bildirim grubu, bildirimlerin herhangi bir ses çıkarmaması gerektiğini belirtmekte kullanılır. Mesela başka bir cihazda aktif olunduğunda (Mühlet) + Bu bildirim grubu, bildirimlerin herhangi bir ses çıkarmaması gerektiğini belirtmekte kullanılır. Mesela başka bir cihazda aktif olunduğunda (Mühlet). Başarısız gönderiler İleti bildirim ayarları Gelen arama bildirimleri ayarları @@ -772,13 +783,13 @@ Medyayı görüntüle Katılımcılar Medya tarayıcısı - Dosya güvenlik ihlalinden dolayı dahil edilmedi + Dosya güvenlik ihlalinden dolayı dahil edilmedi. Video kalitesi Daha düşük kalite, daha ufak dosya anlamına gelir Orta (360P) Yüksek (720p) iptal edildi - Zaten taslak halinde bir iletiniz var + Zaten taslak halinde bir iletiniz var. Özellik uygulanmadı Geçersiz ülke kodu Bir ülke seçin @@ -797,25 +808,25 @@ Tekrar sms gönder (%s) Lütfen bekleyin (%s) geri - Olası kod, otomatik olarak panodan yapıştırıldı + Olası kod, otomatik olarak panodan yapıştırıldı. Lütfen 6 haneli kodu girin. Kayıt sürecini iptal etmek istediğinizden emin misiniz? Evet Hayır - Doğrulanıyor... - SMS talep ediliyor... - Girdiğiniz kod yanlış - Girdiğiniz kodun tarihi geçmiş - Bilinmeyen ağ hatası - Sunucudan bilinmeyen cevap - Sunucuya bağlanılamadı - Güvenli bağlantı oluşturulamadı - Sunucu bulunamadı - Talebinizin işlenmesinde bir hata meydana geldi + Doğrulanıyor… + SMS talep ediliyor… + Girdiğiniz kod yanlış. + Girdiğiniz kodun tarihi geçmiş. + Bilinmeyen ağ hatası. + Sunucudan bilinmeyen cevap. + Sunucuya bağlanılamadı. + Güvenli bağlantı oluşturulamadı. + Sunucu bulunamadı. + Talebinizin işlenmesinde bir hata meydana geldi. Geçersiz kullanıcı girişi Geçici olarak ulaşılamıyor. Daha sonra tekrar deneyiniz. - Ağ bağlantısı yok - Lütfen %s içerisinde tekrar deneyiniz. + Ağ bağlantısı yok. + Lütfen %s içerisinde tekrar deneyiniz Sınırlandınız Çok fazla girişim Bu uygulamamının tarihi geçmiş bir versiyonunu kullanıyorsunuz. @@ -824,22 +835,22 @@ Adres defterlerinde sizin kim olduğunuzu bilmeyen kişilerin sizi tanıması için lütfen isminizi girin. Adınız Adınızı girin - Adınızı belirlemek için düzenle tuşunu kullanın + Adınızı belirlemek için düzenle tuşunu kullanın. Talebi reddet Orbot\'u yükle Orbot\'u başlat - Herhangi bir mağaza uygulaması yüklenmedi - Bu kanal XMPP adresinizi herkese açık hale getirecek. + Herhangi bir mağaza uygulaması yüklenmedi. + Bu kanal XMPP adresinizi herkese açık hale getirecek e-kitap Orijinal (sıkıştırılmamış) - Şununla aç... + Şununla aç… Conversations profil resmi Hesap seç Yedekleri yükle Geri getir Yedekleri geri getirmek için %s hesabının şifrenizi girin. Herhangi bir yüklemeyi klonlama (aynı anda çalışan) girişiminde yedekleri geri yükleme özelliğini kullanmayın. Yedeklerin geri yüklenmesi sadece hesap aktarımları veya asıl cihazı kaybetmeniz durumu için kullanılmalıdır. - Yedekler geri yüklenemedi + Yedekler geri yüklenemedi. Yedekleme çözülemedi. Şifre doğru mu? Yedekleme & Geri yükle XMPP adresini girin @@ -852,15 +863,15 @@ Lütfen kanal için bir isim belirleyin Lütfen bir XMPP adresi sağlayın Bu bir XMPP adresi. Lütfen bir isim belirleyin. - Ortak kanal oluşturuluyor... + Ortak kanal oluşturuluyor… Bu kanal zaten var Varolan bir kanala katıldınız Kanal ayarları kaydedilemedi Herhangi birinin başlığı düzenlemesine izin ver Herhangi birinin davet etmesine izin ver Herhangi biri başlığı düzenleyebilir. - Yöneticiler başlığı düzenleyebilir - Yöneticiler başlığı düzenleyebilir + Yöneticiler başlığı düzenleyebilir. + Yöneticiler başlığı düzenleyebilir. Yöneticiler başkalarını davet edebilir. Herhangi biri başkalarını davet edebilir. XMPP adresleri yöneticelere görünür. @@ -888,8 +899,8 @@ Bu hesap zaten kurulu vaziyette Lütfen bu hesabın şifresini girin Eylem gerçekleştirilemedi - Ortak kanala katılınıyor - Paylaşımda bulunan uygulama dosya erişimi için yetki sağlamıyor + Ortak kanala katılınıyor… + Paylaşımda bulunan uygulama dosya erişimi için yetki sağlamıyor. jabber.network Yerel sunucu From e9883574a515603bf08b5785a8bbafd5e181e37f Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Thu, 26 Oct 2023 07:53:51 +0000 Subject: [PATCH 261/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (970 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 70 +++++++++++++------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index bead6755d..179929bf2 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -36,7 +36,7 @@ 解密消息中。请稍候… OpenPGP 加密的消息 此昵称已在使用中 - 无效的昵称 + 昵称无效 管理员 所有者 主持人 @@ -174,7 +174,7 @@ 注册令牌无效 TLS 协商失败 域名无法验证 - 违反政策 + 违反策略 不兼容的服务器 不兼容的客户端 流错误 @@ -192,13 +192,13 @@ \n对方将无法再向您发送 OpenPGP 加密消息。 OpenPGP 公钥已发布。 启用账号 - 是否确定要删除账号?删除账号会擦除您的全部对话历史记录 + 是否确定要删除账号?删除账号会擦除全部对话历史记录 录制语音 XMPP 地址 屏蔽 XMPP 地址 username@example.com 密码 - 这不是有效的 XMPP 地址 + 此 XMPP 地址无效 空间不足。图片太大 是否要添加 %s 到您的通讯录中? 服务器信息 @@ -278,7 +278,7 @@ 服务器不支持发布头像 私聊 至 %s - 发送私人消息至 %s + 发送私信至 %s 连接 此账号已存在 下一步 @@ -380,7 +380,7 @@ \n无法从服务器获取新密钥。也许是对方的服务器出了问题?
对方没有可用的密钥。 \n确保双方都有在线状态订阅。 - 出了问题 + 出了点问题 正在从服务器获取历史记录 服务器上没有更多历史记录 正在更新… @@ -427,7 +427,7 @@ 标记为已读 输入 Enter 即发送 - 使用 Enter 键发送消息。即使禁用此选项,您始终可以使用 Ctrl+Enter 发送消息。 + 使用 Enter 键发送消息。即使禁用此选项,始终可以使用 Ctrl+Enter 发送消息。 显示 Enter 键 将表情符号键替换为 Enter 键 音频 @@ -472,7 +472,7 @@ 最近使用 选择快捷操作 搜索联系人 - 发送私人消息 + 发送私信 %1$s 离开了群聊 用户名 用户名 @@ -481,7 +481,7 @@ 下载失败:文件未找到 下载失败:无法连接到主机 下载失败:无法写入文件 - 下载失败:无效文件 + 下载失败:文件无效 Tor 网络不可用 绑定失败 服务器不能为域名做出响应 @@ -575,7 +575,7 @@ 没空 忙碌 已生成安全密码 - 设备不支持选择退出电池优化 + 设备不支持退出电池优化 注册失败:稍后再试 注册失败:密码太弱 选择参与者 @@ -586,7 +586,7 @@ 广播使用 - 让对方知道您使用 Conversations 的时间 + 让您的联系人知道您最后使用 Conversations 的时间 隐私 主题 选择主题颜色 @@ -619,13 +619,13 @@ 显示出错消息 出错消息 省流量模式已启用 - 您的操作系统正限制 %1$s 在后台时访问互联网。要接收新消息通知,您应当在“省流量模式”开启时允许 %1$s 无限制访问。 + 操作系统正限制 %1$s 在后台时访问互联网。要接收新消息通知,应当在“省流量模式”开启时允许 %1$s 无限制访问。 \n%1$s 仍将在可能的情况下努力节省数据。 设备不支持对 %1$s 禁用省流量模式。 无法创建临时文件 此设备已通过验证 复制指纹 - 您已验证了您拥有的所有 OMEMO 密钥 + 您已验证您拥有的所有 OMEMO 密钥 二维码中不包含此对话的指纹。 已验证的指纹 使用相机扫描对方二维码 @@ -643,12 +643,12 @@ 清理私人存储空间 清理保存文件的私人存储(它们可以从服务器重新下载) 我从可信来源收到此链接 - 点击链接后,您将验证 %1$s 的 OMEMO 密钥。只有当您从可信来源(只有 %2$s 可以发布此链接)收到此链接时,这才是安全的。 - 您将验证自己账号的 OMEMO 密钥。只有当您从可信来源(只有您可以发布此链接)收到此链接时,这才是安全的。 + 点击链接后,您将验证 %1$s 的 OMEMO 密钥。只有从可信来源(只有 %2$s 可以发布此链接)收到此链接才是安全的。 + 您将验证自己账号的 OMEMO 密钥。只有从可信来源(只有您可以发布此链接)收到此链接才是安全的。 继续 验证 OMEMO 密钥 - 显示不活跃的设备 - 隐藏不活跃的设备 + 显示非活动设备 + 隐藏非活动设备 不再信任设备 是否确定要移除此设备的验证? \n将此设备及其消息标记为“不信任的”。 @@ -701,7 +701,7 @@ 复制到剪贴板 消息已复制到剪贴板 消息 - 已禁用私人消息 + 已禁用私信 受保护的应用 为了在屏幕关闭时也能收到消息提醒,您需要将 Conversations 加入受保护的应用列表。 接受未知的证书? @@ -711,7 +711,7 @@ 是否仍要连接? 证书详情: 仅一次 - 二维码扫描器需要访问相机 + 需要访问相机来扫描二维码 滚动至底部 发送消息后向下滚屏 编辑状态信息 @@ -722,7 +722,7 @@ 无法获取密钥 提示:某些情况下,可以通过双方添加到联系人列表来解决此问题。 是否确定要禁用此对话的 OMEMO 加密? -\n这将允许服务器管理员阅读您的消息,但这可能是与使用过时客户端的用户交流的唯一方法。 +\n这将允许服务器管理员读取您的消息,但这可能是与使用过时客户端的用户交流的唯一方法。 立即禁用 草稿: OMEMO 加密 @@ -740,7 +740,7 @@ 消息未对本设备加密。 解密 OMEMO 消息失败。 撤销 - 位置分享已禁用 + 已禁用位置共享 固定位置 取消固定位置 复制位置 @@ -755,11 +755,11 @@ 搜索消息 GIF 查看对话 - 分享位置插件 - 使用分享位置插件代替内置地图 + 位置共享插件 + 使用“位置共享插件”代替内置地图 复制 web 地址 复制 XMPP 地址 - 用于 S3 的 HTTP 文件分享 + 用于 S3 的 HTTP 文件共享 直接搜索 在“开始对话”屏幕上打开键盘并将光标放在搜索栏中 群聊头像 @@ -784,13 +784,13 @@ 正在进行的通话 未接来电 静音消息 - 此通知组用于显示不应触发任何声音的通知。 例如,在另一台设备上处于活跃状态时(静默期)。 + 此通知组用于显示不应触发任何声音的通知。例如,在另一台设备上处于活动状态时(静默期)。 传递失败 消息通知设置 来电通知设置 重要性、声音、振动 视频压缩 - 查看媒体文件 + 查看媒体 参与者 媒体浏览器 由于违反安全规定,文件已删除。 @@ -827,12 +827,12 @@ 正在请求短信… 您输入的 PIN 码有误。 我们发送给您的 PIN 码已过期。 - 未知网络错误。 - 未知服务器响应。 + 未知的网络错误。 + 服务器响应未知。 无法连接到服务器。 无法建立安全连接。 无法找到服务器。 - 处理您的请求时出了问题。 + 处理请求时出了问题。 用户输入无效 暂时不可用。稍后再试。 无网络连接。 @@ -899,18 +899,18 @@ 添加已有账号 注册新账号 这看起来像是域名地址 - 无论如何都要添加 + 仍要添加 这看起来像是频道地址 分享备份文件 Conversations 备份 事件 打开备份 - 您所选的文件不是 Conversations 备份文件 + 所选的文件不是 Conversations 备份文件 此账号已完成设置 请输入此账号的密码 无法执行此操作 加入公开频道… - 分享应用未授予访问此文件的权限。 + 共享应用未授予访问此文件的权限。 群聊 & 频道 jabber.network 本地服务器 @@ -933,7 +933,7 @@ 忽略 正在发现设备 正在响铃 - 占线 + 正忙 无法连接通话 连接已中断 已撤回通话 @@ -994,8 +994,8 @@ 邀请至 Conversations 无法解析邀请 服务器不支持生成邀请 - 没有活跃账号支持此功能 - 备份已开始。一旦完成,您将会收到通知。 + 没有活动账号支持此功能 + 备份已开始。一旦完成,将会收到通知。 无法启用视频。 纯文本文档 不支持账号注册 From 4f82f8b8161f811a07218f0a120a3182a1bbe4d5 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Thu, 26 Oct 2023 07:48:29 +0000 Subject: [PATCH 262/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (9 of 9 strings) Translation: Conversations/Android App (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-quicksy/zh_Hans/ --- src/quicksy/res/values-zh-rCN/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/quicksy/res/values-zh-rCN/strings.xml b/src/quicksy/res/values-zh-rCN/strings.xml index 7bbb85c6c..0e12958dc 100644 --- a/src/quicksy/res/values-zh-rCN/strings.xml +++ b/src/quicksy/res/values-zh-rCN/strings.xml @@ -1,8 +1,8 @@ - Quicksy 发现另一台设备上的活动后在此期间保持安静 + 发现另一台设备上的活动后,Quicksy 在此期间保持安静 通过发送堆栈跟踪,您正在帮助 Quicksy 的持续开发 - 让对方知道您使用 Quicksy 的时间 + 让您的所有联系人知道您最后使用 Quicksy 的时间 为了在屏幕关闭时也能收到消息提醒,您需要将 Quicksy 加入受保护的应用列表。 Quicksy 个人资料图片 Quicksy 在您所在的国家/地区无法使用。 From b0795db9abc3447dfa0cdc4f619e3407815fa2a8 Mon Sep 17 00:00:00 2001 From: gallegonovato Date: Thu, 26 Oct 2023 15:40:32 +0000 Subject: [PATCH 263/402] Translated using Weblate (Spanish) Currently translated at 100.0% (52 of 52 strings) Translation: Conversations/App Store Metadata (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/es/ --- fastlane/metadata/android/es-ES/changelogs/393.txt | 3 +++ fastlane/metadata/android/es-ES/changelogs/394.txt | 2 ++ fastlane/metadata/android/es-ES/changelogs/395.txt | 3 +++ fastlane/metadata/android/es-ES/changelogs/397.txt | 3 +++ fastlane/metadata/android/es-ES/changelogs/398.txt | 4 ++++ fastlane/metadata/android/es-ES/changelogs/401.txt | 2 ++ fastlane/metadata/android/es-ES/changelogs/402.txt | 3 +++ fastlane/metadata/android/es-ES/changelogs/403.txt | 3 +++ fastlane/metadata/android/es-ES/changelogs/404.txt | 1 + fastlane/metadata/android/es-ES/changelogs/405.txt | 1 + fastlane/metadata/android/es-ES/changelogs/407.txt | 3 +++ fastlane/metadata/android/es-ES/changelogs/42000.txt | 4 ++++ fastlane/metadata/android/es-ES/changelogs/42006.txt | 2 ++ fastlane/metadata/android/es-ES/changelogs/42010.txt | 2 ++ fastlane/metadata/android/es-ES/changelogs/42012.txt | 1 + fastlane/metadata/android/es-ES/changelogs/42013.txt | 1 + fastlane/metadata/android/es-ES/changelogs/42014.txt | 2 ++ fastlane/metadata/android/es-ES/changelogs/42015.txt | 1 + fastlane/metadata/android/es-ES/changelogs/42018.txt | 3 +++ fastlane/metadata/android/es-ES/changelogs/42022.txt | 2 ++ fastlane/metadata/android/es-ES/changelogs/42023.txt | 2 ++ fastlane/metadata/android/es-ES/changelogs/42037.txt | 11 +++++++++++ fastlane/metadata/android/es-ES/changelogs/42038.txt | 2 ++ fastlane/metadata/android/es-ES/changelogs/42041.txt | 5 +++++ fastlane/metadata/android/es-ES/changelogs/42042.txt | 2 ++ fastlane/metadata/android/es-ES/changelogs/42043.txt | 1 + fastlane/metadata/android/es-ES/changelogs/42044.txt | 3 +++ fastlane/metadata/android/es-ES/changelogs/42046.txt | 1 + fastlane/metadata/android/es-ES/changelogs/42047.txt | 1 + fastlane/metadata/android/es-ES/changelogs/42050.txt | 1 + fastlane/metadata/android/es-ES/changelogs/42059.txt | 2 ++ fastlane/metadata/android/es-ES/changelogs/42060.txt | 1 + fastlane/metadata/android/es-ES/changelogs/42061.txt | 1 + fastlane/metadata/android/es-ES/changelogs/42062.txt | 1 + fastlane/metadata/android/es-ES/changelogs/42065.txt | 1 + fastlane/metadata/android/es-ES/changelogs/42068.txt | 2 ++ fastlane/metadata/android/es-ES/changelogs/42072.txt | 3 +++ fastlane/metadata/android/es-ES/changelogs/42076.txt | 3 +++ 38 files changed, 89 insertions(+) create mode 100644 fastlane/metadata/android/es-ES/changelogs/393.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/394.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/395.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/397.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/398.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/401.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/402.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/403.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/404.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/405.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/407.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42000.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42006.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42010.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42012.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42013.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42014.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42015.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42018.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42022.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42023.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42037.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42038.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42041.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42042.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42043.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42044.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42046.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42047.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42050.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42059.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42060.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42061.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42062.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42065.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42068.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42072.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/42076.txt diff --git a/fastlane/metadata/android/es-ES/changelogs/393.txt b/fastlane/metadata/android/es-ES/changelogs/393.txt new file mode 100644 index 000000000..e6f08c87a --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/393.txt @@ -0,0 +1,3 @@ +* Mostrar botón de ayuda si falla la llamada A/V +* Corregidos algunos fallos molestos +* Corregidas conexiones Jingle (transferencia de archivos + llamadas) con JIDs sin ocultar diff --git a/fastlane/metadata/android/es-ES/changelogs/394.txt b/fastlane/metadata/android/es-ES/changelogs/394.txt new file mode 100644 index 000000000..72b50cdfb --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/394.txt @@ -0,0 +1,2 @@ +* Se ha corregido el problema de las notificaciones que no aparecían en determinadas circunstancias. +* Se han solucionado problemas de compatibilidad y bloqueos relacionados con las llamadas A/V diff --git a/fastlane/metadata/android/es-ES/changelogs/395.txt b/fastlane/metadata/android/es-ES/changelogs/395.txt new file mode 100644 index 000000000..7fd679913 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/395.txt @@ -0,0 +1,3 @@ +* Añadir 'Volver al chat' a la pantalla de llamada de audio +* Mejorar los atajos del teclado +* corrección de errores diff --git a/fastlane/metadata/android/es-ES/changelogs/397.txt b/fastlane/metadata/android/es-ES/changelogs/397.txt new file mode 100644 index 000000000..5bf18c91d --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/397.txt @@ -0,0 +1,3 @@ +* Gestión de archivos GPX +* Mejorar el rendimiento de la restauración de las copias de seguridad +* Corrección de errores diff --git a/fastlane/metadata/android/es-ES/changelogs/398.txt b/fastlane/metadata/android/es-ES/changelogs/398.txt new file mode 100644 index 000000000..b665a46bd --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/398.txt @@ -0,0 +1,4 @@ +* Buscar conversaciones individuales +* Notificar al usuario si falla la entrega del mensaje +* Recordar los nombres de usuario (nicks) de los usuarios de Quicksy en los reinicios +* Añadir el botón para iniciar Orbot (Tor) desde la notificación si es necesario diff --git a/fastlane/metadata/android/es-ES/changelogs/401.txt b/fastlane/metadata/android/es-ES/changelogs/401.txt new file mode 100644 index 000000000..f0818cbe9 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/401.txt @@ -0,0 +1,2 @@ +* búsqueda fija en Android <= 5 +* optimizar el consumo de la memoria diff --git a/fastlane/metadata/android/es-ES/changelogs/402.txt b/fastlane/metadata/android/es-ES/changelogs/402.txt new file mode 100644 index 000000000..079ced197 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/402.txt @@ -0,0 +1,3 @@ +* Ofrece la generación de invitaciones fáciles en los servidores compatibles +* Mostrar GIFs enviados desde Movim +* Almacenar avatares en caché diff --git a/fastlane/metadata/android/es-ES/changelogs/403.txt b/fastlane/metadata/android/es-ES/changelogs/403.txt new file mode 100644 index 000000000..3a4c6b698 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/403.txt @@ -0,0 +1,3 @@ +* Corregidos problemas de conectividad cuando diferentes cuentas utilizaban diferentes mecanismos SCRAM. +* Añadir soporte para SCRAM-SHA-512 +* Permitir la transferencia de archivos P2P (Jingle) con autocontacto diff --git a/fastlane/metadata/android/es-ES/changelogs/404.txt b/fastlane/metadata/android/es-ES/changelogs/404.txt new file mode 100644 index 000000000..c594e57cd --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/404.txt @@ -0,0 +1 @@ +* Pequeñas mejoras de estabilidad en las llamadas A/V diff --git a/fastlane/metadata/android/es-ES/changelogs/405.txt b/fastlane/metadata/android/es-ES/changelogs/405.txt new file mode 100644 index 000000000..a341b6579 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/405.txt @@ -0,0 +1 @@ +* Quicksy: Recibir automáticamente SMS de verificación diff --git a/fastlane/metadata/android/es-ES/changelogs/407.txt b/fastlane/metadata/android/es-ES/changelogs/407.txt new file mode 100644 index 000000000..3958fd6ef --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/407.txt @@ -0,0 +1,3 @@ +* Mostrar botón de llamada para contactos desconectados si previamente anunciaron soporte +* El botón Atrás ya no finaliza la llamada cuando está conectada. +* Corrección de errores diff --git a/fastlane/metadata/android/es-ES/changelogs/42000.txt b/fastlane/metadata/android/es-ES/changelogs/42000.txt new file mode 100644 index 000000000..8ad2c5472 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42000.txt @@ -0,0 +1,4 @@ +* Posibilidad de seleccionar el tono de la llamada entrante +* Corrección de la identificación de claves OpenPGP para OpenKeychain 5.6+. +* Verificación correcta de los certificados TLS punycode +* Mejora de la estabilidad del establecimiento de sesiones RTP (llamadas) diff --git a/fastlane/metadata/android/es-ES/changelogs/42006.txt b/fastlane/metadata/android/es-ES/changelogs/42006.txt new file mode 100644 index 000000000..eb1ea92f4 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42006.txt @@ -0,0 +1,2 @@ +* Verificar llamadas A/V con sesiones OMEMO preexistentes +* Mejorar la compatibilidad con implementaciones WebRTC no libwebrtc diff --git a/fastlane/metadata/android/es-ES/changelogs/42010.txt b/fastlane/metadata/android/es-ES/changelogs/42010.txt new file mode 100644 index 000000000..41e1148ba --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42010.txt @@ -0,0 +1,2 @@ +* Varias correcciones de errores en torno a la compatibilidad con Tor +* Mejora de la compatibilidad de llamadas con Dino diff --git a/fastlane/metadata/android/es-ES/changelogs/42012.txt b/fastlane/metadata/android/es-ES/changelogs/42012.txt new file mode 100644 index 000000000..814a09be7 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42012.txt @@ -0,0 +1 @@ +* Corrección de la carga/descarga HTTP para usuarios que no confían en las CA del sistema diff --git a/fastlane/metadata/android/es-ES/changelogs/42013.txt b/fastlane/metadata/android/es-ES/changelogs/42013.txt new file mode 100644 index 000000000..e31ca2cab --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42013.txt @@ -0,0 +1 @@ +* Solucionados los problemas de 'No Conectividad' en Android 7.1 diff --git a/fastlane/metadata/android/es-ES/changelogs/42014.txt b/fastlane/metadata/android/es-ES/changelogs/42014.txt new file mode 100644 index 000000000..a06654b64 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42014.txt @@ -0,0 +1,2 @@ +* Verificar siempre el nombre del dominio. No sobrescribir al usuario +* Soporta pre autenticación de roster diff --git a/fastlane/metadata/android/es-ES/changelogs/42015.txt b/fastlane/metadata/android/es-ES/changelogs/42015.txt new file mode 100644 index 000000000..ad8b35003 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42015.txt @@ -0,0 +1 @@ +* pequeñas mejoras en A/V diff --git a/fastlane/metadata/android/es-ES/changelogs/42018.txt b/fastlane/metadata/android/es-ES/changelogs/42018.txt new file mode 100644 index 000000000..25ec35a9b --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42018.txt @@ -0,0 +1,3 @@ +* Mostrar barras negras cuando el vídeo remoto no coincide con la relación del aspecto de la pantalla. +* Mejorar el rendimiento de la búsqueda +* Añadir configuración para evitar capturas de pantalla diff --git a/fastlane/metadata/android/es-ES/changelogs/42022.txt b/fastlane/metadata/android/es-ES/changelogs/42022.txt new file mode 100644 index 000000000..db5c79bc7 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42022.txt @@ -0,0 +1,2 @@ +* Corrección de un problema que impedía comprimir algunos vídeos. +* Corrección de un fallo poco frecuente al abrir una notificación diff --git a/fastlane/metadata/android/es-ES/changelogs/42023.txt b/fastlane/metadata/android/es-ES/changelogs/42023.txt new file mode 100644 index 000000000..0a1dd4ce3 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42023.txt @@ -0,0 +1,2 @@ +* Corrección de fallos en la representación de algunas citas +* Corrección del fallo en la pantalla de bienvenida diff --git a/fastlane/metadata/android/es-ES/changelogs/42037.txt b/fastlane/metadata/android/es-ES/changelogs/42037.txt new file mode 100644 index 000000000..b10095829 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42037.txt @@ -0,0 +1,11 @@ +Versión 2.10.9 +* Pedir permisos Bluetooth al hacer llamadas A/V (Puede rechazar esto si no utiliza auriculares Bluetooth). +* Corrección de error al llamar a Movim +* Corregir avatar incorrecto que se muestra para los chats de grupo +* Preguntar siempre por las optimizaciones de batería +* Establecer sólo local bandera en 'x cuentas conectadas' notificaciones +* Corrección de la interacción con Google Maps Share Location Plugin +* Eliminar nota a pie de página con respecto a la cuota del servidor +* Almacenar archivos en la ubicación adecuada para Android 11 +* Intento de reconectar llamada tras cambio de red +* Mostrar el JID de la persona que llama y el JID de la cuenta en la pantalla de llamada entrante diff --git a/fastlane/metadata/android/es-ES/changelogs/42038.txt b/fastlane/metadata/android/es-ES/changelogs/42038.txt new file mode 100644 index 000000000..0864d1d84 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42038.txt @@ -0,0 +1,2 @@ +* Corrección de errores menores +* Restaurar la capacidad de llamar a través de JMP y otros servicios (versión Playstore) diff --git a/fastlane/metadata/android/es-ES/changelogs/42041.txt b/fastlane/metadata/android/es-ES/changelogs/42041.txt new file mode 100644 index 000000000..03c4e761a --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42041.txt @@ -0,0 +1,5 @@ +* Implementación del perfil SASL extensible, Bind 2.0 y Fast para reconexiones más rápidas. +* Implementación de Channel Binding +* Añadir la posibilidad de cambiar de llamada de audio a videollamada +* Añadir la posibilidad de eliminar el propio avatar +* Notificación de llamadas perdidas diff --git a/fastlane/metadata/android/es-ES/changelogs/42042.txt b/fastlane/metadata/android/es-ES/changelogs/42042.txt new file mode 100644 index 000000000..288d6502a --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42042.txt @@ -0,0 +1,2 @@ +* Corrección del bucle de reenvío en servidores que sólo admiten sm:2 +* Mostrar "Cambiar a vídeo" sólo si la otra parte admite vídeo diff --git a/fastlane/metadata/android/es-ES/changelogs/42043.txt b/fastlane/metadata/android/es-ES/changelogs/42043.txt new file mode 100644 index 000000000..131ea2911 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42043.txt @@ -0,0 +1 @@ +* Corregida una regresión en la transferencia de archivos P2P diff --git a/fastlane/metadata/android/es-ES/changelogs/42044.txt b/fastlane/metadata/android/es-ES/changelogs/42044.txt new file mode 100644 index 000000000..1b98bb2aa --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42044.txt @@ -0,0 +1,3 @@ +* Corrección del reenvío de mensajes al utilizar SASL2 +* Corregir vídeo negro entre algunos dispositivos +* Arreglar fallo en contraseñas vacías diff --git a/fastlane/metadata/android/es-ES/changelogs/42046.txt b/fastlane/metadata/android/es-ES/changelogs/42046.txt new file mode 100644 index 000000000..f1576f520 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42046.txt @@ -0,0 +1 @@ +* Integrar el Distribuidor UnifiedPush para facilitar los mensajes push a otras aplicaciones habilitadas para UnifiedPush como Tusky y Fedilab diff --git a/fastlane/metadata/android/es-ES/changelogs/42047.txt b/fastlane/metadata/android/es-ES/changelogs/42047.txt new file mode 100644 index 000000000..8f3909b76 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42047.txt @@ -0,0 +1 @@ +* Corrección de fallos en el distribuidor de UnifiedPush diff --git a/fastlane/metadata/android/es-ES/changelogs/42050.txt b/fastlane/metadata/android/es-ES/changelogs/42050.txt new file mode 100644 index 000000000..fff8b62cb --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42050.txt @@ -0,0 +1 @@ +* Aumentar el radio de las esquinas en las fotos de perfil diff --git a/fastlane/metadata/android/es-ES/changelogs/42059.txt b/fastlane/metadata/android/es-ES/changelogs/42059.txt new file mode 100644 index 000000000..3a6ce0d00 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42059.txt @@ -0,0 +1,2 @@ +* Actualizar Target SDK a 33 de nuevo +* Corrección de problemas en servidores que soportan SASL2 sin Stream Management en línea diff --git a/fastlane/metadata/android/es-ES/changelogs/42060.txt b/fastlane/metadata/android/es-ES/changelogs/42060.txt new file mode 100644 index 000000000..624c64e92 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42060.txt @@ -0,0 +1 @@ +* Arreglar 'q' falsamente siendo reconocido como cirílico diff --git a/fastlane/metadata/android/es-ES/changelogs/42061.txt b/fastlane/metadata/android/es-ES/changelogs/42061.txt new file mode 100644 index 000000000..da7a92ab9 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42061.txt @@ -0,0 +1 @@ +* Eliminar la función de descubrimiento de canales de la versión de Google Play diff --git a/fastlane/metadata/android/es-ES/changelogs/42062.txt b/fastlane/metadata/android/es-ES/changelogs/42062.txt new file mode 100644 index 000000000..c1729884a --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42062.txt @@ -0,0 +1 @@ +* Desactivar la apertura de archivos de copia de seguridad (.ceb) desde el gestor de archivos diff --git a/fastlane/metadata/android/es-ES/changelogs/42065.txt b/fastlane/metadata/android/es-ES/changelogs/42065.txt new file mode 100644 index 000000000..eceb051e1 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42065.txt @@ -0,0 +1 @@ +* Introducir un nuevo formato de archivo de copia de seguridad diff --git a/fastlane/metadata/android/es-ES/changelogs/42068.txt b/fastlane/metadata/android/es-ES/changelogs/42068.txt new file mode 100644 index 000000000..b651cc178 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42068.txt @@ -0,0 +1,2 @@ +* soporte para los ajustes de la notificación de la conversación +* usar opus para mensajes de voz en Android 10 diff --git a/fastlane/metadata/android/es-ES/changelogs/42072.txt b/fastlane/metadata/android/es-ES/changelogs/42072.txt new file mode 100644 index 000000000..a4b7e971d --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42072.txt @@ -0,0 +1,3 @@ +* Aumenta la dependencia de libwebrtc a M117 y aumenta la de libvpx. +* Volver a AAC para mensajes de voz +* Soporta ajustes de idioma por aplicación diff --git a/fastlane/metadata/android/es-ES/changelogs/42076.txt b/fastlane/metadata/android/es-ES/changelogs/42076.txt new file mode 100644 index 000000000..9396b343d --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/42076.txt @@ -0,0 +1,3 @@ +* Soporta DNS Privado (DNS sobre TLS) +* Icono temático del lanzador +* Corrección de un problema de permisos poco frecuente al compartir archivos en Android 11+ From 1b3d01d014d0b9fcbb960b6a358e9d62528f764b Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Thu, 26 Oct 2023 07:14:30 +0000 Subject: [PATCH 264/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (52 of 52 strings) Translation: Conversations/App Store Metadata (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/app-store-metadata/zh_Hans/ --- fastlane/metadata/android/zh-CN/changelogs/42014.txt | 2 +- fastlane/metadata/android/zh-CN/changelogs/42076.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fastlane/metadata/android/zh-CN/changelogs/42014.txt b/fastlane/metadata/android/zh-CN/changelogs/42014.txt index 937c7f8cc..2784135e0 100644 --- a/fastlane/metadata/android/zh-CN/changelogs/42014.txt +++ b/fastlane/metadata/android/zh-CN/changelogs/42014.txt @@ -1,2 +1,2 @@ -* 始终验证域名。 没有用户覆盖 +* 始终验证域名。没有用户覆盖 * 支持花名册预验证 diff --git a/fastlane/metadata/android/zh-CN/changelogs/42076.txt b/fastlane/metadata/android/zh-CN/changelogs/42076.txt index dfe357cc5..d07b29e61 100644 --- a/fastlane/metadata/android/zh-CN/changelogs/42076.txt +++ b/fastlane/metadata/android/zh-CN/changelogs/42076.txt @@ -1,3 +1,3 @@ -* 支持私人 DNS (DNS over TLS) +* 支持私人 DNS (DNS over TLS) * 支持主题启动器图标 * 修复在 Android 11+ 上分享文件时罕见的权限问题 From df877861776e73c3133c1b05a6576469b404da33 Mon Sep 17 00:00:00 2001 From: SomeTr Date: Fri, 27 Oct 2023 17:43:34 +0000 Subject: [PATCH 265/402] Translated using Weblate (Czech) Currently translated at 97.9% (950 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/cs/ --- src/main/res/values-cs/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/res/values-cs/strings.xml b/src/main/res/values-cs/strings.xml index 1a505ad7f..fc01b569f 100644 --- a/src/main/res/values-cs/strings.xml +++ b/src/main/res/values-cs/strings.xml @@ -103,7 +103,7 @@ Poslat nešifrované Zašifrování se nezdařilo. Možná nemáte správný privátní klíč. OpenKeychain - OpenKeychain k šifrování a dešifrování zpráv a ke správě Vašich veřejných klíčů.

OpenKeychain je vydána pod licencí GPLv3+ a dostupná na F-Droid nebo Google Play.

(Po instalaci, prosím, restartujte%1$s.)]]>
+ %1$s používá <b>OpenKeychain</b> k šifrování a dešifrování zpráv a ke správě Vašich veřejných klíčů.<br><br>OpenKeychain je vydána pod licencí GPLv3+ a dostupná na F-Droid nebo Google Play.<br><br><small>(Po instalaci, prosím, restartujte %1$s.)</small> Restartovat Instalovat Nainstalujte prosím OpenKeychain From 774d2a07cee08cdc6d77eef82c14dc1a3d54a686 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Sat, 28 Oct 2023 08:33:05 +0000 Subject: [PATCH 266/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (970 of 970 strings) Translation: Conversations/Android App (shared) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-shared/zh_Hans/ --- src/main/res/values-zh-rCN/strings.xml | 68 +++++++++++++------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index 179929bf2..dc4c686e0 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -34,7 +34,7 @@
正在发送… 解密消息中。请稍候… - OpenPGP 加密的消息 + OpenPGP 加密消息 此昵称已在使用中 昵称无效 管理员 @@ -85,19 +85,19 @@ 清空对话历史记录 是否要删除此对话中的所有消息? \n -\n警告:将不会影响存储在其他设备或服务器上的消息。 +\n警告:存储在其他设备或服务器上的消息将不受影响。
删除文件 是否确定要删除此文件? \n -\n警告:将不会删除存储在其他设备或服务器上的此文件的副本。 +\n警告:存储在其他设备或服务器上此文件的副本将不会删除。
之后关闭此对话 选择设备 - 发送未加密的消息 + 发送未加密消息 发送消息 发送消息至 %s - 发送 OMEMO 加密的消息 - 发送 v\\OMEMO 加密的消息 - 发送 OpenPGP 加密的消息 + 发送 OMEMO 加密消息 + 发送 v\\OMEMO 加密消息 + 发送 OpenPGP 加密消息 正在使用新昵称 发送未加密的 解密失败。也许您没有正确的私钥。 @@ -135,7 +135,7 @@ 从不发送崩溃报告 通过发送堆栈跟踪,您正在帮助此应用的开发 确认消息 - 让对方知道您已收到并阅读了其消息 + 让您的联系人知道您已收到并阅读了其消息 防止截屏 在切换应用时隐藏应用内容并阻止屏幕截图 用户界面 @@ -157,7 +157,7 @@ 常规 I/O 错误。也许存储空间已用完? 用来选择图片的应用未提供读取文件的足够权限。 \n -\n使用其他文件管理器选择图片 +\n请使用其他文件管理器选择图片
用来分享此文件的应用未提供足够的权限。 未知 暂时禁用 @@ -175,8 +175,8 @@ TLS 协商失败 域名无法验证 违反策略 - 不兼容的服务器 - 不兼容的客户端 + 服务器不兼容 + 客户端不兼容 流错误 流打开错误 未加密的 @@ -222,7 +222,7 @@ 最后上线于 %d 小时前 最后上线于 1 天前 最后上线于 %d 天前 - 加密的消息。请安装 OpenKeychain 以解密。 + 加密消息。请安装 OpenKeychain 解密。 发现新的 OpenPGP 加密消息 OpenPGP 密钥 ID OMEMO 指纹 @@ -295,10 +295,10 @@ 忽略 警告:在双方未更新在线状态的情况下发送此消息将会出现未知问题。 \n -\n前往“联系人详情”以验证在线状态订阅。 +\n请前往“联系人详情”以验证在线状态订阅。
安全 允许消息更正 - 允许对方发送后编辑其消息 + 允许您的联系人发送后编辑其消息 专家设置 请谨慎设置这些 关于 %s @@ -379,7 +379,7 @@ 对方没有可用的密钥。 \n无法从服务器获取新密钥。也许是对方的服务器出了问题? 对方没有可用的密钥。 -\n确保双方都有在线状态订阅。 +\n请确保双方都有在线状态订阅。
出了点问题 正在从服务器获取历史记录 服务器上没有更多历史记录 @@ -441,13 +441,13 @@ 已发布头像! 正在发送 %s 正在提供 %s - 隐藏离线的联系人 + 隐藏离线 %s 正在输入… %s 已停止输入 %s 正在输入… %s 已停止输入 输入通知 - 让对方知道您正在输入 + 让您的联系人知道您正在输入 发送位置 显示位置 未找到可以显示位置的应用 @@ -504,7 +504,7 @@ 无法获取存档首选项 需要验证码 输入上图中的文字 - 不信任的证书链 + 不受信任的证书链 XMPP 地址与证书不匹配 续订证书 获取 OMEMO 密钥时出错! @@ -554,20 +554,20 @@ 此字段是必需的 更正消息 发送更正后的消息 - 您已经安全地验证了此用户的指纹以确认信任。通过选择“完成”以确认 %s 加入群聊。 + 您已经安全地验证了此用户的指纹以确认信任。选择“完成”以确认 %s 加入群聊。 您已禁用了此账号 安全错误:文件访问无效! 未找到可以分享 URI 的应用 分享 URI 至… 同意并继续 - 在 conversations.im 上创建账号的指南已设置。 -\n当选择 conversations.im 作为提供者时,通过向其他 XMPP 用户提供您的完整地址,就能和对方交流。 + 指导您在 conversations.im 上创建账号。 +\n当选择 conversations.im 作为提供者时,向其他 XMPP 用户提供您的完整地址,就能和对方交流。 您的完整 XMPP 地址将是:%s 创建账号 使用我自己的提供者 选择您的用户名 手动更改在线状态 - 在编辑状态信息时,让对方知道您是否可以聊天。 + 在编辑状态信息时,让您的联系人知道您是否可以聊天。 状态信息 有空聊天 在线 @@ -613,8 +613,8 @@ 无法更新账号 举报此 XMPP 地址发送垃圾消息。 删除 OMEMO 身份 - 重新生成 OMEMO 密钥。对方将必须再次验证您。仅将此作为最后的方法。 - 删除所选的密钥 + 重新生成 OMEMO 密钥。您的所有联系人将必须再次验证您。仅将此作为最后的方法。 + 删除已选密钥 需要连接到网络才能发布头像。 显示出错消息 出错消息 @@ -623,7 +623,7 @@ \n%1$s 仍将在可能的情况下努力节省数据。
设备不支持对 %1$s 禁用省流量模式。 无法创建临时文件 - 此设备已通过验证 + 此设备已经过验证 复制指纹 您已验证您拥有的所有 OMEMO 密钥 二维码中不包含此对话的指纹。 @@ -651,7 +651,7 @@ 隐藏非活动设备 不再信任设备 是否确定要移除此设备的验证? -\n将此设备及其消息标记为“不信任的”。 +\n此设备及其消息将标记为“不信任的”。
%d 秒 @@ -671,7 +671,7 @@ %d 个月 自动删除消息 - 自动从此设备上删除超过配置时限的消息。 + 从此设备上自动删除超过配置时限的消息。 正在加密消息 由于本地保留期限设置,无法获取消息。 正在压缩视频 @@ -693,7 +693,7 @@ 显示顶部通知 今天 昨天 - 通过 DNSSEC 验证主机名 + 用 DNSSEC 验证主机名 将包含主机名的服务器证书视为是已验证的 证书不包含 XMPP 地址 部分 @@ -704,7 +704,7 @@ 已禁用私信 受保护的应用 为了在屏幕关闭时也能收到消息提醒,您需要将 Conversations 加入受保护的应用列表。 - 接受未知的证书? + 接受未知证书? 此服务器证书不是由已知的证书颁发机构签发的。 接受不匹配的服务器名称? 由于\"%s\",服务器无法验证。证书仅对此有效: @@ -720,7 +720,7 @@ %1$s 无法发送加密消息到 %2$s。这可能是由于对方使用了过时的服务器或者无法处理 OMEMO 的客户端。 无法获取设备列表 无法获取密钥 - 提示:某些情况下,可以通过双方添加到联系人列表来解决此问题。 + 提示:某些情况下,双方可以添加到联系人列表解决此问题。 是否确定要禁用此对话的 OMEMO 加密? \n这将允许服务器管理员读取您的消息,但这可能是与使用过时客户端的用户交流的唯一方法。 立即禁用 @@ -827,7 +827,7 @@ 正在请求短信… 您输入的 PIN 码有误。 我们发送给您的 PIN 码已过期。 - 未知的网络错误。 + 网络错误未知。 服务器响应未知。 无法连接到服务器。 无法建立安全连接。 @@ -898,9 +898,9 @@ 我已有账号 添加已有账号 注册新账号 - 这看起来像是域名地址 + 这似乎是域名地址 仍要添加 - 这看起来像是频道地址 + 这似乎是频道地址 分享备份文件 Conversations 备份 事件 @@ -986,7 +986,7 @@ 查看 %1$d 位参与者 - 一些消息无法传递 + 无法传递一些消息 传递失败 更多选项 From 67eea304c68df9bf4ac347da2473cb2c0a067f16 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Sat, 28 Oct 2023 08:19:11 +0000 Subject: [PATCH 267/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (13 of 13 strings) Translation: Conversations/Android App (Conversations) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-conversations/zh_Hans/ --- src/conversations/res/values-zh-rCN/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/conversations/res/values-zh-rCN/strings.xml b/src/conversations/res/values-zh-rCN/strings.xml index ddd19704d..058adbf1e 100644 --- a/src/conversations/res/values-zh-rCN/strings.xml +++ b/src/conversations/res/values-zh-rCN/strings.xml @@ -8,9 +8,9 @@ XMPP 是独立于提供者的即时通讯网络。您选择的任何 XMPP 服务器都可以使用此客户端。 \n不过,您可以轻松地在 conversations.im 上创建账号;特别适合与 Conversations 使用的提供者。 您已受邀加入 %1$s。我们将指导您创建账号。 -\n当选择 %1$s 作为提供者时,通过向其他 XMPP 用户提供您的完整地址,就能和对方交流。 +\n当选择 %1$s 作为提供者时,向其他 XMPP 用户提供您的完整地址,就能和对方交流。
您已受邀加入 %1$s。已为您选择了用户名。我们将指导您创建账号。 -\n通过向其他 XMPP 用户提供您的完整地址,就能和对方交流。 +\n向其他 XMPP 用户提供您的完整地址,就能和对方交流。
您的服务器邀请 配置代码格式不正确 点击分享按钮,向您的联系人发送加入 %1$s 的邀请。 From b8c5bcf559639a37c25a28aa5c7bbe459b4075a7 Mon Sep 17 00:00:00 2001 From: Outbreak2096 Date: Sat, 28 Oct 2023 07:02:46 +0000 Subject: [PATCH 268/402] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (9 of 9 strings) Translation: Conversations/Android App (Quicksy) Translate-URL: https://translate.codeberg.org/projects/conversations/android-app-quicksy/zh_Hans/ --- src/quicksy/res/values-zh-rCN/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quicksy/res/values-zh-rCN/strings.xml b/src/quicksy/res/values-zh-rCN/strings.xml index 0e12958dc..839ab36ed 100644 --- a/src/quicksy/res/values-zh-rCN/strings.xml +++ b/src/quicksy/res/values-zh-rCN/strings.xml @@ -7,6 +7,6 @@ Quicksy 个人资料图片 Quicksy 在您所在的国家/地区无法使用。 无法验证服务器身份。 - 未知的安全错误。 + 安全错误未知。 连接到服务器时超时。 \ No newline at end of file From 15042872872217537dabd5883447b0bf02ea6cc1 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 29 Oct 2023 08:32:51 +0100 Subject: [PATCH 269/402] version bump to 2.12.12 fastlane changelog version codes now use the highest version code after abi split (the F-Droid website displays that one) --- build.gradle | 4 ++-- .../android/de-DE/changelogs/{42076.txt => 4207704.txt} | 0 .../android/en-US/changelogs/{42076.txt => 4207704.txt} | 0 .../android/es-ES/changelogs/{42076.txt => 4207704.txt} | 0 .../android/it-IT/changelogs/{42076.txt => 4207704.txt} | 0 .../metadata/android/uk/changelogs/{42076.txt => 4207704.txt} | 0 .../android/zh-CN/changelogs/{42076.txt => 4207704.txt} | 0 7 files changed, 2 insertions(+), 2 deletions(-) rename fastlane/metadata/android/de-DE/changelogs/{42076.txt => 4207704.txt} (100%) rename fastlane/metadata/android/en-US/changelogs/{42076.txt => 4207704.txt} (100%) rename fastlane/metadata/android/es-ES/changelogs/{42076.txt => 4207704.txt} (100%) rename fastlane/metadata/android/it-IT/changelogs/{42076.txt => 4207704.txt} (100%) rename fastlane/metadata/android/uk/changelogs/{42076.txt => 4207704.txt} (100%) rename fastlane/metadata/android/zh-CN/changelogs/{42076.txt => 4207704.txt} (100%) diff --git a/build.gradle b/build.gradle index d0a51faa9..a6b384372 100644 --- a/build.gradle +++ b/build.gradle @@ -95,8 +95,8 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 33 - versionCode 42076 - versionName "2.12.12-beta.3" + versionCode 42077 + versionName "2.12.12" archivesBaseName += "-$versionName" applicationId "eu.siacs.conversations" resValue "string", "applicationId", applicationId diff --git a/fastlane/metadata/android/de-DE/changelogs/42076.txt b/fastlane/metadata/android/de-DE/changelogs/4207704.txt similarity index 100% rename from fastlane/metadata/android/de-DE/changelogs/42076.txt rename to fastlane/metadata/android/de-DE/changelogs/4207704.txt diff --git a/fastlane/metadata/android/en-US/changelogs/42076.txt b/fastlane/metadata/android/en-US/changelogs/4207704.txt similarity index 100% rename from fastlane/metadata/android/en-US/changelogs/42076.txt rename to fastlane/metadata/android/en-US/changelogs/4207704.txt diff --git a/fastlane/metadata/android/es-ES/changelogs/42076.txt b/fastlane/metadata/android/es-ES/changelogs/4207704.txt similarity index 100% rename from fastlane/metadata/android/es-ES/changelogs/42076.txt rename to fastlane/metadata/android/es-ES/changelogs/4207704.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/42076.txt b/fastlane/metadata/android/it-IT/changelogs/4207704.txt similarity index 100% rename from fastlane/metadata/android/it-IT/changelogs/42076.txt rename to fastlane/metadata/android/it-IT/changelogs/4207704.txt diff --git a/fastlane/metadata/android/uk/changelogs/42076.txt b/fastlane/metadata/android/uk/changelogs/4207704.txt similarity index 100% rename from fastlane/metadata/android/uk/changelogs/42076.txt rename to fastlane/metadata/android/uk/changelogs/4207704.txt diff --git a/fastlane/metadata/android/zh-CN/changelogs/42076.txt b/fastlane/metadata/android/zh-CN/changelogs/4207704.txt similarity index 100% rename from fastlane/metadata/android/zh-CN/changelogs/42076.txt rename to fastlane/metadata/android/zh-CN/changelogs/4207704.txt From 7e5bf623ae21352be2045e2d462a43d1448c01ca Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 20 Oct 2023 10:45:28 +0200 Subject: [PATCH 270/402] bump target SDK to 34 (Android 14) --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index a6b384372..f9743fa8f 100644 --- a/build.gradle +++ b/build.gradle @@ -90,11 +90,11 @@ ext { android { namespace 'eu.siacs.conversations' - compileSdkVersion 33 + compileSdkVersion 34 defaultConfig { minSdkVersion 21 - targetSdkVersion 33 + targetSdkVersion 34 versionCode 42077 versionName "2.12.12" archivesBaseName += "-$versionName" From 418d6b09a0eda97cf05646c56032a5e9691cdb1b Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 17 Oct 2023 08:19:31 +0200 Subject: [PATCH 271/402] explicitly declare foreground service type --- src/main/AndroidManifest.xml | 40 ++++++++--- .../services/XmppConnectionService.java | 67 ++++++++++++++++--- 2 files changed, 88 insertions(+), 19 deletions(-) diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index d7da25ccc..56b7865c9 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -3,8 +3,13 @@ xmlns:tools="http://schemas.android.com/tools"> - - + + + + + + + + + @@ -77,32 +92,40 @@ - + + + - @@ -150,7 +173,6 @@
+ android:exported="true"> @@ -265,7 +286,6 @@ diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 5a072e9c6..6c87fd94a 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -19,6 +19,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.PackageManager; +import android.content.pm.ServiceInfo; import android.database.ContentObserver; import android.graphics.Bitmap; import android.media.AudioManager; @@ -487,6 +488,7 @@ public class XmppConnectionService extends Service { private WakeLock wakeLock; private LruCache mBitmapCache; private final BroadcastReceiver mInternalEventReceiver = new InternalEventReceiver(); + private final BroadcastReceiver mInternalRestrictedEventReceiver = new RestrictedEventReceiver(Arrays.asList(TorServiceUtils.ACTION_STATUS)); private final BroadcastReceiver mInternalScreenEventReceiver = new InternalEventReceiver(); private static String generateFetchKey(Account account, final Avatar avatar) { @@ -1236,16 +1238,26 @@ public class XmppConnectionService extends Service { toggleForegroundService(); updateUnreadCountBadge(); toggleScreenEventReceiver(); - final IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(TorServiceUtils.ACTION_STATUS); + final IntentFilter systemBroadcastFilter = new IntentFilter(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { scheduleNextIdlePing(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); + systemBroadcastFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); } - intentFilter.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED); + systemBroadcastFilter.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED); } - registerReceiver(this.mInternalEventReceiver, intentFilter); + ContextCompat.registerReceiver( + this, + this.mInternalEventReceiver, + systemBroadcastFilter, + ContextCompat.RECEIVER_NOT_EXPORTED); + final IntentFilter exportedBroadcastFilter = new IntentFilter(); + exportedBroadcastFilter.addAction(TorServiceUtils.ACTION_STATUS); + ContextCompat.registerReceiver( + this, + this.mInternalRestrictedEventReceiver, + exportedBroadcastFilter, + ContextCompat.RECEIVER_EXPORTED); mForceDuringOnCreate.set(false); toggleForegroundService(); setupPhoneStateListener(); @@ -1315,6 +1327,7 @@ public class XmppConnectionService extends Service { public void onDestroy() { try { unregisterReceiver(this.mInternalEventReceiver); + unregisterReceiver(this.mInternalRestrictedEventReceiver); unregisterReceiver(this.mInternalScreenEventReceiver); } catch (final IllegalArgumentException e) { //ignored @@ -1396,9 +1409,26 @@ public class XmppConnectionService extends Service { private void startForegroundOrCatch(final int id, final Notification notification) { try { - startForeground(id, notification); - } catch (final IllegalStateException e) { - Log.e(Config.LOGTAG,"Could not start foreground service", e); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + final int foregroundServiceType; + if (getSystemService(PowerManager.class) + .isIgnoringBatteryOptimizations(getPackageName())) { + foregroundServiceType = ServiceInfo.FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED; + } else if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) + == PackageManager.PERMISSION_GRANTED) { + foregroundServiceType = ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE; + } else if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) + == PackageManager.PERMISSION_GRANTED) { + foregroundServiceType = ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA; + } else { + foregroundServiceType = ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE; + } + startForeground(id, notification, foregroundServiceType); + } else { + startForeground(id, notification); + } + } catch (final IllegalStateException | SecurityException e) { + Log.e(Config.LOGTAG, "Could not start foreground service", e); } } @@ -5027,11 +5057,30 @@ public class XmppConnectionService extends Service { private class InternalEventReceiver extends BroadcastReceiver { @Override - public void onReceive(Context context, Intent intent) { + public void onReceive(final Context context, final Intent intent) { onStartCommand(intent, 0, 0); } } + private class RestrictedEventReceiver extends BroadcastReceiver { + + private final Collection allowedActions; + + private RestrictedEventReceiver(final Collection allowedActions) { + this.allowedActions = allowedActions; + } + + @Override + public void onReceive(final Context context, final Intent intent) { + final String action = intent == null ? null : intent.getAction(); + if (allowedActions.contains(action)) { + onStartCommand(intent,0,0); + } else { + Log.e(Config.LOGTAG,"restricting broadcast of event "+action); + } + } + } + public static class OngoingCall { public final AbstractJingleConnection.Id id; public final Set media; From f042efd550e90ea543e91488dbbbb4b1cfeaf03c Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 18 Oct 2023 14:02:10 +0200 Subject: [PATCH 272/402] add 'log out' button to foreground notifcation this temporarily disconnects all accounts until the user opens the app again. essentially this akin to an 'Exit' button Users previously had the option to 'disable' accounts but this provides a faster way to "free up resources" until the next time the app is opened. --- .../ui/ManageAccountActivity.java | 1 + .../siacs/conversations/entities/Account.java | 10 ++ .../services/NotificationService.java | 110 +++++++++--------- .../services/XmppConnectionService.java | 56 +++++---- .../ui/ChooseContactActivity.java | 5 +- .../ui/ConversationFragment.java | 3 + .../conversations/ui/EditAccountActivity.java | 3 +- .../conversations/ui/ShortcutActivity.java | 2 +- .../ui/StartConversationActivity.java | 6 +- .../ui/adapter/AccountAdapter.java | 1 + .../conversations/utils/AccountUtils.java | 2 +- .../conversations/xmpp/XmppConnection.java | 9 +- .../res/drawable/ic_logout_white_24dp.xml | 5 + src/main/res/values/strings.xml | 6 +- 14 files changed, 131 insertions(+), 88 deletions(-) create mode 100644 src/main/res/drawable/ic_logout_white_24dp.xml diff --git a/src/conversations/java/eu/siacs/conversations/ui/ManageAccountActivity.java b/src/conversations/java/eu/siacs/conversations/ui/ManageAccountActivity.java index 888a1f13e..4446acefe 100644 --- a/src/conversations/java/eu/siacs/conversations/ui/ManageAccountActivity.java +++ b/src/conversations/java/eu/siacs/conversations/ui/ManageAccountActivity.java @@ -359,6 +359,7 @@ public class ManageAccountActivity extends XmppActivity implements OnAccountUpda private void enableAccount(Account account) { account.setOption(Account.OPTION_DISABLED, false); + account.setOption(Account.OPTION_SOFT_DISABLED, false); final XmppConnection connection = account.getXmppConnection(); if (connection != null) { connection.resetEverything(); diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index eb042a1a6..0fdece061 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -70,6 +70,7 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable public static final int OPTION_UNVERIFIED = 8; public static final int OPTION_FIXED_USERNAME = 9; public static final int OPTION_QUICKSTART_AVAILABLE = 10; + public static final int OPTION_SOFT_DISABLED = 11; private static final String KEY_PGP_SIGNATURE = "pgp_signature"; private static final String KEY_PGP_ID = "pgp_id"; @@ -248,6 +249,10 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable return !isOptionSet(Account.OPTION_DISABLED); } + public boolean isConnectionEnabled() { + return !isOptionSet(Account.OPTION_DISABLED) && !isOptionSet(Account.OPTION_SOFT_DISABLED); + } + public boolean isOptionSet(final int option) { return ((options & (1 << option)) != 0); } @@ -322,6 +327,8 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable public State getStatus() { if (isOptionSet(OPTION_DISABLED)) { return State.DISABLED; + } else if (isOptionSet(OPTION_SOFT_DISABLED)) { + return State.LOGGED_OUT; } else { return this.status; } @@ -765,6 +772,7 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable public enum State { DISABLED(false, false), + LOGGED_OUT(false,false), OFFLINE(false), CONNECTING(false), ONLINE(false), @@ -824,6 +832,8 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable switch (this) { case DISABLED: return R.string.account_status_disabled; + case LOGGED_OUT: + return R.string.account_state_logged_out; case ONLINE: return R.string.account_status_online; case CONNECTING: diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java index ce3f43857..641e2e109 100644 --- a/src/main/java/eu/siacs/conversations/services/NotificationService.java +++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java @@ -22,6 +22,7 @@ import android.os.Build; import android.os.SystemClock; import android.os.Vibrator; import android.preference.PreferenceManager; +import android.provider.Settings; import android.text.SpannableString; import android.text.style.StyleSpan; import android.util.DisplayMetrics; @@ -40,6 +41,7 @@ import androidx.core.graphics.drawable.IconCompat; import com.google.common.base.Joiner; import com.google.common.base.Strings; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import java.io.File; @@ -1661,12 +1663,25 @@ public class NotificationService { } private PendingIntent createCallAction(String sessionId, final String action, int requestCode) { - final Intent intent = new Intent(mXmppConnectionService, XmppConnectionService.class); + return pendingServiceIntent(mXmppConnectionService, action, requestCode, ImmutableMap.of(RtpSessionActivity.EXTRA_SESSION_ID, sessionId)); + } + + private PendingIntent createSnoozeIntent(final Conversation conversation) { + return pendingServiceIntent(mXmppConnectionService, XmppConnectionService.ACTION_SNOOZE, generateRequestCode(conversation,22),ImmutableMap.of("uuid",conversation.getUuid())); + } + + private static PendingIntent pendingServiceIntent(final Context context, final String action, final int requestCode) { + return pendingServiceIntent(context, action, requestCode, ImmutableMap.of()); + } + + private static PendingIntent pendingServiceIntent(final Context context, final String action, final int requestCode, final Map extras) { + final Intent intent = new Intent(context, XmppConnectionService.class); intent.setAction(action); - intent.setPackage(mXmppConnectionService.getPackageName()); - intent.putExtra(RtpSessionActivity.EXTRA_SESSION_ID, sessionId); + for(final Map.Entry entry : extras.entrySet()) { + intent.putExtra(entry.getKey(), entry.getValue()); + } return PendingIntent.getService( - mXmppConnectionService, + context, requestCode, intent, s() @@ -1674,44 +1689,6 @@ public class NotificationService { : PendingIntent.FLAG_UPDATE_CURRENT); } - private PendingIntent createSnoozeIntent(Conversation conversation) { - final Intent intent = new Intent(mXmppConnectionService, XmppConnectionService.class); - intent.setAction(XmppConnectionService.ACTION_SNOOZE); - intent.putExtra("uuid", conversation.getUuid()); - intent.setPackage(mXmppConnectionService.getPackageName()); - return PendingIntent.getService( - mXmppConnectionService, - generateRequestCode(conversation, 22), - intent, - s() - ? PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT - : PendingIntent.FLAG_UPDATE_CURRENT); - } - - private PendingIntent createTryAgainIntent() { - final Intent intent = new Intent(mXmppConnectionService, XmppConnectionService.class); - intent.setAction(XmppConnectionService.ACTION_TRY_AGAIN); - return PendingIntent.getService( - mXmppConnectionService, - 45, - intent, - s() - ? PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT - : PendingIntent.FLAG_UPDATE_CURRENT); - } - - private PendingIntent createDismissErrorIntent() { - final Intent intent = new Intent(mXmppConnectionService, XmppConnectionService.class); - intent.setAction(XmppConnectionService.ACTION_DISMISS_ERROR_NOTIFICATIONS); - return PendingIntent.getService( - mXmppConnectionService, - 69, - intent, - s() - ? PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT - : PendingIntent.FLAG_UPDATE_CURRENT); - } - private boolean wasHighlightedOrPrivate(final Message message) { if (message.getConversation() instanceof Conversation) { Conversation conversation = (Conversation) message.getConversation(); @@ -1756,17 +1733,15 @@ public class NotificationService { final Notification.Builder mBuilder = new Notification.Builder(mXmppConnectionService); mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.app_name)); final List accounts = mXmppConnectionService.getAccounts(); - int enabled = 0; - int connected = 0; - if (accounts != null) { - for (Account account : accounts) { - if (account.isOnlineAndConnected()) { - connected++; - enabled++; - } else if (account.isEnabled()) { - enabled++; - } - } + final int enabled; + final int connected; + if (accounts == null) { + enabled = 0; + connected = 0; + } else { + enabled = Iterables.size(Iterables.filter(accounts, Account::isEnabled)); + connected = + Iterables.size(Iterables.filter(accounts, Account::isOnlineAndConnected)); } mBuilder.setContentText( mXmppConnectionService.getString(R.string.connected_accounts, connected, enabled)); @@ -1784,11 +1759,36 @@ public class NotificationService { if (Compatibility.runsTwentySix()) { mBuilder.setChannelId("foreground"); + mBuilder.addAction( + R.drawable.ic_logout_white_24dp, + mXmppConnectionService.getString(R.string.log_out), + pendingServiceIntent( + mXmppConnectionService, + XmppConnectionService.ACTION_TEMPORARILY_DISABLE, + 87)); + mBuilder.addAction( + R.drawable.ic_notifications_off_white_24dp, + mXmppConnectionService.getString(R.string.hide_notification), + pendingNotificationSettingsIntent(mXmppConnectionService)); } return mBuilder.build(); } + @RequiresApi(api = Build.VERSION_CODES.O) + private static PendingIntent pendingNotificationSettingsIntent(final Context context) { + final Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS); + intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName()); + intent.putExtra(Settings.EXTRA_CHANNEL_ID, "foreground"); + return PendingIntent.getActivity( + context, + 89, + intent, + s() + ? PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT + : PendingIntent.FLAG_UPDATE_CURRENT); + } + private PendingIntent createOpenConversationsIntent() { try { return PendingIntent.getActivity( @@ -1839,7 +1839,7 @@ public class NotificationService { mBuilder.addAction( R.drawable.ic_autorenew_white_24dp, mXmppConnectionService.getString(R.string.try_again), - createTryAgainIntent()); + pendingServiceIntent(mXmppConnectionService, XmppConnectionService.ACTION_TRY_AGAIN, 45)); if (torNotAvailable) { if (TorServiceUtils.isOrbotInstalled(mXmppConnectionService)) { mBuilder.addAction( @@ -1867,7 +1867,7 @@ public class NotificationService { : PendingIntent.FLAG_UPDATE_CURRENT)); } } - mBuilder.setDeleteIntent(createDismissErrorIntent()); + mBuilder.setDeleteIntent(pendingServiceIntent(mXmppConnectionService,XmppConnectionService.ACTION_DISMISS_ERROR_NOTIFICATIONS, 69)); mBuilder.setVisibility(Notification.VISIBILITY_PRIVATE); mBuilder.setSmallIcon(R.drawable.ic_warning_white_24dp); mBuilder.setLocalOnly(true); diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 6c87fd94a..5ac66cf9b 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -184,6 +184,8 @@ public class XmppConnectionService extends Service { public static final String ACTION_CLEAR_MISSED_CALL_NOTIFICATION = "clear_missed_call_notification"; public static final String ACTION_DISMISS_ERROR_NOTIFICATIONS = "dismiss_error"; public static final String ACTION_TRY_AGAIN = "try_again"; + + public static final String ACTION_TEMPORARILY_DISABLE = "temporarily_disable"; public static final String ACTION_IDLE_PING = "idle_ping"; public static final String ACTION_FCM_TOKEN_REFRESH = "fcm_token_refresh"; public static final String ACTION_FCM_MESSAGE_RECEIVED = "fcm_message_received"; @@ -452,9 +454,9 @@ public class XmppConnectionService extends Service { joinMuc(conversation); } scheduleWakeUpCall(Config.PING_MAX_INTERVAL, account.getUuid().hashCode()); - } else if (account.getStatus() == Account.State.OFFLINE || account.getStatus() == Account.State.DISABLED) { + } else if (account.getStatus() == Account.State.OFFLINE || account.getStatus() == Account.State.DISABLED || account.getStatus() == Account.State.LOGGED_OUT) { resetSendingToWaiting(account); - if (account.isEnabled() && isInLowPingTimeoutMode(account)) { + if (account.isConnectionEnabled() && isInLowPingTimeoutMode(account)) { Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": went into offline state during low ping mode. reconnecting now"); reconnectAccount(account, true, false); } else { @@ -846,6 +848,9 @@ public class XmppConnectionService extends Service { Log.d(Config.LOGTAG, "received uri permission for " + uri); } return START_STICKY; + case ACTION_TEMPORARILY_DISABLE: + toggleSoftDisabled(true); + return START_NOT_STICKY; } } synchronized (this) { @@ -961,6 +966,16 @@ public class XmppConnectionService extends Service { return pingNow; } + private void toggleSoftDisabled(final boolean softDisabled) { + for(final Account account : this.accounts) { + if (account.isEnabled()) { + if (account.setOption(Account.OPTION_SOFT_DISABLED, softDisabled)) { + updateAccount(account); + } + } + } + } + public boolean processUnifiedPushMessage(final Account account, final Jid transport, final Element push) { return unifiedPushBroker.processPushMessage(account, transport, push); } @@ -1449,7 +1464,7 @@ public class XmppConnectionService extends Service { private void logoutAndSave(boolean stop) { int activeAccounts = 0; for (final Account account : accounts) { - if (account.getStatus() != Account.State.DISABLED) { + if (account.isConnectionEnabled()) { databaseBackend.writeRoster(account.getRoster()); activeAccounts++; } @@ -2808,6 +2823,7 @@ public class XmppConnectionService extends Service { } private void switchToForeground() { + toggleSoftDisabled(false); final boolean broadcastLastActivity = broadcastLastActivity(); for (Conversation conversation : getConversations()) { if (conversation.getMode() == Conversation.MODE_MULTI) { @@ -3188,8 +3204,8 @@ public class XmppConnectionService extends Service { if (this.accounts == null) { return false; } - for (Account account : this.accounts) { - if (account.isEnabled()) { + for (final Account account : this.accounts) { + if (account.isConnectionEnabled()) { return true; } } @@ -3587,23 +3603,23 @@ public class XmppConnectionService extends Service { }); } - private void disconnect(Account account, boolean force) { - if ((account.getStatus() == Account.State.ONLINE) - || (account.getStatus() == Account.State.DISABLED)) { - final XmppConnection connection = account.getXmppConnection(); - if (!force) { - List conversations = getConversations(); - for (Conversation conversation : conversations) { - if (conversation.getAccount() == account) { - if (conversation.getMode() == Conversation.MODE_MULTI) { - leaveMuc(conversation, true); - } + private void disconnect(final Account account, boolean force) { + final XmppConnection connection = account.getXmppConnection(); + if (connection == null) { + return; + } + if (!force) { + final List conversations = getConversations(); + for (Conversation conversation : conversations) { + if (conversation.getAccount() == account) { + if (conversation.getMode() == Conversation.MODE_MULTI) { + leaveMuc(conversation, true); } } - sendOfflinePresence(account); } - connection.disconnect(force); + sendOfflinePresence(account); } + connection.disconnect(force); } @Override @@ -4093,7 +4109,7 @@ public class XmppConnectionService extends Service { account.setXmppConnection(connection); } boolean hasInternet = hasInternetConnection(); - if (account.isEnabled() && hasInternet) { + if (account.isConnectionEnabled() && hasInternet) { if (!force) { disconnect(account, false); } @@ -4581,7 +4597,7 @@ public class XmppConnectionService extends Service { public void refreshAllPresences() { boolean includeIdleTimestamp = checkListeners() && broadcastLastActivity(); for (Account account : getAccounts()) { - if (account.isEnabled()) { + if (account.isConnectionEnabled()) { sendPresence(account, includeIdleTimestamp); } } diff --git a/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java b/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java index 9da5c7546..246e39855 100644 --- a/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java @@ -270,7 +270,7 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im return; } for (final Account account : xmppConnectionService.getAccounts()) { - if (account.getStatus() != Account.State.DISABLED) { + if (account.isEnabled()) { for (final Contact contact : account.getRoster().getContacts()) { if (contact.showInContactList() && !filterContacts.contains(contact.getJid().asBareJid().toString()) @@ -362,7 +362,7 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im filterContacts(); this.mActivatedAccounts.clear(); for (Account account : xmppConnectionService.getAccounts()) { - if (account.getStatus() != Account.State.DISABLED) { + if (account.isEnabled()) { if (Config.DOMAIN_LOCK != null) { this.mActivatedAccounts.add(account.getJid().getEscapedLocal()); } else { @@ -382,6 +382,7 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); ScanActivity.onRequestPermissionResult(this, requestCode, grantResults); } diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 79d938274..6063d613e 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -416,6 +416,7 @@ public class ConversationFragment extends XmppFragment public void onClick(View v) { final Account account = conversation == null ? null : conversation.getAccount(); if (account != null) { + account.setOption(Account.OPTION_SOFT_DISABLED, false); account.setOption(Account.OPTION_DISABLED, false); activity.xmppConnectionService.updateAccount(account); } @@ -2660,6 +2661,8 @@ public class ConversationFragment extends XmppFragment R.string.this_account_is_disabled, R.string.enable, this.mEnableAccountListener); + } else if (account.getStatus() == Account.State.LOGGED_OUT) { + showSnackbar(R.string.this_account_is_logged_out,R.string.log_in,this.mEnableAccountListener); } else if (conversation.isBlocked()) { showSnackbar(R.string.contact_blocked, R.string.unblock, this.mUnblockClickListener); } else if (contact != null diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index e58a05729..f15d18b3c 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -149,7 +149,8 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat if (mInitMode && mAccount != null) { mAccount.setOption(Account.OPTION_DISABLED, false); } - if (mAccount != null && mAccount.getStatus() == Account.State.DISABLED && !accountInfoEdited) { + if (mAccount != null && Arrays.asList(Account.State.DISABLED, Account.State.LOGGED_OUT).contains(mAccount.getStatus()) && !accountInfoEdited) { + mAccount.setOption(Account.OPTION_SOFT_DISABLED, false); mAccount.setOption(Account.OPTION_DISABLED, false); if (!xmppConnectionService.updateAccount(mAccount)) { Toast.makeText(EditAccountActivity.this, R.string.unable_to_update_account, Toast.LENGTH_SHORT).show(); diff --git a/src/main/java/eu/siacs/conversations/ui/ShortcutActivity.java b/src/main/java/eu/siacs/conversations/ui/ShortcutActivity.java index 33164c95c..ff935beae 100644 --- a/src/main/java/eu/siacs/conversations/ui/ShortcutActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ShortcutActivity.java @@ -61,7 +61,7 @@ public class ShortcutActivity extends AbstractSearchableListItemActivity { return; } for (final Account account : xmppConnectionService.getAccounts()) { - if (account.getStatus() != Account.State.DISABLED) { + if (account.isEnabled()) { for (final Contact contact : account.getRoster().getContacts()) { if (contact.showInContactList() && contact.match(this, needle)) { diff --git a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java index 09bc1e839..bc9538d54 100644 --- a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java @@ -971,8 +971,8 @@ public class StartConversationActivity extends XmppActivity implements XmppConne protected void filterContacts(String needle) { this.contacts.clear(); final List accounts = xmppConnectionService.getAccounts(); - for (Account account : accounts) { - if (account.getStatus() != Account.State.DISABLED) { + for (final Account account : accounts) { + if (account.isEnabled()) { for (Contact contact : account.getRoster().getContacts()) { Presence.Status s = contact.getShownStatus(); if (contact.showInContactList() && contact.match(this, needle) @@ -991,7 +991,7 @@ public class StartConversationActivity extends XmppActivity implements XmppConne protected void filterConferences(String needle) { this.conferences.clear(); for (final Account account : xmppConnectionService.getAccounts()) { - if (account.getStatus() != Account.State.DISABLED) { + if (account.isEnabled()) { for (final Bookmark bookmark : account.getBookmarks()) { if (bookmark.match(this, needle)) { this.conferences.add(bookmark); diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/AccountAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/AccountAdapter.java index b070a63bb..038f255ea 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/AccountAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/AccountAdapter.java @@ -59,6 +59,7 @@ public class AccountAdapter extends ArrayAdapter { viewHolder.binding.accountStatus.setTextColor(StyledAttributes.getColor(activity, R.attr.TextColorOnline)); break; case DISABLED: + case LOGGED_OUT: case CONNECTING: viewHolder.binding.accountStatus.setTextColor(StyledAttributes.getColor(activity, android.R.attr.textColorSecondary)); break; diff --git a/src/main/java/eu/siacs/conversations/utils/AccountUtils.java b/src/main/java/eu/siacs/conversations/utils/AccountUtils.java index 6f3e4a49e..7b7397123 100644 --- a/src/main/java/eu/siacs/conversations/utils/AccountUtils.java +++ b/src/main/java/eu/siacs/conversations/utils/AccountUtils.java @@ -60,7 +60,7 @@ public class AccountUtils { public static List getEnabledAccounts(final XmppConnectionService service) { final ArrayList accounts = new ArrayList<>(); for (final Account account : service.getAccounts()) { - if (account.getStatus() != Account.State.DISABLED) { + if (account.isEnabled()) { if (Config.DOMAIN_LOCK != null) { accounts.add(account.getJid().getEscapedLocal()); } else { diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 402cd1ba2..348cf3657 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -233,10 +233,11 @@ public class XmppConnection implements Runnable { return; } if (account.getStatus() != nextStatus) { - if ((nextStatus == Account.State.OFFLINE) - && (account.getStatus() != Account.State.CONNECTING) - && (account.getStatus() != Account.State.ONLINE) - && (account.getStatus() != Account.State.DISABLED)) { + if (nextStatus == Account.State.OFFLINE + && account.getStatus() != Account.State.CONNECTING + && account.getStatus() != Account.State.ONLINE + && account.getStatus() != Account.State.DISABLED + && account.getStatus() != Account.State.LOGGED_OUT) { return; } if (nextStatus == Account.State.ONLINE) { diff --git a/src/main/res/drawable/ic_logout_white_24dp.xml b/src/main/res/drawable/ic_logout_white_24dp.xml new file mode 100644 index 000000000..5f818ab16 --- /dev/null +++ b/src/main/res/drawable/ic_logout_white_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index cb97f7afb..bb809192e 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -153,6 +153,7 @@ The app you used to share this file did not provide enough permissions. Unknown Temporarily disabled + Logged out Online Connecting\u2026 Offline @@ -538,6 +539,7 @@ Send corrected message You have already validated this persons fingerprint securely to confirm trust. By selecting “Done” you are just confirming that %s is part of this group chat. You have disabled this account + You have logged out of this account Security error: Invalid file access! No app found to share URI Share URI with… @@ -1013,5 +1015,7 @@ Decline Remove account from server Could not delete account from server - + Hide notification + Log out + Log in From 69425e677cde4a09f69a11b4c0549807b0d4cbb2 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 18 Oct 2023 18:18:16 +0200 Subject: [PATCH 273/402] remove soft disable flag when attempting call --- src/main/java/eu/siacs/conversations/entities/Account.java | 3 +++ .../java/eu/siacs/conversations/ui/ConversationFragment.java | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 0fdece061..3146abe46 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -258,6 +258,9 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable } public boolean setOption(final int option, final boolean value) { + if (value && (option == OPTION_DISABLED || option == OPTION_SOFT_DISABLED)) { + this.setStatus(State.OFFLINE); + } final int before = this.options; if (value) { this.options |= 1 << option; diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 6063d613e..096a704cd 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -1609,6 +1609,10 @@ public class ConversationFragment extends XmppFragment .show(); return; } + final Account account = conversation.getAccount(); + if (account.setOption(Account.OPTION_SOFT_DISABLED, false)) { + activity.xmppConnectionService.updateAccount(account); + } final Contact contact = conversation.getContact(); if (RtpCapability.jmiSupport(contact)) { triggerRtpSession(contact.getAccount(), contact.getJid().asBareJid(), action); From d1f648f2e396bc4840828d7982b0aaf8497acc2f Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 18 Oct 2023 21:37:00 +0200 Subject: [PATCH 274/402] code clean up in onStartCommand --- .../services/XmppConnectionService.java | 424 +++++++++--------- 1 file changed, 218 insertions(+), 206 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 5ac66cf9b..4bdc8c7c1 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -186,7 +186,9 @@ public class XmppConnectionService extends Service { public static final String ACTION_TRY_AGAIN = "try_again"; public static final String ACTION_TEMPORARILY_DISABLE = "temporarily_disable"; + public static final String ACTION_PING = "ping"; public static final String ACTION_IDLE_PING = "idle_ping"; + public static final String ACTION_INTERNAL_PING = "internal_ping"; public static final String ACTION_FCM_TOKEN_REFRESH = "fcm_token_refresh"; public static final String ACTION_FCM_MESSAGE_RECEIVED = "fcm_message_received"; public static final String ACTION_DISMISS_CALL = "dismiss_call"; @@ -653,235 +655,245 @@ public class XmppConnectionService extends Service { } @Override - public int onStartCommand(Intent intent, int flags, int startId) { - final String action = intent == null ? null : intent.getAction(); + public int onStartCommand(final Intent intent, int flags, int startId) { + final String action = Strings.nullToEmpty(intent == null ? null : intent.getAction()); final boolean needsForegroundService = intent != null && intent.getBooleanExtra(EventReceiver.EXTRA_NEEDS_FOREGROUND_SERVICE, false); if (needsForegroundService) { Log.d(Config.LOGTAG, "toggle forced foreground service after receiving event (action=" + action + ")"); toggleForegroundService(true); } - String pushedAccountHash = null; - boolean interactive = false; - if (action != null) { - final String uuid = intent.getStringExtra("uuid"); - switch (action) { - case QuickConversationsService.SMS_RETRIEVED_ACTION: - mQuickConversationsService.handleSmsReceived(intent); - break; - case ConnectivityManager.CONNECTIVITY_ACTION: - if (hasInternetConnection()) { - if (Config.POST_CONNECTIVITY_CHANGE_PING_INTERVAL > 0) { - schedulePostConnectivityChange(); - } - if (Config.RESET_ATTEMPT_COUNT_ON_NETWORK_CHANGE) { - resetAllAttemptCounts(true, false); - } - Resolver.clearCache(); + final String uuid = intent == null ? null : intent.getStringExtra("uuid"); + switch (action) { + case QuickConversationsService.SMS_RETRIEVED_ACTION: + mQuickConversationsService.handleSmsReceived(intent); + break; + case ConnectivityManager.CONNECTIVITY_ACTION: + if (hasInternetConnection()) { + if (Config.POST_CONNECTIVITY_CHANGE_PING_INTERVAL > 0) { + schedulePostConnectivityChange(); } - break; - case Intent.ACTION_SHUTDOWN: - logoutAndSave(true); - return START_NOT_STICKY; - case ACTION_CLEAR_MESSAGE_NOTIFICATION: - mNotificationExecutor.execute(() -> { - try { - final Conversation c = findConversationByUuid(uuid); - if (c != null) { - mNotificationService.clearMessages(c); - } else { - mNotificationService.clearMessages(); - } - restoredFromDatabaseLatch.await(); - - } catch (InterruptedException e) { - Log.d(Config.LOGTAG, "unable to process clear message notification"); - } - }); - break; - case ACTION_CLEAR_MISSED_CALL_NOTIFICATION: - mNotificationExecutor.execute(() -> { - try { - final Conversation c = findConversationByUuid(uuid); - if (c != null) { - mNotificationService.clearMissedCalls(c); - } else { - mNotificationService.clearMissedCalls(); - } - restoredFromDatabaseLatch.await(); - - } catch (InterruptedException e) { - Log.d(Config.LOGTAG, "unable to process clear missed call notification"); - } - }); - break; - case ACTION_DISMISS_CALL: { - final String sessionId = intent.getStringExtra(RtpSessionActivity.EXTRA_SESSION_ID); - Log.d(Config.LOGTAG, "received intent to dismiss call with session id " + sessionId); - mJingleConnectionManager.rejectRtpSession(sessionId); - break; - } - case TorServiceUtils.ACTION_STATUS: - final String status = intent.getStringExtra(TorServiceUtils.EXTRA_STATUS); - //TODO port and host are in 'extras' - but this may not be a reliable source? - if ("ON".equals(status)) { - handleOrbotStartedEvent(); - return START_STICKY; + if (Config.RESET_ATTEMPT_COUNT_ON_NETWORK_CHANGE) { + resetAllAttemptCounts(true, false); } - break; - case ACTION_END_CALL: { - final String sessionId = intent.getStringExtra(RtpSessionActivity.EXTRA_SESSION_ID); - Log.d(Config.LOGTAG, "received intent to end call with session id " + sessionId); - mJingleConnectionManager.endRtpSession(sessionId); + Resolver.clearCache(); } break; - case ACTION_PROVISION_ACCOUNT: { - final String address = intent.getStringExtra("address"); - final String password = intent.getStringExtra("password"); - if (QuickConversationsService.isQuicksy() || Strings.isNullOrEmpty(address) || Strings.isNullOrEmpty(password)) { - break; - } - provisionAccount(address, password); - break; - } - case ACTION_DISMISS_ERROR_NOTIFICATIONS: - dismissErrorNotifications(); - break; - case ACTION_TRY_AGAIN: - resetAllAttemptCounts(false, true); - interactive = true; - break; - case ACTION_REPLY_TO_CONVERSATION: - Bundle remoteInput = RemoteInput.getResultsFromIntent(intent); - if (remoteInput == null) { - break; - } - final CharSequence body = remoteInput.getCharSequence("text_reply"); - final boolean dismissNotification = intent.getBooleanExtra("dismiss_notification", false); - final String lastMessageUuid = intent.getStringExtra("last_message_uuid"); - if (body == null || body.length() <= 0) { - break; - } - mNotificationExecutor.execute(() -> { - try { - restoredFromDatabaseLatch.await(); - final Conversation c = findConversationByUuid(uuid); - if (c != null) { - directReply(c, body.toString(), lastMessageUuid, dismissNotification); - } - } catch (InterruptedException e) { - Log.d(Config.LOGTAG, "unable to process direct reply"); - } - }); - break; - case ACTION_MARK_AS_READ: - mNotificationExecutor.execute(() -> { + case Intent.ACTION_SHUTDOWN: + logoutAndSave(true); + return START_NOT_STICKY; + case ACTION_CLEAR_MESSAGE_NOTIFICATION: + mNotificationExecutor.execute(() -> { + try { final Conversation c = findConversationByUuid(uuid); - if (c == null) { - Log.d(Config.LOGTAG, "received mark read intent for unknown conversation (" + uuid + ")"); - return; - } - try { - restoredFromDatabaseLatch.await(); - sendReadMarker(c, null); - } catch (InterruptedException e) { - Log.d(Config.LOGTAG, "unable to process notification read marker for conversation " + c.getName()); + if (c != null) { + mNotificationService.clearMessages(c); + } else { + mNotificationService.clearMessages(); } + restoredFromDatabaseLatch.await(); - }); - break; - case ACTION_SNOOZE: - mNotificationExecutor.execute(() -> { + } catch (InterruptedException e) { + Log.d(Config.LOGTAG, "unable to process clear message notification"); + } + }); + break; + case ACTION_CLEAR_MISSED_CALL_NOTIFICATION: + mNotificationExecutor.execute(() -> { + try { final Conversation c = findConversationByUuid(uuid); - if (c == null) { - Log.d(Config.LOGTAG, "received snooze intent for unknown conversation (" + uuid + ")"); - return; + if (c != null) { + mNotificationService.clearMissedCalls(c); + } else { + mNotificationService.clearMissedCalls(); } - c.setMutedTill(System.currentTimeMillis() + 30 * 60 * 1000); - mNotificationService.clearMessages(c); - updateConversation(c); - }); - case AudioManager.RINGER_MODE_CHANGED_ACTION: - case NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED: - if (dndOnSilentMode()) { - refreshAllPresences(); + restoredFromDatabaseLatch.await(); + + } catch (InterruptedException e) { + Log.d(Config.LOGTAG, "unable to process clear missed call notification"); } + }); + break; + case ACTION_DISMISS_CALL: { + if (intent == null) { break; - case Intent.ACTION_SCREEN_ON: - deactivateGracePeriod(); - case Intent.ACTION_USER_PRESENT: - case Intent.ACTION_SCREEN_OFF: - if (awayWhenScreenLocked()) { - refreshAllPresences(); - } - break; - case ACTION_FCM_TOKEN_REFRESH: - refreshAllFcmTokens(); - break; - case ACTION_RENEW_UNIFIED_PUSH_ENDPOINTS: - final String instance = intent.getStringExtra("instance"); - final String application = intent.getStringExtra("application"); - final Messenger messenger = intent.getParcelableExtra("messenger"); - final UnifiedPushBroker.PushTargetMessenger pushTargetMessenger; - if (messenger != null && application != null && instance != null) { - pushTargetMessenger = new UnifiedPushBroker.PushTargetMessenger(new UnifiedPushDatabase.PushTarget(application, instance),messenger); - Log.d(Config.LOGTAG,"found push target messenger"); - } else { - pushTargetMessenger = null; - } - final Optional transport = renewUnifiedPushEndpoints(pushTargetMessenger); - if (instance != null && transport.isPresent()) { - unifiedPushBroker.rebroadcastEndpoint(messenger, instance, transport.get()); - } - break; - case ACTION_IDLE_PING: - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - scheduleNextIdlePing(); - } - break; - case ACTION_FCM_MESSAGE_RECEIVED: - pushedAccountHash = intent.getStringExtra("account"); - Log.d(Config.LOGTAG, "push message arrived in service. account=" + pushedAccountHash); - break; - case Intent.ACTION_SEND: - Uri uri = intent.getData(); - if (uri != null) { - Log.d(Config.LOGTAG, "received uri permission for " + uri); - } - return START_STICKY; - case ACTION_TEMPORARILY_DISABLE: - toggleSoftDisabled(true); - return START_NOT_STICKY; - } - } - synchronized (this) { - WakeLockHelper.acquire(wakeLock); - boolean pingNow = ConnectivityManager.CONNECTIVITY_ACTION.equals(action) || (Config.POST_CONNECTIVITY_CHANGE_PING_INTERVAL > 0 && ACTION_POST_CONNECTIVITY_CHANGE.equals(action)); - final HashSet pingCandidates = new HashSet<>(); - final String androidId = PhoneHelper.getAndroidId(this); - for (Account account : accounts) { - final boolean pushWasMeantForThisAccount = CryptoHelper.getAccountFingerprint(account, androidId).equals(pushedAccountHash); - pingNow |= processAccountState(account, - interactive, - "ui".equals(action), - pushWasMeantForThisAccount, - pingCandidates); - } - if (pingNow) { - for (Account account : pingCandidates) { - final boolean lowTimeout = isInLowPingTimeoutMode(account); - account.getXmppConnection().sendPing(); - Log.d(Config.LOGTAG, account.getJid().asBareJid() + " send ping (action=" + action + ",lowTimeout=" + lowTimeout + ")"); - scheduleWakeUpCall(lowTimeout ? Config.LOW_PING_TIMEOUT : Config.PING_TIMEOUT, account.getUuid().hashCode()); } + final String sessionId = intent.getStringExtra(RtpSessionActivity.EXTRA_SESSION_ID); + Log.d(Config.LOGTAG, "received intent to dismiss call with session id " + sessionId); + mJingleConnectionManager.rejectRtpSession(sessionId); + break; } - WakeLockHelper.release(wakeLock); + case TorServiceUtils.ACTION_STATUS: + final String status = intent == null ? null : intent.getStringExtra(TorServiceUtils.EXTRA_STATUS); + //TODO port and host are in 'extras' - but this may not be a reliable source? + if ("ON".equals(status)) { + handleOrbotStartedEvent(); + return START_STICKY; + } + break; + case ACTION_END_CALL: { + if (intent == null) { + break; + } + final String sessionId = intent.getStringExtra(RtpSessionActivity.EXTRA_SESSION_ID); + Log.d(Config.LOGTAG, "received intent to end call with session id " + sessionId); + mJingleConnectionManager.endRtpSession(sessionId); + } + break; + case ACTION_PROVISION_ACCOUNT: { + if (intent == null) { + break; + } + final String address = intent.getStringExtra("address"); + final String password = intent.getStringExtra("password"); + if (QuickConversationsService.isQuicksy() || Strings.isNullOrEmpty(address) || Strings.isNullOrEmpty(password)) { + break; + } + provisionAccount(address, password); + break; + } + case ACTION_DISMISS_ERROR_NOTIFICATIONS: + dismissErrorNotifications(); + break; + case ACTION_TRY_AGAIN: + resetAllAttemptCounts(false, true); + break; + case ACTION_REPLY_TO_CONVERSATION: + final Bundle remoteInput = intent == null ? null : RemoteInput.getResultsFromIntent(intent); + if (remoteInput == null) { + break; + } + final CharSequence body = remoteInput.getCharSequence("text_reply"); + final boolean dismissNotification = intent.getBooleanExtra("dismiss_notification", false); + final String lastMessageUuid = intent.getStringExtra("last_message_uuid"); + if (body == null || body.length() <= 0) { + break; + } + mNotificationExecutor.execute(() -> { + try { + restoredFromDatabaseLatch.await(); + final Conversation c = findConversationByUuid(uuid); + if (c != null) { + directReply(c, body.toString(), lastMessageUuid, dismissNotification); + } + } catch (InterruptedException e) { + Log.d(Config.LOGTAG, "unable to process direct reply"); + } + }); + break; + case ACTION_MARK_AS_READ: + mNotificationExecutor.execute(() -> { + final Conversation c = findConversationByUuid(uuid); + if (c == null) { + Log.d(Config.LOGTAG, "received mark read intent for unknown conversation (" + uuid + ")"); + return; + } + try { + restoredFromDatabaseLatch.await(); + sendReadMarker(c, null); + } catch (InterruptedException e) { + Log.d(Config.LOGTAG, "unable to process notification read marker for conversation " + c.getName()); + } + + }); + break; + case ACTION_SNOOZE: + mNotificationExecutor.execute(() -> { + final Conversation c = findConversationByUuid(uuid); + if (c == null) { + Log.d(Config.LOGTAG, "received snooze intent for unknown conversation (" + uuid + ")"); + return; + } + c.setMutedTill(System.currentTimeMillis() + 30 * 60 * 1000); + mNotificationService.clearMessages(c); + updateConversation(c); + }); + case AudioManager.RINGER_MODE_CHANGED_ACTION: + case NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED: + if (dndOnSilentMode()) { + refreshAllPresences(); + } + break; + case Intent.ACTION_SCREEN_ON: + deactivateGracePeriod(); + case Intent.ACTION_USER_PRESENT: + case Intent.ACTION_SCREEN_OFF: + if (awayWhenScreenLocked()) { + refreshAllPresences(); + } + break; + case ACTION_FCM_TOKEN_REFRESH: + refreshAllFcmTokens(); + break; + case ACTION_RENEW_UNIFIED_PUSH_ENDPOINTS: + if (intent == null) { + break; + } + final String instance = intent.getStringExtra("instance"); + final String application = intent.getStringExtra("application"); + final Messenger messenger = intent.getParcelableExtra("messenger"); + final UnifiedPushBroker.PushTargetMessenger pushTargetMessenger; + if (messenger != null && application != null && instance != null) { + pushTargetMessenger = new UnifiedPushBroker.PushTargetMessenger(new UnifiedPushDatabase.PushTarget(application, instance),messenger); + Log.d(Config.LOGTAG,"found push target messenger"); + } else { + pushTargetMessenger = null; + } + final Optional transport = renewUnifiedPushEndpoints(pushTargetMessenger); + if (instance != null && transport.isPresent()) { + unifiedPushBroker.rebroadcastEndpoint(messenger, instance, transport.get()); + } + break; + case ACTION_IDLE_PING: + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + scheduleNextIdlePing(); + } + break; + case ACTION_FCM_MESSAGE_RECEIVED: + Log.d(Config.LOGTAG, "push message arrived in service. account"); + break; + case Intent.ACTION_SEND: + final Uri uri = intent == null ? null : intent.getData(); + if (uri != null) { + Log.d(Config.LOGTAG, "received uri permission for " + uri); + } + return START_STICKY; + case ACTION_TEMPORARILY_DISABLE: + toggleSoftDisabled(true); + return START_NOT_STICKY; } + manageAccountConnectionStates(action, intent == null ? null : intent.getExtras()); if (SystemClock.elapsedRealtime() - mLastExpiryRun.get() >= Config.EXPIRY_INTERVAL) { expireOldMessages(); } return START_STICKY; } + private synchronized void manageAccountConnectionStates(final String action, final Bundle extras) { + final String pushedAccountHash = extras == null ? null : extras.getString("account"); + final boolean interactive = Arrays.asList(ACTION_TRY_AGAIN).contains(action); + WakeLockHelper.acquire(wakeLock); + boolean pingNow = ConnectivityManager.CONNECTIVITY_ACTION.equals(action) || (Config.POST_CONNECTIVITY_CHANGE_PING_INTERVAL > 0 && ACTION_POST_CONNECTIVITY_CHANGE.equals(action)); + final HashSet pingCandidates = new HashSet<>(); + final String androidId = PhoneHelper.getAndroidId(this); + for (final Account account : accounts) { + final boolean pushWasMeantForThisAccount = CryptoHelper.getAccountFingerprint(account, androidId).equals(pushedAccountHash); + pingNow |= processAccountState(account, + interactive, + "ui".equals(action), + pushWasMeantForThisAccount, + pingCandidates); + } + if (pingNow) { + for (Account account : pingCandidates) { + final boolean lowTimeout = isInLowPingTimeoutMode(account); + account.getXmppConnection().sendPing(); + Log.d(Config.LOGTAG, account.getJid().asBareJid() + " send ping (action=" + action + ",lowTimeout=" + lowTimeout + ")"); + scheduleWakeUpCall(lowTimeout ? Config.LOW_PING_TIMEOUT : Config.PING_TIMEOUT, account.getUuid().hashCode()); + } + } + WakeLockHelper.release(wakeLock); + } + private void handleOrbotStartedEvent() { for (final Account account : accounts) { if (account.getStatus() == Account.State.TOR_NOT_AVAILABLE) { @@ -1500,14 +1512,14 @@ public class XmppConnectionService extends Service { } } - public void scheduleWakeUpCall(int seconds, int requestCode) { + public void scheduleWakeUpCall(final int seconds, final int requestCode) { final long timeToWake = SystemClock.elapsedRealtime() + (seconds < 0 ? 1 : seconds + 1) * 1000L; final AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); if (alarmManager == null) { return; } final Intent intent = new Intent(this, EventReceiver.class); - intent.setAction("ping"); + intent.setAction(ACTION_PING); try { final PendingIntent pendingIntent; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { From 2dd8896dc2516eb22b09de432d24922e7a5fab12 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 19 Oct 2023 08:52:25 +0200 Subject: [PATCH 275/402] stop service on log out when UI is not active --- .../eu/siacs/conversations/services/XmppConnectionService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 4bdc8c7c1..2049f9b95 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -859,6 +859,9 @@ public class XmppConnectionService extends Service { return START_STICKY; case ACTION_TEMPORARILY_DISABLE: toggleSoftDisabled(true); + if (checkListeners()) { + stopSelf(); + } return START_NOT_STICKY; } manageAccountConnectionStates(action, intent == null ? null : intent.getExtras()); From 928db01ae86492339d23e0128fed1407817df0c8 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 19 Oct 2023 08:54:19 +0200 Subject: [PATCH 276/402] do not init connection for disabled accounts --- .../conversations/services/XmppConnectionService.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 2049f9b95..3cf82d319 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -4118,12 +4118,17 @@ public class XmppConnectionService extends Service { private void reconnectAccount(final Account account, final boolean force, final boolean interactive) { synchronized (account) { - XmppConnection connection = account.getXmppConnection(); - if (connection == null) { + final XmppConnection existingConnection = account.getXmppConnection(); + final XmppConnection connection; + if (existingConnection != null) { + connection = existingConnection; + } else if (account.isConnectionEnabled()) { connection = createConnection(account); account.setXmppConnection(connection); + } else { + return; } - boolean hasInternet = hasInternetConnection(); + final boolean hasInternet = hasInternetConnection(); if (account.isConnectionEnabled() && hasInternet) { if (!force) { disconnect(account, false); From a162d72c2af020ee4c315675d542d7371cbbbbfb Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 19 Oct 2023 08:57:28 +0200 Subject: [PATCH 277/402] code clean up in processAccountState() --- .../services/XmppConnectionService.java | 124 +++++++++--------- 1 file changed, 60 insertions(+), 64 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 3cf82d319..3352c4c3b 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -906,79 +906,75 @@ public class XmppConnectionService extends Service { } private boolean processAccountState(Account account, boolean interactive, boolean isUiAction, boolean isAccountPushed, HashSet pingCandidates) { - boolean pingNow = false; - if (account.getStatus().isAttemptReconnect()) { - if (!hasInternetConnection()) { - account.setStatus(Account.State.NO_INTERNET); - if (statusListener != null) { - statusListener.onStatusChanged(account); - } - } else { - if (account.getStatus() == Account.State.NO_INTERNET) { - account.setStatus(Account.State.OFFLINE); - if (statusListener != null) { - statusListener.onStatusChanged(account); - } - } - if (account.getStatus() == Account.State.ONLINE) { - synchronized (mLowPingTimeoutMode) { - long lastReceived = account.getXmppConnection().getLastPacketReceived(); - long lastSent = account.getXmppConnection().getLastPingSent(); - long pingInterval = isUiAction ? Config.PING_MIN_INTERVAL * 1000 : Config.PING_MAX_INTERVAL * 1000; - long msToNextPing = (Math.max(lastReceived, lastSent) + pingInterval) - SystemClock.elapsedRealtime(); - int pingTimeout = mLowPingTimeoutMode.contains(account.getJid().asBareJid()) ? Config.LOW_PING_TIMEOUT * 1000 : Config.PING_TIMEOUT * 1000; - long pingTimeoutIn = (lastSent + pingTimeout) - SystemClock.elapsedRealtime(); - if (lastSent > lastReceived) { - if (pingTimeoutIn < 0) { - Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": ping timeout"); - this.reconnectAccount(account, true, interactive); - } else { - int secs = (int) (pingTimeoutIn / 1000); - this.scheduleWakeUpCall(secs, account.getUuid().hashCode()); - } + if (!account.getStatus().isAttemptReconnect()) { + return false; + } + if (!hasInternetConnection()) { + account.setStatus(Account.State.NO_INTERNET); + statusListener.onStatusChanged(account); + } else { + if (account.getStatus() == Account.State.NO_INTERNET) { + account.setStatus(Account.State.OFFLINE); + statusListener.onStatusChanged(account); + } + if (account.getStatus() == Account.State.ONLINE) { + synchronized (mLowPingTimeoutMode) { + long lastReceived = account.getXmppConnection().getLastPacketReceived(); + long lastSent = account.getXmppConnection().getLastPingSent(); + long pingInterval = isUiAction ? Config.PING_MIN_INTERVAL * 1000 : Config.PING_MAX_INTERVAL * 1000; + long msToNextPing = (Math.max(lastReceived, lastSent) + pingInterval) - SystemClock.elapsedRealtime(); + int pingTimeout = mLowPingTimeoutMode.contains(account.getJid().asBareJid()) ? Config.LOW_PING_TIMEOUT * 1000 : Config.PING_TIMEOUT * 1000; + long pingTimeoutIn = (lastSent + pingTimeout) - SystemClock.elapsedRealtime(); + if (lastSent > lastReceived) { + if (pingTimeoutIn < 0) { + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": ping timeout"); + this.reconnectAccount(account, true, interactive); } else { - pingCandidates.add(account); - if (isAccountPushed) { - pingNow = true; - if (mLowPingTimeoutMode.add(account.getJid().asBareJid())) { - Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": entering low ping timeout mode"); - } - } else if (msToNextPing <= 0) { - pingNow = true; - } else { - this.scheduleWakeUpCall((int) (msToNextPing / 1000), account.getUuid().hashCode()); - if (mLowPingTimeoutMode.remove(account.getJid().asBareJid())) { - Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": leaving low ping timeout mode"); - } + int secs = (int) (pingTimeoutIn / 1000); + this.scheduleWakeUpCall(secs, account.getUuid().hashCode()); + } + } else { + pingCandidates.add(account); + if (isAccountPushed) { + if (mLowPingTimeoutMode.add(account.getJid().asBareJid())) { + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": entering low ping timeout mode"); + } + return true; + } else if (msToNextPing <= 0) { + return true; + } else { + this.scheduleWakeUpCall((int) (msToNextPing / 1000), account.getUuid().hashCode()); + if (mLowPingTimeoutMode.remove(account.getJid().asBareJid())) { + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": leaving low ping timeout mode"); } } } - } else if (account.getStatus() == Account.State.OFFLINE) { + } + } else if (account.getStatus() == Account.State.OFFLINE) { + reconnectAccount(account, true, interactive); + } else if (account.getStatus() == Account.State.CONNECTING) { + long secondsSinceLastConnect = (SystemClock.elapsedRealtime() - account.getXmppConnection().getLastConnect()) / 1000; + long secondsSinceLastDisco = (SystemClock.elapsedRealtime() - account.getXmppConnection().getLastDiscoStarted()) / 1000; + long discoTimeout = Config.CONNECT_DISCO_TIMEOUT - secondsSinceLastDisco; + long timeout = Config.CONNECT_TIMEOUT - secondsSinceLastConnect; + if (timeout < 0) { + Log.d(Config.LOGTAG, account.getJid() + ": time out during connect reconnecting (secondsSinceLast=" + secondsSinceLastConnect + ")"); + account.getXmppConnection().resetAttemptCount(false); reconnectAccount(account, true, interactive); - } else if (account.getStatus() == Account.State.CONNECTING) { - long secondsSinceLastConnect = (SystemClock.elapsedRealtime() - account.getXmppConnection().getLastConnect()) / 1000; - long secondsSinceLastDisco = (SystemClock.elapsedRealtime() - account.getXmppConnection().getLastDiscoStarted()) / 1000; - long discoTimeout = Config.CONNECT_DISCO_TIMEOUT - secondsSinceLastDisco; - long timeout = Config.CONNECT_TIMEOUT - secondsSinceLastConnect; - if (timeout < 0) { - Log.d(Config.LOGTAG, account.getJid() + ": time out during connect reconnecting (secondsSinceLast=" + secondsSinceLastConnect + ")"); - account.getXmppConnection().resetAttemptCount(false); - reconnectAccount(account, true, interactive); - } else if (discoTimeout < 0) { - account.getXmppConnection().sendDiscoTimeout(); - scheduleWakeUpCall((int) Math.min(timeout, discoTimeout), account.getUuid().hashCode()); - } else { - scheduleWakeUpCall((int) Math.min(timeout, discoTimeout), account.getUuid().hashCode()); - } + } else if (discoTimeout < 0) { + account.getXmppConnection().sendDiscoTimeout(); + scheduleWakeUpCall((int) Math.min(timeout, discoTimeout), account.getUuid().hashCode()); } else { - final boolean aggressive = hasJingleRtpConnection(account); - if (account.getXmppConnection().getTimeToNextAttempt(aggressive) <= 0) { - reconnectAccount(account, true, interactive); - } + scheduleWakeUpCall((int) Math.min(timeout, discoTimeout), account.getUuid().hashCode()); + } + } else { + final boolean aggressive = hasJingleRtpConnection(account); + if (account.getXmppConnection().getTimeToNextAttempt(aggressive) <= 0) { + reconnectAccount(account, true, interactive); } } } - return pingNow; + return false; } private void toggleSoftDisabled(final boolean softDisabled) { From 1732ab5cc777e7b6195682d4716edf45c680e348 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 19 Oct 2023 14:55:28 +0200 Subject: [PATCH 278/402] add internal ping timer in case alarm manager fails --- .../conversations/services/XmppConnectionService.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 3352c4c3b..6a3ac9afc 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -85,6 +85,8 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; @@ -202,6 +204,8 @@ public class XmppConnectionService extends Service { public final CountDownLatch restoredFromDatabaseLatch = new CountDownLatch(1); private final static Executor FILE_OBSERVER_EXECUTOR = Executors.newSingleThreadExecutor(); private final static Executor FILE_ATTACHMENT_EXECUTOR = Executors.newSingleThreadExecutor(); + + private final ScheduledExecutorService internalPingExecutor = Executors.newSingleThreadScheduledExecutor(); private final static SerialSingleThreadExecutor VIDEO_COMPRESSION_EXECUTOR = new SerialSingleThreadExecutor("VideoCompression"); private final SerialSingleThreadExecutor mDatabaseWriterExecutor = new SerialSingleThreadExecutor("DatabaseWriter"); private final SerialSingleThreadExecutor mDatabaseReaderExecutor = new SerialSingleThreadExecutor("DatabaseReader"); @@ -871,6 +875,10 @@ public class XmppConnectionService extends Service { return START_STICKY; } + private void manageAccountConnectionStatesInternal() { + manageAccountConnectionStates(ACTION_INTERNAL_PING, null); + } + private synchronized void manageAccountConnectionStates(final String action, final Bundle extras) { final String pushedAccountHash = extras == null ? null : extras.getString("account"); final boolean interactive = Arrays.asList(ACTION_TRY_AGAIN).contains(action); @@ -1287,6 +1295,7 @@ public class XmppConnectionService extends Service { mForceDuringOnCreate.set(false); toggleForegroundService(); setupPhoneStateListener(); + internalPingExecutor.scheduleAtFixedRate(this::manageAccountConnectionStatesInternal,10,10,TimeUnit.SECONDS); } @@ -1360,6 +1369,7 @@ public class XmppConnectionService extends Service { } destroyed = false; fileObserver.stopWatching(); + internalPingExecutor.shutdown(); super.onDestroy(); } From e422b89df507db5fdc203cb1c9146076df7f36b3 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 20 Oct 2023 09:39:25 +0200 Subject: [PATCH 279/402] use aggressive reconnects for see-other-host --- .../services/XmppConnectionService.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 6a3ac9afc..9b4b85d52 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -475,7 +475,8 @@ public class XmppConnectionService extends Service { } else if (account.getStatus() != Account.State.CONNECTING && account.getStatus() != Account.State.NO_INTERNET) { resetSendingToWaiting(account); if (connection != null && account.getStatus().isAttemptReconnect()) { - final boolean aggressive = hasJingleRtpConnection(account); + final boolean aggressive = account.getStatus() == Account.State.SEE_OTHER_HOST + || hasJingleRtpConnection(account); final int next = connection.getTimeToNextAttempt(aggressive); final boolean lowPingTimeoutMode = isInLowPingTimeoutMode(account); if (next <= 0) { @@ -485,6 +486,13 @@ public class XmppConnectionService extends Service { final int attempt = connection.getAttempt() + 1; Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": error connecting account. try again in " + next + "s for the " + attempt + " time. lowPingTimeout=" + lowPingTimeoutMode+", aggressive="+aggressive); scheduleWakeUpCall(next, account.getUuid().hashCode()); + if (aggressive) { + internalPingExecutor.schedule( + XmppConnectionService.this::manageAccountConnectionStatesInternal, + (next * 1000L) + 50, + TimeUnit.MILLISECONDS + ); + } } } } @@ -976,7 +984,7 @@ public class XmppConnectionService extends Service { scheduleWakeUpCall((int) Math.min(timeout, discoTimeout), account.getUuid().hashCode()); } } else { - final boolean aggressive = hasJingleRtpConnection(account); + final boolean aggressive = account.getStatus() == Account.State.SEE_OTHER_HOST || hasJingleRtpConnection(account); if (account.getXmppConnection().getTimeToNextAttempt(aggressive) <= 0) { reconnectAccount(account, true, interactive); } From 417afe6eb16904e2a091ee89ce0399f1b00245e1 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 20 Oct 2023 15:20:43 +0200 Subject: [PATCH 280/402] bump various dependencies --- build.gradle | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index f9743fa8f..4c6e7cacc 100644 --- a/build.gradle +++ b/build.gradle @@ -33,7 +33,7 @@ configurations { dependencies { implementation 'androidx.viewpager:viewpager:1.0.0' - playstoreImplementation('com.google.firebase:firebase-messaging:23.2.1') { + playstoreImplementation('com.google.firebase:firebase-messaging:23.3.0') { exclude group: 'com.google.firebase', module: 'firebase-core' exclude group: 'com.google.firebase', module: 'firebase-analytics' exclude group: 'com.google.firebase', module: 'firebase-measurement-connector' @@ -46,10 +46,10 @@ dependencies { implementation 'androidx.exifinterface:exifinterface:1.3.6' implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' - implementation 'com.google.android.material:material:1.8.0' + implementation 'com.google.android.material:material:1.10.0' - implementation "androidx.emoji2:emoji2:1.2.0" - freeImplementation "androidx.emoji2:emoji2-bundled:1.2.0" + implementation "androidx.emoji2:emoji2:1.4.0" + freeImplementation "androidx.emoji2:emoji2-bundled:1.4.0" implementation 'org.bouncycastle:bcmail-jdk15on:1.64' //zxing stopped supporting Java 7 so we have to stick with 3.3.3 From 35c8d31d423027103361a7850736a953323b2226 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 20 Oct 2023 18:18:15 +0200 Subject: [PATCH 281/402] update gradle and gradle plugin --- build.gradle | 2 +- gradle.properties | 3 +++ gradle/wrapper/gradle-wrapper.properties | 2 +- .../services/XmppConnectionService.java | 13 +++---------- .../conversations/ui/forms/FormFieldWrapper.java | 3 +-- .../ui/widget/SwipeRefreshListFragment.java | 3 +-- 6 files changed, 10 insertions(+), 16 deletions(-) diff --git a/build.gradle b/build.gradle index 4c6e7cacc..7df1a88f2 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.4.2' + classpath 'com.android.tools.build:gradle:8.1.2' } } diff --git a/gradle.properties b/gradle.properties index 431e485f2..d8fa158ee 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,6 @@ android.useAndroidX=true android.enableJetifier=true +android.defaults.buildfeatures.buildconfig=true +android.nonTransitiveRClass=true +android.nonFinalResIds=false org.gradle.jvmargs=-Xmx4096m diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9d41003b2..a2c87f5ef 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-all.zip diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 9b4b85d52..137a24c31 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -1538,16 +1538,9 @@ public class XmppConnectionService extends Service { final Intent intent = new Intent(this, EventReceiver.class); intent.setAction(ACTION_PING); try { - final PendingIntent pendingIntent; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - pendingIntent = - PendingIntent.getBroadcast( - this, requestCode, intent, PendingIntent.FLAG_IMMUTABLE); - } else { - pendingIntent = - PendingIntent.getBroadcast( - this, requestCode, intent, 0); - } + final PendingIntent pendingIntent = + PendingIntent.getBroadcast( + this, requestCode, intent, PendingIntent.FLAG_IMMUTABLE); alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, timeToWake, pendingIntent); } catch (RuntimeException e) { Log.e(Config.LOGTAG, "unable to schedule alarm for ping", e); diff --git a/src/main/java/eu/siacs/conversations/ui/forms/FormFieldWrapper.java b/src/main/java/eu/siacs/conversations/ui/forms/FormFieldWrapper.java index ecc935fa9..4dcef5432 100644 --- a/src/main/java/eu/siacs/conversations/ui/forms/FormFieldWrapper.java +++ b/src/main/java/eu/siacs/conversations/ui/forms/FormFieldWrapper.java @@ -9,7 +9,6 @@ import android.view.View; import java.util.List; -import eu.siacs.conversations.R; import eu.siacs.conversations.ui.util.StyledAttributes; import eu.siacs.conversations.xmpp.forms.Field; @@ -58,7 +57,7 @@ public abstract class FormFieldWrapper { int start = label.length(); int end = label.length() + 2; spannableString.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), start, end, 0); - spannableString.setSpan(new ForegroundColorSpan(StyledAttributes.getColor(context,R.attr.colorAccent)), start, end, 0); + spannableString.setSpan(new ForegroundColorSpan(StyledAttributes.getColor(context, androidx.appcompat.R.attr.colorAccent)), start, end, 0); } return spannableString; } diff --git a/src/main/java/eu/siacs/conversations/ui/widget/SwipeRefreshListFragment.java b/src/main/java/eu/siacs/conversations/ui/widget/SwipeRefreshListFragment.java index b1ef6165a..5f5d6a8cf 100644 --- a/src/main/java/eu/siacs/conversations/ui/widget/SwipeRefreshListFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/widget/SwipeRefreshListFragment.java @@ -26,7 +26,6 @@ import android.widget.ListView; import androidx.fragment.app.ListFragment; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; -import eu.siacs.conversations.R; import eu.siacs.conversations.ui.util.StyledAttributes; /** @@ -57,7 +56,7 @@ public class SwipeRefreshListFragment extends ListFragment { final Context context = getActivity(); if (context != null) { - mSwipeRefreshLayout.setColorSchemeColors(StyledAttributes.getColor(context, R.attr.colorAccent)); + mSwipeRefreshLayout.setColorSchemeColors(StyledAttributes.getColor(context, androidx.appcompat.R.attr.colorAccent)); } if (onRefreshListener != null) { From e83a0af277bccae312fcd3060562e145eb3f8a7b Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 20 Oct 2023 20:57:44 +0200 Subject: [PATCH 282/402] ignore false positive warning wrt foreground service --- src/main/AndroidManifest.xml | 4 +++- .../siacs/conversations/services/XmppConnectionService.java | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 56b7865c9..835d94db3 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -110,10 +110,12 @@ android:name="com.google.android.gms.car.application" android:resource="@xml/automotive_app_desc" /> + + android:foregroundServiceType="specialUse|systemExempted|microphone|camera" + tools:ignore="ForegroundServicePermission"> diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 137a24c31..71fd9844c 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -1466,6 +1466,7 @@ public class XmppConnectionService extends Service { foregroundServiceType = ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA; } else { foregroundServiceType = ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE; + Log.w(Config.LOGTAG,"falling back to special use foreground service type"); } startForeground(id, notification, foregroundServiceType); } else { From 9cd88f00cf4863643f42e40aa289508f0c6659cd Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 20 Oct 2023 21:14:10 +0200 Subject: [PATCH 283/402] fix some linter warnings --- build.gradle | 5 ++++- gradle.properties | 1 - src/main/AndroidManifest.xml | 2 -- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 7df1a88f2..4bca0ec5f 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.1.2' + classpath 'com.android.tools.build:gradle:8.2.0-rc01' } } @@ -233,6 +233,9 @@ android { lint { disable 'MissingTranslation', 'InvalidPackage', 'AppCompatResource', 'ExtraTranslation' } + buildFeatures { + buildConfig true + } android.applicationVariants.all { variant -> variant.outputs.each { output -> diff --git a/gradle.properties b/gradle.properties index d8fa158ee..b0323e6c6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,5 @@ android.useAndroidX=true android.enableJetifier=true -android.defaults.buildfeatures.buildconfig=true android.nonTransitiveRClass=true android.nonFinalResIds=false org.gradle.jvmargs=-Xmx4096m diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 835d94db3..8732a411a 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -24,7 +24,6 @@ - Date: Sat, 21 Oct 2023 09:09:18 +0200 Subject: [PATCH 284/402] bump various dependencies --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 4bca0ec5f..13c4c3e21 100644 --- a/build.gradle +++ b/build.gradle @@ -78,8 +78,8 @@ dependencies { implementation "com.squareup.retrofit2:converter-gson:2.9.0" implementation "com.squareup.okhttp3:okhttp:4.10.0" - implementation 'com.google.guava:guava:31.1-android' - quicksyImplementation 'io.michaelrocks:libphonenumber-android:8.12.49' + implementation 'com.google.guava:guava:32.1.3-android' + quicksyImplementation 'io.michaelrocks:libphonenumber-android:8.13.17' implementation 'im.conversations.webrtc:webrtc-android:117.1.0' } From 48ffde965642111303e103cbfd742807f36f63a6 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 21 Oct 2023 19:47:39 +0200 Subject: [PATCH 285/402] toggle foreground service to set correct type when gaining permissions --- .../services/XmppConnectionService.java | 15 +++++++++++++++ .../conversations/ui/ConversationFragment.java | 5 +++++ .../ui/ConversationsActivity.java | 5 ++++- .../conversations/ui/EditAccountActivity.java | 4 ++++ .../conversations/utils/PermissionUtils.java | 18 ++++++++++++++++-- 5 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 71fd9844c..a202a480c 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -126,6 +126,7 @@ import eu.siacs.conversations.persistance.DatabaseBackend; import eu.siacs.conversations.persistance.FileBackend; import eu.siacs.conversations.persistance.UnifiedPushDatabase; import eu.siacs.conversations.ui.ChooseAccountForProfilePictureActivity; +import eu.siacs.conversations.ui.ConversationsActivity; import eu.siacs.conversations.ui.RtpSessionActivity; import eu.siacs.conversations.ui.SettingsActivity; import eu.siacs.conversations.ui.UiCallback; @@ -5149,4 +5150,18 @@ public class XmppConnectionService extends Service { return Objects.hashCode(id, media, reconnecting); } } + + public static void toggleForegroundService(final XmppConnectionService service) { + if (service == null) { + return; + } + service.toggleForegroundService(); + } + + public static void toggleForegroundService(final ConversationsActivity activity) { + if (activity == null) { + return; + } + toggleForegroundService(activity.xmppConnectionService); + } } diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 096a704cd..a25c4d3c3 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -4,6 +4,8 @@ import static eu.siacs.conversations.ui.XmppActivity.EXTRA_ACCOUNT; import static eu.siacs.conversations.ui.XmppActivity.REQUEST_INVITE_TO_CONVERSATION; import static eu.siacs.conversations.ui.util.SoftKeyboardUtils.hideSoftKeyboard; import static eu.siacs.conversations.utils.PermissionUtils.allGranted; +import static eu.siacs.conversations.utils.PermissionUtils.audioGranted; +import static eu.siacs.conversations.utils.PermissionUtils.cameraGranted; import static eu.siacs.conversations.utils.PermissionUtils.getFirstDenied; import static eu.siacs.conversations.utils.PermissionUtils.writeGranted; @@ -1869,6 +1871,9 @@ public class ConversationFragment extends XmppFragment } refresh(); } + if (cameraGranted(grantResults, permissions) || audioGranted(grantResults, permissions)) { + XmppConnectionService.toggleForegroundService(activity); + } } public void startDownloadable(Message message) { diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java index ba231c584..94801c688 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java @@ -63,6 +63,7 @@ import org.openintents.openpgp.util.OpenPgpApi; import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; import eu.siacs.conversations.Config; @@ -312,14 +313,16 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio } } - private void handleActivityResult(ActivityResult activityResult) { + private void handleActivityResult(final ActivityResult activityResult) { if (activityResult.resultCode == Activity.RESULT_OK) { handlePositiveActivityResult(activityResult.requestCode, activityResult.data); } else { handleNegativeActivityResult(activityResult.requestCode); } if (activityResult.requestCode == REQUEST_BATTERY_OP) { + // the result code is always 0 even when battery permission were granted requestNotificationPermissionIfNeeded(); + XmppConnectionService.toggleForegroundService(xmppConnectionService); } } diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index f15d18b3c..62150d9c2 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -472,6 +472,10 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat if (requestCode == REQUEST_BATTERY_OP || requestCode == REQUEST_DATA_SAVER) { updateAccountInformation(mAccount == null); } + if (requestCode == REQUEST_BATTERY_OP) { + // the result code is always 0 even when battery permission were granted + XmppConnectionService.toggleForegroundService(xmppConnectionService); + } if (requestCode == REQUEST_CHANGE_STATUS) { PresenceTemplate template = mPendingPresenceTemplate.pop(); if (template != null && resultCode == Activity.RESULT_OK) { diff --git a/src/main/java/eu/siacs/conversations/utils/PermissionUtils.java b/src/main/java/eu/siacs/conversations/utils/PermissionUtils.java index 004676156..21d7f42a1 100644 --- a/src/main/java/eu/siacs/conversations/utils/PermissionUtils.java +++ b/src/main/java/eu/siacs/conversations/utils/PermissionUtils.java @@ -24,9 +24,23 @@ public class PermissionUtils { return true; } - public static boolean writeGranted(int[] grantResults, String[] permission) { + public static boolean writeGranted(final int[] grantResults, final String[] permissions) { + return permissionGranted( + Manifest.permission.WRITE_EXTERNAL_STORAGE, grantResults, permissions); + } + + public static boolean audioGranted(final int[] grantResults, final String[] permissions) { + return permissionGranted(Manifest.permission.RECORD_AUDIO, grantResults, permissions); + } + + public static boolean cameraGranted(final int[] grantResults, final String[] permissions) { + return permissionGranted(Manifest.permission.CAMERA, grantResults, permissions); + } + + private static boolean permissionGranted( + final String permission, final int[] grantResults, final String[] permissions) { for (int i = 0; i < grantResults.length; ++i) { - if (Manifest.permission.WRITE_EXTERNAL_STORAGE.equals(permission[i])) { + if (permission.equals(permissions[i])) { return grantResults[i] == PackageManager.PERMISSION_GRANTED; } } From c636401232014ab47c6fd71cc2f5493e9c5702ba Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 22 Oct 2023 21:29:05 +0200 Subject: [PATCH 286/402] add proguard rules to fix issue in retrofit --- proguard-rules.pro | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/proguard-rules.pro b/proguard-rules.pro index 7e4d7d31d..03044d525 100644 --- a/proguard-rules.pro +++ b/proguard-rules.pro @@ -64,7 +64,21 @@ -dontwarn retrofit2.KotlinExtensions -dontwarn retrofit2.KotlinExtensions$* + # With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy # and replaces all potential values with null. Explicitly keeping the interfaces prevents this. -if interface * { @retrofit2.http.* ; } -keep,allowobfuscation interface <1> + +# Keep inherited services. +-if interface * { @retrofit2.http.* ; } +-keep,allowobfuscation interface * extends <1> + +# With R8 full mode generic signatures are stripped for classes that are not +# kept. Suspend functions are wrapped in continuations where the type argument +# is used. +-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation + +# R8 full mode strips generic signatures from return types if not kept. +-if interface * { @retrofit2.http.* public *** *(...); } +-keep,allowoptimization,allowshrinking,allowobfuscation class <3> From 10c47d86e9436a57f32c0a6a8f36bbd85d7edf68 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 25 Oct 2023 19:59:05 +0200 Subject: [PATCH 287/402] add dataSync fgs type for backup import/export --- src/main/AndroidManifest.xml | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 8732a411a..27efddc41 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -54,6 +54,9 @@ + + + @@ -116,7 +119,25 @@ tools:ignore="ForegroundServicePermission"> + android:value="xmpp-im" /> + + + + + + + + + - - - - - - - - Date: Wed, 25 Oct 2023 20:00:44 +0200 Subject: [PATCH 288/402] enable Java 17 language features --- build.gradle | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 13c4c3e21..eb0f369ab 100644 --- a/build.gradle +++ b/build.gradle @@ -31,6 +31,8 @@ configurations { } dependencies { + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3' + implementation 'androidx.viewpager:viewpager:1.0.0' playstoreImplementation('com.google.firebase:firebase-messaging:23.3.0') { @@ -121,8 +123,9 @@ android { } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + coreLibraryDesugaringEnabled true + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } flavorDimensions("mode", "distribution") @@ -231,7 +234,7 @@ android { } } lint { - disable 'MissingTranslation', 'InvalidPackage', 'AppCompatResource', 'ExtraTranslation' + disable 'MissingTranslation', 'InvalidPackage', 'AppCompatResource' } buildFeatures { buildConfig true From ea5ffe92ea6c0a62afd822d3d8e96bc6b16537c0 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 28 Oct 2023 17:44:27 +0200 Subject: [PATCH 289/402] improve logging when PGP decryption fails --- .../eu/siacs/conversations/crypto/PgpDecryptionService.java | 4 +++- .../siacs/conversations/services/XmppConnectionService.java | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/crypto/PgpDecryptionService.java b/src/main/java/eu/siacs/conversations/crypto/PgpDecryptionService.java index db84e0cf4..68447e552 100644 --- a/src/main/java/eu/siacs/conversations/crypto/PgpDecryptionService.java +++ b/src/main/java/eu/siacs/conversations/crypto/PgpDecryptionService.java @@ -156,7 +156,8 @@ public class PgpDecryptionService { && manager.getAutoAcceptFileSize() > 0) { manager.createNewDownloadConnection(message); } - } catch (IOException e) { + } catch (final IOException e) { + Log.d(Config.LOGTAG,"decryption failed", e); message.setEncryption(Message.ENCRYPTION_DECRYPTION_FAILED); } mXmppConnectionService.updateMessage(message); @@ -170,6 +171,7 @@ public class PgpDecryptionService { } break; case OpenPgpApi.RESULT_CODE_ERROR: + Log.d(Config.LOGTAG,"decryption failed (api error)"); message.setEncryption(Message.ENCRYPTION_DECRYPTION_FAILED); mXmppConnectionService.updateMessage(message); break; diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index a202a480c..09ceaeffc 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -1259,7 +1259,7 @@ public class XmppConnectionService extends Service { if (Config.supportOpenPgp()) { this.pgpServiceConnection = new OpenPgpServiceConnection(this, "org.sufficientlysecure.keychain", new OpenPgpServiceConnection.OnBound() { @Override - public void onBound(IOpenPgpService2 service) { + public void onBound(final IOpenPgpService2 service) { for (Account account : accounts) { final PgpDecryptionService pgp = account.getPgpDecryptionService(); if (pgp != null) { @@ -1269,7 +1269,8 @@ public class XmppConnectionService extends Service { } @Override - public void onError(Exception e) { + public void onError(final Exception exception) { + Log.e(Config.LOGTAG,"could not bind to OpenKeyChain", exception); } }); this.pgpServiceConnection.bindToService(); From 0bbc1193e332fa9e2e3130de8664097425c0a803 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 28 Oct 2023 18:02:20 +0200 Subject: [PATCH 290/402] allow background activity start for OpenKeyChain intents --- .../ui/ConversationFragment.java | 5 ++-- .../conversations/ui/EditAccountActivity.java | 3 ++- .../siacs/conversations/ui/XmppActivity.java | 26 +++++++++---------- .../conversations/ui/adapter/UserAdapter.java | 3 ++- .../conversations/utils/Compatibility.java | 24 +++++++++++++---- 5 files changed, 39 insertions(+), 22 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index a25c4d3c3..2ff7d9c6f 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -481,7 +481,8 @@ public class ConversationFragment extends XmppFragment null, 0, 0, - 0); + 0, + Compatibility.pgpStartIntentSenderOptions()); } catch (SendIntentException e) { Toast.makeText( getActivity(), @@ -3400,7 +3401,7 @@ public class ConversationFragment extends XmppFragment try { getActivity() .startIntentSenderForResult( - pendingIntent.getIntentSender(), requestCode, null, 0, 0, 0); + pendingIntent.getIntentSender(), requestCode, null, 0, 0, 0, Compatibility.pgpStartIntentSenderOptions()); } catch (final SendIntentException ignored) { } } diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index 62150d9c2..4011f1e2f 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -66,6 +66,7 @@ import eu.siacs.conversations.ui.util.AvatarWorkerTask; import eu.siacs.conversations.ui.util.MenuDoubleTabUtil; import eu.siacs.conversations.ui.util.PendingItem; import eu.siacs.conversations.ui.util.SoftKeyboardUtils; +import eu.siacs.conversations.utils.Compatibility; import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.Resolver; import eu.siacs.conversations.utils.SignupUtils; @@ -982,7 +983,7 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat public void userInputRequired(PendingIntent pi, String object) { mPendingPresenceTemplate.push(template); try { - startIntentSenderForResult(pi.getIntentSender(), REQUEST_CHANGE_STATUS, null, 0, 0, 0); + startIntentSenderForResult(pi.getIntentSender(), REQUEST_CHANGE_STATUS, null, 0, 0, 0, Compatibility.pgpStartIntentSenderOptions()); } catch (final IntentSender.SendIntentException ignored) { } } diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java index cebb8c22f..8b555f1b9 100644 --- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java @@ -48,7 +48,6 @@ import android.widget.Toast; import androidx.annotation.BoolRes; import androidx.annotation.NonNull; -import androidx.annotation.RequiresApi; import androidx.annotation.StringRes; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog.Builder; @@ -57,12 +56,6 @@ import androidx.databinding.DataBindingUtil; import com.google.common.base.Strings; -import java.io.IOException; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.RejectedExecutionException; - import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.PgpEngine; @@ -80,17 +73,23 @@ import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.services.XmppConnectionService.XmppConnectionBinder; import eu.siacs.conversations.ui.util.MenuDoubleTabUtil; import eu.siacs.conversations.ui.util.PresenceSelector; +import eu.siacs.conversations.ui.util.SettingsUtils; import eu.siacs.conversations.ui.util.SoftKeyboardUtils; import eu.siacs.conversations.utils.AccountUtils; import eu.siacs.conversations.utils.Compatibility; import eu.siacs.conversations.utils.ExceptionHelper; -import eu.siacs.conversations.ui.util.SettingsUtils; import eu.siacs.conversations.utils.SignupUtils; import eu.siacs.conversations.utils.ThemeHelper; import eu.siacs.conversations.xmpp.Jid; import eu.siacs.conversations.xmpp.OnKeyStatusUpdated; import eu.siacs.conversations.xmpp.OnUpdateBlocklist; +import java.io.IOException; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.RejectedExecutionException; + public abstract class XmppActivity extends ActionBarActivity { public static final String EXTRA_ACCOUNT = "account"; @@ -644,9 +643,9 @@ public abstract class XmppActivity extends ActionBarActivity { xmppConnectionService.getPgpEngine().generateSignature(intent, account, status, new UiCallback() { @Override - public void userInputRequired(PendingIntent pi, String signature) { + public void userInputRequired(final PendingIntent pi, final String signature) { try { - startIntentSenderForResult(pi.getIntentSender(), REQUEST_ANNOUNCE_PGP, null, 0, 0, 0); + startIntentSenderForResult(pi.getIntentSender(), REQUEST_ANNOUNCE_PGP, null, 0, 0, 0,Compatibility.pgpStartIntentSenderOptions()); } catch (final SendIntentException ignored) { } } @@ -707,7 +706,7 @@ public abstract class XmppActivity extends ActionBarActivity { public void userInputRequired(PendingIntent pi, Account object) { try { startIntentSenderForResult(pi.getIntentSender(), - REQUEST_CHOOSE_PGP_ID, null, 0, 0, 0); + REQUEST_CHOOSE_PGP_ID, null, 0, 0, 0, Compatibility.pgpStartIntentSenderOptions()); } catch (final SendIntentException ignored) { } } @@ -881,8 +880,9 @@ public abstract class XmppActivity extends ActionBarActivity { try { startIntentSenderForResult( pgp.getIntentForKey(keyId).getIntentSender(), 0, null, 0, - 0, 0); - } catch (Throwable e) { + 0, 0, Compatibility.pgpStartIntentSenderOptions()); + } catch (final Throwable e) { + Log.d(Config.LOGTAG,"could not launch OpenKeyChain", e); Toast.makeText(XmppActivity.this, R.string.openpgp_error, Toast.LENGTH_SHORT).show(); } } diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/UserAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/UserAdapter.java index 41bfb24a1..de3216908 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/UserAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/UserAdapter.java @@ -25,6 +25,7 @@ import eu.siacs.conversations.ui.ConferenceDetailsActivity; import eu.siacs.conversations.ui.XmppActivity; import eu.siacs.conversations.ui.util.AvatarWorkerTask; import eu.siacs.conversations.ui.util.MucDetailsContextMenuHelper; +import eu.siacs.conversations.utils.Compatibility; import eu.siacs.conversations.xmpp.Jid; public class UserAdapter extends ListAdapter implements View.OnCreateContextMenuListener { @@ -104,7 +105,7 @@ public class UserAdapter extends ListAdapter UNUSED_SETTINGS_POST_TWENTYSIX = @@ -41,7 +43,8 @@ public class Compatibility { Collections.singletonList("message_notification_settings"); public static boolean hasStoragePermission(final Context context) { - return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU + return Build.VERSION.SDK_INT < Build.VERSION_CODES.M + || Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU || ContextCompat.checkSelfPermission( context, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; @@ -177,4 +180,15 @@ public class Compatibility { return ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED; } } + + public static Bundle pgpStartIntentSenderOptions() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + return ActivityOptions.makeBasic() + .setPendingIntentBackgroundActivityStartMode( + ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED) + .toBundle(); + } else { + return null; + } + } } From 71b6492d61f818e49337bd224c18d70e01824a23 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 30 Oct 2023 13:06:04 +0100 Subject: [PATCH 291/402] show unverified devices warning in contact and account details --- .../crypto/axolotl/AxolotlService.java | 6 +- .../crypto/axolotl/FingerprintStatus.java | 4 + .../ui/ContactDetailsActivity.java | 8 +- .../conversations/ui/EditAccountActivity.java | 13 +- .../siacs/conversations/ui/OmemoActivity.java | 1 + .../res/layout/activity_contact_details.xml | 13 + src/main/res/layout/activity_edit_account.xml | 227 +++++++++++------- src/main/res/values/strings.xml | 2 + 8 files changed, 178 insertions(+), 96 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java index 05ffdbdca..9cf3d9091 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java @@ -736,8 +736,12 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { return axolotlStore.getFingerprintCertificate(fingerprint); } - public void setFingerprintTrust(String fingerprint, FingerprintStatus status) { + public void setFingerprintTrust(final String fingerprint, final FingerprintStatus status) { axolotlStore.setFingerprintStatus(fingerprint, status); + // TODO we decided to call this after a fingerprint gets toggled to update the 'your contact + // is using unverified devices text'; however this means the entire screen gets redrawn + // after a toggle which might be annoying or cause other weird UI glitches + mXmppConnectionService.updateAccountUi(); } private ListenableFuture verifySessionWithPEP(final XmppAxolotlSession session) { diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/FingerprintStatus.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/FingerprintStatus.java index 2f1856d09..dffde90a1 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/FingerprintStatus.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/FingerprintStatus.java @@ -97,6 +97,10 @@ public class FingerprintStatus implements Comparable { return trust == Trust.TRUSTED || isVerified(); } + public boolean isUnverified() { + return trust == Trust.TRUSTED; + } + public boolean isVerified() { return trust == Trust.VERIFIED || trust == Trust.VERIFIED_X509; } diff --git a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java index 7c1d08643..f1556df6e 100644 --- a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java @@ -455,6 +455,7 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp } boolean skippedInactive = false; boolean showsInactive = false; + boolean showUnverifiedWarning = false; for (final XmppAxolotlSession session : sessions) { final FingerprintStatus trust = session.getTrust(); hasKeys |= !trust.isCompromised(); @@ -470,7 +471,11 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp boolean highlight = session.getFingerprint().equals(messageFingerprint); addFingerprintRow(binding.detailsContactKeys, session, highlight); } + if (trust.isUnverified()) { + showUnverifiedWarning = true; + } } + binding.unverifiedWarning.setVisibility(showUnverifiedWarning ? View.VISIBLE : View.GONE); if (showsInactive || skippedInactive) { binding.showInactiveDevices.setText(showsInactive ? R.string.hide_inactive_devices : R.string.show_inactive_devices); binding.showInactiveDevices.setVisibility(View.VISIBLE); @@ -480,7 +485,8 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp } else { binding.showInactiveDevices.setVisibility(View.GONE); } - binding.scanButton.setVisibility(hasKeys && isCameraFeatureAvailable() ? View.VISIBLE : View.GONE); + final boolean isCameraFeatureAvailable = isCameraFeatureAvailable(); + binding.scanButton.setVisibility(hasKeys && isCameraFeatureAvailable ? View.VISIBLE : View.GONE); if (hasKeys) { binding.scanButton.setOnClickListener((v) -> ScanActivity.scan(this)); } diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index 4011f1e2f..42335048a 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -49,6 +49,7 @@ import java.util.concurrent.atomic.AtomicInteger; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.axolotl.AxolotlService; +import eu.siacs.conversations.crypto.axolotl.FingerprintStatus; import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession; import eu.siacs.conversations.databinding.ActivityEditAccountBinding; import eu.siacs.conversations.databinding.DialogPresenceBinding; @@ -630,6 +631,7 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat this.binding.accountRegisterNew.setVisibility(View.GONE); } this.binding.actionEditYourName.setOnClickListener(this::onEditYourNameClicked); + this.binding.scanButton.setOnClickListener((v) -> ScanActivity.scan(this)); } private void onEditYourNameClicked(View view) { @@ -1166,13 +1168,18 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat this.binding.axolotlFingerprintBox.setVisibility(View.GONE); } boolean hasKeys = false; + boolean showUnverifiedWarning = false; binding.otherDeviceKeys.removeAllViews(); - for (XmppAxolotlSession session : mAccount.getAxolotlService().findOwnSessions()) { - if (!session.getTrust().isCompromised()) { + for (final XmppAxolotlSession session : mAccount.getAxolotlService().findOwnSessions()) { + final FingerprintStatus trust = session.getTrust(); + if (!trust.isCompromised()) { boolean highlight = session.getFingerprint().equals(messageFingerprint); addFingerprintRow(binding.otherDeviceKeys, session, highlight); hasKeys = true; } + if (trust.isUnverified()) { + showUnverifiedWarning = true; + } } if (hasKeys && Config.supportOmemo()) { //TODO: either the button should be visible if we print an active device or the device list should be fed with reactived devices this.binding.otherDeviceKeysCard.setVisibility(View.VISIBLE); @@ -1182,6 +1189,8 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat } else { binding.clearDevices.setVisibility(View.VISIBLE); } + binding.unverifiedWarning.setVisibility(showUnverifiedWarning ? View.VISIBLE : View.GONE); + binding.scanButton.setVisibility(showUnverifiedWarning ? View.VISIBLE : View.GONE); } else { this.binding.otherDeviceKeysCard.setVisibility(View.GONE); } diff --git a/src/main/java/eu/siacs/conversations/ui/OmemoActivity.java b/src/main/java/eu/siacs/conversations/ui/OmemoActivity.java index 89fdae333..44af0d0b2 100644 --- a/src/main/java/eu/siacs/conversations/ui/OmemoActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/OmemoActivity.java @@ -205,6 +205,7 @@ public abstract class OmemoActivity extends XmppActivity { @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); ScanActivity.onRequestPermissionResult(this, requestCode, grantResults); } } diff --git a/src/main/res/layout/activity_contact_details.xml b/src/main/res/layout/activity_contact_details.xml index a7d569a4a..fc7219ee1 100644 --- a/src/main/res/layout/activity_contact_details.xml +++ b/src/main/res/layout/activity_contact_details.xml @@ -186,6 +186,19 @@ android:orientation="vertical" android:padding="@dimen/card_padding_list"/> + + + + + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools"> - + android:layout_marginBottom="@dimen/activity_vertical_margin"> + app:riv_corner_radius="8dp" /> + app:errorTextAppearance="@style/TextAppearance.Conversations.Design.Error" + app:hintTextAppearance="@style/TextAppearance.Conversations.Design.Hint"> + android:textColor="?attr/edit_text_color" /> @@ -76,21 +77,21 @@ android:id="@+id/account_password_layout" android:layout_width="match_parent" android:layout_height="wrap_content" + app:errorTextAppearance="@style/TextAppearance.Conversations.Design.Error" + app:hintTextAppearance="@style/TextAppearance.Conversations.Design.Hint" app:passwordToggleDrawable="@drawable/visibility_toggle_drawable" app:passwordToggleEnabled="true" - app:passwordToggleTint="?android:textColorSecondary" - app:hintTextAppearance="@style/TextAppearance.Conversations.Design.Hint" - app:errorTextAppearance="@style/TextAppearance.Conversations.Design.Error"> + app:passwordToggleTint="?android:textColorSecondary"> + android:textColor="?attr/edit_text_color" /> + app:errorTextAppearance="@style/TextAppearance.Conversations.Design.Error" + app:hintTextAppearance="@style/TextAppearance.Conversations.Design.Hint"> + android:inputType="textWebEmailAddress" /> @@ -135,16 +136,16 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/account_settings_port" - app:hintTextAppearance="@style/TextAppearance.Conversations.Design.Hint" - app:errorTextAppearance="@style/TextAppearance.Conversations.Design.Error"> + app:errorTextAppearance="@style/TextAppearance.Conversations.Design.Error" + app:hintTextAppearance="@style/TextAppearance.Conversations.Design.Hint"> + android:maxLength="5" /> @@ -155,7 +156,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" - android:text="@string/register_account"/> + android:text="@string/register_account" /> @@ -164,10 +165,10 @@ android:id="@+id/os_optimization" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/activity_vertical_margin" android:layout_marginLeft="@dimen/activity_horizontal_margin" - android:layout_marginRight="@dimen/activity_horizontal_margin" android:layout_marginTop="@dimen/activity_vertical_margin" + android:layout_marginRight="@dimen/activity_horizontal_margin" + android:layout_marginBottom="@dimen/activity_vertical_margin" android:visibility="gone"> + android:textAppearance="@style/TextAppearance.Conversations.Title" /> + android:textAppearance="@style/TextAppearance.Conversations.Body1" /> + android:textColor="?colorAccent" /> @@ -222,10 +223,10 @@ android:id="@+id/stats" android:layout_width="fill_parent" android:layout_height="fill_parent" - android:layout_marginBottom="@dimen/activity_vertical_margin" android:layout_marginLeft="@dimen/activity_horizontal_margin" - android:layout_marginRight="@dimen/activity_horizontal_margin" android:layout_marginTop="@dimen/activity_vertical_margin" + android:layout_marginRight="@dimen/activity_horizontal_margin" + android:layout_marginBottom="@dimen/activity_vertical_margin" android:visibility="gone"> + android:textAppearance="@style/TextAppearance.Conversations.Body1" /> + android:textAppearance="@style/TextAppearance.Conversations.Body1" /> @@ -282,7 +283,7 @@ android:ellipsize="end" android:singleLine="true" android:text="@string/server_info_pep" - android:textAppearance="@style/TextAppearance.Conversations.Body1"/> + android:textAppearance="@style/TextAppearance.Conversations.Body1" /> + tools:ignore="RtlHardcoded" /> + android:textAppearance="@style/TextAppearance.Conversations.Body1" /> + tools:ignore="RtlHardcoded" /> + android:textAppearance="@style/TextAppearance.Conversations.Body1" /> + tools:ignore="RtlHardcoded" /> + android:textAppearance="@style/TextAppearance.Conversations.Body1" /> + tools:ignore="RtlHardcoded" /> + android:textAppearance="@style/TextAppearance.Conversations.Body1" /> + tools:ignore="RtlHardcoded" /> + android:textAppearance="@style/TextAppearance.Conversations.Body1" /> + tools:ignore="RtlHardcoded" /> + android:textAppearance="@style/TextAppearance.Conversations.Body1" /> + tools:ignore="RtlHardcoded" /> + android:textAppearance="@style/TextAppearance.Conversations.Body1" /> + tools:ignore="RtlHardcoded" /> + android:textAppearance="@style/TextAppearance.Conversations.Body1" /> + android:textAppearance="@style/TextAppearance.Conversations.Body1" /> + android:textAppearance="@style/TextAppearance.Conversations.Body1" /> + android:textAppearance="@style/TextAppearance.Conversations.Body1" /> @@ -512,14 +513,14 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/no_name_set_instructions" - android:textAppearance="@style/TextAppearance.Conversations.Body1.Tertiary"/> + android:textAppearance="@style/TextAppearance.Conversations.Body1.Tertiary" /> + android:textAppearance="@style/TextAppearance.Conversations.Caption" /> + android:visibility="visible" /> + android:textAppearance="@style/TextAppearance.Conversations.Fingerprint" /> + android:textAppearance="@style/TextAppearance.Conversations.Caption" /> + android:visibility="visible" /> + android:textAppearance="@style/TextAppearance.Conversations.Fingerprint" /> + android:textAppearance="@style/TextAppearance.Conversations.Caption" /> + android:visibility="visible" /> + android:visibility="gone" /> @@ -642,41 +643,83 @@ android:id="@+id/other_device_keys_card" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/activity_vertical_margin" android:layout_marginLeft="@dimen/activity_horizontal_margin" - android:layout_marginRight="@dimen/activity_horizontal_margin" android:layout_marginTop="@dimen/activity_vertical_margin" + android:layout_marginRight="@dimen/activity_horizontal_margin" + android:layout_marginBottom="@dimen/activity_vertical_margin" android:visibility="gone"> - - + android:orientation="vertical"> + android:orientation="vertical" + android:padding="@dimen/card_padding_list"> -