Merge tag '2.11.3'

Stephen Paul Weber created

* tag '2.11.3': (55 commits)
  version bump to 2.11.3 + changelog
  fix client crashing on empty passwords (regression)
  downgrade webrtc to m104
  make sure we don’t dispose video source twice
  reset stanza count when enabling SM via SASL inline
  code clean up. use Optional to parse SM’s h attribute
  add log when we requested token but didn’t get one
  bump libwebrtc to 108.0.1
  Translated using Weblate (Spanish)
  Translated using Weblate (Spanish)
  Translated using Weblate (German)
  Translated using Weblate (Chinese (Simplified))
  Translated using Weblate (German)
  Translated using Weblate (German)
  Translated using Weblate (German)
  Translated using Weblate (Italian)
  Translated using Weblate (Galician)
  Translated using Weblate (Spanish)
  Translated using Weblate (German)
  Translated using Weblate (Italian)
  ...

Change summary

.github/FUNDING.yml                                                            |   3 
.github/workflows/android.yml                                                  |  34 
CHANGELOG.md                                                                   |  15 
art/render.rb                                                                  | 299 
build.gradle                                                                   |   6 
fastlane/metadata/android/de-DE/changelogs/349.txt                             |   4 
fastlane/metadata/android/de-DE/changelogs/351.txt                             |   3 
fastlane/metadata/android/de-DE/changelogs/353.txt                             |   4 
fastlane/metadata/android/de-DE/changelogs/360.txt                             |   1 
fastlane/metadata/android/de-DE/changelogs/362.txt                             |   1 
fastlane/metadata/android/de-DE/changelogs/364.txt                             |   2 
fastlane/metadata/android/de-DE/changelogs/367.txt                             |   2 
fastlane/metadata/android/de-DE/changelogs/379.txt                             |   1 
fastlane/metadata/android/de-DE/changelogs/381.txt                             |   2 
fastlane/metadata/android/de-DE/changelogs/382.txt                             |   2 
fastlane/metadata/android/de-DE/changelogs/383.txt                             |   3 
fastlane/metadata/android/de-DE/changelogs/387.txt                             |   2 
fastlane/metadata/android/de-DE/changelogs/388.txt                             |   3 
fastlane/metadata/android/de-DE/changelogs/390.txt                             |   1 
fastlane/metadata/android/de-DE/changelogs/393.txt                             |   3 
fastlane/metadata/android/de-DE/changelogs/394.txt                             |   2 
fastlane/metadata/android/de-DE/changelogs/395.txt                             |   3 
fastlane/metadata/android/de-DE/changelogs/397.txt                             |   3 
fastlane/metadata/android/de-DE/changelogs/398.txt                             |   4 
fastlane/metadata/android/de-DE/changelogs/401.txt                             |   2 
fastlane/metadata/android/de-DE/changelogs/402.txt                             |   3 
fastlane/metadata/android/de-DE/changelogs/403.txt                             |   3 
fastlane/metadata/android/de-DE/changelogs/404.txt                             |   1 
fastlane/metadata/android/de-DE/changelogs/405.txt                             |   1 
fastlane/metadata/android/de-DE/changelogs/407.txt                             |   3 
fastlane/metadata/android/de-DE/changelogs/42000.txt                           |   4 
fastlane/metadata/android/de-DE/changelogs/42006.txt                           |   2 
fastlane/metadata/android/de-DE/changelogs/42010.txt                           |   2 
fastlane/metadata/android/de-DE/changelogs/42012.txt                           |   1 
fastlane/metadata/android/de-DE/changelogs/42013.txt                           |   1 
fastlane/metadata/android/de-DE/changelogs/42014.txt                           |   2 
fastlane/metadata/android/de-DE/changelogs/42015.txt                           |   1 
fastlane/metadata/android/de-DE/changelogs/42018.txt                           |   3 
fastlane/metadata/android/de-DE/changelogs/42022.txt                           |   2 
fastlane/metadata/android/de-DE/changelogs/42023.txt                           |   2 
fastlane/metadata/android/de-DE/changelogs/42037.txt                           |   9 
fastlane/metadata/android/de-DE/changelogs/42038.txt                           |   2 
fastlane/metadata/android/de-DE/changelogs/42041.txt                           |   5 
fastlane/metadata/android/de-DE/changelogs/42042.txt                           |   2 
fastlane/metadata/android/de-DE/changelogs/42043.txt                           |   1 
fastlane/metadata/android/de-DE/full_description.txt                           |  39 
fastlane/metadata/android/de-DE/short_description.txt                          |   1 
fastlane/metadata/android/en-US/changelogs/42042.txt                           |   2 
fastlane/metadata/android/en-US/changelogs/42043.txt                           |   1 
fastlane/metadata/android/en-US/changelogs/42044.txt                           |   3 
fastlane/metadata/android/it-IT/full_description.txt                           |  39 
fastlane/metadata/android/it-IT/short_description.txt                          |   1 
src/conversations/res/values-es/strings.xml                                    |   5 
src/conversations/res/values-gl/strings.xml                                    |   2 
src/conversations/res/values-it/strings.xml                                    |   8 
src/conversations/res/values-zh-rCN/strings.xml                                |   2 
src/main/java/eu/siacs/conversations/crypto/sasl/ScramMechanism.java           |  21 
src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha1.java                |   4 
src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha1Plus.java            |   4 
src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha256.java              |   4 
src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha256Plus.java          |   4 
src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha512.java              |   4 
src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha512Plus.java          |   4 
src/main/java/eu/siacs/conversations/services/ContactChooserTargetService.java |  50 
src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java                |  28 
src/main/java/eu/siacs/conversations/xml/Element.java                          |  11 
src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java                  | 145 
src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java      |   6 
src/main/java/eu/siacs/conversations/xmpp/jingle/VideoSourceWrapper.java       |  10 
src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java            |  12 
src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java          |  11 
src/main/res/values-ca-rES/strings.xml                                         |   2 
src/main/res/values-da-rDK/strings.xml                                         |  22 
src/main/res/values-de/strings.xml                                             |  32 
src/main/res/values-es/strings.xml                                             |  96 
src/main/res/values-fa/strings.xml                                             |   2 
src/main/res/values-gl/strings.xml                                             |  89 
src/main/res/values-hr/strings.xml                                             |  14 
src/main/res/values-it/strings.xml                                             |  40 
src/main/res/values-ja/strings.xml                                             |  36 
src/main/res/values-zh-rCN/strings.xml                                         | 117 
src/main/res/values/about.xml                                                  |   4 
src/quicksy/AndroidManifest.xml                                                |   5 
src/quicksy/res/values-de/strings.xml                                          |   6 
src/quicksy/res/values-es/strings.xml                                          |  10 
src/quicksy/res/values-gl/strings.xml                                          |   4 
src/quicksy/res/values-hr/strings.xml                                          |  12 
src/quicksy/res/values-zh-rCN/strings.xml                                      |  14 
88 files changed, 869 insertions(+), 512 deletions(-)

Detailed changes

.github/FUNDING.yml 🔗

@@ -1,3 +0,0 @@
-github: inputmice
-liberapay: inputmice
-custom: https://gultsch.de/donate.html

.github/workflows/android.yml 🔗

@@ -1,34 +0,0 @@
-name: Android CI
-
-on:
-  push:
-    branches: [ master ]
-  pull_request:
-    branches: [ master ]
-
-jobs:
-  build:
-
-    runs-on: ubuntu-latest
-
-    steps:
-    - uses: actions/checkout@v2
-    - name: set up JDK 11
-      uses: actions/setup-java@v2
-      with:
-        java-version: '11'
-        distribution: 'adopt'
-    - name: Download WebRTC
-      run: mkdir libs && wget -O libs/libwebrtc-m99.aar https://gultsch.de/files/libwebrtc-m99.aar
-    - name: Grant execute permission for gradlew
-      run: chmod +x gradlew
-    - name: Build Quicksy
-      run: ./gradlew assembleQuicksyFreeDebug
-    - name: Build Conversations
-      run: ./gradlew assembleConversationsFreeDebug
-    - uses: actions/upload-artifact@v2
-      with:
-        name: Conversations all-flavors (debug)
-        path: ./build/outputs/apk/**/debug/Conversations-*.apk
-
-      

CHANGELOG.md 🔗

@@ -1,5 +1,20 @@
 # Changelog
 
+### Version 2.11.3
+
+* Fix messages getting resend when using SASL2
+* Fix black video between some devices
+* Fix crash on empty passwords
+
+### Version 2.11.2
+
+* Fixed regression in P2P file transfer
+
+### Version 2.11.1
+
+* Fix resend loop on servers that support only sm:2
+* Show 'Switch to video' only if other party supports video
+
 ### Version 2.11.0
 
 * Implement Extensible SASL Profile, Bind 2.0 and Fast for faster reconnects

art/render.rb 🔗

@@ -1,168 +1,157 @@
 #!/bin/env ruby
+# frozen_string_literal: true
 
 require 'xml'
 
 resolutions = {
-	'mdpi' => 1,
-	'hdpi' => 1.5,
-	'xhdpi' => 2,
-	'xxhdpi' => 3,
-	'xxxhdpi' => 4,
-	}
+  'mdpi' => 1,
+  'hdpi' => 1.5,
+  'xhdpi' => 2,
+  'xxhdpi' => 3,
+  'xxxhdpi' => 4
+}
 
 images = {
-	'main_logo.svg' => ['conversations/main_logo', 200],
-    'quicksy_main_logo.svg' => ['quicksy/main_logo', 200],
-    'splash_logo.svg' => ['conversations/splash_logo', 144],
-    'quicksy_splash_logo.svg' => ['quicksy/splash_logo', 144],
-    'ic_search_black.svg' => ['ic_search_background_black', 144],
-    'ic_search_white.svg' => ['ic_search_background_white', 144],
-    'ic_no_results_white.svg' => ['ic_no_results_background_white', 144],
-    'ic_no_results_black.svg' => ['ic_no_results_background_black', 144],
-	'play_video_white.svg' => ['play_video_white', 128],
-	'play_gif_white.svg' => ['play_gif_white', 128],
-    'play_video_black.svg' => ['play_video_black', 128],
-    'play_gif_black.svg' => ['play_gif_black', 128],
-    'open_pdf_black.svg' => ['open_pdf_black', 128],
-    'open_pdf_white.svg' => ['open_pdf_white', 128],
-	'conversations_mono.svg' => ['conversations/ic_notification', 24],
-    'quicksy_mono.svg' => ['quicksy/ic_notification', 24],
-    'flip_camera_android-black-24dp.svg' => ['ic_flip_camera_android_black_24dp', 24],
-    'ic_missed_call_notification.svg' => ['ic_missed_call_notification', 24],
-	'ic_send_text_offline.svg' => ['ic_send_text_offline', 36],
-	'ic_send_text_offline_white.svg' => ['ic_send_text_offline_white', 36],
-	'ic_send_text_online.svg' => ['ic_send_text_online', 36],
-	'ic_send_text_away.svg' => ['ic_send_text_away', 36],
-	'ic_send_text_dnd.svg' => ['ic_send_text_dnd', 36],
-	'ic_send_photo_online.svg' => ['ic_send_photo_online', 36],
-	'ic_send_photo_offline.svg' => ['ic_send_photo_offline', 36],
-	'ic_send_photo_offline_white.svg' => ['ic_send_photo_offline_white', 36],
-	'ic_send_photo_away.svg' => ['ic_send_photo_away', 36],
-	'ic_send_photo_dnd.svg' => ['ic_send_photo_dnd', 36],
-	'ic_send_location_online.svg' => ['ic_send_location_online', 36],
-	'ic_send_location_offline.svg' => ['ic_send_location_offline', 36],
-	'ic_send_location_offline_white.svg' => ['ic_send_location_offline_white', 36],
-	'ic_send_location_away.svg' => ['ic_send_location_away', 36],
-	'ic_send_location_dnd.svg' => ['ic_send_location_dnd', 36],
-	'ic_send_voice_online.svg' => ['ic_send_voice_online', 36],
-	'ic_send_voice_offline.svg' => ['ic_send_voice_offline', 36],
-	'ic_send_voice_offline_white.svg' => ['ic_send_voice_offline_white', 36],
-	'ic_send_voice_away.svg' => ['ic_send_voice_away', 36],
-	'ic_send_voice_dnd.svg' => ['ic_send_voice_dnd', 36],
-	'ic_send_cancel_online.svg' => ['ic_send_cancel_online', 36],
-	'ic_send_cancel_offline.svg' => ['ic_send_cancel_offline', 36],
-	'ic_send_cancel_offline_white.svg' => ['ic_send_cancel_offline_white', 36],
-	'ic_send_cancel_away.svg' => ['ic_send_cancel_away', 36],
-	'ic_send_cancel_dnd.svg' => ['ic_send_cancel_dnd', 36],
-	'ic_send_picture_online.svg' => ['ic_send_picture_online', 36],
-	'ic_send_picture_offline.svg' => ['ic_send_picture_offline', 36],
-	'ic_send_picture_offline_white.svg' => ['ic_send_picture_offline_white', 36],
-	'ic_send_picture_away.svg' => ['ic_send_picture_away', 36],
-	'ic_send_picture_dnd.svg' => ['ic_send_picture_dnd', 36],
-	'ic_send_videocam_online.svg' => ['ic_send_videocam_online', 36],
-	'ic_send_videocam_offline.svg' => ['ic_send_videocam_offline', 36],
-	'ic_send_videocam_offline_white.svg' => ['ic_send_videocam_offline_white', 36],
-	'ic_send_videocam_away.svg' => ['ic_send_videocam_away', 36],
-	'ic_send_videocam_dnd.svg' => ['ic_send_videocam_dnd', 36],
-	'ic_notifications_none_white80.svg' => ['ic_notifications_none_white80', 24],
-	'ic_notifications_off_white80.svg' => ['ic_notifications_off_white80', 24],
-	'ic_notifications_paused_white80.svg' => ['ic_notifications_paused_white80', 24],
-	'ic_notifications_white80.svg' => ['ic_notifications_white80', 24],
-	'ic_verified_fingerprint.svg' => ['ic_verified_fingerprint', 36],
-    'qrcode-scan.svg' => ['ic_qr_code_scan_white_24dp', 24],
-	'message_bubble_received.svg' => ['message_bubble_received.9', 0],
-	'message_bubble_received_grey.svg' => ['message_bubble_received_grey.9', 0],
-	'message_bubble_received_dark.svg' => ['message_bubble_received_dark.9', 0],
-	'message_bubble_received_warning.svg' => ['message_bubble_received_warning.9', 0],
-	'message_bubble_received_white.svg' => ['message_bubble_received_white.9', 0],
-	'message_bubble_sent.svg' => ['message_bubble_sent.9', 0],
-	'message_bubble_sent_grey.svg' => ['message_bubble_sent_grey.9', 0],
-	'date_bubble_white.svg' => ['date_bubble_white.9', 0],
-	'date_bubble_grey.svg' => ['date_bubble_grey.9', 0],
-	'marker.svg' => ['marker', 0]
-	}
-
-# Executable paths for Mac OSX
-# "/Applications/Inkscape.app/Contents/Resources/bin/inkscape"
-
-inkscape = "inkscape"
-imagemagick = "magick"
+  'main_logo.svg' => ['conversations/main_logo', 200],
+  'quicksy_main_logo.svg' => ['quicksy/main_logo', 200],
+  'splash_logo.svg' => ['conversations/splash_logo', 144],
+  'quicksy_splash_logo.svg' => ['quicksy/splash_logo', 144],
+  'ic_search_black.svg' => ['ic_search_background_black', 144],
+  'ic_search_white.svg' => ['ic_search_background_white', 144],
+  'ic_no_results_white.svg' => ['ic_no_results_background_white', 144],
+  'ic_no_results_black.svg' => ['ic_no_results_background_black', 144],
+  'play_video_white.svg' => ['play_video_white', 128],
+  'play_gif_white.svg' => ['play_gif_white', 128],
+  'play_video_black.svg' => ['play_video_black', 128],
+  'play_gif_black.svg' => ['play_gif_black', 128],
+  'open_pdf_black.svg' => ['open_pdf_black', 128],
+  'open_pdf_white.svg' => ['open_pdf_white', 128],
+  'conversations_mono.svg' => ['conversations/ic_notification', 24],
+  'quicksy_mono.svg' => ['quicksy/ic_notification', 24],
+  'flip_camera_android-black-24dp.svg' => ['ic_flip_camera_android_black_24dp', 24],
+  'ic_send_text_offline.svg' => ['ic_send_text_offline', 36],
+  'ic_send_text_offline_white.svg' => ['ic_send_text_offline_white', 36],
+  'ic_send_text_online.svg' => ['ic_send_text_online', 36],
+  'ic_send_text_away.svg' => ['ic_send_text_away', 36],
+  'ic_send_text_dnd.svg' => ['ic_send_text_dnd', 36],
+  'ic_send_photo_online.svg' => ['ic_send_photo_online', 36],
+  'ic_send_photo_offline.svg' => ['ic_send_photo_offline', 36],
+  'ic_send_photo_offline_white.svg' => ['ic_send_photo_offline_white', 36],
+  'ic_send_photo_away.svg' => ['ic_send_photo_away', 36],
+  'ic_send_photo_dnd.svg' => ['ic_send_photo_dnd', 36],
+  'ic_send_location_online.svg' => ['ic_send_location_online', 36],
+  'ic_send_location_offline.svg' => ['ic_send_location_offline', 36],
+  'ic_send_location_offline_white.svg' => ['ic_send_location_offline_white', 36],
+  'ic_send_location_away.svg' => ['ic_send_location_away', 36],
+  'ic_send_location_dnd.svg' => ['ic_send_location_dnd', 36],
+  'ic_send_voice_online.svg' => ['ic_send_voice_online', 36],
+  'ic_send_voice_offline.svg' => ['ic_send_voice_offline', 36],
+  'ic_send_voice_offline_white.svg' => ['ic_send_voice_offline_white', 36],
+  'ic_send_voice_away.svg' => ['ic_send_voice_away', 36],
+  'ic_send_voice_dnd.svg' => ['ic_send_voice_dnd', 36],
+  'ic_send_cancel_online.svg' => ['ic_send_cancel_online', 36],
+  'ic_send_cancel_offline.svg' => ['ic_send_cancel_offline', 36],
+  'ic_send_cancel_offline_white.svg' => ['ic_send_cancel_offline_white', 36],
+  'ic_send_cancel_away.svg' => ['ic_send_cancel_away', 36],
+  'ic_send_cancel_dnd.svg' => ['ic_send_cancel_dnd', 36],
+  'ic_send_picture_online.svg' => ['ic_send_picture_online', 36],
+  'ic_send_picture_offline.svg' => ['ic_send_picture_offline', 36],
+  'ic_send_picture_offline_white.svg' => ['ic_send_picture_offline_white', 36],
+  'ic_send_picture_away.svg' => ['ic_send_picture_away', 36],
+  'ic_send_picture_dnd.svg' => ['ic_send_picture_dnd', 36],
+  'ic_send_videocam_online.svg' => ['ic_send_videocam_online', 36],
+  'ic_send_videocam_offline.svg' => ['ic_send_videocam_offline', 36],
+  'ic_send_videocam_offline_white.svg' => ['ic_send_videocam_offline_white', 36],
+  'ic_send_videocam_away.svg' => ['ic_send_videocam_away', 36],
+  'ic_send_videocam_dnd.svg' => ['ic_send_videocam_dnd', 36],
+  'ic_notifications_none_white80.svg' => ['ic_notifications_none_white80', 24],
+  'ic_notifications_off_white80.svg' => ['ic_notifications_off_white80', 24],
+  'ic_notifications_paused_white80.svg' => ['ic_notifications_paused_white80', 24],
+  'ic_notifications_white80.svg' => ['ic_notifications_white80', 24],
+  'ic_verified_fingerprint.svg' => ['ic_verified_fingerprint', 36],
+  'qrcode-scan.svg' => ['ic_qr_code_scan_white_24dp', 24],
+  'message_bubble_received.svg' => ['message_bubble_received.9', 0],
+  'message_bubble_received_grey.svg' => ['message_bubble_received_grey.9', 0],
+  'message_bubble_received_dark.svg' => ['message_bubble_received_dark.9', 0],
+  'message_bubble_received_warning.svg' => ['message_bubble_received_warning.9', 0],
+  'message_bubble_received_white.svg' => ['message_bubble_received_white.9', 0],
+  'message_bubble_sent.svg' => ['message_bubble_sent.9', 0],
+  'message_bubble_sent_grey.svg' => ['message_bubble_sent_grey.9', 0],
+  'date_bubble_white.svg' => ['date_bubble_white.9', 0],
+  'date_bubble_grey.svg' => ['date_bubble_grey.9', 0],
+  'marker.svg' => ['marker', 0]
+}
+
+inkscape = 'inkscape'
+imagemagick = 'convert'
 
 def execute_cmd(cmd)
-	puts cmd
-	system cmd
+  puts cmd
+  system cmd
 end
 
 images.each do |source_filename, settings|
-	svg_content = File.read(source_filename)
-
-	svg = XML::Document.string(svg_content)
-	base_width = svg.root["width"].to_i
-	base_height = svg.root["height"].to_i
-
-	guides = svg.find(".//sodipodi:guide","sodipodi:http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd")
-
-	resolutions.each do |resolution, factor|
-		output_filename, base_size = settings
-
-		if base_size > 0
-			width = factor * base_size
-			height = factor * base_size
-		else
-			width = factor * base_width
-			height = factor * base_height
-		end
-
-        output_parts = output_filename.split('/')
-
-        if output_parts.count != 2
-    		path = "../src/main/res/drawable-#{resolution}/#{output_filename}.png"
-        else
-            path = "../src/#{output_parts[0]}/res/drawable-#{resolution}/#{output_parts[1]}.png"
-        end
-		execute_cmd "#{inkscape} #{source_filename} -C -w #{width} -h #{height} -e #{path}"
-
-		top = []
-		right = []
-		bottom = []
-		left = []
-
-		guides.each do |guide|
-			orientation = guide["orientation"]
-			x, y = guide["position"].split(",")
-			x, y = x.to_i, y.to_i
-
-			if orientation == "1,0" and y == base_height
-				top.push(x * factor)
-			end
-
-			if orientation == "0,1" and x == base_width
-				right.push((base_height - y) * factor)
-			end
-
-			if orientation == "1,0" and y == 0
-				bottom.push(x * factor)
-			end
-
-			if orientation == "0,1" and x == 0
-				left.push((base_height - y) * factor)
-			end
-		end
-
-		next if top.length != 2
-		next if right.length != 2
-		next if bottom.length != 2
-		next if left.length != 2
-
-		execute_cmd "#{imagemagick} -background none PNG32:#{path} -gravity center -extent #{width+2}x#{height+2} PNG32:#{path}"
-
-		draw_format = "-draw \"line %d,%d %d,%d\""
-		top_line = draw_format % [top.min + 1, 0, top.max, 0]
-		right_line = draw_format % [width + 1, right.min + 1, width + 1, right.max]
-		bottom_line = draw_format % [bottom.min + 1, height + 1, bottom.max, height + 1]
-		left_line = draw_format % [0, left.min + 1, 0, left.max]
-		draws = "#{top_line} #{right_line} #{bottom_line} #{left_line}"
-
-		execute_cmd "#{imagemagick} -background none PNG32:#{path} -fill black -stroke none #{draws} PNG32:#{path}"
-	end
+  svg_content = File.read(source_filename)
+  output_filename, base_size = settings
+
+  svg = XML::Document.string(svg_content)
+  base_width = svg.root['width'].to_i
+  base_height = svg.root['height'].to_i
+
+  guides = svg.find('.//sodipodi:guide', 'sodipodi:http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd')
+
+  resolutions.each do |resolution, factor|
+    if base_size.positive?
+      width = factor * base_size
+      height = factor * base_size
+    else
+      width = factor * base_width
+      height = factor * base_height
+    end
+
+    output_parts = output_filename.split('/')
+
+    path = if output_parts.count != 2
+             "../src/main/res/drawable-#{resolution}/#{output_filename}.png"
+           else
+             "../src/#{output_parts[0]}/res/drawable-#{resolution}/#{output_parts[1]}.png"
+           end
+    execute_cmd "#{inkscape} #{source_filename} -C -w #{width.to_i} -h #{height.to_i} --export-filename=#{path}"
+
+    top = []
+    right = []
+    bottom = []
+    left = []
+
+    guides.each do |guide|
+      orientation = guide['orientation']
+      x, y = guide['position'].split(',')
+      x = x.to_i
+      y = y.to_i
+
+      top.push(x * factor) if (orientation == '1,0') && (y == base_height)
+
+      right.push((base_height - y) * factor) if (orientation == '0,1') && (x == base_width)
+
+      bottom.push(x * factor) if (orientation == '1,0') && y.zero?
+
+      left.push((base_height - y) * factor) if (orientation == '0,1') && x.zero?
+    end
+
+    next if top.length != 2
+    next if right.length != 2
+    next if bottom.length != 2
+    next if left.length != 2
+
+    execute_cmd "#{imagemagick} -background none PNG32:#{path} -gravity center -extent #{width + 2}x#{height + 2} PNG32:#{path}"
+
+    draw_format = '-draw "line %d,%d %d,%d"'
+    top_line = format(draw_format, top.min + 1, 0, top.max, 0)
+    right_line = format(draw_format, width + 1, right.min + 1, width + 1, right.max)
+    bottom_line = format(draw_format, bottom.min + 1, height + 1, bottom.max, height + 1)
+    left_line = format(draw_format, 0, left.min + 1, 0, left.max)
+    draws = "#{top_line} #{right_line} #{bottom_line} #{left_line}"
+
+    execute_cmd "#{imagemagick} -background none PNG32:#{path} -fill black -stroke none #{draws} PNG32:#{path}"
+  end
 end

build.gradle 🔗

@@ -49,7 +49,7 @@ dependencies {
 
     implementation 'androidx.viewpager:viewpager:1.0.0'
 
-    playstoreImplementation('com.google.firebase:firebase-messaging:23.1.0') {
+    playstoreImplementation('com.google.firebase:firebase-messaging:23.1.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'
@@ -103,7 +103,6 @@ dependencies {
 }
 
 ext {
-    travisBuild = System.getenv("TRAVIS") == "true"
     preDexEnabled = System.getProperty("pre-dex", "true")
     abiCodes = ['armeabi-v7a': 1, 'x86': 2, 'x86_64': 3, 'arm64-v8a': 4]
 }
@@ -125,7 +124,6 @@ android {
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
     }
 
-
     configurations {
         implementation.exclude group: 'org.jetbrains' , module:'annotations'
     }
@@ -151,7 +149,7 @@ android {
 
             def appName = "Quicksy"
             resValue "string", "app_name", appName
-            buildConfigField "String", "APP_NAME", "\"$appName\"";
+            buildConfigField "String", "APP_NAME", "\"$appName\""
         }
 
         conversations {

fastlane/metadata/android/de-DE/changelogs/349.txt 🔗

@@ -0,0 +1,4 @@
+* Einführung einer Experteneinstellung zur Channel-Erkennung auf dem lokalen Server anstelle von search.jabber.network
+* Standardmäßig Zustellungshäkchen aktiviert und Einstellung entfernt
+* Standardmäßig 'Sendetaste zeigt Status an' aktiviert und die Einstellung entfernt
+* Einstellungen für Sicherung und Vordergrunddienst in den Hauptbereich verschoben

fastlane/metadata/android/de-DE/changelogs/353.txt 🔗

@@ -0,0 +1,4 @@
+* Benutzer können ihren eigenen Nicknamen festlegen
+* Wiederaufnahme des Downloads von OMEMO-verschlüsselten Dateien
+* Channels verwenden jetzt '#' als Symbol im Profilbild
+* Quicksy verwendet 'immer' als OMEMO-Verschlüsselungsstandard (versteckt das Schlosssymbol)

fastlane/metadata/android/de-DE/changelogs/383.txt 🔗

@@ -0,0 +1,3 @@
+* Anrufsymbol nach links verschoben, damit die anderen Symbole der Symbolleiste an einer einheitlichen Stelle bleiben
+* Anzeige der Gesprächsdauer bei Sprachanrufen
+* Unterbrechung der Verbindung bei A/V-Anrufen (zwei Personen rufen sich gleichzeitig an)

fastlane/metadata/android/de-DE/changelogs/388.txt 🔗

@@ -0,0 +1,3 @@
+* Reduzierung des Echos bei Anrufen auf einigen Geräten
+* Anmeldung korrigiert, wenn Passwörter Sonderzeichen enthalten
+* Wähl- und Besetztzeichen bei Videoanrufen auf dem Lautsprecher abspielen

fastlane/metadata/android/de-DE/changelogs/398.txt 🔗

@@ -0,0 +1,4 @@
+* Suche in einzelnen Unterhaltungen
+* Benutzer werden benachrichtigt, wenn die Nachrichtenzustellung fehlschlägt
+* Anzeigenamen (Nicks) von Quicksy-Benutzern über Neustarts hinweg speichern
+* Hinzufügen einer Schaltfläche zum Starten von Orbot (Tor) aus der Benachrichtigung heraus, falls erforderlich

fastlane/metadata/android/de-DE/changelogs/403.txt 🔗

@@ -0,0 +1,3 @@
+* Behebung von Verbindungsproblemen, wenn verschiedene Konten unterschiedliche SCRAM-Mechanismen verwenden
+* Unterstützung für SCRAM-SHA-512 hinzugefügt
+* P2P (Jingle) Dateiübertragung mit eigenem Kontakt zulassen

fastlane/metadata/android/de-DE/changelogs/42000.txt 🔗

@@ -0,0 +1,4 @@
+* Möglichkeit zur Auswahl des Klingeltons für eingehende Anrufe
+* Behebung der OpenPGP-Schlüsselerkennung für OpenKeychain 5.6+
+* Korrekte Verifizierung von Punycode-TLS-Zertifikaten
+* Verbesserte Stabilität des RTP-Sitzungsaufbaus (Anrufe)

fastlane/metadata/android/de-DE/changelogs/42037.txt 🔗

@@ -0,0 +1,9 @@
+* Abfrage der Bluetooth-Berechtigung bei A/V-Anrufen (nur bei Bluetooth-Headsets erforderlich)
+* Fehler beim Anrufen von Movim behoben
+* Anzeige eines falschen Profilbilds bei Gruppenchats behoben
+* Immer nach dem Opt-Out für Akku-Optimierungen fragen
+* Interaktion mit Google Maps Share Location Plugin behoben
+* Fußnote bezüglich der Servergebühr entfernt
+* Dateien an einem für Android 11 geeigneten Ort speichern
+* Anruf nach Netzwechsel erneut versuchen zu verbinden
+* JID des Anrufers und JID des Kontos im Bildschirm für eingehende Anrufe anzeigen

fastlane/metadata/android/de-DE/changelogs/42041.txt 🔗

@@ -0,0 +1,5 @@
+* Implementierung von Extensible SASL Profile, Bind 2.0 und Fast für schnellere Wiederverbindungen
+* Implementierung von Channel Binding
+* Möglichkeit von einem Audioanruf zu einem Videoanruf zu wechseln
+* Möglichkeit zum Löschen des eigenen Profilbildes hinzugefügt
+* Benachrichtigung für verpasste Anrufe hinzugefügt

fastlane/metadata/android/de-DE/full_description.txt 🔗

@@ -0,0 +1,39 @@
+Einfach zu bedienen, zuverlässig, batteriefreundlich. Mit integrierter Unterstützung für Bilder, Gruppenchats und E2E-Verschlüsselung.
+
+Designprinzipien:
+
+* Möglichst schön und benutzerfreundlich, ohne Abstriche bei der Sicherheit und Privatsphäre
+* Auf bestehende, gut etablierte Protokolle zurückgreifen
+* Kein Google-Konto oder speziell Google Cloud Messaging (GCM) erforderlich
+* So wenig Berechtigungen wie möglich erfordern
+
+Funktionen:
+
+* Ende-zu-Ende-Verschlüsselung entweder mit <a href="http://conversations.im/omemo/">OMEMO</a> oder <a href="http://openpgp.org/about/">OpenPGP</a>
+* Senden und Empfangen von Bildern
+* Verschlüsselte Audio- und Videoanrufe (DTLS-SRTP)
+* Intuitives UI, das den Android Design Richtlinien folgt
+* Bilder / Profilbilder für deine Kontakte
+* Synchronisation mit Desktop-Client
+* Konferenzen (mit Unterstützung für Lesezeichen)
+* Adressbucheinbindung
+* Mehrere Konten / einheitlicher Posteingang
+* Sehr geringe Auswirkungen auf die Akkulaufzeit
+
+Mit Conversations ist es sehr einfach, ein Konto auf dem kostenlosen conversations.im-Server zu erstellen. Dennoch funktioniert Conversations auch mit jedem anderen XMPP-Server. Zahlreiche XMPP-Server werden von Freiwilligen betrieben und sind kostenlos.
+
+XMPP-Funktionen:
+
+Conversations funktioniert mit jedem XMPP-Server. XMPP ist jedoch ein erweiterbares Protokoll. Diese Erweiterungen sind ebenfalls in sogenannten XEP's standardisiert. Conversations unterstützt einige davon, um die Benutzerfreundlichkeit zu verbessern. Es besteht die Möglichkeit, dass Ihr aktueller XMPP-Server diese Erweiterungen nicht unterstützt. Um Conversations optimal nutzen zu können, solltest du daher entweder zu einem XMPP-Server wechseln, der dies unterstützt, oder - noch besser - einen eigenen XMPP-Server für dich und deine Freunde betreiben.
+
+Diese XEPs sind es derzeit:
+
+* XEP-0065: SOCKS5 Bytestreams (oder mod_proxy65). Wird für die Übertragung von Dateien verwendet, wenn sich beide Parteien hinter einer Firewall (NAT) befinden.
+* XEP-0163: Personal Eventing Protocol für Profilbilder
+* XEP-0191: Mit dem Blockierungsbefehl kannst du Spammer auf eine schwarze Liste setzen oder Kontakte blockieren, ohne sie aus deiner Liste zu entfernen.
+* XEP-0198: Stream Management ermöglicht es XMPP, kleinere Netzwerkausfälle und Änderungen der zugrunde liegenden TCP-Verbindung zu überstehen.
+* XEP-0280: Message Carbons, das die von dir gesendeten Nachrichten automatisch mit deinem Desktop-Client synchronisiert und es dir somit ermöglicht, innerhalb einer Unterhaltung nahtlos von deinem mobilen Client zu deinem Desktop-Client und zurück zu wechseln.
+* XEP-0237: Roster Versioning hauptsächlich, um Bandbreite bei schlechten mobilen Verbindungen zu sparen
+* XEP-0313: Nachrichtenarchiv-Management synchronisiert den Nachrichtenverlauf mit dem Server. Aufholen von Nachrichten, die gesendet wurden, während Conversations offline war.
+* XEP-0352: Client State Indication lässt den Server wissen, ob Conversations im Hintergrund läuft oder nicht. Ermöglicht es dem Server, Bandbreite zu sparen, indem er unwichtige Pakete zurückhält.
+* XEP-0363: HTTP File Upload ermöglicht den Austausch von Dateien in Konferenzen und mit Offline-Kontakten. Erfordert eine zusätzliche Komponente auf deinem Server.

fastlane/metadata/android/it-IT/full_description.txt 🔗

@@ -0,0 +1,39 @@
+Facile da usare, affidabile, leggero sulla batteria. Con supporto integrato per immagini, chat di gruppo e crittografia e2e.
+
+Principi di design:
+
+* Essere il più bello e facile da usare possibile senza sacrificare la sicurezza o la privacy
+* Affidarsi a protocolli esistenti ben affermati
+* Non richiedere un account Google o nello specifico Google Cloud Messaging (GCM)
+* Richiedere il minor numero di autorizzazioni possibile
+
+Caratteristiche:
+
+* Crittografia end-to-end con <a href="http://conversations.im/omemo/">OMEMO</a> o <a href="http://openpgp.org/about/">OpenPGP</a>
+* Invio e ricezione di immagini
+* Chiamate audio e video crittografate (DTLS-SRTP)
+* Interfaccia utente intuitiva che segue le linee guida del design di Android
+* Immagini / Avatar per i tuoi contatti
+* Sincronizzazione con client desktop
+* Conferenze (con supporto ai segnalibri)
+* Integrazione della rubrica
+* Profili multipli / messaggi unificati
+* Consumo molto basso della batteria
+
+Conversations rende veramente facile creare un profilo sul server gratuito conversations.im. Tuttavia Conversations funzionerà anche con qualsiasi altro server XMPP. Molti server XMPP vengono gestiti da volontari e sono gratuiti.
+
+Caratteristiche di XMPP:
+
+Conversations funziona con tutti i server XMPP. Tuttavia XMPP è un protocollo estensibile. Anche queste estensioni sono standardizzate, con il nome XEP. Conversations supporta alcune di esse per rendere migliore l'esperienza utente. È possibile che il server XMPP che stai usando non supporti queste estensioni. Perciò, per ottenere il meglio da Conversations dovresti considerare di passare ad un server XMPP che le supporta o, ancora meglio, installarne uno tuo per te e i tuoi amici.
+
+Queste XEP sono, ad oggi:
+
+* XEP-0065: SOCKS5 Bytestreams (o mod_proxy65). Usata per trasferire file se entrambe le parti sono dietro un firewall (NAT).
+* XEP-0163: Personal Eventing Protocol. Per gli avatar.
+* XEP-0191: Blocking command. Ti consente di bloccare lo spam o i contatti senza rimuoverli dal tuo elenco.
+* XEP-0198: Stream Management. Consente a XMPP di resistere a brevi disconnessioni e cambi della connessione TCP sottostante.
+* XEP-0280: Message Carbons. Sincronizza automaticamente i messaggi che invii al client desktop, quindi ti consente di passare senza problemi dal mobile al desktop e viceversa con un'unica conversazione.
+* XEP-0237: Roster Versioning. Principalmente per risparmiare banda di rete in connessioni mobili deboli
+* XEP-0313: Message Archive Management. Sincronizza la cronologia dei messaggi con il server. Recupera i messaggi che sono stati inviati mentre Conversations era offline.
+* XEP-0352: Client State Indication. Fa sapere al server se Conversations è in secondo piano o no. Permette al server di risparmiare banda di rete trattenendo i pacchetti non importanti.
+* XEP-0363: HTTP File Upload. Ti consente di condividere file nelle conferenze e con i contatti offline. Richiede un componente aggiuntivo sul tuo server.

src/conversations/res/values-es/strings.xml 🔗

@@ -4,7 +4,8 @@
     <string name="use_conversations.im">Usa conversations.im</string>
     <string name="create_new_account">Crear nueva cuenta</string>
     <string name="do_you_have_an_account">¿Ya tienes una cuenta XMPP? Este puede ser el caso si ya estás usando un cliente XMPP diferente o has usado Conversations anteriormente. Si no es así, puedes crear una nueva cuenta XMPP ahora mismo.\nConsejo: Algunos proveedores de email también ofrecen una cuenta XMPP.</string>
-    <string name="server_select_text">XMPP es una red de mensajería instantánea independiente del proveedor. Puedes usar este cliente con cualquier servidor XMPP que elijas.\nSin embargo, para tu conveniencia, hacemos de forma sencilla la creación de una cuenta en conversations.im; un proveedor especializado para el uso con Conversations </string>
+    <string name="server_select_text">XMPP es una red de mensajería instantánea independiente del proveedor. Puedes usar este cliente con cualquier servidor XMPP que elijas.
+\nSin embargo, para tu conveniencia, hacemos de forma sencilla la creación de una cuenta en conversations.im; un proveedor especializado para el uso con Conversations.</string>
     <string name="magic_create_text_on_x">Has sido invitado a %1$s. Te guiaremos durante el proceso de creación de la cuenta.\nCuando selecciones %1$s como proveedor podrás comunicarte con usuarios de otros servidores proporcionándoles tu dirección XMPP completa. </string>
     <string name="magic_create_text_fixed">Has sido invitado a %1$s. Un nombre de usuario ya ha sido escogido para ti. Te guiaremos durante el proceso de creación de la cuenta.\nPodrás comunicarte con otros usuarios de otros servidores proporcionándoles tu dirección XMPP completa. </string>
     <string name="your_server_invitation">Tu invitación al servidor</string>
@@ -12,5 +13,5 @@
     <string name="tap_share_button_send_invite">Pulsa el botón de compartir para enviar a tu contacto una invitación a %1$s.</string>
     <string name="if_contact_is_nearby_use_qr">Si tu contacto está cerca, también puede escanear el código mostrado debajo para aceptar tu invitación.</string>
     <string name="easy_invite_share_text">Únete a %1$s y chatea conmigo: %2$s</string>
-    <string name="share_invite_with">Compartir invitación con...</string>
+    <string name="share_invite_with">Comparte la invitación con…</string>
 </resources>

src/conversations/res/values-gl/strings.xml 🔗

@@ -12,5 +12,5 @@
     <string name="tap_share_button_send_invite">Toca no botón compartir para convidar ao teu contacto a %1$s.</string>
     <string name="if_contact_is_nearby_use_qr">Se o contacto está preto de ti, pode escanear o código inferior para aceptar o teu convite.</string>
     <string name="easy_invite_share_text">Únete a %1$s e conversa conmigo: %2$s</string>
-    <string name="share_invite_with">Enviar convite a...</string>
+    <string name="share_invite_with">Enviar convite a…</string>
 </resources>

src/conversations/res/values-it/strings.xml 🔗

@@ -3,10 +3,10 @@
     <string name="pick_a_server">Scegli il tuo fornitore XMPP</string>
     <string name="use_conversations.im">Usa conversations.im</string>
     <string name="create_new_account">Crea un nuovo profilo</string>
-    <string name="do_you_have_an_account">Possiedi già un profilo XMPP? Questo succede se stai già usando un diverso client XMPP o hai già usato prima Conversations. In caso negativo puoi creare un profilo XMPP adesso.
-Suggerimento: alcuni provider di email forniscono anche un account XMPP.</string>
+    <string name="do_you_have_an_account">Hai già un profilo XMPP\? Può accadere se stai già usando un client XMPP diverso o hai già usato prima Conversations. In caso negativo, puoi creare un profilo XMPP adesso.
+\nNota: alcuni fornitori di email offrono anche account XMPP.</string>
     <string name="server_select_text">XMPP è una rete di messaggistica istantanea indipendente dal fornitore. Puoi usare questo client con qualsiasi server XMPP.
-In ogni caso per facilitare puoi creare facilmente un account su conversations.im, un fornitore pensato apposta per essere usato con Conversations.</string>
+\nTuttavia, per comodità, puoi creare facilmente un account su conversations.im; un fornitore pensato apposta per essere usato con Conversations.</string>
     <string name="magic_create_text_on_x">Hai ricevuto un invito per %1$s. Ti guideremo nel procedimento per creare un profilo.\nQuando scegli %1$s come fornitore sarai in grado di comunicare con utenti di altri fornitori dando loro l\'indirizzo XMPP completo.</string>
     <string name="magic_create_text_fixed">Hai ricevuto un invito per %1$s. È già stato scelto un nome utente per te. Ti guideremo nel procedimento per creare un profilo.\nSarai in grado di comunicare con utenti di altri fornitori dando loro l\'indirizzo XMPP completo.</string>
     <string name="your_server_invitation">Il tuo invito al server</string>
@@ -14,5 +14,5 @@ In ogni caso per facilitare puoi creare facilmente un account su conversations.i
     <string name="tap_share_button_send_invite">Tocca il pulsante condividi per inviare al contatto un invito per %1$s.</string>
     <string name="if_contact_is_nearby_use_qr">Se il contatto è vicino, può anche scansionare il codice sottostante per accettare il tuo invito.</string>
     <string name="easy_invite_share_text">Unisciti a %1$s e chatta con me: %2$s</string>
-    <string name="share_invite_with">Condividi invito con...</string>
+    <string name="share_invite_with">Condividi invito con…</string>
 </resources>

src/conversations/res/values-zh-rCN/strings.xml 🔗

@@ -12,5 +12,5 @@
     <string name="tap_share_button_send_invite">点击分享按钮向您的联系人发送加入 %1$s 的邀请。</string>
     <string name="if_contact_is_nearby_use_qr">如果你的联系人在附近,他们也可以扫描下面的代码来接受你的邀请。</string>
     <string name="easy_invite_share_text">加入 %1$s 和我聊天:%2$s</string>
-    <string name="share_invite_with">分享邀请</string>
+    <string name="share_invite_with">分享邀请…</string>
 </resources>

src/main/java/eu/siacs/conversations/crypto/sasl/ScramMechanism.java 🔗

@@ -1,7 +1,6 @@
 package eu.siacs.conversations.crypto.sasl;
 
 import android.util.Base64;
-import android.util.Log;
 
 import com.google.common.base.CaseFormat;
 import com.google.common.base.Objects;
@@ -13,14 +12,32 @@ import java.nio.charset.Charset;
 import java.security.InvalidKeyException;
 import java.util.concurrent.ExecutionException;
 
+import javax.crypto.SecretKey;
 import javax.net.ssl.SSLSocket;
 
-import eu.siacs.conversations.Config;
 import eu.siacs.conversations.entities.Account;
 import eu.siacs.conversations.utils.CryptoHelper;
 
 abstract class ScramMechanism extends SaslMechanism {
 
+    public static final SecretKey EMPTY_KEY =
+            new SecretKey() {
+                @Override
+                public String getAlgorithm() {
+                    return "HMAC";
+                }
+
+                @Override
+                public String getFormat() {
+                    return "RAW";
+                }
+
+                @Override
+                public byte[] getEncoded() {
+                    return new byte[0];
+                }
+            };
+
     private static final byte[] CLIENT_KEY_BYTES = "Client Key".getBytes();
     private static final byte[] SERVER_KEY_BYTES = "Server Key".getBytes();
     private static final Cache<CacheKey, KeyPair> CACHE =

src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha1.java 🔗

@@ -15,7 +15,9 @@ public class ScramSha1 extends ScramMechanism {
 
     @Override
     protected HashFunction getHMac(final byte[] key) {
-        return Hashing.hmacSha1(key);
+        return (key == null || key.length == 0)
+                ? Hashing.hmacSha1(EMPTY_KEY)
+                : Hashing.hmacSha1(key);
     }
 
     @Override

src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha256.java 🔗

@@ -19,7 +19,9 @@ public class ScramSha256 extends ScramMechanism {
 
     @Override
     protected HashFunction getHMac(final byte[] key) {
-        return Hashing.hmacSha256(key);
+        return (key == null || key.length == 0)
+                ? Hashing.hmacSha256(EMPTY_KEY)
+                : Hashing.hmacSha256(key);
     }
 
     @Override

src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha512.java 🔗

@@ -19,7 +19,9 @@ public class ScramSha512 extends ScramMechanism {
 
     @Override
     protected HashFunction getHMac(final byte[] key) {
-        return Hashing.hmacSha512(key);
+        return (key == null || key.length == 0)
+                ? Hashing.hmacSha512(EMPTY_KEY)
+                : Hashing.hmacSha512(key);
     }
 
     @Override

src/main/java/eu/siacs/conversations/services/ContactChooserTargetService.java 🔗

@@ -1,5 +1,6 @@
 package eu.siacs.conversations.services;
 
+import android.annotation.SuppressLint;
 import android.annotation.TargetApi;
 import android.content.ComponentName;
 import android.content.Context;
@@ -12,19 +13,23 @@ import android.os.Bundle;
 import android.os.IBinder;
 import android.service.chooser.ChooserTarget;
 import android.service.chooser.ChooserTargetService;
+import android.util.Log;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
+import eu.siacs.conversations.Config;
 import eu.siacs.conversations.entities.Conversation;
 import eu.siacs.conversations.ui.ConversationsActivity;
 import eu.siacs.conversations.utils.Compatibility;
 
+@SuppressLint("Deprecated")
 @TargetApi(Build.VERSION_CODES.M)
 public class ContactChooserTargetService extends ChooserTargetService implements ServiceConnection {
 
     private final Object lock = new Object();
-    private final int MAX_TARGETS = 5;
+    private static final int MAX_TARGETS = 5;
     private XmppConnectionService mXmppConnectionService;
 
     private static boolean textOnly(IntentFilter filter) {
@@ -37,10 +42,10 @@ public class ContactChooserTargetService extends ChooserTargetService implements
     }
 
     @Override
-    public List<ChooserTarget> onGetChooserTargets(ComponentName targetActivityName, IntentFilter matchedFilter) {
-        final ArrayList<ChooserTarget> chooserTargets = new ArrayList<>();
+    public List<ChooserTarget> onGetChooserTargets(
+            final ComponentName targetActivityName, final IntentFilter matchedFilter) {
         if (!EventReceiver.hasEnabledAccounts(this)) {
-            return chooserTargets;
+            return Collections.emptyList();
         }
         final Intent intent = new Intent(this, XmppConnectionService.class);
         intent.setAction("contact_chooser");
@@ -48,37 +53,48 @@ public class ContactChooserTargetService extends ChooserTargetService implements
         bindService(intent, this, Context.BIND_AUTO_CREATE);
         try {
             waitForService();
-            final ArrayList<Conversation> conversations = new ArrayList<>();
             if (!mXmppConnectionService.areMessagesInitialized()) {
-                return chooserTargets;
+                return Collections.emptyList();
             }
-            
-            mXmppConnectionService.populateWithOrderedConversations(conversations, textOnly(matchedFilter));
-            final ComponentName componentName = new ComponentName(this, ConversationsActivity.class);
+            final ArrayList<Conversation> conversations = new ArrayList<>();
+            mXmppConnectionService.populateWithOrderedConversations(
+                    conversations, textOnly(matchedFilter));
+            final ComponentName componentName =
+                    new ComponentName(this, ConversationsActivity.class);
             final int pixel = AvatarService.getSystemUiAvatarSize(this);
-            for (Conversation conversation : conversations) {
+            final ArrayList<ChooserTarget> chooserTargets = new ArrayList<>();
+            for (final Conversation conversation : conversations) {
                 if (conversation.sentMessagesCount() == 0) {
                     continue;
                 }
                 final String name = conversation.getName().toString();
-                final Icon icon = Icon.createWithBitmap(mXmppConnectionService.getAvatarService().get(conversation, pixel));
+                final Icon icon =
+                        Icon.createWithBitmap(
+                                mXmppConnectionService.getAvatarService().get(conversation, pixel));
                 final float score = 1 - (1.0f / MAX_TARGETS) * chooserTargets.size();
                 final Bundle extras = new Bundle();
                 extras.putString(ConversationsActivity.EXTRA_CONVERSATION, conversation.getUuid());
                 chooserTargets.add(new ChooserTarget(name, icon, score, componentName, extras));
                 if (chooserTargets.size() >= MAX_TARGETS) {
-                    break;
+                    return chooserTargets;
                 }
             }
-        } catch (InterruptedException e) {
+            return chooserTargets;
+        } catch (final InterruptedException e) {
+            Log.d(
+                    Config.LOGTAG,
+                    "Thread got interrupted before binding to XmppConnectionService",
+                    e);
+        } finally {
+            unbindService(this);
         }
-        unbindService(this);
-        return chooserTargets;
+        return Collections.emptyList();
     }
 
     @Override
-    public void onServiceConnected(ComponentName name, IBinder service) {
-        XmppConnectionService.XmppConnectionBinder binder = (XmppConnectionService.XmppConnectionBinder) service;
+    public void onServiceConnected(final ComponentName name, final IBinder service) {
+        XmppConnectionService.XmppConnectionBinder binder =
+                (XmppConnectionService.XmppConnectionBinder) service;
         mXmppConnectionService = binder.getService();
         synchronized (this.lock) {
             lock.notifyAll();

src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java 🔗

@@ -1443,8 +1443,8 @@ public class RtpSessionActivity extends XmppActivity
 
     @Override
     public void onAudioDeviceChanged(
-            AppRTCAudioManager.AudioDevice selectedAudioDevice,
-            Set<AppRTCAudioManager.AudioDevice> availableAudioDevices) {
+            final AppRTCAudioManager.AudioDevice selectedAudioDevice,
+            final Set<AppRTCAudioManager.AudioDevice> availableAudioDevices) {
         Log.d(
                 Config.LOGTAG,
                 "onAudioDeviceChanged in activity: selected:"
@@ -1452,24 +1452,26 @@ public class RtpSessionActivity extends XmppActivity
                         + ", available:"
                         + availableAudioDevices);
         try {
-            if (getMedia().contains(Media.VIDEO)) {
-                Log.d(Config.LOGTAG, "nothing to do; in video mode");
-                return;
-            }
             final RtpEndUserState endUserState = requireRtpConnection().getEndUserState();
-            if (endUserState == RtpEndUserState.CONNECTED) {
-                final AppRTCAudioManager audioManager = requireRtpConnection().getAudioManager();
-                updateInCallButtonConfigurationSpeaker(
-                        audioManager.getSelectedAudioDevice(),
-                        audioManager.getAudioDevices().size());
-            } else if (END_CARD.contains(endUserState)) {
+            final Set<Media> media = getMedia();
+            if (END_CARD.contains(endUserState)) {
                 Log.d(
                         Config.LOGTAG,
                         "onAudioDeviceChanged() nothing to do because end card has been reached");
             } else {
+                if (Media.audioOnly(media) && endUserState == RtpEndUserState.CONNECTED) {
+                    final AppRTCAudioManager audioManager =
+                            requireRtpConnection().getAudioManager();
+                    updateInCallButtonConfigurationSpeaker(
+                            audioManager.getSelectedAudioDevice(),
+                            audioManager.getAudioDevices().size());
+                }
+                Log.d(
+                        Config.LOGTAG,
+                        "put proximity wake lock into proper state after device update");
                 putProximityWakeLockInProperState(selectedAudioDevice);
             }
-        } catch (IllegalStateException e) {
+        } catch (final IllegalStateException e) {
             Log.d(Config.LOGTAG, "RTP connection was not available when audio device changed");
         }
     }

src/main/java/eu/siacs/conversations/xml/Element.java 🔗

@@ -1,5 +1,8 @@
 package eu.siacs.conversations.xml;
 
+import com.google.common.base.Optional;
+import com.google.common.primitives.Ints;
+
 import org.jetbrains.annotations.NotNull;
 
 import java.util.ArrayList;
@@ -190,6 +193,14 @@ public class Element implements Node {
 		}
 	}
 
+	public Optional<Integer> getOptionalIntAttribute(final String name) {
+		final String value = getAttribute(name);
+		if (value == null) {
+			return Optional.absent();
+		}
+		return Optional.fromNullable(Ints.tryParse(value));
+	}
+
 	public Jid getAttributeAsJid(String name) {
 		final String jid = this.getAttribute(name);
 		if (jid != null && !jid.isEmpty()) {

src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java 🔗

@@ -16,6 +16,7 @@ import android.util.SparseArray;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import com.google.common.base.Optional;
 import com.google.common.base.Strings;
 
 import org.xmlpull.v1.XmlPullParserException;
@@ -162,6 +163,7 @@ public class XmppConnection implements Runnable {
     private String streamId = null;
     private int stanzasReceived = 0;
     private int stanzasSent = 0;
+    private int stanzasSentBeforeAuthentication;
     private long lastPacketReceived = 0;
     private long lastPingSent = 0;
     private long lastConnect = 0;
@@ -631,20 +633,21 @@ public class XmppConnection implements Runnable {
                 }
                 final Element ack = tagReader.readElement(nextTag);
                 lastPacketReceived = SystemClock.elapsedRealtime();
-                try {
-                    final boolean acknowledgedMessages;
-                    synchronized (this.mStanzaQueue) {
-                        final int serverSequence = Integer.parseInt(ack.getAttribute("h"));
-                        acknowledgedMessages = acknowledgeStanzaUpTo(serverSequence);
-                    }
-                    if (acknowledgedMessages) {
-                        mXmppConnectionService.updateConversationUi();
+                final boolean acknowledgedMessages;
+                synchronized (this.mStanzaQueue) {
+                    final Optional<Integer> serverSequence = ack.getOptionalIntAttribute("h");
+                    if (serverSequence.isPresent()) {
+                        acknowledgedMessages = acknowledgeStanzaUpTo(serverSequence.get());
+                    } else {
+                        acknowledgedMessages = false;
+                        Log.d(
+                                Config.LOGTAG,
+                                account.getJid().asBareJid()
+                                        + ": server send ack without sequence number");
                     }
-                } catch (NumberFormatException | NullPointerException e) {
-                    Log.d(
-                            Config.LOGTAG,
-                            account.getJid().asBareJid()
-                                    + ": server send ack without sequence number");
+                }
+                if (acknowledgedMessages) {
+                    mXmppConnectionService.updateConversationUi();
                 }
             } else if (nextTag.isStart("failed")) {
                 final Element failed = tagReader.readElement(nextTag);
@@ -758,10 +761,9 @@ public class XmppConnection implements Runnable {
                         account.getJid().asBareJid()
                                 + ": jid changed during SASL 2.0. updating database");
             }
-            final boolean nopStreamFeatures;
             final Element bound = success.findChild("bound", Namespace.BIND2);
-            final Element resumed = success.findChild("resumed", "urn:xmpp:sm:3");
-            final Element failed = success.findChild("failed", "urn:xmpp:sm:3");
+            final Element resumed = success.findChild("resumed", Namespace.STREAM_MANAGEMENT);
+            final Element failed = success.findChild("failed", Namespace.STREAM_MANAGEMENT);
             final Element tokenWrapper = success.findChild("token", Namespace.FAST);
             final String token = tokenWrapper == null ? null : tokenWrapper.getAttribute("token");
             if (bound != null && resumed != null) {
@@ -785,6 +787,7 @@ public class XmppConnection implements Runnable {
                 final Element carbonsEnabled = bound.findChild("enabled", Namespace.CARBONS);
                 final boolean waitForDisco;
                 if (streamManagementEnabled != null) {
+                    resetOutboundStanzaQueue();
                     processEnabled(streamManagementEnabled);
                     waitForDisco = true;
                 } else {
@@ -811,8 +814,16 @@ 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);
+                this.account.setFastToken(tokenMechanism, token);
+                Log.d(
+                        Config.LOGTAG,
+                        account.getJid().asBareJid() + ": storing hashed token " + tokenMechanism);
+            } else if (this.hashTokenRequest != null) {
+                Log.w(
+                        Config.LOGTAG,
+                        account.getJid().asBareJid()
+                                + ": no response to our hashed token request "
+                                + this.hashTokenRequest);
             }
             // a successful resume will not send stream features
             if (processNopStreamFeatures) {
@@ -836,6 +847,37 @@ public class XmppConnection implements Runnable {
         }
     }
 
+    private void resetOutboundStanzaQueue() {
+        synchronized (this.mStanzaQueue) {
+            final List<AbstractAcknowledgeableStanza> intermediateStanzas = new ArrayList<>();
+            if (Config.EXTENDED_SM_LOGGING) {
+                Log.d(
+                        Config.LOGTAG,
+                        account.getJid().asBareJid()
+                                + ": stanzas sent before auth: "
+                                + this.stanzasSentBeforeAuthentication);
+            }
+            for (int i = this.stanzasSentBeforeAuthentication + 1; i <= this.stanzasSent; ++i) {
+                final AbstractAcknowledgeableStanza stanza = this.mStanzaQueue.get(i);
+                if (stanza != null) {
+                    intermediateStanzas.add(stanza);
+                }
+            }
+            this.mStanzaQueue.clear();
+            for (int i = 0; i < intermediateStanzas.size(); ++i) {
+                this.mStanzaQueue.put(i, intermediateStanzas.get(i));
+            }
+            this.stanzasSent = intermediateStanzas.size();
+            if (Config.EXTENDED_SM_LOGGING) {
+                Log.d(
+                        Config.LOGTAG,
+                        account.getJid().asBareJid()
+                                + ": resetting outbound stanza queue to "
+                                + this.stanzasSent);
+            }
+        }
+    }
+
     private void processNopStreamFeatures() throws IOException {
         final Tag tag = tagReader.readTag();
         if (tag != null && tag.isStart("features", Namespace.STREAMS)) {
@@ -935,15 +977,11 @@ public class XmppConnection implements Runnable {
         this.isBound = true;
         this.tagWriter.writeStanzaAsync(new RequestPacket());
         lastPacketReceived = SystemClock.elapsedRealtime();
-        final String h = resumed.getAttribute("h");
-        if (h == null) {
-            resetStreamId();
-            throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER);
-        }
+        final Optional<Integer> h = resumed.getOptionalIntAttribute("h");
         final int serverCount;
-        try {
-            serverCount = Integer.parseInt(h);
-        } catch (final NumberFormatException e) {
+        if (h.isPresent()) {
+            serverCount = h.get();
+        } else {
             resetStreamId();
             throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER);
         }
@@ -992,28 +1030,22 @@ public class XmppConnection implements Runnable {
     }
 
     private void processFailed(final Element failed, final boolean sendBindRequest) {
-        final int serverCount;
-        try {
-            serverCount = Integer.parseInt(failed.getAttribute("h"));
-        } catch (final NumberFormatException | NullPointerException e) {
-            Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": resumption failed");
-            resetStreamId();
-            if (sendBindRequest) {
-                sendBindRequest();
+        final Optional<Integer> serverCount = failed.getOptionalIntAttribute("h");
+        if (serverCount.isPresent()) {
+            Log.d(
+                    Config.LOGTAG,
+                    account.getJid().asBareJid()
+                            + ": resumption failed but server acknowledged stanza #"
+                            + serverCount.get());
+            final boolean acknowledgedMessages;
+            synchronized (this.mStanzaQueue) {
+                acknowledgedMessages = acknowledgeStanzaUpTo(serverCount.get());
             }
-            return;
-        }
-        Log.d(
-                Config.LOGTAG,
-                account.getJid().asBareJid()
-                        + ": resumption failed but server acknowledged stanza #"
-                        + serverCount);
-        final boolean acknowledgedMessages;
-        synchronized (this.mStanzaQueue) {
-            acknowledgedMessages = acknowledgeStanzaUpTo(serverCount);
-        }
-        if (acknowledgedMessages) {
-            mXmppConnectionService.updateConversationUi();
+            if (acknowledgedMessages) {
+                mXmppConnectionService.updateConversationUi();
+            }
+        } else {
+            Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": resumption failed");
         }
         resetStreamId();
         if (sendBindRequest) {
@@ -1021,7 +1053,7 @@ public class XmppConnection implements Runnable {
         }
     }
 
-    private boolean acknowledgeStanzaUpTo(int serverCount) {
+    private boolean acknowledgeStanzaUpTo(final int serverCount) {
         if (serverCount > stanzasSent) {
             Log.e(
                     Config.LOGTAG,
@@ -1403,7 +1435,7 @@ public class XmppConnection implements Runnable {
             quickStartAvailable = false;
         } else if (version == SaslMechanism.Version.SASL_2) {
             final Element inline = authElement.findChild("inline", Namespace.SASL_2);
-            final boolean sm = inline != null && inline.hasChild("sm", "urn:xmpp:sm:3");
+            final boolean sm = inline != null && inline.hasChild("sm", Namespace.STREAM_MANAGEMENT);
             final HashedToken.Mechanism hashTokenRequest;
             if (usingFast) {
                 hashTokenRequest = null;
@@ -1447,7 +1479,10 @@ public class XmppConnection implements Runnable {
                         + "/"
                         + this.saslMechanism.getMechanism());
         authenticate.setAttribute("mechanism", this.saslMechanism.getMechanism());
-        tagWriter.writeElement(authenticate);
+        synchronized (this.mStanzaQueue) {
+            this.stanzasSentBeforeAuthentication = this.stanzasSent;
+            tagWriter.writeElement(authenticate);
+        }
     }
 
     private static boolean isFastTokenAvailable(final Element authentication) {
@@ -2174,7 +2209,10 @@ public class XmppConnection implements Runnable {
                     generateAuthenticationRequest(quickStartMechanism.getClientFirstMessage(sslSocketOrNull(this.socket)), usingFast);
             authenticate.setAttribute("mechanism", quickStartMechanism.getMechanism());
             sendStartStream(true, false);
-            tagWriter.writeElement(authenticate);
+            synchronized (this.mStanzaQueue) {
+                this.stanzasSentBeforeAuthentication = this.stanzasSent;
+                tagWriter.writeElement(authenticate);
+            }
             Log.d(
                     Config.LOGTAG,
                     account.getJid().toString()
@@ -2270,6 +2308,9 @@ public class XmppConnection implements Runnable {
                 }
 
                 ++stanzasSent;
+                if (Config.EXTENDED_SM_LOGGING) {
+                    Log.d(Config.LOGTAG, account.getJid().asBareJid()+": counting outbound "+packet.getName()+" as #" + stanzasSent);
+                }
                 this.mStanzaQueue.append(stanzasSent, stanza);
                 if (stanza instanceof MessagePacket && stanza.getId() != null && inSmacksSession) {
                     if (Config.EXTENDED_SM_LOGGING) {
@@ -2666,7 +2707,7 @@ public class XmppConnection implements Runnable {
         public boolean sm() {
             return streamId != null
                     || (connection.streamFeatures != null
-                            && connection.streamFeatures.hasChild("sm"));
+                            && connection.streamFeatures.hasChild("sm", Namespace.STREAM_MANAGEMENT));
         }
 
         public boolean csi() {

src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java 🔗

@@ -2643,6 +2643,12 @@ 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.
                                         final PeerConnection.IceServer.Builder iceServerBuilder =
                                                 PeerConnection.IceServer.builder(
                                                         String.format(

src/main/java/eu/siacs/conversations/xmpp/jingle/VideoSourceWrapper.java 🔗

@@ -87,7 +87,15 @@ class VideoSourceWrapper {
     public void dispose() {
         this.cameraVideoCapturer.dispose();
         if (this.videoSource != null) {
-            this.videoSource.dispose();
+            dispose(this.videoSource);
+        }
+    }
+
+    private static void dispose(final VideoSource videoSource) {
+        try {
+            videoSource.dispose();
+        } catch (final IllegalStateException e) {
+            Log.e(Config.LOGTAG, "unable to dispose video source", e);
         }
     }
 

src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java 🔗

@@ -456,9 +456,14 @@ public class WebRTCWrapper {
 
     public void setIsReadyToReceiveIceCandidates(final boolean ready) {
         readyToReceivedIceCandidates.set(ready);
+        final int was = iceCandidates.size();
         while (ready && iceCandidates.peek() != null) {
             eventCallback.onIceCandidate(iceCandidates.poll());
         }
+        final int is = iceCandidates.size();
+        Log.d(
+                EXTENDED_LOGGING_TAG,
+                "setIsReadyToReceiveCandidates(" + ready + ") was=" + was + " is=" + is);
     }
 
     synchronized void close() {
@@ -478,6 +483,7 @@ public class WebRTCWrapper {
         this.localVideoTrack = null;
         this.remoteVideoTrack = null;
         if (videoSourceWrapper != null) {
+            this.videoSourceWrapper = null;
             try {
                 videoSourceWrapper.stopCapture();
             } catch (final InterruptedException e) {
@@ -694,7 +700,11 @@ public class WebRTCWrapper {
     }
 
     public PeerConnection.SignalingState getSignalingState() {
-        return requirePeerConnection().signalingState();
+        try {
+            return requirePeerConnection().signalingState();
+        } catch (final IllegalStateException e) {
+            return PeerConnection.SignalingState.CLOSED;
+        }
     }
 
     EglBase.Context getEglBaseContext() {

src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java 🔗

@@ -64,7 +64,9 @@ public class Content extends Element {
             return null;
         }
         final String namespace = description.getNamespace();
-        if (Namespace.JINGLE_APPS_RTP.equals(namespace)) {
+        if (FileTransferDescription.NAMESPACES.contains(namespace)) {
+            return FileTransferDescription.upgrade(description);
+        } else if (Namespace.JINGLE_APPS_RTP.equals(namespace)) {
             return RtpDescription.upgrade(description);
         } else {
             return GenericDescription.upgrade(description);
@@ -84,7 +86,11 @@ public class Content extends Element {
     public GenericTransportInfo getTransport() {
         final Element transport = this.findChild("transport");
         final String namespace = transport == null ? null : transport.getNamespace();
-        if (Namespace.JINGLE_TRANSPORT_ICE_UDP.equals(namespace)) {
+        if (Namespace.JINGLE_TRANSPORTS_IBB.equals(namespace)) {
+            return IbbTransportInfo.upgrade(transport);
+        } else if (Namespace.JINGLE_TRANSPORTS_S5B.equals(namespace)) {
+            return S5BTransportInfo.upgrade(transport);
+        } else if (Namespace.JINGLE_TRANSPORT_ICE_UDP.equals(namespace)) {
             return IceUdpTransportInfo.upgrade(transport);
         } else if (transport != null) {
             return GenericTransportInfo.upgrade(transport);
@@ -93,6 +99,7 @@ public class Content extends Element {
         }
     }
 
+
     public void setTransport(GenericTransportInfo transportInfo) {
         this.addChild(transportInfo);
     }

src/main/res/values-da-rDK/strings.xml 🔗

@@ -170,6 +170,7 @@
     <string name="account_status_tls_error_domain">Domæne kan ikke verificeres</string>
     <string name="account_status_policy_violation">Brud på retningslinjer</string>
     <string name="account_status_incompatible_server">Inkompatibel server</string>
+    <string name="account_status_incompatible_client">Inkompatibel klient</string>
     <string name="account_status_stream_error">Strømfejl</string>
     <string name="account_status_stream_opening_error">Fejl ved streamåbning</string>
     <string name="encryption_choice_unencrypted">TLS</string>
@@ -765,6 +766,7 @@
     <string name="messages_channel_name">Beskeder</string>
     <string name="incoming_calls_channel_name">Indkommende opkald</string>
     <string name="ongoing_calls_channel_name">Udgående opkald</string>
+    <string name="missed_calls_channel_name">Mistet opkald</string>
     <string name="silent_messages_channel_name">Lydløse beskeder</string>
     <string name="silent_messages_channel_description">Denne notifikationsgruppe bruges til at vise notifikationer, der ikke bør udløse nogen lyd. For eksempel når du er aktiv på en anden enhed (Fredningsperiode).</string>
     <string name="delivery_failed_channel_name">Mislykkede leverancer</string>
@@ -905,6 +907,8 @@
     <string name="make_call">Lav opkald</string>
     <string name="rtp_state_incoming_call">Indkommende opkald</string>
     <string name="rtp_state_incoming_video_call">Indkommende videoopkald</string>
+    <string name="rtp_state_content_add_video">Skift til videoopkald</string>
+    <string name="rtp_state_content_add">Tilføje yderligere spor?</string>
     <string name="rtp_state_connecting">Forbinder</string>
     <string name="rtp_state_connected">Forbundet</string>
     <string name="rtp_state_reconnecting">Forbinder igen</string>
@@ -932,6 +936,18 @@
     <string name="outgoing_call">Udgående opkald</string>
     <string name="outgoing_call_duration">Udgående opkald · %s</string>
     <string name="missed_call">Mistet opkald</string>
+    <plurals name="n_missed_calls_from_x">
+        <item quantity="one">%1$d mistet opkald fra %2$s</item>
+        <item quantity="other">%1$d mistet opkald fra %2$s</item>
+    </plurals>
+    <plurals name="n_missed_calls">
+        <item quantity="one">%d mistet opkald</item>
+        <item quantity="other">%d mistet opkald</item>
+    </plurals>
+    <plurals name="n_missed_calls_from_m_contacts">
+        <item quantity="one">%1$d mistet opkald fra %2$d kontakt</item>
+        <item quantity="other">%1$d mistet opkald fra %2$d kontakter</item>
+    </plurals>
     <string name="audio_call">Lydopkald</string>
     <string name="video_call">Videoopkald</string>
     <string name="help">Hjælp</string>
@@ -978,4 +994,8 @@
     <string name="no_xmpp_adddress_found">Ingen XMPP-adresse fundet</string>
     <string name="account_status_temporary_auth_failure">Midlertidig godkendelsesfejl</string>
     <string name="delete_avatar">Slet avatar</string>
-    </resources>
+    <string name="audio_video_disabled_tor">Opkald er deaktiveret ved brug af Tor</string>
+    <string name="switch_to_video">Skift til video</string>
+    <string name="reject_switch_to_video">Afvis skift til video anmodning</string>
+
+</resources>

src/main/res/values-de/strings.xml 🔗

@@ -31,10 +31,7 @@
     <string name="minutes_ago">vor %d Minuten</string>
     <plurals name="x_unread_conversations">
         <item quantity="one">%d ungelesene Unterhaltung</item>
-
-    
         <item quantity="other">%d ungelesene Unterhaltungen</item>
-
     </plurals>
     <string name="sending">senden…</string>
     <string name="message_decrypting">Nachricht wird entschlüsselt. Bitte warten…</string>
@@ -89,7 +86,9 @@
     <string name="clear_conversation_history">Unterhaltungsverlauf löschen</string>
     <string name="clear_histor_msg">Möchtest du alle Nachrichten in dieser Unterhaltung löschen?\n\n<b>Achtung:</b> Dies beeinflusst nicht Nachrichten, die auf anderen Geräten oder Servern gespeichert sind.</string>
     <string name="delete_file_dialog">Datei löschen</string>
-    <string name="delete_file_dialog_msg">Bist du sicher, dass du diese Datei löschen möchtest?\n\n<b>Achtung:</b> Dies löscht keine Kopien dieser Datei, die auf anderen Geräten oder Servern gespeichert sind.</string>
+    <string name="delete_file_dialog_msg">Bist du sicher, dass du diese Datei löschen möchtest\?
+\n
+\n<b>Achtung:</b> Dies löscht keine Kopien dieser Datei, die auf anderen Geräten oder Servern gespeichert sind. </string>
     <string name="also_end_conversation">Diese Unterhaltung danach beenden</string>
     <string name="choose_presence">Gerät auswählen</string>
     <string name="send_unencrypted_message">Unverschlüsselt schreiben…</string>
@@ -194,7 +193,7 @@
     <string name="password">Passwort</string>
     <string name="invalid_jid">Ungültige XMPP-Adresse</string>
     <string name="error_out_of_memory">Zu wenig Speicher vorhanden. Bild ist zu groß</string>
-    <string name="add_phone_book_text">%s zum Telefonbuch hinzufügen</string>
+    <string name="add_phone_book_text">Möchtest du %s in dein Telefonbuch hinzufügen\?</string>
     <string name="server_info_show_more">Server-Info</string>
     <string name="server_info_mam">XEP-0313: MAM</string>
     <string name="server_info_carbon_messages">XEP-0280: Message Carbons</string>
@@ -262,7 +261,7 @@
     <string name="publish">Veröffentlichen</string>
     <string name="touch_to_choose_picture">Profilbild antippen, um ein Bild aus der Galerie auszuwählen</string>
     <string name="publishing">Veröffentliche…</string>
-    <string name="error_publish_avatar_server_reject">Der Server hat die Veröffentlichung des Avatars abgelehnt.</string>
+    <string name="error_publish_avatar_server_reject">Server hat die Veröffentlichung des Profilbildes abgelehnt</string>
     <string name="error_publish_avatar_converting">Bild konnte nicht konvertiert werden</string>
     <string name="error_saving_avatar">Profilbild kann nicht gespeichert werden</string>
     <string name="or_long_press_for_default">(Oder klicke lange, um den Standard wiederherzustellen)</string>
@@ -282,7 +281,9 @@
     <string name="request_presence_updates">Bitte zuerst den Online-Status von deinem Kontakt anfragen.\n\n<small>Dies wird verwendet, um festzustellen, welche Chat-App dein Kontakt nutzt.</small></string>
     <string name="request_now">Jetzt anfordern</string>
     <string name="ignore">Ignorieren</string>
-    <string name="without_mutual_presence_updates"><b>Achtung:</b> Ohne gegenseitige Kenntnis des Online-Status kann es zu unerwarteten Problemen kommen.\n\n<small>Gehe zu \"Kontaktdetails\", um die Einstellungen zu überprüfen.</small></string>
+    <string name="without_mutual_presence_updates"><b>Achtung:</b> Ohne gegenseitige Kenntnis des Online-Status kann es zu unerwarteten Problemen kommen.
+\n
+\n<small>Gehe zu \"Kontaktdetails\", um deine Einstellungen zu überprüfen.</small></string>
     <string name="pref_security_settings">Sicherheit</string>
     <string name="pref_allow_message_correction">Nachrichtenkorrektur erlauben</string>
     <string name="pref_allow_message_correction_summary">Erlaube deinen Kontakten das nachträgliche Korrigieren ihrer Nachrichten</string>
@@ -429,7 +430,7 @@
     <string name="hide_offline">Offline verstecken</string>
     <string name="contact_is_typing">%s schreibt…</string>
     <string name="contact_has_stopped_typing">%s schreibt nicht mehr</string>
-    <string name="contacts_are_typing">%s schreiben...</string>
+    <string name="contacts_are_typing">%s schreiben…</string>
     <string name="contacts_have_stopped_typing">%s schreiben nicht mehr</string>
     <string name="pref_chat_states">Tipp-Benachrichtigung</string>
     <string name="pref_chat_states_summary">Informiere deine Kontakte, wenn du eine Nachricht schreibst</string>
@@ -734,7 +735,7 @@
     <string name="title_activity_show_location">Standort anzeigen</string>
     <string name="share">Teilen</string>
     <string name="unable_to_start_recording">Aufnahme konnte nicht gestartet werden</string>
-    <string name="please_wait">Bitte warten...</string>
+    <string name="please_wait">Bitte warten…</string>
     <string name="no_microphone_permission">%1$s den Zugriff auf das Mikrofon gewähren</string>
     <string name="search_messages">Nachrichten durchsuchen</string>
     <string name="gif">GIF</string>
@@ -807,8 +808,8 @@
     <string name="abort_registration_procedure">Bist du sicher, dass du den Registrierungsprozess abbrechen willst?</string>
     <string name="yes">Ja</string>
     <string name="no">Nein</string>
-    <string name="verifying">Überprüfen...</string>
-    <string name="requesting_sms">SMS anfordern...</string>
+    <string name="verifying">Überprüfen…</string>
+    <string name="requesting_sms">SMS anfordern…</string>
     <string name="incorrect_pin">Die eingegebene PIN ist falsch.</string>
     <string name="pin_expired">Die von uns zugesandte PIN ist abgelaufen.</string>
     <string name="unknown_api_error_network">Unbekannter Netzwerkfehler.</string>
@@ -837,7 +838,7 @@
     <string name="group_chat_will_make_your_jabber_id_public">Dieser Channel wird deine XMPP-Adresse veröffentlichen</string>
     <string name="ebook">E-Book</string>
     <string name="video_original">Original (unkomprimiert)</string>
-    <string name="open_with">Öffnen mit...</string>
+    <string name="open_with">Öffnen mit…</string>
     <string name="set_profile_picture">Conversations Profilbild</string>
     <string name="choose_account">Konto auswählen</string>
     <string name="restore_backup">Sicherung wiederherstellen</string>
@@ -857,7 +858,7 @@
     <string name="please_enter_name">Bitte einen Namen für den Channel eingeben</string>
     <string name="please_enter_xmpp_address">Bitte eine XMPP-Adresse eingeben</string>
     <string name="this_is_an_xmpp_address">Dies ist eine XMPP-Adresse. Bitte einen Namen eingeben.</string>
-    <string name="creating_channel">Öffentlichen Channel erstellen...</string>
+    <string name="creating_channel">Öffentlichen Channel erstellen…</string>
     <string name="channel_already_exists">Dieser Channel existiert bereits</string>
     <string name="joined_an_existing_channel">Du bist einem bestehenden Channel beigetreten</string>
     <string name="unable_to_set_channel_configuration">Channeleinstellung konnte nicht gespeichert werden</string>
@@ -894,7 +895,7 @@
     <string name="account_already_setup">Dieses Konto wurde bereits eingerichtet</string>
     <string name="please_enter_password">Bitte gib das Passwort für dieses Konto ein</string>
     <string name="unable_to_perform_this_action">Diese Aktion konnte nicht durchgeführt werden</string>
-    <string name="open_join_dialog">Öffentlichen Channel beitreten...</string>
+    <string name="open_join_dialog">Öffentlichen Channel beitreten…</string>
     <string name="sharing_application_not_grant_permission">Die teilende App hat keine Berechtigung für den Zugriff auf diese Datei erteilt.</string>
     <string name="group_chats_and_channels"><![CDATA[Gruppenchats & Channels]]></string>
     <string name="jabber_network">jabber.network</string>
@@ -997,5 +998,4 @@
     <string name="audio_video_disabled_tor">Anrufe sind bei der Verwendung von Tor deaktiviert</string>
     <string name="switch_to_video">Umschalten auf Video</string>
     <string name="reject_switch_to_video">Umschalten auf Video ablehnen</string>
-
-</resources>
+</resources>

src/main/res/values-es/strings.xml 🔗

@@ -31,16 +31,11 @@
     <string name="minutes_ago">hace %d min</string>
     <plurals name="x_unread_conversations">
         <item quantity="one">%d conversación sin leer</item>
-
-    
         <item quantity="many">%dconversaciones sin leer</item>
-
-    
         <item quantity="other">%dconversaciones sin leer</item>
-
     </plurals>
     <string name="sending">enviando…</string>
-    <string name="message_decrypting">Descifrando mensaje. Por favor, espera...</string>
+    <string name="message_decrypting">Descifrando el mensaje. Espere por favor…</string>
     <string name="pgp_message">Mensaje cifrado con OpenPGP</string>
     <string name="nick_in_use">El apodo ya está en uso</string>
     <string name="invalid_muc_nick">Apodo inválido</string>
@@ -59,7 +54,7 @@
     <string name="remove_bookmark_text">¿Quieres eliminar %s de tus marcadores? Las conversaciones con este marcador no serán eliminadas.</string>
     <string name="register_account">Registrar nueva cuenta en servidor</string>
     <string name="change_password_on_server">Cambiar contraseña en servidor</string>
-    <string name="share_with">Compartir con...</string>
+    <string name="share_with">Compartir con…</string>
     <string name="start_conversation">Comenzar conversación</string>
     <string name="invite_contact">Invitar a contacto</string>
     <string name="invite">Invitar</string>
@@ -87,12 +82,14 @@
     <string name="send_failed">Error al enviar</string>
     <string name="preparing_image">Preparando para enviar imagen</string>
     <string name="preparing_images">Preparando para enviar imágenes</string>
-    <string name="sharing_files_please_wait">Compartiendo ficheros. Por favor, espera...</string>
+    <string name="sharing_files_please_wait">Compartiendo el archivo, por favor espere…</string>
     <string name="action_clear_history">Limpiar historial</string>
     <string name="clear_conversation_history">Limpiar historial de conversación</string>
     <string name="clear_histor_msg">¿Quieres borrar todos los mensajes de esta conversación?\n\n<b>Aviso:</b> Esto no afectará a los mensajes guardados en otros dispositivos o servidores.</string>
     <string name="delete_file_dialog">Eliminar fichero</string>
-    <string name="delete_file_dialog_msg">¿Estás seguro de que quieres borrar este fichero?\n\n<b>Aviso:</b>Esto no borrará las copias de este fichero almacenado en otros dispositivos o servidores.</string>
+    <string name="delete_file_dialog_msg">¿Está seguro de que desea eliminar este archivo\?
+\n
+\n<b>Advertencia:</b> Esto no eliminará las copias de este archivo almacenadas en otros dispositivos o servidores. </string>
     <string name="also_end_conversation">Cerrar esta conversación después</string>
     <string name="choose_presence">Seleccionar dispositivo</string>
     <string name="send_unencrypted_message">Enviar mensaje sin cifrar</string>
@@ -129,10 +126,10 @@
     <string name="pref_notification_sound_summary">Sonido de notificación para nuevos mensajes</string>
     <string name="pref_call_ringtone_summary">Tono para las nuevas llamadas</string>
     <string name="pref_notification_grace_period">Periodo de gracia</string>
-    <string name="pref_notification_grace_period_summary">El periodo de tiempo en el que las notificaciones están silenciadas tras  detectar actividad en otro de tus dispositivos.</string>
+    <string name="pref_notification_grace_period_summary">Después de que se detecte actividad en otros dispositivos, las notificaciones se silenciarán durante este período de tiempo.</string>
     <string name="pref_advanced_options">Avanzado</string>
     <string name="pref_never_send_crash">Nunca informar de errores</string>
-    <string name="pref_never_send_crash_summary">Al enviar las trazas de error estás ayudando en el desarrollo</string>
+    <string name="pref_never_send_crash_summary">Estará ayudando al desarrollo si elige enviar un informe de error</string>
     <string name="pref_confirm_messages">Confirmar mensajes</string>
     <string name="pref_confirm_messages_summary">Permitir a tus contactos saber cuando has recibido y leído sus mensajes</string>
     <string name="pref_prevent_screenshots">Impedir capturas de pantalla</string>
@@ -154,8 +151,10 @@
     <string name="error_compressing_image">No se pudo comprimir el archivo de imagen</string>
     <string name="error_file_not_found">Archivo no encontrado</string>
     <string name="error_io_exception">Error general. ¿Es posible que no tengas espacio en disco?</string>
-    <string name="error_security_exception_during_image_copy">La aplicación usaste para seleccionar esta imagen no proporcionó suficientes permisos para leer el archivo.\n\n<small>Utiliza un explorador de archivos diferente para seleccionar la imagen</small></string>
-    <string name="error_security_exception">La aplicación que has utilizado para compartir este archivo no presentó permisos suficientes</string>
+    <string name="error_security_exception_during_image_copy">La aplicación que utilizó para seleccionar la imagen no tiene los permisos necesarios para ver la imagen.
+\n
+\n<small>Use otro administrador de archivos para seleccionar una imagen</small>.</string>
+    <string name="error_security_exception">La aplicación que utilizó para compartir este archivo no tiene suficientes permisos.</string>
     <string name="account_status_unknown">Desconocido</string>
     <string name="account_status_disabled">Deshabilitado temporalmente</string>
     <string name="account_status_online">Conectado</string>
@@ -171,7 +170,7 @@
     <string name="account_status_regis_invalid_token">Token de registro inválido</string>
     <string name="account_status_tls_error">Error de negociación TLS</string>
     <string name="account_status_tls_error_domain">Dominio no verificable</string>
-    <string name="account_status_policy_violation">Policy violation</string>
+    <string name="account_status_policy_violation">Violación de los términos</string>
     <string name="account_status_incompatible_server">Servidor incompatible</string>
     <string name="account_status_incompatible_client">Cliente incompatible</string>
     <string name="account_status_stream_error">Error de flujo</string>
@@ -221,14 +220,14 @@
     <string name="last_seen_days">Visto última vez hace %d días</string>
     <string name="install_openkeychain">Mensaje cifrado. Por favor instala OpenKeychain para descifrarlo.</string>
     <string name="openpgp_messages_found">Encontrado un nuevo mensaje cifrado con OpenPGP</string>
-    <string name="openpgp_key_id">OpenPGP Key ID</string>
+    <string name="openpgp_key_id">Identificador de la clave OpenPGP</string>
     <string name="omemo_fingerprint">Huella digital OMEMO</string>
     <string name="omemo_fingerprint_x509">Huella digital v\\OMEMO</string>
     <string name="omemo_fingerprint_selected_message">Huella digital OMEMO (origen del mensaje)</string>
     <string name="omemo_fingerprint_x509_selected_message">Huella digital v\\OMEMO (origen del mensaje)</string>
     <string name="other_devices">Otros dispositivos</string>
     <string name="trust_omemo_fingerprints">Huellas digitales OMEMO de confianza</string>
-    <string name="fetching_keys">Buscando claves...</string>
+    <string name="fetching_keys">Descargando claves…</string>
     <string name="done">Hecho</string>
     <string name="decrypt">Descifrar</string>
     <string name="bookmarks">Marcadores</string>
@@ -254,7 +253,7 @@
     <string name="could_not_destroy_channel">No se ha podido destruir el canal</string>
     <string name="action_edit_subject">Editar asunto de la conversación</string>
     <string name="topic">Asunto</string>
-    <string name="joining_conference">Uniéndose a conversación...</string>
+    <string name="joining_conference">Uniéndose a un chat de grupo…</string>
     <string name="leave">Salir</string>
     <string name="contact_added_you">El contacto te ha añadido a su lista de contactos</string>
     <string name="add_back">Añadir contacto</string>
@@ -307,7 +306,7 @@
     <string name="conference_kicked">Has sido expulsado de esta conversación</string>
     <string name="conference_shutdown">La conversación en grupo ha sido cerrada</string>
     <string name="conference_unknown_error">Ya no estás dentro de esta conversación en grupo</string>
-    <string name="conference_technical_problems">Has dejado esta conversación en grupo debido a razones técnicas.</string>
+    <string name="conference_technical_problems">Abandonaste esta conversación de grupo por motivos técnicos</string>
     <string name="using_account">Usando cuenta %s</string>
     <string name="hosted_on">alojado en %s</string>
     <string name="checking_x">Comprobando %s en servidor HTTP</string>
@@ -339,7 +338,7 @@
     <string name="notification_backup_created_subtitle">Los ficheros de respaldo han sido almacenados en %s</string>
     <string name="restoring_backup">Restaurando copia de respaldo</string>
     <string name="notification_restored_backup_title">Tu copia de respaldo ha sido restaurada</string>
-    <string name="notification_restored_backup_subtitle">No olvides habilitar esta cuenta</string>
+    <string name="notification_restored_backup_subtitle">No olvides activar la cuenta.</string>
     <string name="choose_file">Seleccionar archivo</string>
     <string name="receiving_x_file">Recibiendo %1$s (%2$d%% completado)</string>
     <string name="download_x_file">Descargar %s</string>
@@ -430,9 +429,9 @@
     <string name="sending_x_file">Enviando %s</string>
     <string name="offering_x_file">Ofreciendo %s</string>
     <string name="hide_offline">Ocultar desconectados</string>
-    <string name="contact_is_typing">%s está escribiendo...</string>
+    <string name="contact_is_typing">%s está escribiendo…</string>
     <string name="contact_has_stopped_typing">%s ha dejado de escribir</string>
-    <string name="contacts_are_typing">%s están escribiendo...</string>
+    <string name="contacts_are_typing">%s están escribiendo…</string>
     <string name="contacts_have_stopped_typing">%s han dejado de escribir</string>
     <string name="pref_chat_states">Notificación de escritura</string>
     <string name="pref_chat_states_summary">Permitir a tus contactos saber cuando estás escribiendo un mensaje</string>
@@ -473,7 +472,7 @@
     <string name="download_failed_could_not_connect">Error al descargar: No se ha podido conectar con el servidor</string>
     <string name="download_failed_could_not_write_file">Falló la descarga: No se puede escribir el fichero</string>
     <string name="download_failed_invalid_file">Error al descargar: Archivo no válido</string>
-    <string name="account_status_tor_unavailable">Red Tor no disponible.</string>
+    <string name="account_status_tor_unavailable">La red Tor no está disponible</string>
     <string name="account_status_bind_failure">Fallo de enlace</string>
     <string name="account_status_host_unknown">El servidor no es responsable de este dominio</string>
     <string name="server_info_broken">Error</string>
@@ -491,7 +490,7 @@
     <string name="unable_to_parse_certificate">No se ha podido leer el certificado</string>
     <string name="mam_prefs">Preferencias de archivado</string>
     <string name="server_side_mam_prefs">Preferencias de archivado en servidor</string>
-    <string name="fetching_mam_prefs">Buscando preferencias de archivado. Por favor, espera...</string>
+    <string name="fetching_mam_prefs">Recuperando la configuración del archivo. Espere por favor…</string>
     <string name="unable_to_fetch_mam_prefs">No se ha podido conseguir las preferencias de archivado</string>
     <string name="captcha_required">Captcha requerido</string>
     <string name="captcha_hint">Introduce el texto de la imagen de arriba</string>
@@ -506,7 +505,7 @@
     <string name="pref_use_tor_summary">Todas las conexiones se realizan a través de la red TOR. Requiere Orbot</string>
     <string name="account_settings_hostname">Hostname</string>
     <string name="account_settings_port">Puerto</string>
-    <string name="hostname_or_onion">Server- or .onion-address</string>
+    <string name="hostname_or_onion">Dirección del servidor o .onion</string>
     <string name="not_a_valid_port">Éste no es un número de puerto válido</string>
     <string name="not_valid_hostname">Éste no es un hostame válido</string>
     <string name="connected_accounts">%1$d de %2$d cuentas conectadas</string>
@@ -546,10 +545,11 @@
     <string name="this_account_is_disabled">Has deshabilitado esta cuenta</string>
     <string name="security_error_invalid_file_access">Error de seguridad: ¡Acceso a archivo inválido!</string>
     <string name="no_application_to_share_uri">No se ha encontrado ninguna aplicación para compartir la URI</string>
-    <string name="share_uri_with">Compartir URI con...</string>
-    <string name="welcome_text_quicksy"><![CDATA[Quicksy es un derivado del popular cliente XMPP Conversations con detección automática de contactos.<br><br>El registro se realiza con tu número de teléfono y Quicksy automáticamente—basado en los teléfonos de tu agenda de contactos—te sugerirá posibles contactos.<br><br>Registrándote en Quicksy aceptas nuestra <a href="https://quicksy.im/#privacy">política de privacidad</a>.]]> </string>
+    <string name="share_uri_with">Compartir URI con…</string>
+    <string name="welcome_text_quicksy">Quicksy es un derivado del popular cliente XMPP Conversations con detección automática de contactos.&lt;br&gt;&lt;br&gt;El registro se realiza con tu número de teléfono y Quicksy automáticamente—basado en los teléfonos de tu agenda de contactos—te sugerirá posibles contactos.&lt;br&gt;&lt;br&gt;Registrándote en Quicksy aceptas nuestra &lt;a href=https://quicksy.im/#privacy&gt;política de privacidad&lt;/a&gt;.</string>
     <string name="agree_and_continue">Aceptar y continuar</string>
-    <string name="magic_create_text">Una guía te ayudará en el proceso de creación de la cuenta en conversations.im.¹\nCuando selecciones conversations.im como proveedor podrás comunicarte con usuarios de otros servidores proporcionándoles tu dirección XMPP completa. </string>
+    <string name="magic_create_text">Una guía te ayudará en el proceso de creación de la cuenta en conversations.im.¹
+\nCuando selecciones conversations.im como proveedor podrás comunicarte con usuarios de otros servidores proporcionándoles tu dirección XMPP completa.</string>
     <string name="your_full_jid_will_be">Tu dirección XMPP completa será: %s</string>
     <string name="create_account">Crear cuenta</string>
     <string name="use_own_provider">Usar otro proveedor de mi elección</string>
@@ -567,7 +567,7 @@
     <string name="registration_please_wait">El registro falló. Prueba de nuevo más tarde</string>
     <string name="registration_password_too_weak">Error en el registro: La contraseña es demasiado débil</string>
     <string name="choose_participants">Elige a los participantes</string>
-    <string name="creating_conference">Creando conversación en grupo...</string>
+    <string name="creating_conference">Creando un chat de grupo…</string>
     <string name="invite_again">Invitar de nuevo</string>
     <string name="gp_disable">Deshabilitar</string>
     <string name="gp_short">Corto</string>
@@ -585,7 +585,7 @@
     <string name="this_device_is_no_longer_in_use">Este dispositivo ya no está en uso</string>
     <string name="type_pc">Ordenador</string>
     <string name="type_phone">Teléfono móvil</string>
-    <string name="type_tablet">Tablet</string>
+    <string name="type_tablet">Tableta</string>
     <string name="type_web">Navegador</string>
     <string name="type_console">Consola</string>
     <string name="payment_required">Pago requerido</string>
@@ -597,11 +597,11 @@
     <string name="remote_server_not_found">Servidor no encontrado</string>
     <string name="remote_server_timeout">Tiempo de espera agotado al servidor remoto</string>
     <string name="unable_to_update_account">No se ha podido actualizar la cuenta</string>
-    <string name="report_jid_as_spammer">Reportar a esta dirección XMPP por enviar mensajes no deseados</string>
+    <string name="report_jid_as_spammer">Reporta esta dirección XMPP como spam.</string>
     <string name="pref_delete_omemo_identities">Eliminar identidades OMEMO</string>
     <string name="pref_delete_omemo_identities_summary">Regenerar tus clave OMEMO. Todos tus contactos tendrán que verificarte de nuevo. Usa esta opción como último recurso.</string>
     <string name="delete_selected_keys">Eliminar claves seleccionadas</string>
-    <string name="error_publish_avatar_offline">Debes estar conectado para publicar la imagen de perfil</string>
+    <string name="error_publish_avatar_offline">Necesitas estar conectado para publicar un avatar.</string>
     <string name="show_error_message">Mostrar mensaje de error</string>
     <string name="error_message">Mensaje de error</string>
     <string name="data_saver_enabled">Optimización de datos habilitado</string>
@@ -628,7 +628,7 @@
     <string name="pref_clean_private_storage">Limpiar datos privados</string>
     <string name="pref_clean_private_storage_summary">Limpiar datos privados de ficheros descargados (Pueden volver a descargarse desde el servidor)</string>
     <string name="i_followed_this_link_from_a_trusted_source">Enlace desde una fuente de confianza</string>
-    <string name="verifying_omemo_keys_trusted_source">Vas a verificar las claves OMEMO de %1$s después de hacer click en el enlace. Esto solo es seguro si conseguiste este enlace desde una fuente de confianza donde solo %2$s pudo haber publicado el enlace</string>
+    <string name="verifying_omemo_keys_trusted_source">Está a punto de verificar las claves OMEMO de %1$s después de hacer clic en un enlace. Esto solo es seguro si siguió este enlace desde una fuente confiable donde solo %2$s podría haber publicado este enlace.</string>
     <string name="verifying_omemo_keys_trusted_source_account">Está a punto de verificar las claves OMEMO de su propia cuenta. Esto solamente es seguro si ha seguido este enlace desde una fuente segura, donde solo usted lo haya publicado.</string>
     <string name="continue_btn">Continuar</string>
     <string name="verify_omemo_keys">Verificar claves OMEMO</string>
@@ -681,7 +681,7 @@
     <string name="online_right_now">Conectado ahora mismo</string>
     <string name="retry_decryption">Reintentar descifrado</string>
     <string name="session_failure">Fallo de sesión</string>
-    <string name="sasl_downgrade">Downgraded SASL mechanism</string>
+    <string name="sasl_downgrade">Mecanismo SASL degradado</string>
     <string name="account_status_regis_web">El servidor requiere registro en su página web</string>
     <string name="open_website">Abrir página web</string>
     <string name="application_found_to_open_website">No se ha encontrado aplicación para abrir el sitio web</string>
@@ -699,7 +699,7 @@
     <string name="message">Mensaje</string>
     <string name="private_messages_are_disabled">Los mensajes privados están deshabilitados</string>
     <string name="huawei_protected_apps">Aplicaciones protegidas</string>
-    <string name="huawei_protected_apps_summary">Para seguir recibiendo notificaciones, incluso cuando la pantalla está apagada, necesitas añadir Conversations a la lista de aplicaciones protegidas.</string>
+    <string name="huawei_protected_apps_summary">Para recibir notificaciones de mensajes incluso cuando la pantalla está apagada, debe agregar Conversations a la lista de aplicaciones protegidas.</string>
     <string name="mtm_accept_cert">¿Aceptar certificado desconocido?</string>
     <string name="mtm_trust_anchor">El certificado del servidor no está firmado por una Autoridad Certificadora conocida.</string>
     <string name="mtm_accept_servername">¿Aceptar nombre del servidor no coincidente?</string>
@@ -745,7 +745,7 @@
     <string name="title_activity_show_location">Mostrar ubicación</string>
     <string name="share">Compartir</string>
     <string name="unable_to_start_recording">No se ha podido empezar la grabación</string>
-    <string name="please_wait">Por favor, espera...</string>
+    <string name="please_wait">Espere por favor…</string>
     <string name="no_microphone_permission">Permitir a %1$s acceder al micrófono</string>
     <string name="search_messages">Buscar mensajes</string>
     <string name="gif">GIF</string>
@@ -788,7 +788,7 @@
     <string name="view_media">Ver galería</string>
     <string name="group_chat_members">Participantes</string>
     <string name="media_browser">Galería</string>
-    <string name="security_violation_not_attaching_file">Fichero omitido por violación de seguridad</string>
+    <string name="security_violation_not_attaching_file">El archivo se omitió debido a una violación de seguridad.</string>
     <string name="pref_video_compression">Calidad del video</string>
     <string name="pref_video_compression_summary">Calidad más baja indica archivos más pequeños</string>
     <string name="video_360p">Medio (360p)</string>
@@ -818,8 +818,8 @@
     <string name="abort_registration_procedure">¿Estás seguro de que quieres abortar el proceso de registro?</string>
     <string name="yes">Sí</string>
     <string name="no">No</string>
-    <string name="verifying">Verificando...</string>
-    <string name="requesting_sms">Solicitando mensaje SMS...</string>
+    <string name="verifying">Verificando…</string>
+    <string name="requesting_sms">Solicitando un mensaje de texto…</string>
     <string name="incorrect_pin">El código que has introducido no es correcto.</string>
     <string name="pin_expired">El código que te hemos enviado ha expirado.</string>
     <string name="unknown_api_error_network">Error desconocido de red.</string>
@@ -848,8 +848,8 @@
     <string name="group_chat_will_make_your_jabber_id_public">Este canal hará tu dirección XMPP visible públicamente</string>
     <string name="ebook">e-book</string>
     <string name="video_original">Original (sin comprimir)</string>
-    <string name="open_with">Abrir con...</string>
-    <string name="set_profile_picture">Foto de perfil en Conversations</string>
+    <string name="open_with">Abrir con…</string>
+    <string name="set_profile_picture">Establecer la foto del perfil</string>
     <string name="choose_account">Elige una cuenta</string>
     <string name="restore_backup">Restaurar copia de respaldo</string>
     <string name="restore">Restaurar</string>
@@ -867,14 +867,14 @@
     <string name="xmpp_address">Dirección XMPP</string>
     <string name="please_enter_name">Por favor, proporciona un nombre para el canal</string>
     <string name="please_enter_xmpp_address">Por favor, proporciona una dirección XMPP</string>
-    <string name="this_is_an_xmpp_address">Esto es una dirección XMPP. Por favor, proporciona un nombre</string>
-    <string name="creating_channel">Creando canal público...</string>
+    <string name="this_is_an_xmpp_address">Esta es una dirección XMPP. Introduce un nombre.</string>
+    <string name="creating_channel">Creando un canal público…</string>
     <string name="channel_already_exists">Esta canal ya existe</string>
     <string name="joined_an_existing_channel">Te has unido a un canal existente</string>
     <string name="unable_to_set_channel_configuration">No se ha podido guardar la configuración del canal</string>
     <string name="allow_participants_to_edit_subject">Permitir a cualquiera editar el asunto</string>
     <string name="allow_participants_to_invite_others">Permitir a cualquiera invitar a otros contactos</string>
-    <string name="anyone_can_edit_subject">Todos pueden editar el asunto</string>
+    <string name="anyone_can_edit_subject">Cualquiera puede editar el tema.</string>
     <string name="owners_can_edit_subject">Los propietarios pueden editar el asunto.</string>
     <string name="admins_can_edit_subject">Los administradores pueden editar el asunto.</string>
     <string name="owners_can_invite_others">Los propietarios pueden invitar a otros contactos.</string>
@@ -905,7 +905,7 @@
     <string name="account_already_setup">Esta cuenta ya fue configurada</string>
     <string name="please_enter_password">Por favor ingrese la contraseña para esta cuenta</string>
     <string name="unable_to_perform_this_action">No se ha podido realizar esta acción</string>
-    <string name="open_join_dialog">Unirse a canal público...</string>
+    <string name="open_join_dialog">Uniéndose a un canal público…</string>
     <string name="sharing_application_not_grant_permission">La aplicación de compartir no concedió permisos para acceder a este fichero.</string>
     <string name="group_chats_and_channels"><![CDATA[Conversaciones en grupo & Canales]]></string>
     <string name="jabber_network">jabber.network</string>
@@ -918,6 +918,8 @@
     <string name="make_call">Hacer una llamada</string>
     <string name="rtp_state_incoming_call">Llamada entrante</string>
     <string name="rtp_state_incoming_video_call">Videollamada entrante</string>
+    <string name="rtp_state_content_add_video">¿Cambiar a videollamada?</string>
+    <string name="rtp_state_content_add">¿Añadir pistas adicionales?</string>
     <string name="rtp_state_connecting">Conectando</string>
     <string name="rtp_state_connected">Conectado</string>
     <string name="rtp_state_reconnecting">Reconectando</string>
@@ -965,7 +967,7 @@
     <string name="help">Ayuda</string>
     <string name="switch_to_conversation">Cambiar a conversación</string>
     <string name="microphone_unavailable">Tu micrófono no está disponible</string>
-    <string name="only_one_call_at_a_time">Solo puedes hacer una llamada a la vez</string>
+    <string name="only_one_call_at_a_time">Solo se puede hacer una llamada a la vez.</string>
     <string name="return_to_ongoing_call">Volver a la llamada en curso</string>
     <string name="could_not_switch_camera">No se ha podido cambiar de cámara</string>
     <string name="add_to_favorites">Fijar en la parte superior</string>
@@ -1009,4 +1011,6 @@
     <string name="account_status_temporary_auth_failure">Fallo temporal de autenticación</string>
     <string name="delete_avatar">Eliminar imagen de perfil</string>
     <string name="audio_video_disabled_tor">Las llamadas están deshabilitadas cuando se usa Tor</string>
-    </resources>
+    <string name="switch_to_video">Cambiar a vídeo</string>
+    <string name="reject_switch_to_video">Rechazar petición de cambiar a vídeo</string>
+</resources>

src/main/res/values-gl/strings.xml 🔗

@@ -31,13 +31,10 @@
     <string name="minutes_ago">hai %d minutos</string>
     <plurals name="x_unread_conversations">
         <item quantity="one">%d conversa sen ler</item>
-
-    
         <item quantity="other">%d conversas sen ler</item>
-
     </plurals>
     <string name="sending">enviando…</string>
-    <string name="message_decrypting">Descifrando a mensaxe. Agarda por favor...</string>
+    <string name="message_decrypting">Descifrando a mensaxe. Agarda por favor…</string>
     <string name="pgp_message">Mensaxe cifrado con OpenPGP</string>
     <string name="nick_in_use">O alcume xa está en uso</string>
     <string name="invalid_muc_nick">Alcume non válido</string>
@@ -56,7 +53,7 @@
     <string name="remove_bookmark_text">Desexas eliminar o marcador %s? As conversas deste marcador non se eliminarán. </string>
     <string name="register_account">Rexistrar nova conta no servidor</string>
     <string name="change_password_on_server">Cambiar o contrasinal no servidor</string>
-    <string name="share_with">Compartir con</string>
+    <string name="share_with">Compartir con…</string>
     <string name="start_conversation">Comezar conversa</string>
     <string name="invite_contact">Convidar contacto</string>
     <string name="invite">Convidar</string>
@@ -84,12 +81,16 @@
     <string name="send_failed">Erro ao enviar</string>
     <string name="preparing_image">Preparándose para enviar a imaxe</string>
     <string name="preparing_images">Preparándose para enviar imaxes</string>
-    <string name="sharing_files_please_wait">Compartindo ficheiros. Agarda por favor...</string>
+    <string name="sharing_files_please_wait">Compartindo ficheiros. Agarda…</string>
     <string name="action_clear_history">Baleirar historial</string>
     <string name="clear_conversation_history">Eliminar historial da conversa</string>
-    <string name="clear_histor_msg">¿Queres eliminar as mensaxes desta conversa?\n\n<b>Aviso:</b> Esto non lle afecta as mensaxes gardadas noutros dispositivos ou servidores. </string>
+    <string name="clear_histor_msg">¿Queres eliminar tódalas mensaxes desta conversa\?
+\n
+\n<b>Aviso:</b> Esto non lle afecta ás mensaxes gardadas noutros dispositivos ou servidores.</string>
     <string name="delete_file_dialog">Eliminar ficheiro</string>
-    <string name="delete_file_dialog_msg">Tes a certeza de querer eliminar este ficheiro?\n\n<b>Aviso:</b> Esto non eliminará as copias de este ficheiro que están gardadas noutros dispositivos ou servidores.</string>
+    <string name="delete_file_dialog_msg">Tes a certeza de querer eliminar este ficheiro\?
+\n
+\n<b>Aviso:</b> Esto non eliminará as copias de este ficheiro que están gardadas noutros dispositivos ou servidores. </string>
     <string name="also_end_conversation">Pechar a conversa tras baleirar</string>
     <string name="choose_presence">Escoller dispositivo</string>
     <string name="send_unencrypted_message">Enviar mensaxe non cifrada</string>
@@ -107,7 +108,7 @@
     <string name="install">Instalar</string>
     <string name="openkeychain_not_installed">Instala OpenKeychain por favor</string>
     <string name="offering">ofrecendo…</string>
-    <string name="waiting">agardando...</string>
+    <string name="waiting">agardando…</string>
     <string name="no_pgp_key">Clave OpenPGP non atopada</string>
     <string name="contact_has_no_pgp_key">Non se cifrou a mensaxe porque o contacto non está publicando a súa chave pública.\n\n<small>Pídelle ao contacto que configure OpenPGP.</small></string>
     <string name="no_pgp_keys">Non se atoparon chaves OpenPGP</string>
@@ -126,7 +127,7 @@
     <string name="pref_notification_sound_summary">Son da notificación para novas mensaxes</string>
     <string name="pref_call_ringtone_summary">Ton para as chamadas entrantes</string>
     <string name="pref_notification_grace_period">Período de graza</string>
-    <string name="pref_notification_grace_period_summary">O tempo no que as notificacións son silenciadas tras detectar actividade en algún dos teus outros dispositivos.</string>
+    <string name="pref_notification_grace_period_summary">O tempo no que as notificacións son silenciadas tras detectar actividade nalgún dos teus outros dispositivos.</string>
     <string name="pref_advanced_options">Avanzado</string>
     <string name="pref_never_send_crash">Nunca enviar informe de erros</string>
     <string name="pref_never_send_crash_summary">Ao enviar trazas do sistema estás axudando ao desenvolvemento</string>
@@ -151,7 +152,9 @@
     <string name="error_compressing_image">Non se puido converter o ficheiro de imaxe</string>
     <string name="error_file_not_found">Arquivo non atopado</string>
     <string name="error_io_exception">Erro xeral de I/O. ¿Quedaches sen espazo no disco?</string>
-    <string name="error_security_exception_during_image_copy">A app utilizada para seleccionar esta imaxe non deu permisos suficientes para ler o ficheiro.\n\n<small>Usa un xestor de ficheiros diferente para escoller a imaxe</small></string>
+    <string name="error_security_exception_during_image_copy">A app utilizada para seleccionar esta imaxe non deu permisos suficientes para ler o ficheiro.
+\n
+\n<small>Usa un xestor de ficheiros diferente para escoller a imaxe</small>.</string>
     <string name="error_security_exception">A app que usaches para compartir este ficheiro non concedeu os permisos suficientes.</string>
     <string name="account_status_unknown">Descoñecido</string>
     <string name="account_status_disabled">Desactivado temporalmente</string>
@@ -225,7 +228,7 @@
     <string name="omemo_fingerprint_x509_selected_message">v\\Impresión dixital OMEMO (orixe da mensaxe)</string>
     <string name="other_devices">Outros dispositivos</string>
     <string name="trust_omemo_fingerprints">Confiar en impresións dixitais OMEMO</string>
-    <string name="fetching_keys">Obtendo chaves...</string>
+    <string name="fetching_keys">Obtendo chaves…</string>
     <string name="done">Feito</string>
     <string name="decrypt">Descifrar</string>
     <string name="bookmarks">Marcadores</string>
@@ -251,7 +254,7 @@
     <string name="could_not_destroy_channel">Non se puido eliminar a canle</string>
     <string name="action_edit_subject">Editar o tema da conversa en grupo</string>
     <string name="topic">Asunto</string>
-    <string name="joining_conference">Entrando na conversa en grupo</string>
+    <string name="joining_conference">Entrando na conversa en grupo…</string>
     <string name="leave">Saír</string>
     <string name="contact_added_you">Contacto engadido a túa lista de contactos</string>
     <string name="add_back">Volver a engadir</string>
@@ -261,7 +264,7 @@
     <string name="everyone_has_read_up_to_this_point">Todas leron até aquí</string>
     <string name="publish">Publicar</string>
     <string name="touch_to_choose_picture">Toca no avatar para elixir a imaxe na galería</string>
-    <string name="publishing">Publicando...</string>
+    <string name="publishing">Publicando…</string>
     <string name="error_publish_avatar_server_reject">O servidor rexeitou a túa publicación</string>
     <string name="error_publish_avatar_converting">Non se puido converter a imaxe</string>
     <string name="error_saving_avatar">Non se puido salvar o avatar no disco</string>
@@ -368,7 +371,7 @@
     <string name="error_trustkeys_title">Algo saíu mal</string>
     <string name="fetching_history_from_server">Obtendo historial desde o servidor</string>
     <string name="no_more_history_on_server">Non hai máis historial no servidor</string>
-    <string name="updating">Actualizando....</string>
+    <string name="updating">Actualizando…</string>
     <string name="password_changed">Mudou o contrasinal!</string>
     <string name="could_not_change_password">Non puido mudar o contrasinal</string>
     <string name="change_password">Cambiar contrasinal</string>
@@ -423,13 +426,13 @@
     <string name="pdf_document">documento PDF</string>
     <string name="apk">App Android</string>
     <string name="vcard">Contacto</string>
-    <string name="avatar_has_been_published">Publicouse o avatar</string>
+    <string name="avatar_has_been_published">Publicouse o avatar!</string>
     <string name="sending_x_file">Enviando %s</string>
     <string name="offering_x_file">Ofrecendo %s</string>
     <string name="hide_offline">Ocultar fora de liña</string>
-    <string name="contact_is_typing">%s está a escribir...</string>
+    <string name="contact_is_typing">%s está escribindo…</string>
     <string name="contact_has_stopped_typing">%s deixou de escribir</string>
-    <string name="contacts_are_typing">%s están escribindo...</string>
+    <string name="contacts_are_typing">%s están escribindo…</string>
     <string name="contacts_have_stopped_typing">%s deixaron de escribir</string>
     <string name="pref_chat_states">Notificacións de escritura</string>
     <string name="pref_chat_states_summary">Permitelle aos teus contactos que saiban cando lles estás a escribir</string>
@@ -487,7 +490,7 @@
     <string name="unable_to_parse_certificate">Non se puido procesar o certificado</string>
     <string name="mam_prefs">Gardando axustes</string>
     <string name="server_side_mam_prefs">Axustes de gardado no servidor</string>
-    <string name="fetching_mam_prefs">Obtendo os axustes de gardado. Por favor agarde...</string>
+    <string name="fetching_mam_prefs">Obtendo os axustes de gardado. Agarda…</string>
     <string name="unable_to_fetch_mam_prefs">Non se obtiveron os axustes gardados</string>
     <string name="captcha_required">Requírese o CAPTCHA</string>
     <string name="captcha_hint">Introduza o texto da imaxe superior</string>
@@ -541,7 +544,7 @@
     <string name="this_account_is_disabled">Desactivou esta conta</string>
     <string name="security_error_invalid_file_access">Fallo de seguridade: Acceso non válido ao ficheiro!</string>
     <string name="no_application_to_share_uri">Non se atopou unha app para compartir URI</string>
-    <string name="share_uri_with">Compartir URI con...</string>
+    <string name="share_uri_with">Compartir URI con…</string>
     <string name="welcome_text_quicksy"><![CDATA[Quicksy é un derivado do popular cliente XMPP Conversations con descubrimento automático de contactos.<br><br>Podes rexistrarte co teu número de teléfono e Quicksy suxerirache automáticamente —tomando os números da túa libreta de enderezos como referencia—  posibles contactos para ti.<br><br>Ao rexistrarte aceptas a nosa <a href="https://quicksy.im/#privacy">política de privacidade</a>.]]></string>
     <string name="agree_and_continue">Aceptar e continuar</string>
     <string name="magic_create_text">Tes unha guía para crear unha conta en conversations.im¹\nAo escoller conversations.im como provedor poderás comunicarte con outras usuarias de outros provedores con só darlles o teu enderezo XMPP completo.</string>
@@ -562,7 +565,7 @@
     <string name="registration_please_wait">Fallo no rexistro: inténteo de novo</string>
     <string name="registration_password_too_weak">Fallo no rexistro: contrasinal moi feble</string>
     <string name="choose_participants">Escoller participantes</string>
-    <string name="creating_conference">Creando unha conversa en grupo...</string>
+    <string name="creating_conference">Creando conversa en grupo…</string>
     <string name="invite_again">Convidar de novo</string>
     <string name="gp_disable">Desactivar</string>
     <string name="gp_short">Breve</string>
@@ -595,7 +598,7 @@
     <string name="report_jid_as_spammer">Denuncia esta conta XMPP por facer spam.</string>
     <string name="pref_delete_omemo_identities">Borrar identidades OMEMO</string>
     <string name="pref_delete_omemo_identities_summary">Rexenerar chaves OMEMO. Todos os teus contactos terán que verificar a túa conta de novo. Utiliza esto só como último recurso.</string>
-    <string name="delete_selected_keys">Eliminar as chaves seleccionadas.</string>
+    <string name="delete_selected_keys">Eliminar as chaves seleccionadas</string>
     <string name="error_publish_avatar_offline">Debes ter conexión para publicar o teu avatar.</string>
     <string name="show_error_message">Mostrar mensaxe do fallo</string>
     <string name="error_message">Mensaxe de fallo</string>
@@ -632,7 +635,7 @@
     <string name="distrust_omemo_key">Retirar confianza a dispositivo</string>
     <string name="distrust_omemo_key_text">Tes a certeza de que queres eliminar a verificación deste dispositivo?\nEste dispositivo e as súas mensaxes serán marcados como \"Non confiable\".</string>
     <plurals name="seconds">
-        <item quantity="one">%d segundos</item>
+        <item quantity="one">%d segundo</item>
         <item quantity="other">%d segundos</item>
     </plurals>
     <plurals name="minutes">
@@ -640,7 +643,7 @@
         <item quantity="other">%d minutos</item>
     </plurals>
     <plurals name="hours">
-        <item quantity="one">%d horas</item>
+        <item quantity="one">%d hora</item>
         <item quantity="other">%d horas</item>
     </plurals>
     <plurals name="days">
@@ -652,8 +655,8 @@
         <item quantity="other">%d semanas</item>
     </plurals>
     <plurals name="months">
-        <item quantity="one">%dmeses</item>
-        <item quantity="other">%dmeses</item>
+        <item quantity="one">%d mes</item>
+        <item quantity="other">%d meses</item>
     </plurals>
     <string name="pref_automatically_delete_messages">Borrado automático de mensaxes</string>
     <string name="pref_automatically_delete_messages_description">Borrar mensaxes de xeito automático de este dispositivo que anteriores ao marco temporal configurado.</string>
@@ -670,7 +673,7 @@
     <string name="online_right_now">En liña neste momento</string>
     <string name="retry_decryption">Volver a intentar o descifrado</string>
     <string name="session_failure">Fallo na sesión</string>
-    <string name="sasl_downgrade">Downgraded SASL mechanism</string>
+    <string name="sasl_downgrade">Mecanismo SASL desactualizado</string>
     <string name="account_status_regis_web">O servidor require rexistro no sitio web</string>
     <string name="open_website">Abrir sitio web</string>
     <string name="application_found_to_open_website">Non se atopou app para abrir sitio web</string>
@@ -688,15 +691,15 @@
     <string name="message">Mensaxe</string>
     <string name="private_messages_are_disabled">As mensaxes privadas están desactivadas</string>
     <string name="huawei_protected_apps">Apps protexidos</string>
-    <string name="huawei_protected_apps_summary">Para seguir recibindo notificacións, incluso cando a pantalla está apagada, precisa engadir Conversations a lista de apps protexidos.</string>
+    <string name="huawei_protected_apps_summary">Para seguir recibindo notificacións, incluso cando a pantalla está apagada, tes que engadir Conversations á lista de apps protexidas.</string>
     <string name="mtm_accept_cert">¿Aceptar certificado descoñecido?</string>
     <string name="mtm_trust_anchor">O certificado do servidor non está asinado por unha autoridade de certificación coñecida.</string>
     <string name="mtm_accept_servername">¿Aceptar un nome de servidor que non coincida?</string>
-    <string name="mtm_hostname_mismatch">O servidor non pode autenticarse como  \&quot;%s\&quot;. O certificado só é válido para:</string>
+    <string name="mtm_hostname_mismatch">O servidor non pode autenticarse como  \"%s\". O certificado só é válido para:</string>
     <string name="mtm_connect_anyway">Queres conectarte de todos os xeitos?</string>
     <string name="mtm_cert_details">Detalles do certificado:</string>
     <string name="once">Unha vez</string>
-    <string name="qr_code_scanner_needs_access_to_camera">O escaner de código QR necesita acceso á cámara.</string>
+    <string name="qr_code_scanner_needs_access_to_camera">O escaner de código QR necesita acceso á cámara</string>
     <string name="pref_scroll_to_bottom">Desprazarse ata a parte inferior</string>
     <string name="pref_scroll_to_bottom_summary">Desprazarse cara abaixo logo de enviar unha mensaxe</string>
     <string name="edit_status_message_title">Editar a Mensaxe de Estado</string>
@@ -706,7 +709,8 @@
     <string name="error_trustkey_device_list">Non se obtivo a lista de dispositivos</string>
     <string name="error_trustkey_bundle">Non se obtiveron as chaves de cifrado</string>
     <string name="error_trustkey_hint_mutual">Suxestión: Nalgúns casos, isto pode solucionarse engadíndovos mutuamente as vosas listas de contactos.</string>
-    <string name="disable_encryption_message">¿Tes a certeza de que queres desactivar o cifrado OMEMO para esta conversa? Isto permitirá que o administrador do teu servidor lea as túas mensaxes, pero pode ser a única forma de comunicarse con persoas que usan clientes obsoletos.</string>
+    <string name="disable_encryption_message">Tes a certeza de querer desactivar o cifrado 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.</string>
     <string name="disable_now">Desactivar agora</string>
     <string name="draft">Borrador:</string>
     <string name="pref_omemo_setting">Cifrado OMEMO</string>
@@ -721,8 +725,8 @@
     <string name="small">Pequena</string>
     <string name="medium">Mediana</string>
     <string name="large">Grande</string>
-    <string name="not_encrypted_for_this_device">A mensaxe non foi encriptada para este disposivivo</string>
-    <string name="omemo_decryption_failed">Fallo ao descifrar a mensaxe OMEMO</string>
+    <string name="not_encrypted_for_this_device">A mensaxe non foi cifrada para este disposivivo.</string>
+    <string name="omemo_decryption_failed">Fallo ao descifrar a mensaxe OMEMO.</string>
     <string name="undo">desfacer</string>
     <string name="location_disabled">Compartir Localización está desactivado</string>
     <string name="action_fix_to_location">Fixar posición</string>
@@ -734,7 +738,7 @@
     <string name="title_activity_show_location">Mostrar localización</string>
     <string name="share">Compartir</string>
     <string name="unable_to_start_recording">Non comezou a gravación</string>
-    <string name="please_wait">Por favor, agarde...</string>
+    <string name="please_wait">Por favor, agarda…</string>
     <string name="no_microphone_permission">Permitir que %1$s acceda ao micrófono</string>
     <string name="search_messages">Buscar mensaxes</string>
     <string name="gif">GIF</string>
@@ -789,7 +793,7 @@
     <string name="choose_a_country">Indica un país</string>
     <string name="phone_number">número de teléfono</string>
     <string name="verify_your_phone_number">Valida o teu número de teléfono</string>
-    <string name="enter_country_code_and_phone_number">Quicksy vaiche enviar unha mensaxe SMS (podería ter custos) para validar o teu número de teléfono. Escribe o código de país e número de teléfono.</string>
+    <string name="enter_country_code_and_phone_number">Quicksy vaiche enviar unha mensaxe SMS (podería ter custos) para validar o teu número de teléfono. Escribe o código de país e número de teléfono:</string>
     <string name="we_will_be_verifying"><![CDATA[Validaremos o número de teléfono<br/><br/><b>%s</b><br/><br/>É correcto, ou quere modificar o número?]]></string>
     <string name="not_a_valid_phone_number">%s non é un número de teléfono válido.</string>
     <string name="please_enter_your_phone_number">Por favor escribe o teu número de teléfono.</string>
@@ -807,8 +811,8 @@
     <string name="abort_registration_procedure">Seguro que quere cancelar o proceso de rexistro?</string>
     <string name="yes">Si</string>
     <string name="no">Non</string>
-    <string name="verifying">Validando...</string>
-    <string name="requesting_sms">Solicitando SMS...</string>
+    <string name="verifying">Validando…</string>
+    <string name="requesting_sms">Solicitando SMS…</string>
     <string name="incorrect_pin">O pin introducido non é correcto.</string>
     <string name="pin_expired">O pin que che enviamos caducou.</string>
     <string name="unknown_api_error_network">Fallo descoñecido na rede.</string>
@@ -837,7 +841,7 @@
     <string name="group_chat_will_make_your_jabber_id_public">Esta canle fará público o teu enderezo XMPP</string>
     <string name="ebook">e-book</string>
     <string name="video_original">Orixinal (non comprimido)</string>
-    <string name="open_with">Abrir con...</string>
+    <string name="open_with">Abrir con…</string>
     <string name="set_profile_picture">Imaxe de perfil en Conversations</string>
     <string name="choose_account">Elixir conta</string>
     <string name="restore_backup">Restablecer copia de apoio</string>
@@ -857,7 +861,7 @@
     <string name="please_enter_name">Por favor, escribe un nome para a canle</string>
     <string name="please_enter_xmpp_address">Por favor, escribe un enderezo XMPP</string>
     <string name="this_is_an_xmpp_address">Esto é un enderezo XMPP. Por favor, escribe un nome.</string>
-    <string name="creating_channel">Creando canle pública...</string>
+    <string name="creating_channel">Creando canle pública…</string>
     <string name="channel_already_exists">Esta canle xa existe</string>
     <string name="joined_an_existing_channel">Entraches nunha canle existente</string>
     <string name="unable_to_set_channel_configuration">Non se gardaron os axustes da canle</string>
@@ -894,7 +898,7 @@
     <string name="account_already_setup">Esta conta xa foi configurada</string>
     <string name="please_enter_password">Introduza o contrasinal de esta conta</string>
     <string name="unable_to_perform_this_action">Non se puido completar a acción</string>
-    <string name="open_join_dialog">Unirse a canle pública...</string>
+    <string name="open_join_dialog">Unirse a canle pública…</string>
     <string name="sharing_application_not_grant_permission">A aplicación que comparte non proporciona permiso para acceder ao ficheiro.</string>
     <string name="group_chats_and_channels"><![CDATA[Grupos de conversa & Canles]]></string>
     <string name="jabber_network">jabber.network</string>
@@ -971,7 +975,7 @@
     <string name="record_voice_mail">Gravar correo de voz</string>
     <string name="play_audio">Reproducir audio</string>
     <string name="pause_audio">Pausar audio</string>
-    <string name="add_contact_or_create_or_join_group_chat">Engade un contacto, crea o únete a unha conversa en grupo ou descubre canles.</string>
+    <string name="add_contact_or_create_or_join_group_chat">Engade un contacto, crea o únete a unha conversa en grupo ou descubre canles</string>
     <plurals name="view_users">
         <item quantity="one">Ver %1$d Participante</item>
         <item quantity="other">Ver %1$d Participantes</item>
@@ -997,5 +1001,4 @@
     <string name="audio_video_disabled_tor">As chamadas están desactivadas cando usas Tor</string>
     <string name="switch_to_video">Cambiar a vídeo</string>
     <string name="reject_switch_to_video">Rexeitar a solicitude para cambiar a vídeo</string>
-
-</resources>
+</resources>

src/main/res/values-hr/strings.xml 🔗

@@ -73,4 +73,18 @@
     <string name="unblock">Odblokiraj</string>
     <string name="save">Sačuvaj</string>
     <string name="ok">Ok</string>
+    <string name="send_now">Pošalji sada</string>
+    <string name="send_never">Nikad više ne pitaj</string>
+    <string name="problem_connecting_to_account">Nije moguće povezati se s računom</string>
+    <string name="problem_connecting_to_accounts">Nije moguće povezati se s više računa</string>
+    <string name="touch_to_fix">Dodirnite za upravljanje svojim računima</string>
+    <string name="attach_file">Priložite datoteku</string>
+    <string name="not_in_roster">Dodati ovaj kontakt koji nedostaje na popis kontakata?</string>
+    <string name="add_contact">Dodaj kontakt</string>
+    <string name="send_failed">dostava nije uspjela</string>
+    <string name="preparing_image">Priprema za slanje slike</string>
+    <string name="preparing_images">Priprema za slanje slika</string>
+    <string name="sharing_files_please_wait">Dijeljenje datoteka. Molimo pričekajte…</string>
+    <string name="action_clear_history">Obriši povijest</string>
+    <string name="clear_conversation_history">Obriši povijest razgovora</string>
     </resources>

src/main/res/values-it/strings.xml 🔗

@@ -31,16 +31,11 @@
     <string name="minutes_ago">%d min fa</string>
     <plurals name="x_unread_conversations">
         <item quantity="one">%d conversazione non letta</item>
-
-    
         <item quantity="many">%d conversazioni non lette</item>
-
-    
         <item quantity="other">%d conversazioni non lette</item>
-
     </plurals>
     <string name="sending">invio…</string>
-    <string name="message_decrypting">Decifrazione messaggio. Attendere prego...</string>
+    <string name="message_decrypting">Decifrazione messaggio. Attendere prego…</string>
     <string name="pgp_message">Messaggio cifrato con OpenPGP</string>
     <string name="nick_in_use">Nome utente già in uso</string>
     <string name="invalid_muc_nick">Nickname non valido</string>
@@ -59,7 +54,7 @@
     <string name="remove_bookmark_text">Vuoi rimuovere %s dai segnalibri? Le conversazioni con questo segnalibro non verranno rimosse.</string>
     <string name="register_account">Registra un nuovo profilo sul server</string>
     <string name="change_password_on_server">Cambia la password sul server</string>
-    <string name="share_with">Condividi con</string>
+    <string name="share_with">Condividi con…</string>
     <string name="start_conversation">Inizia conversazione</string>
     <string name="invite_contact">Invita contatto</string>
     <string name="invite">Invita</string>
@@ -87,7 +82,7 @@
     <string name="send_failed">Invio fallito</string>
     <string name="preparing_image">Preparazione per l\'invio dell\'immagine</string>
     <string name="preparing_images">Preparazione per l\'invio delle immagini</string>
-    <string name="sharing_files_please_wait">Condivisione file. Attendere prego...</string>
+    <string name="sharing_files_please_wait">Condivisione file. Attendere prego…</string>
     <string name="action_clear_history">Pulisci la cronologia</string>
     <string name="clear_conversation_history">Pulisci la cronologia della conversazione</string>
     <string name="clear_histor_msg">Vuoi eliminare tutti i messaggi in questa conversazione?\n\n<b>Attenzione:</b> ciò non influenzerà i messaggi salvati su altri dispositivi o server.</string>
@@ -154,7 +149,9 @@
     <string name="error_compressing_image">Impossibile convertire l\'immagine</string>
     <string name="error_file_not_found">File non trovato</string>
     <string name="error_io_exception">Errore di I/O generico. Forse hai esaurito lo spazio?</string>
-    <string name="error_security_exception_during_image_copy">L’app che hai usato per selezionare questa immagine non ha fornito autorizzazioni sufficienti per leggere il file.\n\n<small>Usa un gestore di file differente per scegliere un’immagine</small></string>
+    <string name="error_security_exception_during_image_copy">L’app che hai usato per selezionare questa immagine non ha fornito autorizzazioni sufficienti per leggere il file.
+\n
+\n<small>Usa un gestore di file differente per scegliere un’immagine</small>.</string>
     <string name="error_security_exception">L\'app che hai usato per condividere questo file non ha fornito autorizzazioni sufficienti.</string>
     <string name="account_status_unknown">Sconosciuto</string>
     <string name="account_status_disabled">Disattivato temporaneamente</string>
@@ -228,7 +225,7 @@
     <string name="omemo_fingerprint_x509_selected_message">v\\Impronta OMEMO (origine del messaggio)</string>
     <string name="other_devices">Altri dispositivi</string>
     <string name="trust_omemo_fingerprints">Fidati delle impronte OMEMO</string>
-    <string name="fetching_keys">Ricezione chiavi...</string>
+    <string name="fetching_keys">Ricezione chiavi…</string>
     <string name="done">Fatto</string>
     <string name="decrypt">Decripta</string>
     <string name="bookmarks">Segnalibri</string>
@@ -254,7 +251,7 @@
     <string name="could_not_destroy_channel">Distruzione canale fallita</string>
     <string name="action_edit_subject">Modifica titolo chat di gruppo</string>
     <string name="topic">Argomento</string>
-    <string name="joining_conference">Ingresso nella chat di gruppo...</string>
+    <string name="joining_conference">Ingresso nella chat di gruppo…</string>
     <string name="leave">Abbandona</string>
     <string name="contact_added_you">Il contatto ti ha aggiunto alla sua lista contatti</string>
     <string name="add_back">Aggiungi anche tu</string>
@@ -282,7 +279,9 @@
     <string name="enable">Attiva</string>
     <string name="conference_requires_password">La chat di gruppo richiede una password</string>
     <string name="enter_password">Inserisci la password</string>
-    <string name="request_presence_updates">Richiedi gli aggiornamenti della presenza dal tuo contatto.\n\n<small>Ciò verrà usato per determinare quale app sta usando il tuo contatto.</small></string>
+    <string name="request_presence_updates">Prima chiedi gli aggiornamenti della presenza dal tuo contatto.
+\n
+\n<small>Ciò verrà usato per determinare quale app sta usando il tuo contatto</small>.</string>
     <string name="request_now">Rechiedi adesso</string>
     <string name="ignore">Ignora</string>
     <string name="without_mutual_presence_updates"><b>Attenzione:</b> inviarlo senza aggiornamenti della presenza reciproci può causare problemi inaspettati.\n\n<small>Vai nei dettagli del contatto per verificare le tue sottoscrizioni alla presenza.</small></string>
@@ -430,7 +429,7 @@
     <string name="sending_x_file">Invio %s</string>
     <string name="offering_x_file">Offrendo %s</string>
     <string name="hide_offline">Nascondi i contatti offline</string>
-    <string name="contact_is_typing">%s sta digitando...</string>
+    <string name="contact_is_typing">%s sta digitando…</string>
     <string name="contact_has_stopped_typing">%s ha smesso di digitare</string>
     <string name="contacts_are_typing">%s stanno scrivendo…</string>
     <string name="contacts_have_stopped_typing">%s hanno smesso di scrivere</string>
@@ -491,7 +490,7 @@
     <string name="unable_to_parse_certificate">Impossibile analizzare il certificato</string>
     <string name="mam_prefs">Preferenze di archiviazione</string>
     <string name="server_side_mam_prefs">Preferenze di archiviazione lato server</string>
-    <string name="fetching_mam_prefs">Raccolta preferenze di archiviazione. Attendere prego...</string>
+    <string name="fetching_mam_prefs">Ricezione preferenze di archiviazione. Attendere prego…</string>
     <string name="unable_to_fetch_mam_prefs">Impossibile recuperare le preferenze di archiviazione</string>
     <string name="captcha_required">CAPTCHA necessario</string>
     <string name="captcha_hint">Inserisci il testo dell\'immagine soprastante</string>
@@ -546,7 +545,7 @@
     <string name="this_account_is_disabled">Hai disattivato questo profilo</string>
     <string name="security_error_invalid_file_access">Errore di sicurezza: accesso file non valido!</string>
     <string name="no_application_to_share_uri">Nessuna app trovata per condividere l\'URI</string>
-    <string name="share_uri_with">Condividi l\'URI con...</string>
+    <string name="share_uri_with">Condividi URI con…</string>
     <string name="welcome_text_quicksy"><![CDATA[Quicksy è una variante del popolare client XMPP Conversations con ricerca automatica dei contatti.<br><br>Ti registri con il tuo numero di telefono e Quicksy ti suggerirà—in base ai numeri di telefono nella tua rubrica—automaticamente i possibili contatti.<br><br>Registrandoti accetti la nostra <a href="https://quicksy.im/#privacy">politica sulla privacy</a>.]]></string>
     <string name="agree_and_continue">Accetta e continua</string>
     <string name="magic_create_text">È disponibile una guida per la creazione di un profilo su conversations.im.¹\nQuando scegli conversations.im come fornitore potrai comunicare con utenti di altri fornitori dando il tuo indirizzo XMPP completo.</string>
@@ -567,7 +566,7 @@
     <string name="registration_please_wait">Registrazione fallita: riprova più tardi</string>
     <string name="registration_password_too_weak">Registrazione fallita: password troppo debole</string>
     <string name="choose_participants">Scegli i partecipanti</string>
-    <string name="creating_conference">Creazione chat di gruppo...</string>
+    <string name="creating_conference">Creazione chat di gruppo…</string>
     <string name="invite_again">Invita di nuovo</string>
     <string name="gp_disable">Disattiva</string>
     <string name="gp_short">Breve</string>
@@ -745,7 +744,7 @@
     <string name="title_activity_show_location">Mostra la posizione</string>
     <string name="share">Condividi</string>
     <string name="unable_to_start_recording">Impossibile avviare la registrazione</string>
-    <string name="please_wait">Attendere prego...</string>
+    <string name="please_wait">Attendere prego…</string>
     <string name="no_microphone_permission">Dai a %1$s l\'accesso al microfono</string>
     <string name="search_messages">Cerca messaggi</string>
     <string name="gif">GIF</string>
@@ -803,7 +802,7 @@
     <string name="enter_country_code_and_phone_number">Quicksy invierà un SMS (possono essere applicati costi dal gestore) per verificare il tuo numero. Inserisci il tuo codice nazionale e numero di telefono:</string>
     <string name="we_will_be_verifying"><![CDATA[Verificheremo il numero di telefono<br/><br/><b>%s</b><br/><br/>È corretto o vuoi modificare il numero?]]></string>
     <string name="not_a_valid_phone_number">%s non è un numero di telefono valido.</string>
-    <string name="please_enter_your_phone_number">Inserisci il tuo numero di telefono:</string>
+    <string name="please_enter_your_phone_number">Inserisci il tuo numero di telefono.</string>
     <string name="search_countries">Cerca nazioni</string>
     <string name="verify_x">Verifica %s</string>
     <string name="we_have_sent_you_an_sms_to_x"><![CDATA[Ti abbiamo inviato un SMS a <b>%s</b>.]]></string>
@@ -905,7 +904,7 @@
     <string name="account_already_setup">Questo profilo è già stato configurato</string>
     <string name="please_enter_password">Inserisci la password per questo profilo</string>
     <string name="unable_to_perform_this_action">Impossibile eseguire questa azione</string>
-    <string name="open_join_dialog">Entra in un canale pubblico...</string>
+    <string name="open_join_dialog">Entra in un canale pubblico…</string>
     <string name="sharing_application_not_grant_permission">L\'app di condivisione non ha concesso l\'autorizzazione per accedere a questo file.</string>
     <string name="group_chats_and_channels"><![CDATA[Chat di gruppo e canali]]></string>
     <string name="jabber_network">jabber.network</string>
@@ -1013,5 +1012,4 @@
     <string name="audio_video_disabled_tor">Le chiamate sono disattivate quando si usa Tor</string>
     <string name="switch_to_video">Passa al video</string>
     <string name="reject_switch_to_video">Rifiuta richiesta di passare al video</string>
-
-</resources>
+</resources>

src/main/res/values-ja/strings.xml 🔗

@@ -37,7 +37,7 @@
     <string name="message_decrypting">メッセージを復号しています。しばらくお待ちください…</string>
     <string name="pgp_message">OpenPGP 暗号化メッセージ</string>
     <string name="nick_in_use">ニックネームは既に使用されています</string>
-    <string name="invalid_muc_nick">不正なニックネーム</string>
+    <string name="invalid_muc_nick">このニックネームは使えません</string>
     <string name="admin">管理者</string>
     <string name="owner">所有者</string>
     <string name="moderator">調停者</string>
@@ -167,6 +167,7 @@
     <string name="account_status_tls_error_domain">検証不可能なドメイン</string>
     <string name="account_status_policy_violation">ポリシー違反</string>
     <string name="account_status_incompatible_server">互換性のないサーバー</string>
+    <string name="account_status_incompatible_client">互換性のない端末</string>
     <string name="account_status_stream_error">ストリーム エラー</string>
     <string name="account_status_stream_opening_error">ストリームを開く際にエラー</string>
     <string name="encryption_choice_unencrypted">TLS</string>
@@ -221,7 +222,7 @@
     <string name="omemo_fingerprint_x509_selected_message">v\\OMEMO フィンガープリント (メッセージ起源)</string>
     <string name="other_devices">他のデバイス</string>
     <string name="trust_omemo_fingerprints">OMEMO フィンガープリントを信頼</string>
-    <string name="fetching_keys">鍵の取得中…</string>
+    <string name="fetching_keys">暗号鍵の取得中…</string>
     <string name="done">完了</string>
     <string name="decrypt">復号</string>
     <string name="bookmarks">ブックマーク</string>
@@ -323,7 +324,7 @@
     <string name="confirm">確認</string>
     <string name="try_again">再試行</string>
     <string name="pref_keep_foreground_service">フォアグラウンドサービス</string>
-    <string name="pref_keep_foreground_service_summary">オペレーティングシステムが接続を切断するのを防止します</string>
+    <string name="pref_keep_foreground_service_summary">OSが接続を切断するのを防止します</string>
     <string name="pref_create_backup">バックアップを作成</string>
     <string name="pref_create_backup_summary">バックアップファイルは %s に保存されます </string>
     <string name="notification_create_backup_title">バックアップファイルを作成しています</string>
@@ -348,7 +349,7 @@
     <string name="no_application_found_to_open_file">ファイルを開くアプリケーションが見つかりません</string>
     <string name="no_application_found_to_open_link">リンクを開くアプリケーションが見つかりません</string>
     <string name="no_application_found_to_view_contact">連絡先を表示するアプリケーションが見つかりません</string>
-    <string name="pref_show_dynamic_tags">ダイナミック タグ</string>
+    <string name="pref_show_dynamic_tags">タグ付け</string>
     <string name="pref_show_dynamic_tags_summary">連絡先の下に、読み取り専用タグを表示します</string>
     <string name="enable_notifications">通知を有効化</string>
     <string name="no_conference_server_found">グループチャットのサーバーが見つかりませんでした</string>
@@ -511,7 +512,7 @@
     <string name="no_storage_permission">%1$s に外部ストレージへのアクセス権を付与してください</string>
     <string name="no_camera_permission">%1$s にカメラへのアクセス権を付与</string>
     <string name="sync_with_contacts">連絡先と同期</string>
-    <string name="sync_with_contacts_long">%1$s はあなたのアドレス帳にアクセスして、あなたのXMPP 連絡先名簿と照合する権限を求めています。\nこれにより、連絡先のフルネームとアバターが表示されます。\n\n%1$s は、あなたのサーバーに何かをアップロードすることなく、あなたのアドレス帳を読み込んでローカルに照合するだけです。</string>
+    <string name="sync_with_contacts_long">%1$s はあなたのアドレス帳にアクセスして、あなたのXMPP 連絡先名簿と照合する権限を求めています。\nこれにより、連絡先のフルネームとアバターが表示されます。\n\n%1$s は、あなたのサーバーに何かをアップロードすることなく、あなたのアドレス帳を読み込んで照合するだけです。</string>
     <string name="sync_with_contacts_quicksy"><![CDATA[Quicksyは、既にQuicksyに登録されている連絡先を提案するために、あなたの連絡先の電話番号にアクセスする必要があります。<br><br>Quicksyは、それらの電話番号のコピーを保存することはありません。\n\n詳細は<a href="https://quicksy.im/#privacy">プライバシーポリシー</a>をご覧ください。<br><br>今、連絡先へのアクセス権限を付与するよう求められます。]]></string>
     <string name="notify_on_all_messages">すべてのメッセージで通知</string>
     <string name="notify_only_when_highlighted">メンションされたときにのみ通知</string>
@@ -535,7 +536,7 @@
     <string name="security_error_invalid_file_access">セキュリティエラー: 不正なファイルアクセス!</string>
     <string name="no_application_to_share_uri">URI を共有するアプリが見つかりません</string>
     <string name="share_uri_with">…で URI を共有</string>
-    <string name="welcome_text_quicksy"><![CDATA[Quicksy は人気の XMPP クライアント Conversations の派生で、連絡先の自動検出機能を備えています。<br><br>電話番号を入力して登録すると、アドレス帳に登録されている電話番号をもとに、Quicksyが自動的に連絡先を提案します。<br><br>登録すると、<a href="https://quicksy.im/#privacy">我々のプライバシーポリシー</a>に同意することになります。]]></string>
+    <string name="welcome_text_quicksy"><![CDATA[Quicksy は人気のXMPPアプリConversationsの派生で、連絡先の自動検出機能を備えています。<br><br>電話番号を入力して登録すると、アドレス帳に登録されている電話番号をもとに、Quicksyが自動的に連絡先を提案します。<br><br>登録すると、<a href=\"https://quicksy.im/#privacy\">我々のプライバシーポリシー</a>に同意することになります。]]></string>
     <string name="agree_and_continue">同意して続行</string>
     <string name="magic_create_text">conversations.im 上にアカウントを作成する設定の指南です。¹\nconversations.im をプロバイダーとして選択した場合、あなたの完全な XMPP アドレスを他のプロバイダーのユーザーに示すことで、その人と連絡をとることができます。</string>
     <string name="your_full_jid_will_be">あなたの完全なXMPPアドレスは: %s</string>
@@ -606,10 +607,10 @@
     <string name="share_as_barcode">バーコードで共有</string>
     <string name="share_as_uri">XMPP URI で共有</string>
     <string name="share_as_http">HTTP リンクで共有</string>
-    <string name="pref_blind_trust_before_verification">検証前の盲目的な信頼</string>
+    <string name="pref_blind_trust_before_verification">認証前で鍵を使用</string>
     <string name="pref_blind_trust_before_verification_summary">認証されていない連絡先からの新規デバイスを信頼するが、認証されている連絡先からの新規デバイスについては手動での確認を求める。</string>
-    <string name="blindly_trusted_omemo_keys">OMEMO 鍵を盲目的に信用していた。つまり、他の人かもしれないし、誰かが盗聴しているかもしれない。</string>
-    <string name="not_trusted">信頼できない</string>
+    <string name="blindly_trusted_omemo_keys">認証せずOMEMO 鍵を信用しています。このままでは盗聴される危険性があります。</string>
+    <string name="not_trusted">信頼されていない</string>
     <string name="invalid_barcode">不正な二次元バーコード</string>
     <string name="pref_clean_cache_summary">キャッシュフォルダを消去します (カメラアプリで使用)</string>
     <string name="pref_clean_cache">キャッシュを消去</string>
@@ -752,6 +753,7 @@
     <string name="messages_channel_name">メッセージ</string>
     <string name="incoming_calls_channel_name">着信通話</string>
     <string name="ongoing_calls_channel_name">継続中の通話</string>
+    <string name="missed_calls_channel_name">不在着信</string>
     <string name="silent_messages_channel_name">サイレントメッセージ</string>
     <string name="silent_messages_channel_description">この通知グループは、音を鳴らしてはいけない通知を表示するために使用します。例えば、他のデバイスでアクティブになっているときなどです (猶予期間)。</string>
     <string name="delivery_failed_channel_name">配信に失敗</string>
@@ -891,8 +893,10 @@
     <string name="make_call">通話をする</string>
     <string name="rtp_state_incoming_call">着信通話</string>
     <string name="rtp_state_incoming_video_call">着信映像通話</string>
+    <string name="rtp_state_content_add_video">ビデオ通話に切り替えますか?</string>
     <string name="rtp_state_connecting">接続中</string>
     <string name="rtp_state_connected">接続しました</string>
+    <string name="rtp_state_reconnecting">再接続中</string>
     <string name="rtp_state_accepting_call">通話受入</string>
     <string name="rtp_state_ending_call">通話終了</string>
     <string name="answer_call">応答</string>
@@ -908,6 +912,8 @@
     <string name="hang_up">電話を切る</string>
     <string name="ongoing_call">継続中の通話</string>
     <string name="ongoing_video_call">継続中の映像通話</string>
+    <string name="reconnecting_call">通話再接続中</string>
+    <string name="reconnecting_video_call">ビデオ通話再接続中</string>
     <string name="disable_tor_to_make_call">通話するのに Tor を無効化</string>
     <string name="incoming_call">着信通話</string>
     <string name="incoming_call_duration">着信通話・%s</string>
@@ -915,8 +921,18 @@
     <string name="outgoing_call">発信通話</string>
     <string name="outgoing_call_duration">発信通話・%s</string>
     <string name="missed_call">不在着信通話</string>
+    <plurals name="n_missed_calls_from_x">
+        <item quantity="other">%2$sから%1$d件の不在着信</item>
+    </plurals>
+    <plurals name="n_missed_calls">
+        <item quantity="other">不在着信%d件</item>
+    </plurals>
+    <plurals name="n_missed_calls_from_m_contacts">
+        <item quantity="other">%2$d人から%1$d件の不在着信</item>
+    </plurals>
     <string name="audio_call">音声通話</string>
     <string name="video_call">映像通話</string>
+    <string name="help">ヘルプ</string>
     <string name="switch_to_conversation">会話に切り替え</string>
     <string name="microphone_unavailable">マイクが利用できません</string>
     <string name="only_one_call_at_a_time">1度に1回線の通話のみ。</string>
@@ -958,4 +974,6 @@
     <string name="no_xmpp_adddress_found">XMPPアドレスがみつかりません</string>
     <string name="account_status_temporary_auth_failure">一時的な認証失敗</string>
     <string name="delete_avatar">アバターを削除</string>
+    <string name="audio_video_disabled_tor">Tor使用中のため通話できません</string>
+    <string name="switch_to_video">ビデオ通話切替</string>
     </resources>

src/main/res/values-zh-rCN/strings.xml 🔗

@@ -31,7 +31,6 @@
     <string name="minutes_ago">%d分钟前</string>
     <plurals name="x_unread_conversations">
         <item quantity="other">%d 未读会话</item>
-
     </plurals>
     <string name="sending">发送中…</string>
     <string name="message_decrypting">正在解密信息。请稍候……</string>
@@ -69,7 +68,7 @@
     <string name="save">保存</string>
     <string name="ok">完成</string>
     <string name="crash_report_title">%1$s已崩溃</string>
-    <string name="crash_report_message">用你的 XMPP 账户发送堆栈跟踪来帮助持续开发 %1$s</string>
+    <string name="crash_report_message">用你的 XMPP 账户发送堆栈跟踪来帮助持续开发 %1$s。</string>
     <string name="send_now">立即发送</string>
     <string name="send_never">不再询问</string>
     <string name="problem_connecting_to_account">账户无法连接</string>
@@ -86,7 +85,9 @@
     <string name="clear_conversation_history">清除聊天记录</string>
     <string name="clear_histor_msg">您确定要删除此聊天中的所有消息吗?\n\n<b>警告:</b>这不会删除存储在其他设备或服务器上的那些消息的副本。</string>
     <string name="delete_file_dialog">删除文件</string>
-    <string name="delete_file_dialog_msg">您确定要删除此文件吗?\n\n <b>警告:</b>这不会删除存储在其他设备或服务器上的此文件的副本。</string>
+    <string name="delete_file_dialog_msg">您确定要删除此文件吗?
+\n
+\n<b>警告:</b>这不会删除存储在其他设备或服务器上的此文件的副本。 </string>
     <string name="also_end_conversation">之后关闭此聊天</string>
     <string name="choose_presence">选择设备</string>
     <string name="send_unencrypted_message">发送未加密的信息</string>
@@ -111,7 +112,7 @@
     <string name="contacts_have_no_pgp_keys">因您的联系人未公布其公钥,无法加密您的信息。\n\n<small>请通知您的联系人设置OpenPGP。</small></string>
     <string name="pref_general">常规</string>
     <string name="pref_accept_files">接收文件</string>
-    <string name="pref_accept_files_summary">自动接收小于此大小的文件</string>
+    <string name="pref_accept_files_summary">自动接收小于此大小的文件…</string>
     <string name="pref_attachments">附件</string>
     <string name="pref_notification_settings">通知</string>
     <string name="pref_vibrate">振动</string>
@@ -126,14 +127,14 @@
     <string name="pref_notification_grace_period_summary">在其他设备上检测到活动之后,通知在此时间段内将被静音。</string>
     <string name="pref_advanced_options">高级</string>
     <string name="pref_never_send_crash">从不发送崩溃报告</string>
-    <string name="pref_never_send_crash_summary">通过发送堆栈跟踪,您可以帮助Conversations持续发展</string>
+    <string name="pref_never_send_crash_summary">通过发送堆栈跟踪,您可以为开发提供帮助</string>
     <string name="pref_confirm_messages">确认消息</string>
     <string name="pref_confirm_messages_summary">让对方知道你收到并阅读了他们的消息</string>
     <string name="pref_prevent_screenshots">防止截屏</string>
     <string name="pref_prevent_screenshots_summary">在应用切换中隐藏应用程序内容并阻止截图</string>
     <string name="pref_ui_options">用户界面</string>
     <string name="openpgp_error">OpenKeychain报告一个错误。</string>
-    <string name="bad_key_for_encryption">错误的密钥</string>
+    <string name="bad_key_for_encryption">错误的加密密钥。</string>
     <string name="accept">接受</string>
     <string name="error">产生了一个错误</string>
     <string name="recording_error">错误</string>
@@ -148,7 +149,9 @@
     <string name="error_compressing_image">无法转换图片</string>
     <string name="error_file_not_found">未找到文件</string>
     <string name="error_io_exception">常规I/O错误。可能是存储空间不足?</string>
-    <string name="error_security_exception_during_image_copy">您用来选择图片的程序没有给予读取权限。\n\n &lt;/small&gt;尝试其他文件管理器选择图片&lt;/small&gt;。</string>
+    <string name="error_security_exception_during_image_copy">你用来选择图片的应用没有提供读取文件的足够权限。
+\n
+\n<small>使用不同的文件管理器来选择图片</small>.</string>
     <string name="error_security_exception">你用来共享此文件的应用程序没有提供足够的权限。</string>
     <string name="account_status_unknown">未知</string>
     <string name="account_status_disabled">暂时不可用</string>
@@ -180,7 +183,7 @@
     <string name="mgmt_account_publish_pgp">发布OpenPGP公钥</string>
     <string name="unpublish_pgp">移除OpenPGP公钥</string>
     <string name="unpublish_pgp_message">您确定要从在线状态中移除OpenPGP公钥吗?\n您的联系人将无法再向您发送 OpenPGP 加密信息。</string>
-    <string name="openpgp_has_been_published">OpenPGP公钥已发布</string>
+    <string name="openpgp_has_been_published">OpenPGP 公钥已发布。</string>
     <string name="mgmt_account_enable">启用账户</string>
     <string name="mgmt_account_are_you_sure">确定?</string>
     <string name="mgmt_account_delete_confirm_text">如果您删除帐户,您的所有聊天记录将会丢失</string>
@@ -222,7 +225,7 @@
     <string name="omemo_fingerprint_x509_selected_message">v\\OMEMO 指纹 (消息来源)</string>
     <string name="other_devices">其他设备</string>
     <string name="trust_omemo_fingerprints">信任的OMEMO指纹</string>
-    <string name="fetching_keys">获取密钥中</string>
+    <string name="fetching_keys">获取密钥中…</string>
     <string name="done">完成</string>
     <string name="decrypt">解密</string>
     <string name="bookmarks">书签</string>
@@ -276,7 +279,9 @@
     <string name="enable">启用</string>
     <string name="conference_requires_password">需要密码才能进入该群聊</string>
     <string name="enter_password">输入密码</string>
-    <string name="request_presence_updates">请先发送更新在线状态请求。\n\n<small>以判断您的联系人所用的客户端类型。</small></string>
+    <string name="request_presence_updates">请先请求联系人在线状态更新。
+\n
+\n<small>这将被用来判断您的联系人正在使用的聊天应用</small>。</string>
     <string name="request_now">现在请求</string>
     <string name="ignore">忽略</string>
     <string name="without_mutual_presence_updates"><b>警告:</b>在没有相互更新在线状态的情况下发送将会出现未知问题。\n\n<small>前往联系人详情以验证您订阅的在线状态。</small></string>
@@ -360,7 +365,8 @@
     <string name="regenerate_omemo_key">重新生成OMEMO密钥</string>
     <string name="clear_other_devices">清除设备</string>
     <string name="clear_other_devices_desc">清除所有其他设备的OMEMO通告?下次设备连接时将重新通告,但可能收不到你发送的消息。</string>
-    <string name="error_no_keys_to_trust_server_error">此联系人没有可用的密钥。\n从服务器获取密钥失败。也许你的联系人所在服务器发生问题。</string>
+    <string name="error_no_keys_to_trust_server_error">此联系人没有可用的密钥。
+\n无法从服务器获取新密钥。也许你的联系人所在服务器发生问题了?</string>
     <string name="error_no_keys_to_trust_presence">没有可以用于这个账户的密钥。\n请确保你有相互的在线状态的订阅。</string>
     <string name="error_trustkeys_title">出错了</string>
     <string name="fetching_history_from_server">正在从服务器获取历史记录</string>
@@ -525,7 +531,9 @@
     <string name="large_images_only">仅大图片</string>
     <string name="battery_optimizations_enabled">已启用节电模式</string>
     <string name="battery_optimizations_enabled_explained">你的设备正对 %1$s 实施强力电池优化,这可能导致通知延迟甚至消息丢失。\n建议禁用这些优化。</string>
-    <string name="battery_optimizations_enabled_dialog">你的设备正对 %1$s 实施强力电池优化,这可能导致通知延迟甚至消息丢失。\n你将被请求禁用这些优化。</string>
+    <string name="battery_optimizations_enabled_dialog">你的设备正对 %1$s 实施强力电池优化,这可能导致通知延迟甚至消息丢失。
+\n
+\n你将被请求禁用这些优化。</string>
     <string name="disable">禁用</string>
     <string name="selection_too_large">选择区域过大</string>
     <string name="no_accounts">(没有启用的账户)</string>
@@ -534,7 +542,7 @@
     <string name="send_corrected_message">发送更正后的消息</string>
     <string name="no_keys_just_confirm">您已经验证了该用户。点击“完成”让%s加入群聊。 </string>
     <string name="this_account_is_disabled">你已经禁用了此账户</string>
-    <string name="security_error_invalid_file_access">安全错误:文件访问无效</string>
+    <string name="security_error_invalid_file_access">安全错误:文件访问无效!</string>
     <string name="no_application_to_share_uri">未找到可以分享此链接的应用</string>
     <string name="share_uri_with">分享链接……</string>
     <string name="welcome_text_quicksy"><![CDATA[Quicksy是从受欢迎的XMPP客户端对话中分离出来的,具有自动联系人发现功能<br><br>您注册了电话号码,Quicksy就会根据您的通讯录中的电话号码自动为您建议可能的联系人<br><br>签署即表示您同意我们的<a href="https://quicksy.im/#privacy">隐私政策</a>。]]></string>
@@ -545,7 +553,7 @@
     <string name="use_own_provider">使用我自己的服务器</string>
     <string name="pick_your_username">输入您的用户名</string>
     <string name="pref_manually_change_presence">手动更改在线状态</string>
-    <string name="pref_manually_change_presence_summary">编辑状态信息时,您的状态</string>
+    <string name="pref_manually_change_presence_summary">编辑状态信息时设置您是否有空。</string>
     <string name="status_message">状态信息</string>
     <string name="presence_chat">有空聊天</string>
     <string name="presence_online">在线</string>
@@ -587,11 +595,11 @@
     <string name="remote_server_not_found">找不到远程服务器</string>
     <string name="remote_server_timeout">远程服务器超时</string>
     <string name="unable_to_update_account">无法更新账户</string>
-    <string name="report_jid_as_spammer">举报此账户发送垃圾信息</string>
+    <string name="report_jid_as_spammer">举报此 XMPP 地址发送垃圾信息。</string>
     <string name="pref_delete_omemo_identities">删除OMEMO身份</string>
     <string name="pref_delete_omemo_identities_summary">重新生成OMEMO密钥。所有联系人都需要再次认证。请将此作为最后的办法。</string>
     <string name="delete_selected_keys">删除选择的密钥</string>
-    <string name="error_publish_avatar_offline">你需要连接才能发布头像</string>
+    <string name="error_publish_avatar_offline">你需要连接才能发布头像。</string>
     <string name="show_error_message">显示出错消息</string>
     <string name="error_message">出错信息</string>
     <string name="data_saver_enabled">省流量模式已启用</string>
@@ -610,7 +618,7 @@
     <string name="share_as_http">分享HTTP链接</string>
     <string name="pref_blind_trust_before_verification">验证前盲目信任</string>
     <string name="pref_blind_trust_before_verification_summary">自动信任陌生人的设备,但在验证过联系人添加设备时手动确认。</string>
-    <string name="blindly_trusted_omemo_keys">盲目信任OMEMO密钥,可能会有人冒充对方发送消息</string>
+    <string name="blindly_trusted_omemo_keys">盲目信任的 OMEMO 密钥,表示它们可能时其他人或者某人可能冒充别人发送消息。</string>
     <string name="not_trusted">不信任的</string>
     <string name="invalid_barcode">无效二维码</string>
     <string name="pref_clean_cache_summary">清理缓存文件夹(由相机应用使用)</string>
@@ -645,14 +653,14 @@
         <item quantity="other">%d个月</item>
     </plurals>
     <string name="pref_automatically_delete_messages">自动删除消息</string>
-    <string name="pref_automatically_delete_messages_description">自动从此设备上删除超过配置时间段的消息</string>
+    <string name="pref_automatically_delete_messages_description">自动从此设备上删除超过配置时间段的消息。</string>
     <string name="encrypting_message">消息加密中</string>
     <string name="not_fetching_history_retention_period">由于本地保留期限设置,无法提取消息。</string>
     <string name="transcoding_video">正在压缩视频</string>
     <string name="corresponding_conversations_closed">相应的对话已关闭。</string>
-    <string name="contact_blocked_past_tense">联系人已封禁</string>
+    <string name="contact_blocked_past_tense">联系人已封禁。</string>
     <string name="pref_notifications_from_strangers">陌生人的消息也通知</string>
-    <string name="pref_notifications_from_strangers_summary">提醒来自陌生人的消息与通话</string>
+    <string name="pref_notifications_from_strangers_summary">提醒来自陌生人的消息与通话。</string>
     <string name="received_message_from_stranger">已收到陌生人的信息</string>
     <string name="block_stranger">封禁陌生人</string>
     <string name="block_entire_domain">封禁整个域名</string>
@@ -711,7 +719,7 @@
     <string name="medium">中</string>
     <string name="large">大</string>
     <string name="not_encrypted_for_this_device">消息未对本设备加密。</string>
-    <string name="omemo_decryption_failed">解密OMEMO消息失败</string>
+    <string name="omemo_decryption_failed">解密OMEMO消息失败。</string>
     <string name="undo">撤销</string>
     <string name="location_disabled">位置分享已停用</string>
     <string name="action_fix_to_location">固定位置</string>
@@ -773,42 +781,42 @@
     <string name="video_720p">高(720p)</string>
     <string name="cancelled">已取消</string>
     <string name="already_drafting_message">你已经在起草一条消息了。</string>
-    <string name="feature_not_implemented">功能不支持。</string>
+    <string name="feature_not_implemented">功能未实现</string>
     <string name="invalid_country_code">无效国家代码</string>
     <string name="choose_a_country">选择国家</string>
     <string name="phone_number">手机号</string>
     <string name="verify_your_phone_number">验证手机号</string>
     <string name="enter_country_code_and_phone_number">Quicksy将发送验证码短信(运营商可能收费)。请输入国家代码和手机号:</string>
     <string name="we_will_be_verifying"><![CDATA[我们将验证<br/><br/><b>%s</b><br/><br/>。电话号码正确吗?]]></string>
-    <string name="not_a_valid_phone_number">%s不是有效的电话号码</string>
+    <string name="not_a_valid_phone_number">%s不是有效的电话号码。</string>
     <string name="please_enter_your_phone_number">请输入手机号。</string>
     <string name="search_countries">搜索国家</string>
     <string name="verify_x">验证%s</string>
     <string name="we_have_sent_you_an_sms_to_x"><![CDATA[短信已发至 <b>%s</b>。]]></string>
-    <string name="we_have_sent_you_another_sms">已重新发送6位数验证码短信</string>
-    <string name="please_enter_pin_below">输入6位数的PIN</string>
+    <string name="we_have_sent_you_another_sms">已发送另一条6位数验证码短信。</string>
+    <string name="please_enter_pin_below">请在下方输入6位数的PIN。</string>
     <string name="resend_sms">重新发送短信</string>
     <string name="resend_sms_in">重发短信(%s)</string>
     <string name="wait_x">请稍候(%s)</string>
     <string name="back">返回</string>
-    <string name="possible_pin">已自动从剪贴板粘贴验证码</string>
-    <string name="please_enter_pin">请输入6位代码</string>
+    <string name="possible_pin">自动从剪贴板粘贴了可能是PIN码的数据。</string>
+    <string name="please_enter_pin">请输入6位数PIN码。</string>
     <string name="abort_registration_procedure">确定放弃注册?</string>
     <string name="yes">是</string>
     <string name="no">否</string>
-    <string name="verifying">正在验证...</string>
-    <string name="requesting_sms">请求短信...</string>
+    <string name="verifying">正在验证…</string>
+    <string name="requesting_sms">正请求短信…</string>
     <string name="incorrect_pin">验证码错误。</string>
-    <string name="pin_expired">验证码已失效</string>
-    <string name="unknown_api_error_network">未知网络错误</string>
-    <string name="unknown_api_error_response">未知服务器应答</string>
+    <string name="pin_expired">我们发给你的PIN码已失效。</string>
+    <string name="unknown_api_error_network">未知网络错误。</string>
+    <string name="unknown_api_error_response">未知服务器响应。</string>
     <string name="unable_to_connect_to_server">无法连接服务器。</string>
     <string name="unable_to_establish_secure_connection">无法建立安全连接。</string>
-    <string name="unable_to_find_server">找不到服务器</string>
-    <string name="something_went_wrong_processing_your_request">处理请求时出错</string>
+    <string name="unable_to_find_server">找不到服务器。</string>
+    <string name="something_went_wrong_processing_your_request">处理请求时出错。</string>
     <string name="invalid_user_input">用户输入无效</string>
     <string name="temporarily_unavailable">暂时无法连接。请稍候再试。</string>
-    <string name="no_network_connection">无网络连接</string>
+    <string name="no_network_connection">无网络连接.</string>
     <string name="try_again_in_x">请在%s后重试</string>
     <string name="rate_limited">你被限制速率</string>
     <string name="too_many_attempts">尝试次数过多</string>
@@ -822,16 +830,16 @@
     <string name="reject_request">拒绝请求</string>
     <string name="install_orbot">安装Orbot</string>
     <string name="start_orbot">启动Orbot</string>
-    <string name="no_market_app_installed">软件商店未安装</string>
+    <string name="no_market_app_installed">未安装应用商店。</string>
     <string name="group_chat_will_make_your_jabber_id_public">此频道将公开你的XMPP地址</string>
     <string name="ebook">电子书</string>
     <string name="video_original">原始(未压缩)</string>
-    <string name="open_with">打开方式</string>
-    <string name="set_profile_picture">聊天头像</string>
+    <string name="open_with">打开方式…</string>
+    <string name="set_profile_picture">Conversations 个人资料图片</string>
     <string name="choose_account">选择账户</string>
     <string name="restore_backup">恢复备份</string>
     <string name="restore">恢复</string>
-    <string name="enter_password_to_restore">输入%s的密码以恢复备份</string>
+    <string name="enter_password_to_restore">输入%s账户的密码以恢复备份。</string>
     <string name="restore_warning">请勿使用恢复备份功能来尝试克隆安装的应用程序(同时运行)。恢复备份功能仅用于迁移或丢失原始设备的情况。</string>
     <string name="unable_to_restore_backup">无法恢复备份。</string>
     <string name="unable_to_decrypt_backup">无法解密备份。密码是否正确?</string>
@@ -843,24 +851,24 @@
     <string name="create_public_channel">创建公开频道</string>
     <string name="create_dialog_channel_name">频道名称</string>
     <string name="xmpp_address">XMPP地址</string>
-    <string name="please_enter_name">请为频道提供一个名称。</string>
-    <string name="please_enter_xmpp_address">请提供XMPP地址。</string>
+    <string name="please_enter_name">请提供频道名</string>
+    <string name="please_enter_xmpp_address">请提供XMPP地址</string>
     <string name="this_is_an_xmpp_address">这是一个XMPP地址。请提供一个名称。</string>
-    <string name="creating_channel">创建公开频道</string>
+    <string name="creating_channel">创建公开频道…</string>
     <string name="channel_already_exists">频道已存在</string>
     <string name="joined_an_existing_channel">您加入了一个已经存在的频道</string>
     <string name="unable_to_set_channel_configuration">无法配置频道</string>
     <string name="allow_participants_to_edit_subject">允许任何成员修改主题</string>
     <string name="allow_participants_to_invite_others">允许任何成员邀请其他人</string>
-    <string name="anyone_can_edit_subject">允许任何成员修改主题</string>
-    <string name="owners_can_edit_subject">拥有者可修改主题</string>
-    <string name="admins_can_edit_subject">管理员可修改主题</string>
-    <string name="owners_can_invite_others">所有者可以邀请其他人</string>
-    <string name="anyone_can_invite_others">允许任何成员邀请其他人</string>
+    <string name="anyone_can_edit_subject">任何人可以编辑话题。</string>
+    <string name="owners_can_edit_subject">所有者可修改话题。</string>
+    <string name="admins_can_edit_subject">管理员可修改话题。</string>
+    <string name="owners_can_invite_others">所有者可以邀请其他人。</string>
+    <string name="anyone_can_invite_others">允许任何成员邀请其他人。</string>
     <string name="jabber_ids_are_visible_to_admins">XMPP地址对管理员可见。</string>
-    <string name="jabber_ids_are_visible_to_anyone">XMPP地址对所有人可见</string>
+    <string name="jabber_ids_are_visible_to_anyone">XMPP 地址对所有人可见。</string>
     <string name="no_users_hint_channel">此公开频道无成员。邀请成员或使用分享按钮分享地址。</string>
-    <string name="no_users_hint_group_chat">此私密群聊无成员</string>
+    <string name="no_users_hint_group_chat">此私密群聊无成员。</string>
     <string name="manage_permission">管理权限</string>
     <string name="search_participants">搜索成员</string>
     <string name="file_too_large">文件过大</string>
@@ -883,8 +891,8 @@
     <string name="account_already_setup">账户已设置</string>
     <string name="please_enter_password">请输入此账户的密码</string>
     <string name="unable_to_perform_this_action">无法执行此操作</string>
-    <string name="open_join_dialog">加入公开频道</string>
-    <string name="sharing_application_not_grant_permission">分享程序没有访问文件的权限</string>
+    <string name="open_join_dialog">加入公开频道…</string>
+    <string name="sharing_application_not_grant_permission">分享程序没有访问文件的权限。</string>
     <string name="group_chats_and_channels"><![CDATA[群聊与频道]]> </string>
     <string name="jabber_network">jabber.network</string>
     <string name="local_server">本地服务器</string>
@@ -939,7 +947,7 @@
     <string name="help">帮助</string>
     <string name="switch_to_conversation">切换到对话</string>
     <string name="microphone_unavailable">麦克风不可用</string>
-    <string name="only_one_call_at_a_time">只能同时打一通电话</string>
+    <string name="only_one_call_at_a_time">一次只能打一通电话。</string>
     <string name="return_to_ongoing_call">返回正在进行的通话</string>
     <string name="could_not_switch_camera">无法切换摄像头</string>
     <string name="add_to_favorites">置顶</string>
@@ -972,7 +980,7 @@
     <string name="server_does_not_support_easy_onboarding_invites">服务器不支持生成邀请</string>
     <string name="no_active_accounts_support_this">没有活跃帐户支持此功能</string>
     <string name="backup_started_message">已启动备份。一旦完成,你会收到通知。</string>
-    <string name="unable_to_enable_video">无法启用视频</string>
+    <string name="unable_to_enable_video">无法启用视频。</string>
     <string name="plain_text_document">纯文本文档</string>
     <string name="account_registrations_are_not_supported">不支持注册账户</string>
     <string name="no_xmpp_adddress_found">未找到 XMPP 地址</string>
@@ -981,5 +989,4 @@
     <string name="audio_video_disabled_tor">使用 Tor 时通话被禁用</string>
     <string name="switch_to_video">切换到视频</string>
     <string name="reject_switch_to_video">拒绝切换到视频的请求</string>
-
-</resources>
+</resources>

src/main/res/values/about.xml 🔗

@@ -31,7 +31,7 @@
 <resources>
     <string name="pref_about_message" translatable="false">
 			Conversations • the very last word in instant messaging.
-			\n\nCopyright © 2014-2022 Daniel Gultsch
+			\n\nCopyright © 2014-2023 Daniel Gultsch
 			\n\nThis program is free software: you can redistribute it and/or modify
 			it under the terms of the GNU General Public License as published by
 			the Free Software Foundation, either version 3 of the License, or
@@ -42,7 +42,7 @@
 			GNU General Public License for more details.
 			\n\nYou should have received a copy of the GNU General Public License
 			along with this program. If not, see https://www.gnu.org/licenses
-			\n\nDownload the full source code at https://github.com/iNPUTmice/Conversations
+			\n\nDownload the full source code at https://codeberg.org/iNPUTmice/Conversations
 			\n\n\nLibraries
 			\n\nhttps://webrtc.org\nCopyright (c) 2011, The WebRTC project authors. All rights reserved. (https://webrtc.org/support/license)
 			\n\nhttps://github.com/ypresto/android-transcoder\n(Apache License, Version 2.0)

src/quicksy/AndroidManifest.xml 🔗

@@ -2,10 +2,15 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools">
 
+    <uses-permission
+        android:name="android.permission.REQUEST_INSTALL_PACKAGES"
+        tools:node="remove" />
+
     <application
         android:icon="@mipmap/new_launcher"
         tools:ignore="GoogleAppIndexingWarning"
         tools:replace="android:icon">
+
         <activity
             android:name=".ui.EnterPhoneNumberActivity"
             android:label="@string/verify_your_phone_number"

src/quicksy/res/values-de/strings.xml 🔗

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-    <string name="pref_notification_grace_period_summary">Zeitspanne, in der Quicksy still bleibt, nachdem es Aktivitäten auf einem anderen Gerät erkannt hat.</string>
-    <string name="pref_never_send_crash_summary">Wenn du Absturzberichte einschickst, hilfst du Quicksy stetig zu verbessern</string>
+    <string name="pref_notification_grace_period_summary">Zeitspanne, in der Quicksy still bleibt, nachdem es Aktivitäten auf einem anderen Gerät erkannt hat</string>
+    <string name="pref_never_send_crash_summary">Mit dem Einsenden von Absturzberichten hilfst du bei der Weiterentwicklung von Quicksy</string>
     <string name="pref_broadcast_last_activity_summary">Informiere deine Kontakte, wann du Quicksy nutzt</string>
     <string name="huawei_protected_apps_summary">Um weiterhin Benachrichtigungen zu erhalten, auch wenn der Bildschirm ausgeschaltet ist, musst du Quicksy zur Liste der geschützten Apps hinzufügen.</string>
     <string name="set_profile_picture">Quicksy Profilbild</string>
@@ -9,4 +9,4 @@
     <string name="unable_to_verify_server_identity">Überprüfung der Serveridentität ist nicht möglich.</string>
     <string name="unknown_security_error">Unbekannter Sicherheitsfehler.</string>
     <string name="timeout_while_connecting_to_server">Zeitüberschreitung bei der Verbindung zum Server.</string>
-</resources>
+</resources>

src/quicksy/res/values-es/strings.xml 🔗

@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-    <string name="pref_notification_grace_period_summary">Periodo de tiempo en el que Quicksy deshabilita las notificaciones tras ver que tienes actividad en otro dispositivo</string>
-    <string name="pref_never_send_crash_summary">Si envías registros de error ayudas al desarrollo de Quicksy</string>
+    <string name="pref_notification_grace_period_summary">Cuánto tiempo Quicksy permanece en silencio después de detectar una actividad en otro dispositivo</string>
+    <string name="pref_never_send_crash_summary">Si elige enviar un informe de error, estará ayudando al desarrollo de Quicksy</string>
     <string name="pref_broadcast_last_activity_summary">Informar a tus contactos cuando usas Quicksy</string>
-    <string name="huawei_protected_apps_summary">Para seguir recibiendo notificaciones, incluso cuando la pantalla está apagada, necesitas añadir Quicksy a la lista de aplicaciones protegidas.</string>
-    <string name="set_profile_picture">Foto de perfil en Quicksy</string>
+    <string name="huawei_protected_apps_summary">Para continuar recibiendo notificaciones incluso cuando la pantalla está apagada, debe agregar Quicksy a la lista de aplicaciones protegidas.</string>
+    <string name="set_profile_picture">Foto de perfil de Quicksy</string>
     <string name="not_available_in_your_country">Quicksy no está disponible en tu país.</string>
     <string name="unable_to_verify_server_identity">No se ha podido verificar la identidad del servidor.</string>
     <string name="unknown_security_error">Error de seguridad desconocido.</string>
     <string name="timeout_while_connecting_to_server">Se ha superado el tiempo máximo de espera conectando al servidor.</string>
-</resources>
+</resources>

src/quicksy/res/values-gl/strings.xml 🔗

@@ -3,10 +3,10 @@
     <string name="pref_notification_grace_period_summary">O período de tempo que Quicksy permanece acalado tras ver actividade noutro dispositivo</string>
     <string name="pref_never_send_crash_summary">Enviando trazas do rexistro estás axudando ao desenvolvemento de Quicksy</string>
     <string name="pref_broadcast_last_activity_summary">Permitir a todos os teus contactos saber cando estás a utilizar Quicksy</string>
-    <string name="huawei_protected_apps_summary">Para seguir recibindo notificacións, mesmo coa pantalla apagada, precisas engadir a Quicksy na lista de apps protexidas.</string>
+    <string name="huawei_protected_apps_summary">Para seguir recibindo notificacións, mesmo coa pantalla apagada, tes que engadir a Quicksy á lista de apps protexidas.</string>
     <string name="set_profile_picture">Imaxe de perfil Quicksy</string>
     <string name="not_available_in_your_country">Quicksy non está dispoñible no teu país.</string>
     <string name="unable_to_verify_server_identity">Non se puido verificar a identidade do servidor.</string>
     <string name="unknown_security_error">Fallo de seguridade descoñecido.</string>
     <string name="timeout_while_connecting_to_server">Caducou a conexión mentras conectaba co servidor.</string>
-</resources>
+</resources>

src/quicksy/res/values-hr/strings.xml 🔗

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="pref_notification_grace_period_summary">Duljina vremena u kojem Quicksy šuti nakon što vidi aktivnost na drugom uređaju</string>
+    <string name="pref_never_send_crash_summary">Slanjem tragova hrpe pomažete tekući razvoj Quicksyja</string>
+    <string name="pref_broadcast_last_activity_summary">Obavijestite sve svoje kontakte kada koristite Quicksy</string>
+    <string name="huawei_protected_apps_summary">Kako biste nastavili primati obavijesti, čak i kada je ekran isključen, trebate dodati Quicksy na popis zaštićenih aplikacija.</string>
+    <string name="set_profile_picture">Quicksy profilna slika</string>
+    <string name="not_available_in_your_country">Quicksy nije dostupan u vašoj zemlji.</string>
+    <string name="unable_to_verify_server_identity">Nije moguće potvrditi identitet poslužitelja.</string>
+    <string name="unknown_security_error">Nepoznata sigurnosna pogreška.</string>
+    <string name="timeout_while_connecting_to_server">Istek vremena tijekom povezivanja s poslužiteljem.</string>
+</resources>

src/quicksy/res/values-zh-rCN/strings.xml 🔗

@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
     <string name="pref_notification_grace_period_summary">发现在其它设备上的活动后,Conversations保持安静的时间</string>
-    <string name="pref_never_send_crash_summary">通过发送堆栈跟踪,您可以帮助Quicksy持续发展</string>
+    <string name="pref_never_send_crash_summary">通过发送堆栈跟踪,您可以帮助 Quicksy 的持续开发</string>
     <string name="pref_broadcast_last_activity_summary">让你的所有联系人知道你使用Quicksy的时间</string>
-    <string name="huawei_protected_apps_summary">为了在屏幕关闭时也能收到消息提醒,您需要将Quicksy加入受保护的应用列表。</string>
-    <string name="set_profile_picture">Quicksy个人资料图片</string>
+    <string name="huawei_protected_apps_summary">为了在屏幕关闭时也能收到消息提醒,您需要将 Quicksy 加入受保护的应用列表。</string>
+    <string name="set_profile_picture">Quicksy 个人资料图片</string>
     <string name="not_available_in_your_country">Quicksy在您的国家无服务。</string>
-    <string name="unable_to_verify_server_identity">无法确认服务器身份</string>
-    <string name="unknown_security_error">未知安全错误</string>
-    <string name="timeout_while_connecting_to_server">服务器已超时</string>
-</resources>
+    <string name="unable_to_verify_server_identity">无法验证服务器身份。</string>
+    <string name="unknown_security_error">未知安全错误。</string>
+    <string name="timeout_while_connecting_to_server">连接到服务器时超时。</string>
+</resources>