Merge tag '2.10.1' into develop

This commit is contained in:
genofire 2021-10-13 18:14:50 +02:00
commit 5a7bae592d
46 changed files with 960 additions and 712 deletions

View File

@ -1,5 +1,10 @@
# Changelog
### Version 2.10.1
* Fix issue with some videos not being compressed
* Fix rare crash when opening notification
### Version 2.10.0
* Show black bars when remote video does not match aspect ratio of screen

View File

@ -1,5 +1,3 @@
import com.android.build.OutputFile
// Top-level build file where you can add configuration options common to all
// sub-projects/modules.
buildscript {
@ -46,12 +44,12 @@ dependencies {
quicksyPlaystoreSystemImplementation 'com.google.android.gms:play-services-auth-api-phone:17.5.1'
implementation 'org.sufficientlysecure:openpgp-api:10.0'
implementation 'com.theartofdev.edmodo:android-image-cropper:2.8.0'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'androidx.exifinterface:exifinterface:1.3.3'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'androidx.emoji:emoji:1.1.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'com.google.android.material:material:1.4.0'
compatImplementation 'androidx.emoji:emoji-appcompat:1.1.0'
conversationsFreeCompatImplementation 'androidx.emoji:emoji-bundled:1.1.0'
quicksyFreeCompatImplementation 'androidx.emoji:emoji-bundled:1.1.0'
@ -64,7 +62,8 @@ dependencies {
implementation 'org.whispersystems:signal-protocol-java:2.6.2'
implementation 'com.makeramen:roundedimageview:2.3.0'
implementation "com.wefika:flowlayout:0.4.1"
implementation 'net.ypresto.androidtranscoder:android-transcoder:0.3.0'
implementation 'com.otaliastudios:transcoder:0.10.4'
implementation 'org.jxmpp:jxmpp-jid:1.0.1'
implementation 'org.osmdroid:osmdroid-android:6.1.10'
implementation 'org.hsluv:hsluv:0.2'
@ -93,8 +92,8 @@ android {
defaultConfig {
minSdkVersion 21
targetSdkVersion 29
versionCode 42018
versionName "2.10.0"
versionCode 42022
versionName "2.10.1"
archivesBaseName += "-$versionName"
applicationId "eu.sum7.conversations"
resValue "string", "applicationId", applicationId
@ -265,7 +264,7 @@ android {
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
def baseAbiVersionCode = project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))
def baseAbiVersionCode = project.ext.abiCodes.get(output.getFilter(com.android.build.OutputFile.ABI))
if (baseAbiVersionCode != null) {
output.versionCodeOverride = (100 * variant.versionCode) + baseAbiVersionCode
}

View File

@ -0,0 +1,3 @@
* Show black bars when remote video does not match aspect ratio of screen
* Improve search performance
* Add setting to prevent screenshots

View File

@ -0,0 +1,2 @@
* Fix issue with some videos not being compressed
* Fix rare crash when opening notification

View File

@ -228,6 +228,7 @@ public class ManageAccountActivity extends XmppActivity implements OnAccountUpda
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (grantResults.length > 0) {
if (allGranted(grantResults)) {
switch (requestCode) {

View File

@ -201,6 +201,7 @@ public class WelcomeActivity extends XmppActivity implements XmppConnectionServi
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
UriHandlerActivity.onRequestPermissionResult(this, requestCode, grantResults);
if (grantResults.length > 0) {
if (allGranted(grantResults)) {

View File

@ -0,0 +1,11 @@
package eu.siacs.conversations.utils;
import android.content.Context;
import eu.siacs.conversations.xmpp.Jid;
public class PhoneNumberUtilWrapper {
public static String toFormattedPhoneNumber(Context context, Jid jid) {
throw new AssertionError("This method is not implemented in Conversations");
}
}

View File

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="pick_a_server">Scegli il tuo provider XMPP</string>
<string name="pick_a_server">Scegli il tuo fornitore XMPP</string>
<string name="use_chat.sum7.eu">Usa chat.sum7.eu</string>
<string name="create_new_account">Crea un nuovo account</string>
<string name="do_you_have_an_account">Possiedi già un account XMPP? Questo succede se stai già usando un diverso client XMPP o hai già usato prima Conversations. In caso negativo puoi creare un account XMPP adesso.
<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="server_select_text">XMPP è una rete di instant messaging indipendente dal provider. Puoi usare questo client con qualsiasi server XMPP.
In ogni caso per facilitare puoi creare facilmente un account su chat.sum7.eu, un provider pensato apposta per essere usato con Conversations.</string>
<string name="magic_create_text_on_x">Sei stato invitato su %1$s. Ti guideremo nel procedimento per creare un account.\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">Sei stato invitato su %1$s. È già stato scelto un nome utente per te. Ti guideremo nel procedimento per creare un account.\nSarai in grado di comunicare con utenti di altri fornitori dando loro l\'indirizzo XMPP completo.</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 chat.sum7.eu, 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>
<string name="improperly_formatted_provisioning">Codice di approvvigionamento formattato male</string>
<string name="tap_share_button_send_invite">Tocca il pulsante condividi per inviare al contatto un invito per %1$s.</string>

View File

@ -2,9 +2,9 @@
<resources>
<string name="pick_a_server">XMPP プロバイダーを選択してください</string>
<string name="use_chat.sum7.eu">chat.sum7.eu を利用する</string>
<string name="create_new_account">しいアカウントを作成</string>
<string name="do_you_have_an_account">XMPP アカウントをお持ちですか?既にほかの XMPP クライアントを利用しているか、 Conv6sations を利用したことがある場合はこちら。初めての方は、今すぐ新しい XMPP アカウントを作成できます。\nヒント: e メールのプロバイダーが XMPP アカウントも提供している場合があります。</string>
<string name="server_select_text">XMPP は、プロバイダーに依存しないインスタントメッセージのプロトコルです。 XMPP サーバーならどこでも、このクライアントを使用することができます。\nよろしければ、 Conv6sations に最適化されたプロバイダー chat.sum7.eu で簡単にアカウントを作成することもできます。</string>
<string name="create_new_account">アカウントを作成</string>
<string name="do_you_have_an_account">XMPP アカウントをお持ちですか?既にほかの XMPP クライアントを利用しているか、 Conversations を利用したことがある場合はこちら。初めての方は、今すぐ新規 XMPP アカウントを作成できます。\nヒント: e メールのプロバイダーが XMPP アカウントも提供している場合があります。</string>
<string name="server_select_text">XMPP は、プロバイダーに依存しないインスタントメッセージのプロトコルです。 XMPP サーバーならどこでも、このクライアントを使用することができます。\nよろしければ、 Conversations に最適化されたプロバイダー chat.sum7.eu で簡単にアカウントを作成することもできます。</string>
<string name="magic_create_text_on_x">%1$s へ招待されました。アカウント作成手順をご案内します。 \n%1$s をプロバイダーに選択してほかのプロバイダーのユーザーと会話するには、 XMPP のフルアドレスを相手にお知らせください。</string>
<string name="magic_create_text_fixed">%1$s へ招待されました。ユーザー名は既に選択されています。アカウント作成手順をご案内します。 \nほかのプロバイダーのユーザーと会話するには、 XMPP のフルアドレスを相手にお知らせください。</string>
<string name="your_server_invitation">サーバーの招待</string>

View File

@ -39,8 +39,6 @@
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-sdk tools:overrideLibrary="net.ypresto.androidtranscoder" />
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
@ -54,7 +52,8 @@
<application
android:allowBackup="false"
android:allowBackup="true"
android:fullBackupContent="@xml/backup_content"
android:appCategory="social"
android:hardwareAccelerated="true"
android:icon="@mipmap/new_launcher"
@ -144,6 +143,14 @@
<data android:scheme="imto" />
<data android:host="jabber" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SENDTO" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="imto" />
<data android:host="xmpp" />
</intent-filter>
</activity>
<activity
android:name=".ui.StartConversationActivity"

View File

@ -17,6 +17,21 @@ import eu.siacs.conversations.xmpp.Jid;
public class JabberIdContact extends AbstractPhoneContact {
private static final String[] PROJECTION = new String[]{ContactsContract.Data._ID,
ContactsContract.Data.DISPLAY_NAME,
ContactsContract.Data.PHOTO_URI,
ContactsContract.Data.LOOKUP_KEY,
ContactsContract.CommonDataKinds.Im.DATA
};
private static final String SELECTION = ContactsContract.Data.MIMETYPE + "=? AND (" + ContactsContract.CommonDataKinds.Im.PROTOCOL + "=? or (" + ContactsContract.CommonDataKinds.Im.PROTOCOL + "=? and " + ContactsContract.CommonDataKinds.Im.CUSTOM_PROTOCOL + "=?))";
private static final String[] SELECTION_ARGS = {
ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE,
String.valueOf(ContactsContract.CommonDataKinds.Im.PROTOCOL_JABBER),
String.valueOf(ContactsContract.CommonDataKinds.Im.PROTOCOL_CUSTOM),
"XMPP"
};
private final Jid jid;
private JabberIdContact(Cursor cursor) throws IllegalArgumentException {
@ -36,38 +51,26 @@ public class JabberIdContact extends AbstractPhoneContact {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
return Collections.emptyMap();
}
final String[] PROJECTION = new String[]{ContactsContract.Data._ID,
ContactsContract.Data.DISPLAY_NAME,
ContactsContract.Data.PHOTO_URI,
ContactsContract.Data.LOOKUP_KEY,
ContactsContract.CommonDataKinds.Im.DATA};
final String SELECTION = "(" + ContactsContract.Data.MIMETYPE + "=\""
+ ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE
+ "\") AND (" + ContactsContract.CommonDataKinds.Im.PROTOCOL
+ "=\"" + ContactsContract.CommonDataKinds.Im.PROTOCOL_JABBER
+ "\")";
final Cursor cursor;
try {
cursor = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI, PROJECTION, SELECTION, null, null);
} catch (Exception e) {
try (final Cursor cursor = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI, PROJECTION, SELECTION, SELECTION_ARGS, null)) {
if (cursor == null) {
return Collections.emptyMap();
}
final HashMap<Jid, JabberIdContact> contacts = new HashMap<>();
while (cursor.moveToNext()) {
try {
final JabberIdContact contact = new JabberIdContact(cursor);
final JabberIdContact preexisting = contacts.put(contact.getJid(), contact);
if (preexisting == null || preexisting.rating() < contact.rating()) {
contacts.put(contact.getJid(), contact);
}
} catch (final IllegalArgumentException e) {
Log.d(Config.LOGTAG, "unable to create jabber id contact");
}
}
return contacts;
} catch (final Exception e) {
Log.d(Config.LOGTAG, "unable to query", e);
return Collections.emptyMap();
}
final HashMap<Jid, JabberIdContact> contacts = new HashMap<>();
while (cursor != null && cursor.moveToNext()) {
try {
final JabberIdContact contact = new JabberIdContact(cursor);
final JabberIdContact preexisting = contacts.put(contact.getJid(), contact);
if (preexisting == null || preexisting.rating() < contact.rating()) {
contacts.put(contact.getJid(), contact);
}
} catch (IllegalArgumentException e) {
Log.d(Config.LOGTAG,"unable to create jabber id contact");
}
}
if (cursor != null) {
cursor.close();
}
return contacts;
}
}

View File

@ -28,6 +28,7 @@ import eu.siacs.conversations.persistance.DatabaseBackend;
import eu.siacs.conversations.services.AvatarService;
import eu.siacs.conversations.services.QuickConversationsService;
import eu.siacs.conversations.utils.JidHelper;
import eu.siacs.conversations.utils.MessageUtils;
import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.chatstate.ChatState;
@ -258,9 +259,22 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
public Message findMessageWithFileAndUuid(final String uuid) {
synchronized (this.messages) {
for (final Message message : this.messages) {
final Transferable transferable = message.getTransferable();
final boolean unInitiatedButKnownSize = MessageUtils.unInitiatedButKnownSize(message);
if (message.getUuid().equals(uuid)
&& message.getEncryption() != Message.ENCRYPTION_PGP
&& (message.isFileOrImage() || message.treatAsDownloadable())) {
&& (message.isFileOrImage() || message.treatAsDownloadable() || unInitiatedButKnownSize || (transferable != null && transferable.getStatus() != Transferable.STATUS_UPLOADING))) {
return message;
}
}
}
return null;
}
public Message findMessageWithUuid(final String uuid) {
synchronized (this.messages) {
for (final Message message : this.messages) {
if (message.getUuid().equals(uuid)) {
return message;
}
}

View File

@ -984,13 +984,28 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
}
if (conversation.getMode() == Conversation.MODE_MULTI) {
final Jid nextCounterpart = conversation.getNextCounterpart();
if (nextCounterpart != null) {
message.setCounterpart(nextCounterpart);
message.setTrueCounterpart(conversation.getMucOptions().getTrueCounterpart(nextCounterpart));
message.setType(isFile ? Message.TYPE_PRIVATE_FILE : Message.TYPE_PRIVATE);
return true;
}
return configurePrivateMessage(conversation, message, nextCounterpart, isFile);
}
return false;
}
public static boolean configurePrivateMessage(final Message message, final Jid counterpart) {
final Conversation conversation;
if (message.conversation instanceof Conversation) {
conversation = (Conversation) message.conversation;
} else {
return false;
}
return configurePrivateMessage(conversation, message, counterpart, false);
}
private static boolean configurePrivateMessage(final Conversation conversation, final Message message, final Jid counterpart, final boolean isFile) {
if (counterpart == null) {
return false;
}
message.setCounterpart(counterpart);
message.setTrueCounterpart(conversation.getMucOptions().getTrueCounterpart(counterpart));
message.setType(isFile ? Message.TYPE_PRIVATE_FILE : Message.TYPE_PRIVATE);
return true;
}
}

View File

@ -131,7 +131,6 @@ public class HttpDownloadConnection implements Transferable {
}
private void download(final boolean interactive) {
Log.d(Config.LOGTAG,"download()",new Exception());
EXECUTOR.execute(new FileDownloader(interactive));
}

View File

@ -536,9 +536,6 @@ public class DatabaseBackend extends SQLiteOpenHelper {
db.execSQL(CREATE_RESOLVER_RESULTS_TABLE);
}
if (oldVersion < 42 && newVersion >= 42) {
db.execSQL("DROP TRIGGER IF EXISTS after_message_delete");
}
if (QuickConversationsService.isQuicksy() && oldVersion < 43 && newVersion >= 43) {
List<Account> accounts = getAccounts(db);
for (Account account : accounts) {
@ -586,14 +583,21 @@ public class DatabaseBackend extends SQLiteOpenHelper {
db.beginTransaction();
db.execSQL("DROP TRIGGER IF EXISTS after_message_insert;");
db.execSQL("DROP TRIGGER IF EXISTS after_message_update;");
db.execSQL("DROP TRIGGER IF EXISTS after_message_delete;");
db.execSQL("DROP TABLE IF EXISTS messages_index;");
// a hack that should not be necessary, but
// there was at least one occurence when SQLite failed at this
db.execSQL("DROP TABLE IF EXISTS messages_index_docsize;");
db.execSQL("DROP TABLE IF EXISTS messages_index_segdir;");
db.execSQL("DROP TABLE IF EXISTS messages_index_segments;");
db.execSQL("DROP TABLE IF EXISTS messages_index_stat;");
db.execSQL(CREATE_MESSAGE_INDEX_TABLE);
db.execSQL(CREATE_MESSAGE_INSERT_TRIGGER);
db.execSQL(CREATE_MESSAGE_UPDATE_TRIGGER);
db.execSQL(CREATE_MESSAGE_DELETE_TRIGGER);
requiresMessageIndexRebuild = true;
db.setTransactionSuccessful();
db.endTransaction();
requiresMessageIndexRebuild = true;
}
}

View File

@ -3,16 +3,19 @@ package eu.siacs.conversations.services;
import android.content.Context;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.preference.PreferenceManager;
import android.util.Log;
import net.ypresto.androidtranscoder.MediaTranscoder;
import net.ypresto.androidtranscoder.format.MediaFormatStrategy;
import androidx.annotation.NonNull;
import com.otaliastudios.transcoder.Transcoder;
import com.otaliastudios.transcoder.TranscoderListener;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@ -23,161 +26,164 @@ import eu.siacs.conversations.entities.DownloadableFile;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.persistance.FileBackend;
import eu.siacs.conversations.ui.UiCallback;
import eu.siacs.conversations.utils.Android360pFormatStrategy;
import eu.siacs.conversations.utils.Android720pFormatStrategy;
import eu.siacs.conversations.utils.MimeUtils;
import eu.siacs.conversations.utils.TranscoderStrategies;
public class AttachFileToConversationRunnable implements Runnable, MediaTranscoder.Listener {
public class AttachFileToConversationRunnable implements Runnable, TranscoderListener {
private final XmppConnectionService mXmppConnectionService;
private final Message message;
private final Uri uri;
private final String type;
private final UiCallback<Message> callback;
private final boolean isVideoMessage;
private final long originalFileSize;
private int currentProgress = -1;
private final XmppConnectionService mXmppConnectionService;
private final Message message;
private final Uri uri;
private final String type;
private final UiCallback<Message> callback;
private final boolean isVideoMessage;
private final long originalFileSize;
private int currentProgress = -1;
AttachFileToConversationRunnable(XmppConnectionService xmppConnectionService, Uri uri, String type, Message message, UiCallback<Message> callback) {
this.uri = uri;
this.type = type;
this.mXmppConnectionService = xmppConnectionService;
this.message = message;
this.callback = callback;
final String mimeType = MimeUtils.guessMimeTypeFromUriAndMime(mXmppConnectionService, uri, type);
final int autoAcceptFileSize = mXmppConnectionService.getResources().getInteger(R.integer.auto_accept_filesize);
this.originalFileSize = FileBackend.getFileSize(mXmppConnectionService,uri);
this.isVideoMessage = (mimeType != null && mimeType.startsWith("video/")) && originalFileSize > autoAcceptFileSize && !"uncompressed".equals(getVideoCompression());
}
AttachFileToConversationRunnable(XmppConnectionService xmppConnectionService, Uri uri, String type, Message message, UiCallback<Message> callback) {
this.uri = uri;
this.type = type;
this.mXmppConnectionService = xmppConnectionService;
this.message = message;
this.callback = callback;
final String mimeType = MimeUtils.guessMimeTypeFromUriAndMime(mXmppConnectionService, uri, type);
final int autoAcceptFileSize = mXmppConnectionService.getResources().getInteger(R.integer.auto_accept_filesize);
this.originalFileSize = FileBackend.getFileSize(mXmppConnectionService, uri);
this.isVideoMessage = (mimeType != null && mimeType.startsWith("video/")) && originalFileSize > autoAcceptFileSize && !"uncompressed".equals(getVideoCompression());
}
boolean isVideoMessage() {
return this.isVideoMessage;
}
boolean isVideoMessage() {
return this.isVideoMessage;
}
private void processAsFile() {
final String path = mXmppConnectionService.getFileBackend().getOriginalPath(uri);
if (path != null && !FileBackend.isPathBlacklisted(path)) {
message.setRelativeFilePath(path);
mXmppConnectionService.getFileBackend().updateFileParams(message);
if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
mXmppConnectionService.getPgpEngine().encrypt(message, callback);
} else {
mXmppConnectionService.sendMessage(message);
callback.success(message);
}
} else {
try {
mXmppConnectionService.getFileBackend().copyFileToPrivateStorage(message, uri, type);
mXmppConnectionService.getFileBackend().updateFileParams(message);
if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
final PgpEngine pgpEngine = mXmppConnectionService.getPgpEngine();
if (pgpEngine != null) {
pgpEngine.encrypt(message, callback);
} else if (callback != null) {
callback.error(R.string.unable_to_connect_to_keychain, null);
}
} else {
mXmppConnectionService.sendMessage(message);
callback.success(message);
}
} catch (FileBackend.FileCopyException e) {
callback.error(e.getResId(), message);
}
}
}
private void processAsFile() {
final String path = mXmppConnectionService.getFileBackend().getOriginalPath(uri);
if (path != null && !FileBackend.isPathBlacklisted(path)) {
message.setRelativeFilePath(path);
mXmppConnectionService.getFileBackend().updateFileParams(message);
if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
mXmppConnectionService.getPgpEngine().encrypt(message, callback);
} else {
mXmppConnectionService.sendMessage(message);
callback.success(message);
}
} else {
try {
mXmppConnectionService.getFileBackend().copyFileToPrivateStorage(message, uri, type);
mXmppConnectionService.getFileBackend().updateFileParams(message);
if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
final PgpEngine pgpEngine = mXmppConnectionService.getPgpEngine();
if (pgpEngine != null) {
pgpEngine.encrypt(message, callback);
} else if (callback != null) {
callback.error(R.string.unable_to_connect_to_keychain, null);
}
} else {
mXmppConnectionService.sendMessage(message);
callback.success(message);
}
} catch (FileBackend.FileCopyException e) {
callback.error(e.getResId(), message);
}
}
}
private void processAsVideo() throws FileNotFoundException {
Log.d(Config.LOGTAG,"processing file as video");
mXmppConnectionService.startForcingForegroundNotification();
message.setRelativeFilePath(message.getUuid() + ".mp4");
final DownloadableFile file = mXmppConnectionService.getFileBackend().getFile(message);
final MediaFormatStrategy formatStrategy = "720".equals(getVideoCompression()) ? new Android720pFormatStrategy() : new Android360pFormatStrategy();
file.getParentFile().mkdirs();
final ParcelFileDescriptor parcelFileDescriptor = mXmppConnectionService.getContentResolver().openFileDescriptor(uri, "r");
if (parcelFileDescriptor == null) {
throw new FileNotFoundException("Parcel File Descriptor was null");
}
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
Future<Void> future = MediaTranscoder.getInstance().transcodeVideo(fileDescriptor, file.getAbsolutePath(), formatStrategy, this);
try {
future.get();
} catch (InterruptedException e) {
throw new AssertionError(e);
} catch (ExecutionException e) {
if (e.getCause() instanceof Error) {
mXmppConnectionService.stopForcingForegroundNotification();
processAsFile();
} else {
Log.d(Config.LOGTAG, "ignoring execution exception. Should get handled by onTranscodeFiled() instead", e);
}
}
}
private void processAsVideo() throws FileNotFoundException {
Log.d(Config.LOGTAG, "processing file as video");
mXmppConnectionService.startForcingForegroundNotification();
message.setRelativeFilePath(message.getUuid() + ".mp4");
final DownloadableFile file = mXmppConnectionService.getFileBackend().getFile(message);
if (Objects.requireNonNull(file.getParentFile()).mkdirs()) {
Log.d(Config.LOGTAG, "created parent directory for video file");
}
@Override
public void onTranscodeProgress(double progress) {
final int p = (int) Math.round(progress * 100);
if (p > currentProgress) {
currentProgress = p;
mXmppConnectionService.getNotificationService().updateFileAddingNotification(p,message);
}
}
final boolean highQuality = "720".equals(getVideoCompression());
@Override
public void onTranscodeCompleted() {
mXmppConnectionService.stopForcingForegroundNotification();
final File file = mXmppConnectionService.getFileBackend().getFile(message);
long convertedFileSize = mXmppConnectionService.getFileBackend().getFile(message).getSize();
Log.d(Config.LOGTAG,"originalFileSize="+originalFileSize+" convertedFileSize="+convertedFileSize);
if (originalFileSize != 0 && convertedFileSize >= originalFileSize) {
if (file.delete()) {
Log.d(Config.LOGTAG,"original file size was smaller. deleting and processing as file");
processAsFile();
return;
} else {
Log.d(Config.LOGTAG,"unable to delete converted file");
}
}
mXmppConnectionService.getFileBackend().updateFileParams(message);
if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
mXmppConnectionService.getPgpEngine().encrypt(message, callback);
} else {
mXmppConnectionService.sendMessage(message);
callback.success(message);
}
}
final Future<Void> future = Transcoder.into(file.getAbsolutePath()).
addDataSource(mXmppConnectionService, uri)
.setVideoTrackStrategy(highQuality ? TranscoderStrategies.VIDEO_720P : TranscoderStrategies.VIDEO_360P)
.setAudioTrackStrategy(highQuality ? TranscoderStrategies.AUDIO_HQ : TranscoderStrategies.AUDIO_MQ)
.setListener(this)
.transcode();
try {
future.get();
} catch (InterruptedException e) {
throw new AssertionError(e);
} catch (ExecutionException e) {
if (e.getCause() instanceof Error) {
mXmppConnectionService.stopForcingForegroundNotification();
processAsFile();
} else {
Log.d(Config.LOGTAG, "ignoring execution exception. Should get handled by onTranscodeFiled() instead", e);
}
}
}
@Override
public void onTranscodeCanceled() {
mXmppConnectionService.stopForcingForegroundNotification();
processAsFile();
}
@Override
public void onTranscodeProgress(double progress) {
final int p = (int) Math.round(progress * 100);
if (p > currentProgress) {
currentProgress = p;
mXmppConnectionService.getNotificationService().updateFileAddingNotification(p, message);
}
}
@Override
public void onTranscodeFailed(Exception e) {
mXmppConnectionService.stopForcingForegroundNotification();
Log.d(Config.LOGTAG,"video transcoding failed",e);
processAsFile();
}
@Override
public void onTranscodeCompleted(int successCode) {
mXmppConnectionService.stopForcingForegroundNotification();
final File file = mXmppConnectionService.getFileBackend().getFile(message);
long convertedFileSize = mXmppConnectionService.getFileBackend().getFile(message).getSize();
Log.d(Config.LOGTAG, "originalFileSize=" + originalFileSize + " convertedFileSize=" + convertedFileSize);
if (originalFileSize != 0 && convertedFileSize >= originalFileSize) {
if (file.delete()) {
Log.d(Config.LOGTAG, "original file size was smaller. deleting and processing as file");
processAsFile();
return;
} else {
Log.d(Config.LOGTAG, "unable to delete converted file");
}
}
mXmppConnectionService.getFileBackend().updateFileParams(message);
if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
mXmppConnectionService.getPgpEngine().encrypt(message, callback);
} else {
mXmppConnectionService.sendMessage(message);
callback.success(message);
}
}
@Override
public void run() {
if (this.isVideoMessage()) {
try {
processAsVideo();
} catch (FileNotFoundException e) {
processAsFile();
}
} else {
processAsFile();
}
}
@Override
public void onTranscodeCanceled() {
mXmppConnectionService.stopForcingForegroundNotification();
processAsFile();
}
private String getVideoCompression() {
return getVideoCompression(mXmppConnectionService);
}
@Override
public void onTranscodeFailed(@NonNull @NotNull Throwable exception) {
mXmppConnectionService.stopForcingForegroundNotification();
Log.d(Config.LOGTAG, "video transcoding failed", exception);
processAsFile();
}
public static String getVideoCompression(final Context context) {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
return preferences.getString("video_compression", context.getResources().getString(R.string.video_compression));
}
@Override
public void run() {
if (this.isVideoMessage()) {
try {
processAsVideo();
} catch (FileNotFoundException e) {
processAsFile();
}
} else {
processAsFile();
}
}
private String getVideoCompression() {
return getVideoCompression(mXmppConnectionService);
}
public static String getVideoCompression(final Context context) {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
return preferences.getString("video_compression", context.getResources().getString(R.string.video_compression));
}
}

View File

@ -35,6 +35,7 @@ import androidx.core.content.ContextCompat;
import androidx.core.graphics.drawable.IconCompat;
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
import java.io.File;
import java.io.IOException;
@ -407,7 +408,7 @@ public class NotificationService {
currentInterruptionFilter = 1; //INTERRUPTION_FILTER_ALL
}
if (currentInterruptionFilter != 1) {
Log.d(Config.LOGTAG,"do not ring or vibrate because interruption filter has been set to "+currentInterruptionFilter);
Log.d(Config.LOGTAG, "do not ring or vibrate because interruption filter has been set to " + currentInterruptionFilter);
return;
}
final ScheduledFuture<?> currentVibrationFuture = this.vibrationFuture;
@ -424,13 +425,13 @@ public class NotificationService {
final Resources resources = mXmppConnectionService.getResources();
final String ringtonePreference = preferences.getString("call_ringtone", resources.getString(R.string.incoming_call_ringtone));
if (Strings.isNullOrEmpty(ringtonePreference)) {
Log.d(Config.LOGTAG,"ringtone has been set to none");
Log.d(Config.LOGTAG, "ringtone has been set to none");
return;
}
final Uri uri = Uri.parse(ringtonePreference);
this.currentlyPlayingRingtone = RingtoneManager.getRingtone(mXmppConnectionService, uri);
if (this.currentlyPlayingRingtone == null) {
Log.d(Config.LOGTAG,"unable to find ringtone for uri "+uri);
Log.d(Config.LOGTAG, "unable to find ringtone for uri " + uri);
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
@ -790,17 +791,18 @@ public class NotificationService {
.setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_MARK_AS_READ)
.setShowsUserInterface(false)
.build();
String replyLabel = mXmppConnectionService.getString(R.string.reply);
NotificationCompat.Action replyAction = new NotificationCompat.Action.Builder(
final String replyLabel = mXmppConnectionService.getString(R.string.reply);
final String lastMessageUuid = Iterables.getLast(messages).getUuid();
final NotificationCompat.Action replyAction = new NotificationCompat.Action.Builder(
R.drawable.ic_send_text_offline,
replyLabel,
createReplyIntent(conversation, false))
createReplyIntent(conversation, lastMessageUuid, false))
.setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_REPLY)
.setShowsUserInterface(false)
.addRemoteInput(remoteInput).build();
NotificationCompat.Action wearReplyAction = new NotificationCompat.Action.Builder(R.drawable.ic_wear_reply,
final NotificationCompat.Action wearReplyAction = new NotificationCompat.Action.Builder(R.drawable.ic_wear_reply,
replyLabel,
createReplyIntent(conversation, true)).addRemoteInput(remoteInput).build();
createReplyIntent(conversation, lastMessageUuid, true)).addRemoteInput(remoteInput).build();
mBuilder.extend(new NotificationCompat.WearableExtender().addAction(wearReplyAction));
int addedActionsCount = 1;
mBuilder.addAction(markReadAction);
@ -1066,13 +1068,14 @@ public class NotificationService {
return PendingIntent.getService(mXmppConnectionService, 0, intent, 0);
}
private PendingIntent createReplyIntent(Conversation conversation, boolean dismissAfterReply) {
private PendingIntent createReplyIntent(final Conversation conversation, final String lastMessageUuid, final boolean dismissAfterReply) {
final Intent intent = new Intent(mXmppConnectionService, XmppConnectionService.class);
intent.setAction(XmppConnectionService.ACTION_REPLY_TO_CONVERSATION);
intent.putExtra("uuid", conversation.getUuid());
intent.putExtra("dismiss_notification", dismissAfterReply);
intent.putExtra("last_message_uuid", lastMessageUuid);
final int id = generateRequestCode(conversation, dismissAfterReply ? 12 : 14);
return PendingIntent.getService(mXmppConnectionService, id, intent, 0);
return PendingIntent.getService(mXmppConnectionService, id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
private PendingIntent createReadPendingIntent(Conversation conversation) {

View File

@ -726,6 +726,7 @@ public class XmppConnectionService extends Service {
}
final CharSequence body = remoteInput.getCharSequence("text_reply");
final boolean dismissNotification = intent.getBooleanExtra("dismiss_notification", false);
final String lastMessageUuid = intent.getStringExtra("last_message_uuid");
if (body == null || body.length() <= 0) {
break;
}
@ -734,7 +735,7 @@ public class XmppConnectionService extends Service {
restoredFromDatabaseLatch.await();
final Conversation c = findConversationByUuid(uuid);
if (c != null) {
directReply(c, body.toString(), dismissNotification);
directReply(c, body.toString(), lastMessageUuid, dismissNotification);
}
} catch (InterruptedException e) {
Log.d(Config.LOGTAG, "unable to process direct reply");
@ -932,8 +933,12 @@ public class XmppConnectionService extends Service {
}
}
private void directReply(Conversation conversation, String body, final boolean dismissAfterReply) {
Message message = new Message(conversation, body, conversation.getNextEncryption());
private void directReply(final Conversation conversation, final String body, final String lastMessageUuid, final boolean dismissAfterReply) {
final Message inReplyTo = lastMessageUuid == null ? null : conversation.findMessageWithUuid(lastMessageUuid);
final Message message = new Message(conversation, body, conversation.getNextEncryption());
if (inReplyTo != null && inReplyTo.isPrivateMessage()) {
Message.configurePrivateMessage(message, inReplyTo.getCounterpart());
}
message.markUnread();
if (message.getEncryption() == Message.ENCRYPTION_PGP) {
getPgpEngine().encrypt(message, new UiCallback<Message>() {

View File

@ -45,6 +45,7 @@ import eu.siacs.conversations.databinding.ActivityContactDetailsBinding;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.ListItem;
import eu.siacs.conversations.services.AbstractQuickConversationsService;
import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate;
import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate;
import eu.siacs.conversations.ui.adapter.MediaAdapter;
@ -58,6 +59,7 @@ import eu.siacs.conversations.utils.AccountUtils;
import eu.siacs.conversations.utils.Compatibility;
import eu.siacs.conversations.utils.Emoticons;
import eu.siacs.conversations.utils.IrregularUnicodeDetector;
import eu.siacs.conversations.utils.PhoneNumberUtilWrapper;
import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.utils.XmppUri;
import eu.siacs.conversations.xml.Namespace;
@ -131,15 +133,31 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
}
private void showAddToPhoneBookDialog() {
final Jid jid = contact.getJid();
final boolean quicksyContact = AbstractQuickConversationsService.isQuicksy()
&& Config.QUICKSY_DOMAIN.equals(jid.getDomain())
&& jid.getLocal() != null;
final String value;
if (quicksyContact) {
value = PhoneNumberUtilWrapper.toFormattedPhoneNumber(this, jid);
} else {
value = jid.toEscapedString();
}
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.action_add_phone_book));
builder.setMessage(getString(R.string.add_phone_book_text, contact.getJid().toEscapedString()));
builder.setMessage(getString(R.string.add_phone_book_text, value));
builder.setNegativeButton(getString(R.string.cancel), null);
builder.setPositiveButton(getString(R.string.add), (dialog, which) -> {
final Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
intent.setType(Contacts.CONTENT_ITEM_TYPE);
intent.putExtra(Intents.Insert.IM_HANDLE, contact.getJid().toEscapedString());
intent.putExtra(Intents.Insert.IM_PROTOCOL, CommonDataKinds.Im.PROTOCOL_JABBER);
if (quicksyContact) {
intent.putExtra(Intents.Insert.PHONE, value);
} else {
intent.putExtra(Intents.Insert.IM_HANDLE, value);
intent.putExtra(Intents.Insert.IM_PROTOCOL, CommonDataKinds.Im.PROTOCOL_JABBER);
//TODO for modern use we want PROTOCOL_CUSTOM and an extra field with a value of 'XMPP'
// however we dont have such a field and thus have to use the legacy PROTOCOL_JABBER
}
intent.putExtra("finishActivityOnSaveCompleted", true);
try {
startActivityForResult(intent, 0);
@ -233,6 +251,7 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (grantResults.length > 0)
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (requestCode == REQUEST_SYNC_CONTACTS && xmppConnectionServiceBound) {

View File

@ -135,6 +135,8 @@ import static eu.siacs.conversations.utils.PermissionUtils.allGranted;
import static eu.siacs.conversations.utils.PermissionUtils.getFirstDenied;
import static eu.siacs.conversations.utils.PermissionUtils.writeGranted;
import org.jetbrains.annotations.NotNull;
public class ConversationFragment extends XmppFragment implements EditMessage.KeyboardListener, MessageAdapter.OnContactPictureLongClicked, MessageAdapter.OnContactPictureClicked {
@ -1580,6 +1582,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
}
if (writeGranted(grantResults, permissions)) {
if (activity != null && activity.xmppConnectionService != null) {
activity.xmppConnectionService.getBitmapCache().evictAll();
activity.xmppConnectionService.restartFileObserver();
}
refresh();
@ -1618,9 +1621,9 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
@SuppressLint("InflateParams")
protected void clearHistoryDialog(final Conversation conversation) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
final AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity());
builder.setTitle(getString(R.string.clear_conversation_history));
final View dialogView = getActivity().getLayoutInflater().inflate(R.layout.dialog_clear_history, null);
final View dialogView = requireActivity().getLayoutInflater().inflate(R.layout.dialog_clear_history, null);
final CheckBox endConversationCheckBox = dialogView.findViewById(R.id.end_conversation_checkbox);
builder.setView(dialogView);
builder.setNegativeButton(getString(R.string.cancel), null);
@ -1638,7 +1641,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
}
protected void muteConversationDialog(final Conversation conversation) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
final AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity());
builder.setTitle(R.string.disable_notifications);
final int[] durations = getResources().getIntArray(R.array.mute_options_durations);
final CharSequence[] labels = new CharSequence[durations.length];
@ -1654,13 +1657,13 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
if (durations[which] == -1) {
till = Long.MAX_VALUE;
} else {
till = System.currentTimeMillis() + (durations[which] * 1000);
till = System.currentTimeMillis() + (durations[which] * 1000L);
}
conversation.setMutedTill(till);
activity.xmppConnectionService.updateConversation(conversation);
activity.onConversationsListItemUpdated();
refresh();
getActivity().invalidateOptionsMenu();
requireActivity().invalidateOptionsMenu();
});
builder.create().show();
}
@ -1692,7 +1695,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
this.activity.xmppConnectionService.updateConversation(conversation);
this.activity.onConversationsListItemUpdated();
refresh();
getActivity().invalidateOptionsMenu();
requireActivity().invalidateOptionsMenu();
}
@ -1702,9 +1705,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
switch (attachmentChoice) {
case ATTACHMENT_CHOICE_CHOOSE_IMAGE:
intent.setAction(Intent.ACTION_GET_CONTENT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
}
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
intent.setType("image/*");
chooser = true;
break;
@ -1722,9 +1723,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
case ATTACHMENT_CHOICE_CHOOSE_FILE:
chooser = true;
intent.setType("*/*");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
}
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setAction(Intent.ACTION_GET_CONTENT);
break;
@ -1807,7 +1806,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
}
private void showErrorMessage(final Message message) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity());
builder.setTitle(R.string.error_message);
final String errorMessage = message.getErrorMessage();
final String[] errorMessageParts = errorMessage == null ? new String[0] : errorMessage.split("\\u001f");
@ -1828,7 +1827,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
private void deleteFile(final Message message) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity());
builder.setNegativeButton(R.string.cancel, null);
builder.setTitle(R.string.delete_file_dialog);
builder.setMessage(R.string.delete_file_dialog_msg);
@ -1962,7 +1961,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
}
@Override
public void onSaveInstanceState(Bundle outState) {
public void onSaveInstanceState(@NotNull Bundle outState) {
super.onSaveInstanceState(outState);
if (conversation != null) {
outState.putString(STATE_CONVERSATION_UUID, conversation.getUuid());
@ -3051,4 +3050,12 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
}
activity.switchToAccount(message.getConversation().getAccount(), fingerprint);
}
private Activity requireActivity() {
final Activity activity = getActivity();
if (activity == null) {
throw new IllegalStateException("Activity not attached");
}
return activity;
}
}

View File

@ -281,6 +281,7 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
UriHandlerActivity.onRequestPermissionResult(this, requestCode, grantResults);
if (grantResults.length > 0) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
@ -429,7 +430,7 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio
private void openConversation(Conversation conversation, Bundle extras) {
final FragmentManager fragmentManager = getFragmentManager();
fragmentManager.executePendingTransactions();
executePendingTransactions(fragmentManager);
ConversationFragment conversationFragment = (ConversationFragment) fragmentManager.findFragmentById(R.id.secondary_fragment);
final boolean mainNeedsRefresh;
if (conversationFragment == null) {
@ -461,6 +462,14 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio
}
}
private static void executePendingTransactions(final FragmentManager fragmentManager) {
try {
fragmentManager.executePendingTransactions();
} catch (final Exception e) {
Log.e(Config.LOGTAG,"unable to execute pending fragment transactions");
}
}
public boolean onXmppUriClicked(Uri uri) {
XmppUri xmppUri = new XmppUri(uri);
if (xmppUri.isValidJid() && !xmppUri.hasFingerprints()) {
@ -529,6 +538,7 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio
@Override
protected void onStart() {
super.onStart();
final int theme = findTheme();
if (this.mTheme != theme) {
this.mSkipBackgroundBinding = true;
@ -537,7 +547,6 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio
this.mSkipBackgroundBinding = false;
}
mRedirectInProcess.set(false);
super.onStart();
}
@Override

View File

@ -147,13 +147,7 @@ public class UriHandlerActivity extends AppCompatActivity {
final String body = xmppUri.getBody();
if (jid != null) {
Class clazz;
try {
clazz = Class.forName("eu.siacs.conversations.ui.ShareViaAccountActivity");
} catch (ClassNotFoundException e) {
clazz = null;
}
final Class<?> clazz = findShareViaAccountClass();
if (clazz != null) {
intent = new Intent(this, clazz);
intent.putExtra("contact", jid.toEscapedString());
@ -164,7 +158,6 @@ public class UriHandlerActivity extends AppCompatActivity {
intent.setData(uri);
intent.putExtra("account", accounts.get(0).toEscapedString());
}
} else {
intent = new Intent(this, ShareWithActivity.class);
intent.setAction(Intent.ACTION_SEND);
@ -191,6 +184,14 @@ public class UriHandlerActivity extends AppCompatActivity {
startActivity(intent);
}
private static Class<?> findShareViaAccountClass() {
try {
return Class.forName("eu.siacs.conversations.ui.ShareViaAccountActivity");
} catch (final ClassNotFoundException e) {
return null;
}
}
private void handleIntent(Intent data) {
if (handled) {
return;
@ -248,7 +249,7 @@ public class UriHandlerActivity extends AppCompatActivity {
}
private static boolean looksLikeJsonObject(final String input) {
final String trimmed = Strings.emptyToNull(input).trim();
final String trimmed = Strings.nullToEmpty(input).trim();
return trimmed.charAt(0) == '{' && trimmed.charAt(trimmed.length() - 1) == '}';
}
}

View File

@ -1,76 +0,0 @@
package eu.siacs.conversations.utils;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.os.Build;
import android.util.Log;
import androidx.annotation.RequiresApi;
import net.ypresto.androidtranscoder.format.MediaFormatExtraConstants;
import net.ypresto.androidtranscoder.format.MediaFormatStrategy;
import net.ypresto.androidtranscoder.format.OutputFormatUnavailableException;
import eu.siacs.conversations.Config;
public class Android360pFormatStrategy implements MediaFormatStrategy {
private static final int LONGER_LENGTH = 640;
private static final int SHORTER_LENGTH = 360;
private static final int DEFAULT_VIDEO_BITRATE = 1000 * 1000;
private static final int DEFAULT_AUDIO_BITRATE = 128 * 1000;
private final int mVideoBitrate;
private final int mAudioBitrate;
private final int mAudioChannels;
public Android360pFormatStrategy() {
mVideoBitrate = DEFAULT_VIDEO_BITRATE;
mAudioBitrate = DEFAULT_AUDIO_BITRATE;
mAudioChannels = 2;
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public MediaFormat createVideoOutputFormat(MediaFormat inputFormat) {
int width = inputFormat.getInteger(MediaFormat.KEY_WIDTH);
int height = inputFormat.getInteger(MediaFormat.KEY_HEIGHT);
int longer, shorter, outWidth, outHeight;
if (width >= height) {
longer = width;
shorter = height;
outWidth = LONGER_LENGTH;
outHeight = SHORTER_LENGTH;
} else {
shorter = width;
longer = height;
outWidth = SHORTER_LENGTH;
outHeight = LONGER_LENGTH;
}
if (longer * 9 != shorter * 16) {
throw new OutputFormatUnavailableException("This video is not 16:9, and is not able to transcode. (" + width + "x" + height + ")");
}
if (shorter <= SHORTER_LENGTH) {
Log.d(Config.LOGTAG, "This video is less or equal to 360p, pass-through. (" + width + "x" + height + ")");
return null;
}
MediaFormat format = MediaFormat.createVideoFormat("video/avc", outWidth, outHeight);
format.setInteger(MediaFormat.KEY_BIT_RATE, mVideoBitrate);
format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 3);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
format.setInteger(MediaFormat.KEY_PROFILE ,MediaCodecInfo.CodecProfileLevel.AVCProfileBaseline);
format.setInteger(MediaFormat.KEY_LEVEL, MediaCodecInfo.CodecProfileLevel.AVCLevel13);
}
return format;
}
@Override
public MediaFormat createAudioOutputFormat(MediaFormat inputFormat) {
final MediaFormat format = MediaFormat.createAudioFormat(MediaFormatExtraConstants.MIMETYPE_AUDIO_AAC, inputFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE), mAudioChannels);
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
format.setInteger(MediaFormat.KEY_BIT_RATE, mAudioBitrate);
return format;
}
}

View File

@ -1,76 +0,0 @@
package eu.siacs.conversations.utils;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.os.Build;
import android.util.Log;
import androidx.annotation.RequiresApi;
import net.ypresto.androidtranscoder.format.MediaFormatExtraConstants;
import net.ypresto.androidtranscoder.format.MediaFormatStrategy;
import net.ypresto.androidtranscoder.format.OutputFormatUnavailableException;
import eu.siacs.conversations.Config;
public class Android720pFormatStrategy implements MediaFormatStrategy {
private static final int LONGER_LENGTH = 1280;
private static final int SHORTER_LENGTH = 720;
private static final int DEFAULT_VIDEO_BITRATE = 2000 * 1000;
private static final int DEFAULT_AUDIO_BITRATE = 192 * 1000;
private final int mVideoBitrate;
private final int mAudioBitrate;
private final int mAudioChannels;
public Android720pFormatStrategy() {
mVideoBitrate = DEFAULT_VIDEO_BITRATE;
mAudioBitrate = DEFAULT_AUDIO_BITRATE;
mAudioChannels = 2;
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public MediaFormat createVideoOutputFormat(MediaFormat inputFormat) {
int width = inputFormat.getInteger(MediaFormat.KEY_WIDTH);
int height = inputFormat.getInteger(MediaFormat.KEY_HEIGHT);
int longer, shorter, outWidth, outHeight;
if (width >= height) {
longer = width;
shorter = height;
outWidth = LONGER_LENGTH;
outHeight = SHORTER_LENGTH;
} else {
shorter = width;
longer = height;
outWidth = SHORTER_LENGTH;
outHeight = LONGER_LENGTH;
}
if (longer * 9 != shorter * 16) {
throw new OutputFormatUnavailableException("This video is not 16:9, and is not able to transcode. (" + width + "x" + height + ")");
}
if (shorter <= SHORTER_LENGTH) {
Log.d(Config.LOGTAG, "This video is less or equal to 720p, pass-through. (" + width + "x" + height + ")");
return null;
}
MediaFormat format = MediaFormat.createVideoFormat("video/avc", outWidth, outHeight);
format.setInteger(MediaFormat.KEY_BIT_RATE, mVideoBitrate);
format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 3);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
format.setInteger(MediaFormat.KEY_PROFILE ,MediaCodecInfo.CodecProfileLevel.AVCProfileBaseline);
format.setInteger(MediaFormat.KEY_LEVEL, MediaCodecInfo.CodecProfileLevel.AVCLevel13);
}
return format;
}
@Override
public MediaFormat createAudioOutputFormat(MediaFormat inputFormat) {
final MediaFormat format = MediaFormat.createAudioFormat(MediaFormatExtraConstants.MIMETYPE_AUDIO_AAC, inputFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE), mAudioChannels);
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
format.setInteger(MediaFormat.KEY_BIT_RATE, mAudioBitrate);
return format;
}
}

View File

@ -1,5 +1,7 @@
package eu.siacs.conversations.utils;
import com.google.common.io.ByteStreams;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -12,76 +14,108 @@ import eu.siacs.conversations.Config;
public class SocksSocketFactory {
private static final byte[] LOCALHOST = new byte[]{127,0,0,1};
private static final byte[] LOCALHOST = new byte[]{127, 0, 0, 1};
public static void createSocksConnection(final Socket socket, final String destination, final int port) throws IOException {
final InputStream proxyIs = socket.getInputStream();
final OutputStream proxyOs = socket.getOutputStream();
proxyOs.write(new byte[]{0x05, 0x01, 0x00});
proxyOs.flush();
final byte[] handshake = new byte[2];
proxyIs.read(handshake);
if (handshake[0] != 0x05 || handshake[1] != 0x00) {
throw new SocksConnectionException("Socks 5 handshake failed");
}
final byte[] dest = destination.getBytes();
final ByteBuffer request = ByteBuffer.allocate(7 + dest.length);
request.put(new byte[]{0x05, 0x01, 0x00, 0x03});
request.put((byte) dest.length);
request.put(dest);
request.putShort((short) port);
proxyOs.write(request.array());
proxyOs.flush();
final byte[] response = new byte[7 + dest.length];
proxyIs.read(response);
if (response[1] != 0x00) {
if (response[1] == 0x04) {
throw new HostNotFoundException("Host unreachable");
}
if (response[1] == 0x05) {
throw new HostNotFoundException("Connection refused");
}
throw new SocksConnectionException("Unable to connect to destination "+(int) (response[1]));
}
}
public static void createSocksConnection(final Socket socket, final String destination, final int port) throws IOException {
//TODO use different Socks Addr Type if destination is IP or IPv6
final InputStream proxyIs = socket.getInputStream();
final OutputStream proxyOs = socket.getOutputStream();
proxyOs.write(new byte[]{0x05, 0x01, 0x00});
proxyOs.flush();
final byte[] handshake = new byte[2];
ByteStreams.readFully(proxyIs, handshake);
if (handshake[0] != 0x05 || handshake[1] != 0x00) {
throw new SocksConnectionException("Socks 5 handshake failed");
}
final byte[] dest = destination.getBytes();
final ByteBuffer request = ByteBuffer.allocate(7 + dest.length);
request.put(new byte[]{0x05, 0x01, 0x00, 0x03});
request.put((byte) dest.length);
request.put(dest);
request.putShort((short) port);
proxyOs.write(request.array());
proxyOs.flush();
final byte[] response = new byte[4];
ByteStreams.readFully(proxyIs, response);
final byte ver = response[0];
if (ver != 0x05) {
throw new IOException(String.format("Unknown Socks version %02X ", ver));
}
final byte status = response[1];
final byte bndAddrType = response[3];
final byte[] bndDestination = readDestination(bndAddrType, proxyIs);
final byte[] bndPort = new byte[2];
if (bndAddrType == 0x03) {
final String receivedDestination = new String(bndDestination);
if (!receivedDestination.equalsIgnoreCase(destination)) {
throw new IOException(String.format("Destination mismatch. Received %s Expected %s", receivedDestination, destination));
}
}
ByteStreams.readFully(proxyIs, bndPort);
if (status != 0x00) {
if (status == 0x04) {
throw new HostNotFoundException("Host unreachable");
}
if (status == 0x05) {
throw new HostNotFoundException("Connection refused");
}
throw new IOException(String.format("Unknown status code %02X ", status));
}
}
public static boolean contains(byte needle, byte[] haystack) {
for(byte hay : haystack) {
if (hay == needle) {
return true;
}
}
return false;
}
private static byte[] readDestination(final byte type, final InputStream inputStream) throws IOException {
final byte[] bndDestination;
if (type == 0x01) {
bndDestination = new byte[4];
} else if (type == 0x03) {
final int length = inputStream.read();
bndDestination = new byte[length];
} else if (type == 0x04) {
bndDestination = new byte[16];
} else {
throw new IOException(String.format("Unknown Socks address type %02X ", type));
}
ByteStreams.readFully(inputStream, bndDestination);
return bndDestination;
}
private static Socket createSocket(InetSocketAddress address, String destination, int port) throws IOException {
Socket socket = new Socket();
try {
socket.connect(address, Config.CONNECT_TIMEOUT * 1000);
} catch (IOException e) {
throw new SocksProxyNotFoundException();
}
createSocksConnection(socket, destination, port);
return socket;
}
public static boolean contains(byte needle, byte[] haystack) {
for (byte hay : haystack) {
if (hay == needle) {
return true;
}
}
return false;
}
public static Socket createSocketOverTor(String destination, int port) throws IOException {
return createSocket(new InetSocketAddress(InetAddress.getByAddress(LOCALHOST), 9050), destination, port);
}
private static Socket createSocket(InetSocketAddress address, String destination, int port) throws IOException {
Socket socket = new Socket();
try {
socket.connect(address, Config.CONNECT_TIMEOUT * 1000);
} catch (IOException e) {
throw new SocksProxyNotFoundException();
}
createSocksConnection(socket, destination, port);
return socket;
}
private static class SocksConnectionException extends IOException {
SocksConnectionException(String message) {
super(message);
}
}
public static Socket createSocketOverTor(String destination, int port) throws IOException {
return createSocket(new InetSocketAddress(InetAddress.getByAddress(LOCALHOST), 9050), destination, port);
}
public static class SocksProxyNotFoundException extends IOException {
private static class SocksConnectionException extends IOException {
SocksConnectionException(String message) {
super(message);
}
}
}
public static class SocksProxyNotFoundException extends IOException {
public static class HostNotFoundException extends SocksConnectionException {
HostNotFoundException(String message) {
super(message);
}
}
}
public static class HostNotFoundException extends SocksConnectionException {
HostNotFoundException(String message) {
super(message);
}
}
}

View File

@ -0,0 +1,41 @@
package eu.siacs.conversations.utils;
import com.otaliastudios.transcoder.strategy.DefaultAudioStrategy;
import com.otaliastudios.transcoder.strategy.DefaultVideoStrategy;
public final class TranscoderStrategies {
public static final DefaultVideoStrategy VIDEO_720P = DefaultVideoStrategy.atMost(720)
.bitRate(2L * 1000 * 1000)
.frameRate(30)
.keyFrameInterval(3F)
.build();
public static final DefaultVideoStrategy VIDEO_360P = DefaultVideoStrategy.atMost(360)
.bitRate(1000 * 1000)
.frameRate(30)
.keyFrameInterval(3F)
.build();
//TODO do we want to add 240p (@500kbs) and 1080p (@4mbs?) ?
// see suggested bit rates on https://www.videoproc.com/media-converter/bitrate-setting-for-h264.htm
public static final DefaultAudioStrategy AUDIO_HQ = DefaultAudioStrategy.builder()
.bitRate(192 * 1000)
.channels(2)
.sampleRate(DefaultAudioStrategy.SAMPLE_RATE_AS_INPUT)
.build();
public static final DefaultAudioStrategy AUDIO_MQ = DefaultAudioStrategy.builder()
.bitRate(128 * 1000)
.channels(2)
.sampleRate(DefaultAudioStrategy.SAMPLE_RATE_AS_INPUT)
.build();
//TODO if we add 144p we definitely want to add a lower audio bit rate as well
private TranscoderStrategies() {
throw new IllegalStateException("Do not instantiate me");
}
}

View File

@ -4,12 +4,15 @@ import android.net.Uri;
import androidx.annotation.NonNull;
import com.google.common.base.CharMatcher;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
@ -167,7 +170,7 @@ public class XmppUri {
}
}
this.fingerprints = parseFingerprints(parameters);
} else if ("imto".equalsIgnoreCase(scheme)) {
} else if ("imto".equalsIgnoreCase(scheme) && Arrays.asList("xmpp", "jabber").contains(uri.getHost())) {
// sample: imto://xmpp/foo@bar.com
try {
jid = URLDecoder.decode(uri.getEncodedPath(), "UTF-8").split("/")[1].trim();
@ -189,7 +192,10 @@ public class XmppUri {
}
public boolean isAction(final String action) {
return parameters.containsKey(action);
return Collections2.transform(
parameters.keySet(),
s -> CharMatcher.inRange('a', 'z').or(CharMatcher.inRange('A', 'Z')).retainFrom(s)
).contains(action);
}
public Jid getJid() {

View File

@ -314,7 +314,12 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
}
private ListenableFuture<RtpContentMap> receiveRtpContentMap(final JinglePacket jinglePacket, final boolean expectVerification) {
final RtpContentMap receivedContentMap = RtpContentMap.of(jinglePacket);
final RtpContentMap receivedContentMap;
try {
receivedContentMap = RtpContentMap.of(jinglePacket);
} catch (final Exception e) {
return Futures.immediateFailedFuture(e);
}
if (receivedContentMap instanceof OmemoVerifiedRtpContentMap) {
final ListenableFuture<AxolotlService.OmemoVerifiedPayload<RtpContentMap>> future = id.account.getAxolotlService().decrypt((OmemoVerifiedRtpContentMap) receivedContentMap, id.with);
return Futures.transform(future, omemoVerifiedPayload -> {

View File

@ -3,6 +3,8 @@ package eu.siacs.conversations.xmpp.jingle;
import android.os.PowerManager;
import android.util.Log;
import com.google.common.io.ByteStreams;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -58,22 +60,12 @@ public class JingleSocks5Transport extends JingleTransport {
} else {
destBuilder.append(this.connection.getTransportId());
}
if (candidate.getType() == JingleCandidate.TYPE_PROXY) {
if (candidate.isOurs()) {
destBuilder.append(this.account.getJid());
destBuilder.append(this.connection.getId().with);
} else {
destBuilder.append(this.connection.getId().with);
destBuilder.append(this.account.getJid());
}
if (candidate.isOurs()) {
destBuilder.append(this.account.getJid());
destBuilder.append(this.connection.getId().with);
} else {
if (connection.isInitiator()) {
destBuilder.append(this.account.getJid());
destBuilder.append(this.connection.getId().with);
} else {
destBuilder.append(this.connection.getId().with);
destBuilder.append(this.account.getJid());
}
destBuilder.append(this.connection.getId().with);
destBuilder.append(this.account.getJid());
}
messageDigest.reset();
this.destination = CryptoHelper.bytesToHex(messageDigest.digest(destBuilder.toString().getBytes()));
@ -114,26 +106,26 @@ public class JingleSocks5Transport extends JingleTransport {
final byte[] authBegin = new byte[2];
final InputStream inputStream = socket.getInputStream();
final OutputStream outputStream = socket.getOutputStream();
inputStream.read(authBegin);
ByteStreams.readFully(inputStream, authBegin);
if (authBegin[0] != 0x5) {
socket.close();
}
final short methodCount = authBegin[1];
final byte[] methods = new byte[methodCount];
inputStream.read(methods);
ByteStreams.readFully(inputStream, methods);
if (SocksSocketFactory.contains((byte) 0x00, methods)) {
outputStream.write(new byte[]{0x05, 0x00});
} else {
outputStream.write(new byte[]{0x05, (byte) 0xff});
}
byte[] connectCommand = new byte[4];
inputStream.read(connectCommand);
final byte[] connectCommand = new byte[4];
ByteStreams.readFully(inputStream, connectCommand);
if (connectCommand[0] == 0x05 && connectCommand[1] == 0x01 && connectCommand[3] == 0x03) {
int destinationCount = inputStream.read();
final byte[] destination = new byte[destinationCount];
inputStream.read(destination);
ByteStreams.readFully(inputStream, destination);
final byte[] port = new byte[2];
inputStream.read(port);
ByteStreams.readFully(inputStream, port);
final String receivedDestination = new String(destination);
final ByteBuffer response = ByteBuffer.allocate(7 + destination.length);
final byte[] responseHeader;
@ -187,7 +179,7 @@ public class JingleSocks5Transport extends JingleTransport {
socket.setSoTimeout(0);
isEstablished = true;
callback.established();
} catch (IOException e) {
} catch (final IOException e) {
callback.failed();
}
}).start();

View File

@ -159,7 +159,6 @@ public class RtpContentMap {
} else if (description instanceof RtpDescription) {
rtpDescription = (RtpDescription) description;
} else {
Log.d(Config.LOGTAG, "description was " + description);
throw new UnsupportedApplicationException("Content does not contain rtp description");
}
if (transportInfo instanceof IceUdpTransportInfo) {

View File

@ -29,10 +29,17 @@
<string name="just_now">току-що</string>
<string name="minute_ago">преди 1 минута</string>
<string name="minutes_ago">преди %d минути</string>
<plurals name="x_unread_conversations">
<item quantity="one">%d непрочетен разговор</item>
<item quantity="other">%d непрочетени разговора</item>
</plurals>
<string name="sending">изпращане…</string>
<string name="message_decrypting">Дешифроване на съобщението. Моля, изчакайте…</string>
<string name="pgp_message">Съобщение, шифр. чрез OpenPGP</string>
<string name="nick_in_use">Псевдонимът вече се използва</string>
<string name="nick_in_use">Псевдонимът е зает</string>
<string name="invalid_muc_nick">Неправилен псевдоним</string>
<string name="admin">Администратор</string>
<string name="owner">Собственик</string>
@ -63,14 +70,23 @@
<string name="unblock">Деблокиране</string>
<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="send_now">Изпращане сега</string>
<string name="send_never">Не ме питайте повече</string>
<string name="problem_connecting_to_account">Свързването с профила е невъзможно</string>
<string name="problem_connecting_to_accounts">Свързването с няколко профила е невъзможно</string>
<string name="touch_to_fix">Докоснете за управление на профилите си</string>
<string name="attach_file">Прикачане на файл</string>
<string name="not_in_roster">Добавяне на този липсващ контакт към списъка с контакти?</string>
<string name="add_contact">Добавяне на контакт</string>
<string name="send_failed">доставянето се провали</string>
<string name="preparing_image">Изображението се подготвя за изпращане</string>
<string name="preparing_images">Изображенията се подготвят за изпращане</string>
<string name="sharing_files_please_wait">Споделяне на файлове. Моля, изчакайте…</string>
<string name="action_clear_history">Изчистване на историята</string>
<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="also_end_conversation">Затваряне на този разговор след това</string>
@ -81,16 +97,20 @@
<string name="send_omemo_message">Изпр. на съобщение, шифр. чрез OMEMO</string>
<string name="send_omemo_x509_message">Изпр. на съобщение, шифр. чрез v\\OMEMO</string>
<string name="send_pgp_message">Изпр. на съобщение, шифр. чрез OpenPGP</string>
<string name="your_nick_has_been_changed">Новият псевдоним е зает</string>
<string name="send_unencrypted">Изпращане нешифровано</string>
<string name="decryption_failed">Неуспешно дешифроване. Възможно е да нямате правилния частен ключ.</string>
<string name="openkeychain_required">OpenKeychain</string>
<string name="openkeychain_required_long"><![CDATA[%1$s използва <b>OpenKeychain</b>, за да шифрова и дешифрова съобщенията и да управлява публичните Ви ключове.OpenKeychain е с лиценз GPLv3+ и може се свали от F-Droid и Google Play.<br><br><small>(Моля, рестартирайте %1$s след това.)</small>]]></string>
<string name="restart">Рестартиране</string>
<string name="install">Инсталиране</string>
<string name="openkeychain_not_installed">Моля, инсталирайте OpenKeychain</string>
<string name="offering">предлагане…</string>
<string name="waiting">изчакване…</string>
<string name="no_pgp_key">Не е открит OpenPGP ключ</string>
<string name="contact_has_no_pgp_key">Съобщението Ви не може да се шифрова, тъй като контактът Ви не е обявил публичния си ключ.\n\n<small>Моля, помолете го да инсталира и настрои OpenPGP.</small></string>
<string name="no_pgp_keys">Не са открити OpenPGP ключове</string>
<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>
@ -101,12 +121,20 @@
<string name="pref_led">Известие чрез светодиода</string>
<string name="pref_led_summary">Мигане на индикаторния светодиод при получаване на ново съобщение</string>
<string name="pref_ringtone">Тон на звънене</string>
<string name="pref_notification_sound">Звук за известията</string>
<string name="pref_notification_sound_summary">Звук за известията при получаване на нови съобщения</string>
<string name="pref_call_ringtone_summary">Звук за входящи обаждания</string>
<string name="pref_notification_grace_period">Период на пренебрегване</string>
<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">Изпращайки проследявания на стека, Вие помагате на разработката</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="accept">Приемане</string>
<string name="error">Възникна грешка</string>
@ -119,8 +147,11 @@
<string name="attach_take_picture">Заснемане</string>
<string name="preemptively_grant">Предварително позволяване на абониране при заявка</string>
<string name="error_not_an_image_file">Избраният файл не е изображение</string>
<string name="error_compressing_image">Файлът с изображението не може да бъде преобразуван</string>
<string name="error_file_not_found">Файлът не е открит</string>
<string name="error_io_exception">Обща В/И грешка. Може би нямате достатъчно свободно място?</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>
<string name="account_status_online">На линия</string>
@ -132,7 +163,9 @@
<string name="account_status_regis_fail">Неуспешна регистрация</string>
<string name="account_status_regis_conflict">Потребителското име е заето</string>
<string name="account_status_regis_success">Регистрацията е завършена</string>
<string name="account_status_regis_not_sup">Регистрацията не се поддържа от сървъра</string>
<string name="account_status_tls_error">Договарянето чрез TLS беше неуспешно</string>
<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_stream_error">Поточна грешка</string>
@ -147,13 +180,16 @@
<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="mgmt_account_enable">Активиране на профила</string>
<string name="mgmt_account_are_you_sure">Сигурни ли сте?</string>
<string name="mgmt_account_delete_confirm_text">Изтриването на профила Ви ще изтрие и цялата история на разговорите Ви</string>
<string name="attach_record_voice">Запис на глас</string>
<string name="account_settings_jabber_id">XMPP адрес</string>
<string name="account_settings_example_jabber_id">username@example.com</string>
<string name="password">Парола</string>
<string name="invalid_jid">Това не е валиден XMPP адрес</string>
<string name="error_out_of_memory">Няма достатъчно памет. Изображението е твърде голямо.</string>
<string name="add_phone_book_text">Искате ли да добавите %s към адресния си указател?</string>
<string name="server_info_show_more">Инф. за сървъра</string>
<string name="server_info_mam">XEP-0313: Управление на архива на съобщенията</string>
@ -162,6 +198,7 @@
<string name="server_info_blocking">XEP-0191: Команда за блокиране</string>
<string name="server_info_roster_version">XEP-0237: Поддържане на версия на списъка</string>
<string name="server_info_stream_management">XEP-0198: Управление на потоците</string>
<string name="server_info_external_service_discovery">XEP-0215: Откриване на външни услуги</string>
<string name="server_info_pep">XEP-0163: PEP (Аватари / OMEMO)</string>
<string name="server_info_http_upload">XEP-0363: Качване на файл през HTTP</string>
<string name="server_info_push">XEP-0357: Изпращане</string>
@ -169,12 +206,19 @@
<string name="server_info_unavailable">не е налично</string>
<string name="missing_public_keys">Липсват обявления за публичен ключ</string>
<string name="last_seen_now">последно видян току-що</string>
<string name="last_seen_min">последно видян преди една минута</string>
<string name="last_seen_mins">последно видян преди %d минути</string>
<string name="last_seen_hour">последно видян преди час</string>
<string name="last_seen_hours">последно видян преди %d часа</string>
<string name="last_seen_day">последно видян преди ден</string>
<string name="last_seen_days">последно видян преди %d дни</string>
<string name="install_openkeychain">Шифровано съобщение. Моля, инсталирайте OpenKeychain, за да го дешифровате.</string>
<string name="openpgp_messages_found">Открити са нови съобщения, шифровани чрез OpenPGP</string>
<string name="openpgp_key_id">Ид. на OpenPGP ключа</string>
<string name="omemo_fingerprint">Отпечатък OMEMO</string>
<string name="omemo_fingerprint_x509">Отпечатък v\\OMEMO</string>
<string name="omemo_fingerprint_selected_message">Отпечатък OMEMO (източник на съобщението)</string>
<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>
@ -190,11 +234,16 @@
<string name="select">Избиране</string>
<string name="contact_already_exists">Контактът вече съществува</string>
<string name="join">Присъединяване</string>
<string name="channel_full_jid_example">канал@беседа.сървър.com/псевдоним</string>
<string name="channel_bare_jid_example">канал@беседа.сървър.com</string>
<string name="save_as_bookmark">Запазване като отметка</string>
<string name="delete_bookmark">Изтриване на отметка</string>
<string name="destroy_room">Унищожаване на груповия разговор</string>
<string name="destroy_channel">Унищожаване на канала</string>
<string name="destroy_room_dialog">Наистина ли искате да унищожите този групов разговор?\n\n<b>Внимание:</b> Груповият разговор ще бъде премахнат от сървъра.</string>
<string name="destroy_channel_dialog">Наистина ли искате да унищожите този групов канал?\n\n<b>Внимание:</b> Груповият канал ще бъде напълно премахнат от сървъра.</string>
<string name="could_not_destroy_room">Груповият разговор не може да бъде унищожен</string>
<string name="could_not_destroy_channel">Каналът не може да бъде унищожен</string>
<string name="action_edit_subject">Редактиране на темата на груповия разговор</string>
<string name="topic">Тема</string>
<string name="joining_conference">Присъединяване в групов разговор…</string>
@ -203,18 +252,23 @@
<string name="add_back">Добавяне обратно</string>
<string name="contact_has_read_up_to_this_point">%s е прочел до тук</string>
<string name="contacts_have_read_up_to_this_point">%s човека са прочели до тук</string>
<string name="contacts_and_n_more_have_read_up_to_this_point">%1$s и още %2$d човека са прочели до тук</string>
<string name="everyone_has_read_up_to_this_point">Всички са прочели до тук</string>
<string name="publish">Публикуване</string>
<string name="touch_to_choose_picture">Докоснете аватара, за да изберете снимка от галерията</string>
<string name="publishing">Публикуване…</string>
<string name="error_publish_avatar_server_reject">Сървърът отказа Вашето публикуване</string>
<string name="error_publish_avatar_converting">Снимката Ви не може да бъде преобразувана</string>
<string name="error_saving_avatar">Неуспешно запазване на аватара на диска</string>
<string name="or_long_press_for_default">(Или задръжте, за да върнете началното)</string>
<string name="error_publish_avatar_no_server_support">Сървърът Ви не поддържа публикуване на аватари</string>
<string name="private_message">прошепна</string>
<string name="private_message_to">на %s</string>
<string name="send_private_message_to">Изпращане на лично съобщение до %s</string>
<string name="connect">Свързване</string>
<string name="account_already_exists">Този профил вече съществува</string>
<string name="next">Следващо</string>
<string name="server_info_session_established">Установена сесия</string>
<string name="skip">Пропускане</string>
<string name="disable_notifications">Изключване на известията</string>
<string name="enable">Включване</string>

View File

@ -47,8 +47,8 @@
<string name="participant">Participante</string>
<string name="visitor">Visitante</string>
<string name="remove_contact_text">Desexas eliminar a %s da túa lista de contactos? As conversas con este contacto non se eliminarán.</string>
<string name="block_contact_text">Desexa evitar que %s lle envíe mensaxes?</string>
<string name="unblock_contact_text">Desexa desbloquear %s e permitirlles que lle envíen mensaxes?</string>
<string name="block_contact_text">Queres evitar que %s che envíe mensaxes?</string>
<string name="unblock_contact_text">Queres desbloquear a %s e permitirlle que che envíe mensaxes?</string>
<string name="block_domain_text">Bloquear todos os contactos desde 1%s?</string>
<string name="unblock_domain_text">Desbloquear todos os contactos desde 1%s?</string>
<string name="contact_blocked">Contacto bloqueado</string>
@ -58,7 +58,7 @@
<string name="change_password_on_server">Cambiar o contrasinal no servidor</string>
<string name="share_with">Compartir con</string>
<string name="start_conversation">Comezar conversa</string>
<string name="invite_contact">Invitar contacto</string>
<string name="invite_contact">Convidar contacto</string>
<string name="invite">Convidar</string>
<string name="contacts">Contactos</string>
<string name="contact">Contacto</string>
@ -492,7 +492,7 @@
<string name="action_renew_certificate">Anovar certificado</string>
<string name="error_fetching_omemo_key">Fallo obtendo a chave OMEMO!</string>
<string name="verified_omemo_key_with_certificate">Comprobouse a chave OMEMO co certificado!</string>
<string name="device_does_not_support_certificates">O seu dispositivo non admite a selección de certificados do cliente!</string>
<string name="device_does_not_support_certificates">O teu dispositivo non admite a selección de certificados do cliente!</string>
<string name="pref_connection_options">Conexión</string>
<string name="pref_use_tor">Conectar vía Tor</string>
<string name="pref_use_tor_summary">Facer pasar todas as conexións a través da rede Tor. Require Orbot</string>
@ -541,7 +541,7 @@
<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 chat.sum7.eu\nAo escoller chat.sum7.eu como provedor poderás comunicarte con outras usuarias de outros provedores con só darlles o teu enderezo XMPP completo.</string>
<string name="your_full_jid_will_be">O seu enderezo XMPP completo será: %s</string>
<string name="your_full_jid_will_be">O teu enderezo XMPP completo será: %s</string>
<string name="create_account">Crear conta</string>
<string name="use_own_provider">Utilizar o meu propio proveedor</string>
<string name="pick_your_username">Elixe un identificador</string>
@ -554,12 +554,12 @@
<string name="presence_xa">Non dipoñible</string>
<string name="presence_dnd">Ocupada</string>
<string name="secure_password_generated">Xerouse un contrasinal seguro</string>
<string name="device_does_not_support_battery_op">O seu dispositivo non permite non optimizar a batería</string>
<string name="device_does_not_support_battery_op">O teu dispositivo non permite evitar a optimización a batería</string>
<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="invite_again">Invitar de novo</string>
<string name="invite_again">Convidar de novo</string>
<string name="gp_disable">Desactivar</string>
<string name="gp_short">Breve</string>
<string name="gp_medium">Medio</string>
@ -594,7 +594,7 @@
<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="error_publish_avatar_offline">Precisa estar conectada para publicar o seu avatar.</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>
<string name="data_saver_enabled">Aforrador de datos habilitado</string>
@ -783,15 +783,15 @@
<string name="invalid_country_code">Código de país non válido</string>
<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">Valide o seu número de teléfono</string>
<string name="enter_country_code_and_phone_number">Quicsy enviaralle unha mensaxe SMS (poderíanse aplicar cargos) para validar o seu número de teléfono. Introduza o código de país e 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="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 introduza o seu número de teléfono.</string>
<string name="please_enter_your_phone_number">Por favor escribe o teu número de teléfono.</string>
<string name="search_countries">Buscar países</string>
<string name="verify_x">Validar %s</string>
<string name="we_have_sent_you_an_sms_to_x"><![CDATA[Enviámoslle un SMS a <b>%s</b>.]]></string>
<string name="we_have_sent_you_another_sms">Enviamoslle outro SMS con un código de 6 díxitos.</string>
<string name="we_have_sent_you_an_sms_to_x"><![CDATA[Enviámosche un SMS a <b>%s</b>.]]></string>
<string name="we_have_sent_you_another_sms">Enviamosche outro SMS cun código de 6 díxitos.</string>
<string name="please_enter_pin_below">Por favor, introduza o pin de 6 díxitos inferior.</string>
<string name="resend_sms">Reenviar SMS</string>
<string name="resend_sms_in">Reenviar SMS (%s)</string>
@ -805,7 +805,7 @@
<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 lle enviamos caducou.</string>
<string name="pin_expired">O pin que che enviamos caducou.</string>
<string name="unknown_api_error_network">Fallo descoñecido na rede.</string>
<string name="unknown_api_error_response">Resposta descoñecida desde o servidor.</string>
<string name="unable_to_connect_to_server">Non se puido conectar co servidor.</string>
@ -822,9 +822,9 @@
<string name="update">Actualizar</string>
<string name="logged_in_with_another_device">Este número de teléfono está actualmente ligado a outro dispositivo.</string>
<string name="enter_your_name_instructions">Por favor, escribe o teu nome para permitir que a xente que non te ten na axenda de enderezos sepa quen es.</string>
<string name="your_name">O seu nome</string>
<string name="enter_your_name">Introduza o seu nome</string>
<string name="no_name_set_instructions">Utilice o botón editar para escribir o seu nome.</string>
<string name="your_name">O teu nome</string>
<string name="enter_your_name">Escribe o teu nome</string>
<string name="no_name_set_instructions">Establece o teu nome usando o botón editar.</string>
<string name="reject_request">Rexeitar solicitude</string>
<string name="install_orbot">Instalar Orbot</string>
<string name="start_orbot">Iniciar Orbot</string>
@ -834,7 +834,7 @@
<string name="video_original">Orixinal (non comprimido)</string>
<string name="open_with">Abrir con...</string>
<string name="set_profile_picture">Imaxe de perfil en Conversations</string>
<string name="choose_account">Escoller conta</string>
<string name="choose_account">Elexir conta</string>
<string name="restore_backup">Restablecer copia de apoio</string>
<string name="restore">Restablecer</string>
<string name="enter_password_to_restore">Escribe o contrasinal da conta %s para restablecer a copia.</string>

View File

@ -2,13 +2,13 @@
<resources>
<string name="action_settings">Impostazioni</string>
<string name="action_add">Nuova conversazione</string>
<string name="action_accounts">Gestisci account</string>
<string name="action_account">Gestisci account</string>
<string name="action_accounts">Gestisci profili</string>
<string name="action_account">Gestisci profilo</string>
<string name="action_end_conversation">Chiudi conversazione</string>
<string name="action_contact_details">Dettagli del contatto</string>
<string name="action_muc_details">Dettagli chat di gruppo</string>
<string name="channel_details">Dettagli canale</string>
<string name="action_add_account">Aggiungi account</string>
<string name="action_add_account">Aggiungi profilo</string>
<string name="action_edit_contact">Modifica il nome</string>
<string name="action_add_phone_book">Aggiungi alla rubrica</string>
<string name="action_delete_contact">Cancella dalla lista</string>
@ -18,7 +18,7 @@
<string name="action_unblock_domain">Sblocca dominio</string>
<string name="action_block_participant">Blocca partecipante</string>
<string name="action_unblock_participant">Sblocca partecipante</string>
<string name="title_activity_manage_accounts">Gestisci account</string>
<string name="title_activity_manage_accounts">Gestisci profili</string>
<string name="title_activity_settings">Impostazioni</string>
<string name="title_activity_sharewith">Condividi con Conversation</string>
<string name="title_activity_start_conversation">Inizia una conversazione</string>
@ -54,7 +54,7 @@
<string name="contact_blocked">Contatto bloccato</string>
<string name="blocked">Bloccato</string>
<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 account sul server</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="start_conversation">Inizia conversazione</string>
@ -72,12 +72,12 @@
<string name="save">Salva</string>
<string name="ok">OK</string>
<string name="crash_report_title">Errore di %1$s</string>
<string name="crash_report_message">Usare il tuo account XMPP per inviare segnalazioni di errore aiuta lo sviluppo in corso di %1$s.</string>
<string name="crash_report_message">Usare il tuo profilo XMPP per inviare segnalazioni di errore aiuta lo sviluppo in corso di %1$s.</string>
<string name="send_now">Invia adesso</string>
<string name="send_never">Non chiedere più</string>
<string name="problem_connecting_to_account">Impossibile connettersi all\'account</string>
<string name="problem_connecting_to_accounts">Impossibile connettersi a più account</string>
<string name="touch_to_fix">Tocca per gestire i tuoi account</string>
<string name="problem_connecting_to_account">Impossibile connettersi al profilo</string>
<string name="problem_connecting_to_accounts">Impossibile connettersi a più profili</string>
<string name="touch_to_fix">Tocca per gestire i tuoi profili</string>
<string name="attach_file">Allega file</string>
<string name="not_in_roster">Aggiungere questo contatto alla lista dei contatti?</string>
<string name="add_contact">Aggiungi contatto</string>
@ -130,9 +130,9 @@
<string name="pref_advanced_options">Avanzate</string>
<string name="pref_never_send_crash">Non inviare mai segnalazioni di errore</string>
<string name="pref_never_send_crash_summary">Se scegli di inviare una segnalazione dellerrore aiuterai lo sviluppo</string>
<string name="pref_confirm_messages">Conferma messaggi</string>
<string name="pref_confirm_messages">Conferma i messaggi</string>
<string name="pref_confirm_messages_summary">Fai sapere ai tuoi contatti quando hai ricevuto e letto i loro messaggi</string>
<string name="pref_prevent_screenshots">Impedisci cattura schermo</string>
<string name="pref_prevent_screenshots">Impedisci la cattura dello schermo</string>
<string name="pref_prevent_screenshots_summary">Nascondi i contenuti dell\'app nell\'elenco recenti e blocca la cattura delle schermate</string>
<string name="pref_ui_options">Interfaccia utente</string>
<string name="openpgp_error">OpenKeychain ha generato un errore.</string>
@ -140,7 +140,7 @@
<string name="accept">Accetta</string>
<string name="error">Si è verificato un errore</string>
<string name="recording_error">Errore</string>
<string name="your_account">Il tuo account</string>
<string name="your_account">Il tuo profilo</string>
<string name="send_presence_updates">Invia aggiornamenti della presenza</string>
<string name="receive_presence_updates">Ricevi aggiornamenti della presenza</string>
<string name="ask_for_presence_updates">Chiedi aggiornamenti della presenza</string>
@ -155,7 +155,7 @@
<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>
<string name="account_status_online">Online</string>
<string name="account_status_online">In linea</string>
<string name="account_status_connecting">In connessione\u2026</string>
<string name="account_status_offline">Offline</string>
<string name="account_status_unauthorized">Non autorizzato</string>
@ -176,16 +176,16 @@
<string name="encryption_choice_otr">OTR</string>
<string name="encryption_choice_pgp">OpenPGP</string>
<string name="encryption_choice_omemo">OMEMO</string>
<string name="mgmt_account_delete">Elimina utente</string>
<string name="mgmt_account_delete">Elimina profilo</string>
<string name="mgmt_account_disable">Disattiva temporaneamente</string>
<string name="mgmt_account_publish_avatar">Pubblica avatar</string>
<string name="mgmt_account_publish_pgp">Pubblica chiave pubblica OpenPGP</string>
<string name="unpublish_pgp">Rimuovi chiave pubblica OpenPGP</string>
<string name="unpublish_pgp_message">Sei sicuro di volere rimuovere la tua chiave pubblica OpenPGP dalla dichiarazione di presenza?\nI tuoi contatti non potranno più inviarti messaggi cifrati con OpenPGP.</string>
<string name="openpgp_has_been_published">Chiave pubblica OpenPGP pubblicata.</string>
<string name="mgmt_account_enable">Attiva utente</string>
<string name="mgmt_account_enable">Attiva profilo</string>
<string name="mgmt_account_are_you_sure">Sei sicuro?</string>
<string name="mgmt_account_delete_confirm_text">L\'eliminazione del tuo account cancellerà tutta la cronologia dielle conversazioni</string>
<string name="mgmt_account_delete_confirm_text">L\'eliminazione del tuo profilo cancellerà tutta la cronologia dielle conversazioni</string>
<string name="attach_record_voice">Registra la voce</string>
<string name="account_settings_jabber_id">Indirizzo XMPP</string>
<string name="block_jabber_id">Blocca indirizzo XMPP</string>
@ -219,9 +219,9 @@
<string name="openpgp_messages_found">Nuovi messaggi cifrati con OpenPGP trovati</string>
<string name="openpgp_key_id">ID chiave OpenPGP</string>
<string name="omemo_fingerprint">Impronta OMEMO</string>
<string name="omemo_fingerprint_x509">v\\OMEMO impronta</string>
<string name="omemo_fingerprint_selected_message">OMEMO fingerprint (messaggio originatore)</string>
<string name="omemo_fingerprint_x509_selected_message">v\\OMEMO fingerprint (messaggio originatore)</string>
<string name="omemo_fingerprint_x509">v\\Impronta OMEMO</string>
<string name="omemo_fingerprint_selected_message">Impronta OMEMO (origine del messaggio)</string>
<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>
@ -270,7 +270,7 @@
<string name="private_message_to">a %s</string>
<string name="send_private_message_to">Invia messaggio privato a %s</string>
<string name="connect">Connetti</string>
<string name="account_already_exists">Questo utente esiste già</string>
<string name="account_already_exists">Questo profilo esiste già</string>
<string name="next">Successivo</string>
<string name="server_info_session_established">Sessione stabilita</string>
<string name="skip">Salta</string>
@ -285,7 +285,7 @@
<string name="pref_security_settings">Sicurezza</string>
<string name="pref_allow_message_correction">Permetti correzione del messaggio</string>
<string name="pref_allow_message_correction_summary">Consenti ai tuoi contatti di modificare retroattivamente i loro messaggi</string>
<string name="pref_expert_options">Impostazioni esperto</string>
<string name="pref_expert_options">Impostazioni per esperti</string>
<string name="pref_expert_options_summary">Fai attenzione con queste impostazioni</string>
<string name="title_activity_about_x">Informazioni su %s</string>
<string name="title_pref_quiet_hours">Ore di quiete</string>
@ -303,7 +303,7 @@
<string name="conference_kicked">Sei stato buttato fuori da questa chat di gruppo</string>
<string name="conference_shutdown">La chat di gruppo è stata chiusa</string>
<string name="conference_unknown_error">Non sei più in questa chat di gruppo</string>
<string name="using_account">usando laccount %s</string>
<string name="using_account">usando il profilo %s</string>
<string name="hosted_on">ospitato su %s</string>
<string name="checking_x">Controllo %s su host HTTP</string>
<string name="not_connected_try_again">Non sei connesso. Riprova più tardi</string>
@ -322,19 +322,19 @@
<string name="scan_qr_code">Scansiona codice a barre 2D</string>
<string name="show_qr_code">Mostra codice a barre 2D</string>
<string name="show_block_list">Mostra la lista nera</string>
<string name="account_details">Dettagli account</string>
<string name="account_details">Dettagli del profilo</string>
<string name="confirm">Conferma</string>
<string name="try_again">Prova di nuovo</string>
<string name="pref_keep_foreground_service">Servizio in primo piano</string>
<string name="pref_keep_foreground_service_summary">Evita che il sistema operativo chiuda la connessione</string>
<string name="pref_create_backup">Crea backup</string>
<string name="pref_create_backup">Crea un backup</string>
<string name="pref_create_backup_summary">I file di backup verranno salvati in %s</string>
<string name="notification_create_backup_title">Creazione file di backup</string>
<string name="notification_create_backup_title">Creazione dei file di backup</string>
<string name="notification_backup_created_title">Il tuo backup è stato creato</string>
<string name="notification_backup_created_subtitle">I file di backup sono stati salvati in %s</string>
<string name="restoring_backup">Ripristino backup</string>
<string name="notification_restored_backup_title">Il tuo backup è stato ripristinato</string>
<string name="notification_restored_backup_subtitle">Non dimenticare di attivare l\'account.</string>
<string name="notification_restored_backup_subtitle">Non dimenticare di attivare il profilo.</string>
<string name="choose_file">Scegli un file</string>
<string name="receiving_x_file">Ricezione di %1$s file (%2$d%% completato)</string>
<string name="download_x_file">Scarica %s</string>
@ -356,7 +356,7 @@
<string name="enable_notifications">Attiva le notifiche</string>
<string name="no_conference_server_found">Nessun server per chat di gruppo trovato</string>
<string name="conference_creation_failed">Impossibile creare la chat di gruppo</string>
<string name="account_image_description">Avatar utente</string>
<string name="account_image_description">Avatar del profilo</string>
<string name="copy_omemo_clipboard_description">Copia impronta OMEMO negli appunti</string>
<string name="regenerate_omemo_key">Rigenera chiave OMEMO</string>
<string name="clear_other_devices">Pulisci dispositivi</string>
@ -373,8 +373,8 @@
<string name="current_password">Password attuale</string>
<string name="new_password">Nuova password</string>
<string name="password_should_not_be_empty">La password non può essere vuota</string>
<string name="enable_all_accounts">Attiva tutti gli account</string>
<string name="disable_all_accounts">Disattiva tutti gli account</string>
<string name="enable_all_accounts">Attiva tutti i profili</string>
<string name="disable_all_accounts">Disattiva tutti i profili</string>
<string name="perform_action_with">Esegui azione con</string>
<string name="no_affiliation">Nessuna affiliazione</string>
<string name="no_role">Offline</string>
@ -409,7 +409,7 @@
<string name="reply">Rispondi</string>
<string name="mark_as_read">Segna come già letto</string>
<string name="pref_input_options">Input</string>
<string name="pref_enter_is_send">Invio spedisce</string>
<string name="pref_enter_is_send">Il tasto Invio spedisce</string>
<string name="pref_enter_is_send_summary">Usa il tasto Invio per spedire il messaggio. Puoi sempre usare Ctrl+Invio per spedire, anche se questa opzione è disattivata.</string>
<string name="pref_display_enter_key">Mostra il tasto invio</string>
<string name="pref_display_enter_key_summary">Cambia il tasto delle faccine nel tasto di invio</string>
@ -477,7 +477,7 @@
<string name="pref_treat_vibrate_as_silent">Tratta vibrazione come modalità silenziosa</string>
<string name="pref_treat_vibrate_as_dnd_summary">Imposta come occupato quando il dispositivo è in modalità vibrazione</string>
<string name="pref_show_connection_options">Impostazioni estese di connessione</string>
<string name="pref_show_connection_options_summary">Mostra nome host e impostazioni della porta quando configuri un account</string>
<string name="pref_show_connection_options_summary">Mostra nome host e impostazioni della porta quando configuri un profilo</string>
<string name="hostname_example">xmpp.esempio.it</string>
<string name="action_add_account_with_certificate">Accedi con certificato</string>
<string name="unable_to_parse_certificate">Impossibile analizzare il certificato</string>
@ -501,7 +501,7 @@
<string name="hostname_or_onion">Indirizzo server o .onion</string>
<string name="not_a_valid_port">Questo non è un numero di porta valido</string>
<string name="not_valid_hostname">Questo non è un nome host valido</string>
<string name="connected_accounts">%1$d su %2$d account connessi</string>
<string name="connected_accounts">%1$d su %2$d profili connessi</string>
<plurals name="x_messages">
<item quantity="one">%d messaggio</item>
<item quantity="other">%d messaggi</item>
@ -520,7 +520,7 @@
<string name="notify_only_when_highlighted">Notifica solo quando menzionato</string>
<string name="notify_never">Notifiche disattivate</string>
<string name="notify_paused">Notifiche in pausa</string>
<string name="pref_picture_compression">Compressione immagini</string>
<string name="pref_picture_compression">Compressione delle immagini</string>
<string name="pref_picture_compression_summary">Suggerimento: usa \"Scegli un file\" invece di \"Scegli un\'immagine\" per inviare singole immagini non compresse a prescindere da questa impostazione.</string>
<string name="always">Sempre</string>
<string name="large_images_only">Solo immagini grandi</string>
@ -529,27 +529,27 @@
<string name="battery_optimizations_enabled_dialog">Il tuo dispositivo sta facendo delle ingenti ottimizzazioni della batteria per %1$s che potrebbero portare ritardi alle notifiche o anche perdita di messaggi.\n\nTi verrà ora chiesto di disattivarle.</string>
<string name="disable">Disattiva</string>
<string name="selection_too_large">L\'area selezionata è troppo grande</string>
<string name="no_accounts">(Nessun account attivo)</string>
<string name="no_accounts">(Nessun profilo attivo)</string>
<string name="this_field_is_required">Questo campo è obbligatorio</string>
<string name="correct_message">Correggi messaggio</string>
<string name="send_corrected_message">Invia messaggio corretto</string>
<string name="no_keys_just_confirm">Hai già validato l\'impronta di questa persona in modo sicuro per confermarne la fiducia. Selezionando “Fatto” stai solo confermando che %s fa parte di questa chat di gruppo.</string>
<string name="this_account_is_disabled">Hai disattivato questo account</string>
<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="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 account su chat.sum7.eu.\nQuando scegli chat.sum7.eu come fornitore potrai comunicare con utenti di altri fornitori dando il tuo indirizzo XMPP completo.</string>
<string name="magic_create_text">È disponibile una guida per la creazione di un profilo su chat.sum7.eu.\nQuando scegli chat.sum7.eu come fornitore potrai comunicare con utenti di altri fornitori dando il tuo indirizzo XMPP completo.</string>
<string name="your_full_jid_will_be">Il tuo indirizzo XMPP completo sarà: %s</string>
<string name="create_account">Crea account</string>
<string name="use_own_provider">Usa un altro provider</string>
<string name="create_account">Crea profilo</string>
<string name="use_own_provider">Usa un altro fornitore</string>
<string name="pick_your_username">Scegli il tuo nome utente</string>
<string name="pref_manually_change_presence">Gestisci manualmente la disponibilità</string>
<string name="pref_manually_change_presence_summary">Imposta la tua disponibilità quando modifichi il messaggio di stato.</string>
<string name="status_message">Messaggio di stato</string>
<string name="presence_chat">Disponibile a chattare</string>
<string name="presence_online">Online</string>
<string name="presence_online">In linea</string>
<string name="presence_away">Assente</string>
<string name="presence_xa">Non disponibile</string>
<string name="presence_dnd">Occupato</string>
@ -564,7 +564,7 @@
<string name="gp_short">Breve</string>
<string name="gp_medium">Medio</string>
<string name="gp_long">Lungo</string>
<string name="pref_broadcast_last_activity">Trasmissione</string>
<string name="pref_broadcast_last_activity">Trasmetti l\'utilizzo</string>
<string name="pref_broadcast_last_activity_summary">Fa sapere ai tuoi contatti quando usi Conversations</string>
<string name="pref_privacy">Privacy</string>
<string name="pref_theme_options">Tema</string>
@ -573,7 +573,7 @@
<string name="pref_theme_light">Chiaro</string>
<string name="pref_theme_dark">Scuro</string>
<string name="pref_use_green_background">Sfondo verde</string>
<string name="pref_use_green_background_summary">Usa sfondo verde per messaggi ricevuti</string>
<string name="pref_use_green_background_summary">Usa uno sfondo verde per i messaggi ricevuti</string>
<string name="unable_to_connect_to_keychain">Impossibile connettersi a OpenKeychain</string>
<string name="this_device_is_no_longer_in_use">Questo dispositivo non è più in uso</string>
<string name="type_pc">Computer</string>
@ -589,9 +589,9 @@
<string name="no_permission_to_access_x">Nessuna autorizzazione per accedere a %s</string>
<string name="remote_server_not_found">Server remoto non trovato</string>
<string name="remote_server_timeout">Scadenza server remoto</string>
<string name="unable_to_update_account">Impossibile aggiornare l\'account</string>
<string name="unable_to_update_account">Impossibile aggiornare il profilo</string>
<string name="report_jid_as_spammer">Segnala questo indirizzo XMPP per spam.</string>
<string name="pref_delete_omemo_identities">Elimina identità OMEMO</string>
<string name="pref_delete_omemo_identities">Elimina le identità OMEMO</string>
<string name="pref_delete_omemo_identities_summary">Rigenera le tue chiavi OMEMO. I tuoi contatti dovranno verificare un\'altra volta la tua identità. Usalo solo come ultima spiaggia.</string>
<string name="delete_selected_keys">Cancella le chiavi selezionate</string>
<string name="error_publish_avatar_offline">Devi essere connesso per pubblicare l\'avatar.</string>
@ -651,7 +651,7 @@
<item quantity="one">%d mese</item>
<item quantity="other">%d mesi</item>
</plurals>
<string name="pref_automatically_delete_messages">Eliminazione automatica messaggi</string>
<string name="pref_automatically_delete_messages">Eliminazione automatica dei messaggi</string>
<string name="pref_automatically_delete_messages_description">Elimina automaticamente da questo dispositivo i messaggi più vecchi del lasso di tempo configurato.</string>
<string name="encrypting_message">Cifratura del messaggio</string>
<string name="not_fetching_history_retention_period">Nessun recupero di messaggi a causa del periodo di conservazione locale.</string>
@ -706,11 +706,11 @@
<string name="disable_now">Disattiva adesso</string>
<string name="draft">Bozza:</string>
<string name="pref_omemo_setting">Cifratura OMEMO</string>
<string name="pref_omemo_setting_summary_always">OMEMO verrà sempre usato per chat singole e di gruppi privati.</string>
<string name="pref_omemo_setting_summary_always">OMEMO verrà sempre usato per chat singole e gruppi privati.</string>
<string name="pref_omemo_setting_summary_default_on">OMEMO verrà usato in modo predefinito nelle nuove conversazioni.</string>
<string name="pref_omemo_setting_summary_default_off">OMEMO dovrà essere attivato a mano nelle nuove conversazioni.</string>
<string name="create_shortcut">Crea scorciatoia</string>
<string name="pref_font_size">Dimensione carattere</string>
<string name="pref_font_size">Dimensione dei caratteri</string>
<string name="pref_font_size_summary">La dimensione dei caratteri usata all\'interno dell\'app.</string>
<string name="default_on">On in modo predefinito</string>
<string name="default_off">Off in modo predefinito</string>
@ -756,7 +756,7 @@
<string name="foreground_service_channel_description">Questa categoria di notifiche è usata per mostrare una notifica permanente per indicare che %1$s è in esecuzione.</string>
<string name="notification_group_status_information">Informazioni di stato</string>
<string name="error_channel_name">Problemi di connettività</string>
<string name="error_channel_description">Questa categoria di notifiche è usata per mostrare un notifica in caso si verifichi un problema nella connessione ad un account.</string>
<string name="error_channel_description">Questa categoria di notifiche è usata per mostrare un notifica in caso si verifichi un problema nella connessione ad un profilo.</string>
<string name="notification_group_messages">Messaggi</string>
<string name="notification_group_calls">Chiamate</string>
<string name="messages_channel_name">Messaggi</string>
@ -773,7 +773,7 @@
<string name="group_chat_members">Partecipanti</string>
<string name="media_browser">Browser multimediale</string>
<string name="security_violation_not_attaching_file">File omesso per violazione di sicurezza.</string>
<string name="pref_video_compression">Qualità video</string>
<string name="pref_video_compression">Qualità dei video</string>
<string name="pref_video_compression_summary">Una qualità inferiore comporta file più piccoli</string>
<string name="video_360p">Media (360p)</string>
<string name="video_720p">Alta (720p)</string>
@ -834,10 +834,10 @@
<string name="video_original">Originale (non compresso)</string>
<string name="open_with">Apri con…</string>
<string name="set_profile_picture">Immagine profilo di Conversations</string>
<string name="choose_account">Scegli account</string>
<string name="choose_account">Scegli un profilo</string>
<string name="restore_backup">Ripristina backup</string>
<string name="restore">Ripristina</string>
<string name="enter_password_to_restore">Inserisci la tua password per l\'account %s per ripristinare il backup.</string>
<string name="enter_password_to_restore">Inserisci la tua password per il profilo %s per ripristinare il backup.</string>
<string name="restore_warning">Non usare la funzione di ripristino del backup tentando di clonare (eseguire simultaneamente) un\'installazione. Il ripristino di un backup è inteso solo per migrazioni o in caso di smarrimento del dispositivo.</string>
<string name="unable_to_restore_backup">Impossibile ripristinare il backup.</string>
<string name="unable_to_decrypt_backup">Impossibile decifrare il backup. La password è giusta?</string>
@ -874,10 +874,10 @@
<string name="discover_channels">Individua i canali</string>
<string name="search_channels">Cerca i canali</string>
<string name="channel_discovery_opt_in_title">Possibile violazione della privacy!</string>
<string name="channel_discover_opt_in_message"><![CDATA[La scoperta dei canali usa un servizio di terze parti chiamato <a href="https://search.jabber.network">search.jabber.network</a>.<br><br>L\'uso di questa funzione trasmetterà il tuo indirizzo IP e i termini di ricerca a quel servizio. Vedi la loro <a href="https://search.jabber.network/privacy">Informativa sulla Privacy</a> per saperne di più.]]></string>
<string name="i_already_have_an_account">Ho già un account</string>
<string name="add_existing_account">Aggiungi un account pre-esistente</string>
<string name="register_new_account">Registra un nuovo account</string>
<string name="channel_discover_opt_in_message"><![CDATA[La ricerca dei canali usa un servizio di terze parti chiamato <a href=\"https://search.jabber.network\">search.jabber.network</a>.<br><br>L\'uso di questa funzione trasmetterà il tuo indirizzo IP e i termini di ricerca a quel servizio. Vedi la loro <a href=\"https://search.jabber.network/privacy\">informativa sulla privacy</a> per maggiori informazioni.]]></string>
<string name="i_already_have_an_account">Ho già un profilo</string>
<string name="add_existing_account">Aggiungi un profilo esistente</string>
<string name="register_new_account">Registra un nuovo profilo</string>
<string name="this_looks_like_a_domain">Questo sembra un indirizzo di dominio</string>
<string name="add_anway">Aggiungere comunque</string>
<string name="this_looks_like_channel">Questo sembra un indirizzo di canale</string>
@ -886,8 +886,8 @@
<string name="event">Evento</string>
<string name="open_backup">Apri backup</string>
<string name="not_a_backup_file">Il file selezionato non è un file di backup di Conversations</string>
<string name="account_already_setup">Questo account è già stato configurato</string>
<string name="please_enter_password">Inserisci la password per questo account</string>
<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="sharing_application_not_grant_permission">L\'app di condivisione non ha concesso l\'autorizzazione per accedere a questo file.</string>
@ -895,10 +895,10 @@
<string name="jabber_network">jabber.network</string>
<string name="local_server">Server locale</string>
<string name="pref_channel_discovery_summary">La maggior parte degli utenti dovrebbe scegliere jabber.network per migliori suggerimenti dall\'intero ecosistema XMPP pubblico.</string>
<string name="pref_channel_discovery">Metodo di scoperta canali</string>
<string name="pref_channel_discovery">Metodo di scoperta dei canali</string>
<string name="backup">Backup</string>
<string name="category_about">Al riguardo</string>
<string name="please_enable_an_account">Devi attivare un account</string>
<string name="please_enable_an_account">Devi attivare un profilo</string>
<string name="make_call">Chiama</string>
<string name="rtp_state_incoming_call">Chiamata in arrivo</string>
<string name="rtp_state_incoming_video_call">Chiamata video in arrivo</string>
@ -964,7 +964,7 @@
<string name="invite_to_app">Invita su Conversations</string>
<string name="unable_to_parse_invite">Impossibile analizzare l\'invito</string>
<string name="server_does_not_support_easy_onboarding_invites">Il server non supporta la generazione di inviti</string>
<string name="no_active_accounts_support_this">Nessun account attivo supporta questa funzione</string>
<string name="no_active_accounts_support_this">Nessun profilo attivo supporta questa funzione</string>
<string name="backup_started_message">Il backup è iniziato. Riceverai una notifica una volta completato.</string>
<string name="unable_to_enable_video">Impossibile attivare il video.</string>
<string name="plain_text_document">Documento di testo</string>

View File

@ -30,14 +30,14 @@
<string name="minute_ago">1分前</string>
<string name="minutes_ago">%d分前</string>
<plurals name="x_unread_conversations">
<item quantity="other">未読%d件</item>
<item quantity="other">%d件の未読の会話</item>
</plurals>
<string name="sending">送信中…</string>
<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>
@ -47,11 +47,11 @@
<string name="block_contact_text">%s からあなたに送信されるメッセージをブロックしますか?</string>
<string name="unblock_contact_text">%s のブロックを解除し、あなたにメッセージを送信できるようにしますか?</string>
<string name="block_domain_text">%s からの連絡をすべてブロックしますか?</string>
<string name="unblock_domain_text">%s からの連絡をすべてブロック解除しますか?</string>
<string name="unblock_domain_text">%s からすべての連絡先のブロック解除しますか?</string>
<string name="contact_blocked">連絡先をブロックしました</string>
<string name="blocked">ブロックしました</string>
<string name="remove_bookmark_text">%s のブックマークを削除しますか? このブックマークとの会話は削除されません。</string>
<string name="register_account">サーバーに新しいアカウントを登録</string>
<string name="register_account">サーバーに新アカウントを登録</string>
<string name="change_password_on_server">サーバーのパスワードを変更</string>
<string name="share_with">…で共有</string>
<string name="start_conversation">会話を始める</string>
@ -59,7 +59,7 @@
<string name="invite">招待</string>
<string name="contacts">連絡先</string>
<string name="contact">連絡先</string>
<string name="cancel">キャンセル</string>
<string name="cancel">中止</string>
<string name="set">設定</string>
<string name="add">追加</string>
<string name="edit">編集</string>
@ -105,9 +105,9 @@
<string name="openkeychain_not_installed">OpenKeychain をインストールしてください</string>
<string name="offering">依頼中…</string>
<string name="waiting">待機中…</string>
<string name="no_pgp_key">OpenPGP の鍵はありません</string>
<string name="no_pgp_key">OpenPGP 鍵が見つかりません</string>
<string name="contact_has_no_pgp_key">連絡先が公開鍵を通知しないため、あなたのメッセージを暗号化することができません。\n\n<small>連絡先に OpenPGP をセットアップするように依頼してください。</small></string>
<string name="no_pgp_keys">OpenPGP の鍵はありません</string>
<string name="no_pgp_keys">OpenPGP 鍵が見つかりません</string>
<string name="contacts_have_no_pgp_keys">連絡先が公開鍵を通知しないため、あなたのメッセージを暗号化することができません。\n\n<small>連絡先に OpenPGP をセットアップするように依頼してください。</small></string>
<string name="pref_general">全般</string>
<string name="pref_accept_files">ファイルを受取</string>
@ -115,9 +115,9 @@
<string name="pref_attachments">添付ファイル</string>
<string name="pref_notification_settings">通知</string>
<string name="pref_vibrate">振動</string>
<string name="pref_vibrate_summary">しいメッセージが届いたときに振動します</string>
<string name="pref_vibrate_summary">メッセージが届いたときに振動します</string>
<string name="pref_led">LED 通知</string>
<string name="pref_led_summary">しいメッセージが届いたときに通知ライトを点滅します</string>
<string name="pref_led_summary">メッセージが届いたときに通知ライトを点滅します</string>
<string name="pref_ringtone">着信音</string>
<string name="pref_notification_sound">通知音</string>
<string name="pref_notification_sound_summary">新着メッセージの通知音</string>
@ -128,22 +128,22 @@
<string name="pref_never_send_crash">クラッシュレポートを送信しない</string>
<string name="pref_never_send_crash_summary">スタックトレースを送信すると、 Conversations の開発を支援します</string>
<string name="pref_confirm_messages">メッセージを確認</string>
<string name="pref_confirm_messages_summary">あなたがメッセージを受信して読んだときに、連絡先に知らせます</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">UI</string>
<string name="openpgp_error">OpenKeychain でエラーが発生しました。</string>
<string name="bad_key_for_encryption">暗号化の鍵が不正です。</string>
<string name="accept"></string>
<string name="accept">け入れる</string>
<string name="error">エラーが発生しました</string>
<string name="recording_error">エラー</string>
<string name="your_account">あなたのアカウント</string>
<string name="send_presence_updates">参加アップデートを送信</string>
<string name="receive_presence_updates">参加アップデートを受信</string>
<string name="ask_for_presence_updates">参加アップデートを問合せ</string>
<string name="send_presence_updates">出席情報アップデートを送信</string>
<string name="receive_presence_updates">出席情報アップデートを受信</string>
<string name="ask_for_presence_updates">出席情報アップデートを求める</string>
<string name="attach_choose_picture">画像を選択</string>
<string name="attach_take_picture">写真を撮影</string>
<string name="preemptively_grant">事前にサブスクリプション要求を許可する</string>
<string name="preemptively_grant">サブスクリプション要求を事前に付与する</string>
<string name="error_not_an_image_file">選択したファイルは画像ではありません</string>
<string name="error_compressing_image">画像ファイルを変換できません</string>
<string name="error_file_not_found">ファイルが見つかりません</string>
@ -162,7 +162,7 @@
<string name="account_status_regis_conflict">ユーザー名は既に使用されています</string>
<string name="account_status_regis_success">登録が完了しました</string>
<string name="account_status_regis_not_sup">サーバーは登録をサポートしていません</string>
<string name="account_status_regis_invalid_token">トークンが無効です</string>
<string name="account_status_regis_invalid_token">登録トークンが無効です</string>
<string name="account_status_tls_error">TLS ネゴシエーションに失敗しました</string>
<string name="account_status_tls_error_domain">検証不可能なドメイン</string>
<string name="account_status_policy_violation">ポリシー違反</string>
@ -174,13 +174,13 @@
<string name="encryption_choice_pgp">OpenPGP</string>
<string name="encryption_choice_omemo">OMEMO</string>
<string name="mgmt_account_delete">アカウントを削除</string>
<string name="mgmt_account_disable">一時的に無効にする</string>
<string name="mgmt_account_disable">一時的に無効</string>
<string name="mgmt_account_publish_avatar">アバターを公開</string>
<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="unpublish_pgp_message">出席情報告知から OpenPGP 公開鍵を削除してもよろしいですか?\n連絡先はあなたに OpenPGP 暗号化メッセージを送信できなくなります。</string>
<string name="openpgp_has_been_published">OpenPGP 公開鍵を公開しました。</string>
<string name="mgmt_account_enable">アカウントを有効にする</string>
<string name="mgmt_account_enable">アカウントを有効</string>
<string name="mgmt_account_are_you_sure">よろしいですか?</string>
<string name="mgmt_account_delete_confirm_text">アカウントを削除すると会話履歴がすべて消去されます</string>
<string name="attach_record_voice">音声を録音</string>
@ -213,7 +213,7 @@
<string name="last_seen_day">1日前に会いました</string>
<string name="last_seen_days">%d日前に会いました</string>
<string name="install_openkeychain">暗号化されたメッセージです。復号するには OpenKeychain をインストールしてください。</string>
<string name="openpgp_messages_found">しい OpenPGP で暗号化されたメッセージが見つかりました</string>
<string name="openpgp_messages_found">規の OpenPGP で暗号化されたメッセージが見つかりました</string>
<string name="openpgp_key_id">OpenPGP 鍵 ID</string>
<string name="omemo_fingerprint">OMEMO フィンガープリント</string>
<string name="omemo_fingerprint_x509">v\\OMEMO フィンガープリント</string>
@ -251,7 +251,7 @@
<string name="add_back">戻りを追加</string>
<string name="contact_has_read_up_to_this_point">%s はここまで読みました</string>
<string name="contacts_have_read_up_to_this_point">%s はここまで読みました</string>
<string name="contacts_and_n_more_have_read_up_to_this_point">%1$s +%2$d 全員ここまで読みました</string>
<string name="contacts_and_n_more_have_read_up_to_this_point">%1$s +%2$d人がここまで読みました</string>
<string name="everyone_has_read_up_to_this_point">全員がここまで読みました</string>
<string name="publish">公開</string>
<string name="touch_to_choose_picture">アバターをタップしてギャラリーから画像を選択します</string>
@ -269,14 +269,14 @@
<string name="next">次へ</string>
<string name="server_info_session_established">セッションが確立</string>
<string name="skip">スキップ</string>
<string name="disable_notifications">通知を無効にする</string>
<string name="disable_notifications">通知を無効</string>
<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>
<string name="without_mutual_presence_updates"><b>警告:</b> 相互の出席情報アップデートなしにこれを送信すると、予期しない問題が発生する可能性があります。\n\n<small>あなたの出席情報サブスクリプションを検証するために、“連絡先の詳細に移動します。</small></string>
<string name="pref_security_settings">セキュリティ</string>
<string name="pref_allow_message_correction">メッセージの修正を許可</string>
<string name="pref_allow_message_correction_summary">連絡先が、遡及的に自分のメッセージを編集することを許可します</string>
@ -286,7 +286,7 @@
<string name="title_pref_quiet_hours">消音時間</string>
<string name="title_pref_quiet_hours_start_time">開始時刻</string>
<string name="title_pref_quiet_hours_end_time">終了時刻</string>
<string name="title_pref_enable_quiet_hours">消音時間を有効にする</string>
<string name="title_pref_enable_quiet_hours">消音時間を有効</string>
<string name="pref_quiet_hours_summary">消音時間の間、通知は無音になります</string>
<string name="pref_expert_options_other">その他</string>
<string name="pref_autojoin">ブックマークと同期</string>
@ -294,10 +294,10 @@
<string name="toast_message_omemo_fingerprint">OMEMO フィンガープリントをクリップボードにコピーしました</string>
<string name="conference_banned">このグループチャットから出禁にされています</string>
<string name="conference_members_only">このグループチャットはメンバー制です</string>
<string name="conference_resource_constraint">リソース制</string>
<string name="conference_resource_constraint">リソース制</string>
<string name="conference_kicked">このグループチャットから蹴り出されています</string>
<string name="conference_shutdown">このグループチャットは閉鎖されました</string>
<string name="conference_unknown_error">既にこのグループチャットに参加していません</string>
<string name="conference_unknown_error">あなたはもうこのグループチャットに参加していません</string>
<string name="using_account">アカウント %s を使用</string>
<string name="hosted_on">%s 上でホストされた</string>
<string name="checking_x">HTTP ホスト上の %s を確認中</string>
@ -319,7 +319,7 @@
<string name="show_block_list">ブロック一覧を表示</string>
<string name="account_details">アカウントの詳細</string>
<string name="confirm">確認</string>
<string name="try_again">度実行してください</string>
<string name="try_again">試行</string>
<string name="pref_keep_foreground_service">フォアグラウンドサービス</string>
<string name="pref_keep_foreground_service_summary">オペレーティングシステムが接続を切断するのを防止します</string>
<string name="pref_create_backup">バックアップを作成</string>
@ -329,7 +329,7 @@
<string name="notification_backup_created_subtitle">バックアップファイルは %s に保存されました</string>
<string name="restoring_backup">バックアップを復元</string>
<string name="notification_restored_backup_title">バックアップを復元しました</string>
<string name="notification_restored_backup_subtitle">アカウントを有効してください。</string>
<string name="notification_restored_backup_subtitle">アカウントを有効してください。</string>
<string name="choose_file">ファイルを選択</string>
<string name="receiving_x_file">%1$s 受信中 (%2$d%% 完了)</string>
<string name="download_x_file">%s をダウンロード</string>
@ -339,16 +339,16 @@
<string name="sending_file">送信中 (%1$d%% 完了)</string>
<string name="preparing_file">転送用ファイルの準備中</string>
<string name="x_file_offered_for_download">%s ダウンロード依頼中</string>
<string name="cancel_transmission">転送をキャンセル</string>
<string name="cancel_transmission">転送を中止</string>
<string name="file_transmission_failed">ファイル転送に失敗しました</string>
<string name="file_transmission_cancelled">転送をキャンセルしました</string>
<string name="file_transmission_cancelled">ファイル転送を中止しました</string>
<string name="file_deleted">ファイルを削除しました</string>
<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_summary">連絡先の下に、読み取り専用タグを表示します</string>
<string name="enable_notifications">通知を有効にする</string>
<string name="enable_notifications">通知を有効</string>
<string name="no_conference_server_found">グループチャットのサーバーが見つかりませんでした</string>
<string name="conference_creation_failed">グループチャットを作成できません</string>
<string name="account_image_description">アカウントのアバター</string>
@ -357,7 +357,7 @@
<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_presence">この連絡先で利用可能な鍵はありません。\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>
<string name="no_more_history_on_server">サーバーにこれ以上履歴がありません</string>
@ -368,8 +368,8 @@
<string name="current_password">現在のパスワード</string>
<string name="new_password">新しいパスワード</string>
<string name="password_should_not_be_empty">パスワードは空にできません</string>
<string name="enable_all_accounts">すべてのアカウントを有効にする</string>
<string name="disable_all_accounts">すべてのアカウントを無効にする</string>
<string name="enable_all_accounts">すべてのアカウントを有効</string>
<string name="disable_all_accounts">すべてのアカウントを無効</string>
<string name="perform_action_with">アクションを実行...</string>
<string name="no_affiliation">所属なし</string>
<string name="no_role">オフライン</string>
@ -396,12 +396,12 @@
<string name="non_anonymous">XMPPアドレスを誰でも見れるようにする</string>
<string name="moderated">談話室の調停をする</string>
<string name="you_are_not_participating">あなたは参加していません</string>
<string name="modified_conference_options">グループチャットのオプションが変更されました!</string>
<string name="could_not_modify_conference_options">グループチャットのオプションを変更できませんでした</string>
<string name="modified_conference_options">グループチャットの設定が変更されました!</string>
<string name="could_not_modify_conference_options">グループチャットの設定を変更できませんでした</string>
<string name="never">なし</string>
<string name="until_further_notice">通知が来るまで</string>
<string name="snooze">スヌーズ</string>
<string name="reply">返信する</string>
<string name="reply">返信</string>
<string name="mark_as_read">既読にする</string>
<string name="pref_input_options">入力</string>
<string name="pref_enter_is_send">Enter で送信</string>
@ -424,7 +424,7 @@
<string name="contacts_are_typing">%s さんが入力中…</string>
<string name="contacts_have_stopped_typing">%s さんが入力を止めました</string>
<string name="pref_chat_states">入力中通知</string>
<string name="pref_chat_states_summary">あなたがメッセージを書いているときに、連絡先に知らせます</string>
<string name="pref_chat_states_summary">あなたがメッセージを書いているときに、連絡先に知らせ</string>
<string name="send_location">位置を送信</string>
<string name="show_location">位置を表示</string>
<string name="no_application_found_to_display_location">位置を表示するアプリケーションが見つかりません</string>
@ -471,7 +471,7 @@
<string name="pref_treat_vibrate_as_silent">バイブレートをサイレントモードとして扱う</string>
<string name="pref_treat_vibrate_as_dnd_summary">デバイスがバイブレートのときは取込中と表示</string>
<string name="pref_show_connection_options">拡張接続設定</string>
<string name="pref_show_connection_options_summary">アカウントを設定するときにホスト名とポートの設定を表示します</string>
<string name="pref_show_connection_options_summary">アカウントを設定するときにホスト名とポートの設定を表示</string>
<string name="hostname_example">xmpp.example.com</string>
<string name="action_add_account_with_certificate">証明書でログイン</string>
<string name="unable_to_parse_certificate">証明書を解析できません</string>
@ -481,7 +481,7 @@
<string name="unable_to_fetch_mam_prefs">アーカイブ設定を取得できません</string>
<string name="captcha_required">キャプチャが要求されました</string>
<string name="captcha_hint">上の画像からテキストを入力してください</string>
<string name="certificate_chain_is_not_trusted">信頼されていない証明書チェーン</string>
<string name="certificate_chain_is_not_trusted">信頼できない証明書チェーン</string>
<string name="jid_does_not_match_certificate">XMPP アドレスが証明書と一致しません</string>
<string name="action_renew_certificate">証明書を更新</string>
<string name="error_fetching_omemo_key">OMEMO 鍵の取得中にエラー!</string>
@ -518,8 +518,8 @@
<string name="always">常に</string>
<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\n今、それらを無効するように求められます。</string>
<string name="battery_optimizations_enabled_explained">お使いのデバイスは、%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>
@ -527,7 +527,7 @@
<string name="correct_message">メッセージを修正</string>
<string name="send_corrected_message">修正したメッセージを送信</string>
<string name="no_keys_just_confirm">あなたは信頼を確認するために、この人の指紋を安全に検証しました。“完了”を選択すると、 %s がこのグループチャットの一員であることを確認したことになります。</string>
<string name="this_account_is_disabled">このアカウントを無効しました</string>
<string name="this_account_is_disabled">このアカウントを無効しました</string>
<string name="security_error_invalid_file_access">セキュリティエラー: 不正なファイルアクセス!</string>
<string name="no_application_to_share_uri">URI を共有するアプリが見つかりません</string>
<string name="share_uri_with">…で URI を共有</string>
@ -536,7 +536,7 @@
<string name="magic_create_text">conversations.im 上にアカウントを作成する設定の指南です。¹\nconversations.im をプロバイダーとして選択した場合、あなたの完全な XMPP アドレスを他のプロバイダーのユーザーに示すことで、その人と連絡をとることができます。</string>
<string name="your_full_jid_will_be">あなたの完全なXMPPアドレスは: %s</string>
<string name="create_account">アカウントを作成</string>
<string name="use_own_provider">自のプロバイダーを使用する</string>
<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>
@ -548,7 +548,7 @@
<string name="presence_dnd">取込中</string>
<string name="secure_password_generated">安全なパスワードが生成されました</string>
<string name="device_does_not_support_battery_op">お使いのデバイスは電池最適化の停止をサポートしていません</string>
<string name="registration_please_wait">登録に失敗しました: 後でもう一度試しください</string>
<string name="registration_please_wait">登録に失敗しました: 後でもう一度試しください</string>
<string name="registration_password_too_weak">登録に失敗しました: パスワードが弱すぎます</string>
<string name="choose_participants">参加者を選択</string>
<string name="creating_conference">グループチャットを作成しています…</string>
@ -572,16 +572,16 @@
<string name="type_pc">コンピューター</string>
<string name="type_phone">携帯電話</string>
<string name="type_tablet">タブレット</string>
<string name="type_web">Web ブラウザー</string>
<string name="type_web">ウェブブラウザ</string>
<string name="type_console">コンソール</string>
<string name="payment_required">支払が必要です</string>
<string name="missing_internet_permission">インターネット使用権限の付与</string>
<string name="me">自分</string>
<string name="contact_asks_for_presence_subscription">連絡先が、参加サブスクリプションを問い合わせしています</string>
<string name="contact_asks_for_presence_subscription">連絡先が出席情報サブスクリプションを求めています</string>
<string name="allow">許可</string>
<string name="no_permission_to_access_x">%s にアクセスする権限がありません</string>
<string name="remote_server_not_found">リモートサーバーが見つかりません</string>
<string name="remote_server_timeout">リモートサーバータイムアウト</string>
<string name="remote_server_timeout">リモートサーバータイムアウト</string>
<string name="unable_to_update_account">アカウントを更新できません</string>
<string name="report_jid_as_spammer">この XMPP アドレスをスパムとして報告する。</string>
<string name="pref_delete_omemo_identities">OMEMO ID を削除</string>
@ -590,8 +590,8 @@
<string name="error_publish_avatar_offline">アバターを公開するには接続する必要があります。</string>
<string name="show_error_message">エラーメッセージを表示</string>
<string name="error_message">エラーメッセージ</string>
<string name="data_saver_enabled">データセーバーを有効しました</string>
<string name="data_saver_enabled_explained">お使いのオペレーティングシステムは、%1$s がバックグラウンドのときにインターネットにアクセスすることを制限しています。新しいメッセージの通知を受信するには、“データセーバー”がオンならば、%1$s に無制限のアクセスを許可する必要があります。\n%1$s は可能なときにデータを保存するための努力をします。</string>
<string name="data_saver_enabled">データセーバーを有効しました</string>
<string name="data_saver_enabled_explained">お使いのオペレーティングシステムは、%1$s がバックグラウンドのときにインターネットにアクセスすることを制限しています。新メッセージの通知を受信するには、“データセーバー”がオンならば、%1$s に無制限のアクセスを許可する必要があります。\n%1$s は可能なときにデータを保存するための努力をします。</string>
<string name="device_does_not_support_data_saver">お使いのデバイスは、%1$s のデータセーバーを無効にできません。</string>
<string name="error_unable_to_create_temporary_file">一時ファイルを作成できません</string>
<string name="this_device_has_been_verified">このデバイスは検証済です</string>
@ -604,10 +604,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="not_trusted">信頼できない</string>
<string name="invalid_barcode">不正な二次元バーコード</string>
<string name="pref_clean_cache_summary">キャッシュフォルダを消去します (カメラアプリで使用)</string>
<string name="pref_clean_cache">キャッシュを消去</string>
@ -647,21 +647,21 @@
<string name="contact_blocked_past_tense">連絡先をブロックしました</string>
<string name="pref_notifications_from_strangers">見知らぬ人からの通知</string>
<string name="pref_notifications_from_strangers_summary">見知らぬ人から受信したメッセージと通話を通知します。</string>
<string name="received_message_from_stranger">見知らぬ人からメッセージを受け取りました</string>
<string name="received_message_from_stranger">見知らぬ人からメッセージを受信しました</string>
<string name="block_stranger">見知らぬ人をブロック</string>
<string name="block_entire_domain">ドメイン全体をブロック</string>
<string name="online_right_now">今すぐオンライン</string>
<string name="retry_decryption">復号を再試行</string>
<string name="session_failure">セッション失敗</string>
<string name="sasl_downgrade">ダウングレードされた SASL メカニズム</string>
<string name="account_status_regis_web">サーバーはWebサイトでの登録が必要です</string>
<string name="open_website">Webサイトを開く</string>
<string name="application_found_to_open_website">Webサイトを開くアプリが見つかりません</string>
<string name="account_status_regis_web">サーバーはウェブサイトでの登録が必要です</string>
<string name="open_website">ウェブサイトを開く</string>
<string name="application_found_to_open_website">ウェブサイトを開くアプリが見つかりません</string>
<string name="pref_headsup_notifications">Heads-up 通知</string>
<string name="pref_headsup_notifications_summary">Heads-up 通知を表示</string>
<string name="today">今日</string>
<string name="yesterday">昨日</string>
<string name="pref_validate_hostname">DNSSEC でホスト名を検証</string>
<string name="pref_validate_hostname">DNSSEC でホスト名の妥当性を確認</string>
<string name="pref_validate_hostname_summary">検証されたホスト名を含むサーバー証明書は検証済みと見なされます</string>
<string name="certificate_does_not_contain_jid">証明書は XMPP アドレスを含みません</string>
<string name="server_info_partial">一時的</string>
@ -669,12 +669,12 @@
<string name="copy_to_clipboard">クリップボードにコピー</string>
<string name="message_copied_to_clipboard">メッセージをクリップボードにコピーしました</string>
<string name="message">メッセージ</string>
<string name="private_messages_are_disabled">非公開メッセージを無効しました</string>
<string name="private_messages_are_disabled">非公開メッセージを無効しました</string>
<string name="huawei_protected_apps">保護されたアプリ</string>
<string name="huawei_protected_apps_summary">画面がオフになっている場合でも通知を受信し続けるには、保護されたアプリの一覧に Conversations を追加する必要があります。</string>
<string name="huawei_protected_apps_summary">画面がオフになっているときでも通知を受信し続けるには、保護されたアプリの一覧に Conversations を追加する必要があります。</string>
<string name="mtm_accept_cert">未知の証明書を受け入れますか?</string>
<string name="mtm_trust_anchor">サーバー証明書が既知の認証局によって署名されていません。</string>
<string name="mtm_accept_servername">不一致サーバー名を受け入れますか?</string>
<string name="mtm_accept_servername">不一致サーバー名を受け入れますか?</string>
<string name="mtm_hostname_mismatch">サーバーは\&quot;%s\&quot;として認証できませんでした。証明書は次の場合にのみ有効です:</string>
<string name="mtm_connect_anyway">それでも接続を希望しますか?</string>
<string name="mtm_cert_details">証明書の詳細:</string>
@ -684,12 +684,12 @@
<string name="pref_scroll_to_bottom_summary">メッセージ送信後に下へスクロール</string>
<string name="edit_status_message_title">ステータスメッセージを編集</string>
<string name="edit_status_message">ステータスメッセージを編集</string>
<string name="disable_encryption">暗号化をしない</string>
<string name="disable_encryption">暗号化が無効</string>
<string name="error_trustkey_general">%1$s は %2$s に暗号化メッセージを送れません。連絡先が利用しているサーバーが古すぎるか、クライアントが OMEMO を扱えません。</string>
<string name="error_trustkey_device_list">デバイスの一覧を取得できません</string>
<string name="error_trustkey_bundle">暗号化の鍵を取得できません</string>
<string name="error_trustkey_hint_mutual">ヒント: お互いが連絡先名簿に加えれば解決するでしょう。</string>
<string name="disable_encryption_message">この会話でOMEMOの暗号化を無効にしてよろしいですか?\n\nこれにより、サーバー管理者がメッセージを読むことが可能になりますが、時代遅れのクライアントを使っている人と連絡をとるには、この方法しかないかもしれません。</string>
<string name="disable_encryption_message">この会話で OMEMO の暗号化を無効化してもよろしいですか?\nこれにより、サーバー管理者がメッセージを読むことが可能になりますが、時代遅れのクライアントを使っている人と連絡をとるには、この方法しかないかもしれません。</string>
<string name="disable_now">今すぐ無効化</string>
<string name="draft">下書き:</string>
<string name="pref_omemo_setting">OMEMO 暗号化</string>
@ -737,6 +737,7 @@
<string name="providing_a_name_is_optional">名前の記入は任意です</string>
<string name="create_dialog_group_chat_name">グループチャット名</string>
<string name="conference_destroyed">このグループチャットは破棄されました</string>
<string name="unable_to_save_recording">録音を保存できません</string>
<string name="foreground_service_channel_name">フォアグラウンドサービス</string>
<string name="foreground_service_channel_description">この通知カテゴリーは %1$s が実行していることを表示する、永続的な通知を表示するために使用されます。</string>
<string name="notification_group_status_information">ステータス情報</string>
@ -745,13 +746,13 @@
<string name="notification_group_messages">メッセージ</string>
<string name="notification_group_calls">通話</string>
<string name="messages_channel_name">メッセージ</string>
<string name="incoming_calls_channel_name">着信</string>
<string name="ongoing_calls_channel_name">発信</string>
<string name="incoming_calls_channel_name">着信通話</string>
<string name="ongoing_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>
<string name="pref_message_notification_settings">メッセージ通知設定</string>
<string name="pref_incoming_call_notification_settings">通話着信の通知設定</string>
<string name="pref_incoming_call_notification_settings">着信通話の通知設定</string>
<string name="pref_more_notification_settings_summary">重要性、音、振動</string>
<string name="video_compression_channel_name">ビデオの圧縮</string>
<string name="view_media">メディアを表示</string>
@ -762,8 +763,9 @@
<string name="pref_video_compression_summary">質が低い程、ファイルは小さくなります</string>
<string name="video_360p">中 (360p)</string>
<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>
@ -783,7 +785,7 @@
<string name="back">戻る</string>
<string name="possible_pin">クリップボードから可能な pin を自動的に貼り付ける。</string>
<string name="please_enter_pin">6桁の pin を入力してください。</string>
<string name="abort_registration_procedure">本当に登録手続きを中止してもよろしいのですか?</string>
<string name="abort_registration_procedure">登録手続きを中止してもよろしいのですか?</string>
<string name="yes">はい</string>
<string name="no">いいえ</string>
<string name="verifying">検証しています…</string>
@ -797,7 +799,7 @@
<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="temporarily_unavailable">一時的に入手不可能です。後でもう一度試しください。</string>
<string name="no_network_connection">ネットワーク接続なし。</string>
<string name="try_again_in_x">%s でもう一度お試しください。</string>
<string name="rate_limited">上限に到達しました</string>
@ -813,9 +815,9 @@
<string name="install_orbot">Orbot をインストール</string>
<string name="start_orbot">Orbot を開始</string>
<string name="no_market_app_installed">マーケットアプリがインストールされていません。</string>
<string name="group_chat_will_make_your_jabber_id_public">この談話室では、あなたのXMPPアドレスを公開します</string>
<string name="group_chat_will_make_your_jabber_id_public">この談話室では、あなたの XMPP アドレスを公開します</string>
<string name="ebook">電子書籍</string>
<string name="video_original">原物 (非圧縮)</string>
<string name="video_original">そのまま (非圧縮)</string>
<string name="open_with">…で開く</string>
<string name="set_profile_picture">Conversations プロフィール画像</string>
<string name="choose_account">アカウントを選択</string>
@ -849,7 +851,7 @@
<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="no_users_hint_channel">この公開談話室には参加者がいません。連絡先を招待したり、共有ボタンを使て XMPP アドレスを配布できます。</string>
<string name="no_users_hint_channel">この公開談話室には参加者がいません。連絡先を招待したり、共有ボタンを使用して XMPP アドレスを配布できます。</string>
<string name="no_users_hint_group_chat">この非公開グループチャットには参加者がいません。</string>
<string name="manage_permission">権限を管理</string>
<string name="search_participants">参加者を検索</string>
@ -860,8 +862,8 @@
<string name="channel_discovery_opt_in_title">プライバシー侵害の可能性あり!</string>
<string name="channel_discover_opt_in_message"><![CDATA[談話室発見は、第三者のサービスである<a href=\"https://search.jabber.network\">search.jabber.network</a>を利用します。<br><br>この機能を使うと、あなたののIPアドレスや検索キーワードがそのサービスに送信されます。詳しくは、<a href=\"https://search.jabber.network/privacy\">プライバシーポリシー</a>をご覧ください。]]></string>
<string name="i_already_have_an_account">既にアカウントを持っています</string>
<string name="add_existing_account">在するアカウントを追加</string>
<string name="register_new_account">しいアカウントを登録</string>
<string name="add_existing_account">存アカウントを追加</string>
<string name="register_new_account">アカウントを登録</string>
<string name="this_looks_like_a_domain">これはドメインアドレスのようです</string>
<string name="add_anway">とにかく追加</string>
<string name="this_looks_like_channel">これは談話室アドレスのようです</string>
@ -874,16 +876,17 @@
<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="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>
<string name="pref_channel_discovery_summary">ほとんどのユーザーは、公開されている XMPP エコシステム全体からより良い提案を得るために、jabber.networkを選択するはずです。</string>
<string name="pref_channel_discovery">談話室の発見方法</string>
<string name="please_enable_an_account">アカウントを有効にしてください</string>
<string name="backup">バックアップ</string>
<string name="please_enable_an_account">アカウントを有効化してください</string>
<string name="make_call">通話をする</string>
<string name="rtp_state_incoming_call">通話着信</string>
<string name="rtp_state_incoming_video_call">映像通話着信</string>
<string name="rtp_state_incoming_call">着信通話</string>
<string name="rtp_state_incoming_video_call">着信映像通話</string>
<string name="rtp_state_connecting">接続中</string>
<string name="rtp_state_connected">接続しました</string>
<string name="rtp_state_accepting_call">通話受入</string>
@ -896,21 +899,23 @@
<string name="rtp_state_connectivity_error">通話に接続できません</string>
<string name="rtp_state_connectivity_lost_error">接続切断</string>
<string name="rtp_state_retracted">撤回された通話</string>
<string name="hang_up">ハングアップ</string>
<string name="rtp_state_application_failure">アプリの失敗</string>
<string name="rtp_state_security_error">検証に問題</string>
<string name="hang_up">電話を切る</string>
<string name="ongoing_call">継続中の通話</string>
<string name="ongoing_video_call">継続中の映像通話</string>
<string name="disable_tor_to_make_call">通話するのに Tor を無効にする</string>
<string name="incoming_call">通話着信</string>
<string name="incoming_call_duration">通話着信・%s</string>
<string name="missed_call_timestamp">不在通話着信・%s</string>
<string name="outgoing_call">通話発信</string>
<string name="outgoing_call_duration">通話発信・%s</string>
<string name="missed_call">不在通話着信</string>
<string name="disable_tor_to_make_call">通話するのに Tor を無効</string>
<string name="incoming_call">着信通話</string>
<string name="incoming_call_duration">着信通話・%s</string>
<string name="missed_call_timestamp">不在着信通話・%s</string>
<string name="outgoing_call">発信通話</string>
<string name="outgoing_call_duration">発信通話・%s</string>
<string name="missed_call">不在着信通話</string>
<string name="audio_call">音声通話</string>
<string name="video_call">映像通話</string>
<string name="switch_to_conversation">会話に切り替え</string>
<string name="microphone_unavailable">マイクが利用できません</string>
<string name="only_one_call_at_a_time">1回につき1回線のみ</string>
<string name="only_one_call_at_a_time">1度に1回線の通話のみ。</string>
<string name="return_to_ongoing_call">継続中の通話に戻る</string>
<string name="could_not_switch_camera">カメラを切り替えできません</string>
<string name="add_to_favorites">最上に留める</string>
@ -940,7 +945,7 @@
<string name="no_application_found">アプリケーションが見つかりません</string>
<string name="invite_to_app">会話に招待</string>
<string name="unable_to_parse_invite">招待を解析できません</string>
<string name="server_does_not_support_easy_onboarding_invites">サーバーは招待をサポートしていません</string>
<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>

View File

@ -131,11 +131,14 @@
<string name="pref_notification_sound_summary">Zvuk oznámenia nových správ</string>
<string name="pref_call_ringtone_summary">Zvonenie pre prichádzajúce hovory</string>
<string name="pref_notification_grace_period">Ochranná doba</string>
<string name="pref_notification_grace_period_summary">Doba, počas ktorej budú oznámenia stíšené po detekcii aktivity na jednom z vašich ostatných zariadení.</string>
<string name="pref_advanced_options">Pokročilé</string>
<string name="pref_never_send_crash">Neodosielať detaily o zlyhaní aplikácie</string>
<string name="pref_never_send_crash_summary">Keď pošlete detaily o dôvode zlyhania, pomáhate vývoju</string>
<string name="pref_confirm_messages">Potvrdzovať správy</string>
<string name="pref_confirm_messages_summary">Dajte vedieť svojim kontaktom, keď prijmete a prečítate si správy</string>
<string name="pref_prevent_screenshots">Zakázať snímok obrazovky</string>
<string name="pref_prevent_screenshots_summary">Skryje obsah aplikácie v posledných aplikáciách a zablokuje snímky obrazovky.</string>
<string name="pref_ui_options">Prostredie</string>
<string name="bad_key_for_encryption">Nesprávny kľúč na šifrovanie.</string>
<string name="accept">Prijať</string>
@ -152,6 +155,7 @@
<string name="error_compressing_image">Nemohol som konvertovať obrázkový súbor</string>
<string name="error_file_not_found">Súbor sa nenašiel</string>
<string name="error_io_exception">Všeobecná I/O chyba. Možno už nie je voľné miesto?</string>
<string name="error_security_exception_during_image_copy">Aplikácia, ktorú ste použili pre výber obrázka neposkytla dostatočné oprávnenia na prečítanie súboru.\n\n<small>Skúste použiť iného správcu súborov pre výber obrázka</small></string>
<string name="error_security_exception">Aplikácia, ktorú ste použili na zdieľanie tohto súboru neposkytla dostatočné povolenia.</string>
<string name="account_status_unknown">Neznámy</string>
<string name="account_status_disabled">Dočasne vypnutý</string>
@ -166,6 +170,7 @@
<string name="account_status_regis_success">Registrácia ukončená</string>
<string name="account_status_regis_not_sup">Registrácia nie je podporovaná serverom.</string>
<string name="account_status_regis_invalid_token">Neplatný registračný token</string>
<string name="account_status_tls_error">Nadviazanie spojenia TLS zlyhalo</string>
<string name="account_status_tls_error_domain">Doména sa nedá overiť</string>
<string name="account_status_policy_violation">Porušenie pravidiel</string>
<string name="account_status_incompatible_server">Nekompatibilný server</string>
@ -177,6 +182,7 @@
<string name="mgmt_account_disable">Dočasne vypnúť</string>
<string name="mgmt_account_publish_avatar">Zverejniť avatar</string>
<string name="mgmt_account_publish_pgp">Zverejniť OpenPGP kľúč</string>
<string name="unpublish_pgp">Odstrániť OpenPGP  verejný kľúč</string>
<string name="mgmt_account_enable">Povoliť účet</string>
<string name="mgmt_account_are_you_sure">Ste si istý?</string>
<string name="attach_record_voice">Nahrať hlas</string>
@ -219,6 +225,7 @@
<string name="decrypt">Dešifrovať</string>
<string name="bookmarks">Záložky</string>
<string name="search">Hľadať</string>
<string name="enter_contact">Vložiť Kontakt</string>
<string name="delete_contact">Zmazať kontakt</string>
<string name="view_contact_details">Zobraziť detaily kontaktu</string>
<string name="block_contact">Zablokovať kontakt</string>
@ -233,6 +240,7 @@
<string name="delete_bookmark">Vymazať záložku</string>
<string name="destroy_room">Vymazať skupinový rozhovor</string>
<string name="destroy_channel">Vymazať kanál</string>
<string name="destroy_room_dialog">Ste si istý, že chcete zrušiť tento skupinový rozhovor?\n\n<b>Upozornenie:</b> Skupinový rozhovor bude kompletne vymazaný zo servera.</string>
<string name="could_not_destroy_room">Nemohol som vymazať skupinový rozhovor</string>
<string name="could_not_destroy_channel">Nemohol som vymazať kanál</string>
<string name="action_edit_subject">Upraviť predmet skupinového rozhovoru</string>
@ -259,9 +267,11 @@
<string name="connect">Pripojiť </string>
<string name="account_already_exists">Tento účet už existuje</string>
<string name="next">Ďalší</string>
<string name="server_info_session_established">Spojenie naviazané</string>
<string name="skip">Preskočiť</string>
<string name="disable_notifications">Vypnúť upozornenia</string>
<string name="enable">Povoliť</string>
<string name="conference_requires_password">Skupinový rozhovor požaduje heslo</string>
<string name="enter_password">Vložiť heslo</string>
<string name="request_now">Ihneď vyžiadať</string>
<string name="ignore">Ignorovať</string>
@ -282,6 +292,7 @@
<string name="toast_message_omemo_fingerprint">OMEMO odtlačok skopírovaný do schránky</string>
<string name="conference_banned">Ste zakázaný na tomto skupinovom rozhovore</string>
<string name="conference_members_only">Skupinový rozhovor len pre členov</string>
<string name="conference_kicked">Boli ste vyhodení z tohto skupinového rozhovoru</string>
<string name="conference_shutdown">Skupinový rozhovor bol zastavený</string>
<string name="conference_unknown_error">Už viac nie ste v tomto skupinovom rozhovore</string>
<string name="using_account">Používa sa účet %s</string>
@ -306,18 +317,34 @@
<string name="account_details">Detaily účtu</string>
<string name="confirm">Potvrdiť</string>
<string name="try_again">Skúste znova</string>
<string name="pref_keep_foreground_service">Služba v popredí</string>
<string name="pref_keep_foreground_service_summary">Zamedzí operačnému systému ukončiť pripojenie </string>
<string name="pref_create_backup">Vytvoriť zálohu</string>
<string name="pref_create_backup_summary">Súbory zálohy budú uložené v %s</string>
<string name="notification_create_backup_title">Vytváram súbor zálohy</string>
<string name="notification_backup_created_title">Vaša záloha bola vytvorená</string>
<string name="notification_backup_created_subtitle">Súbor zálohy bol uložený v %s</string>
<string name="restoring_backup">Obnovujem zálohu</string>
<string name="notification_restored_backup_title">Vaša záloha bola obnovená</string>
<string name="notification_restored_backup_subtitle">Nezabudnite si zapnúť konto.</string>
<string name="choose_file">Vybrať súbor</string>
<string name="receiving_x_file">Prijímam %1$s (%2$d%% ukončený)</string>
<string name="download_x_file">Stiahnuť %s</string>
<string name="delete_x_file">Zmazať %s</string>
<string name="file">súbor</string>
<string name="open_x_file">Otvoriť %s</string>
<string name="sending_file">posielam (%1$d%% ukončený)</string>
<string name="preparing_file">Pripravuje sa zdieľanie súboru</string>
<string name="x_file_offered_for_download">%s ponúknutý na stiahnutie </string>
<string name="cancel_transmission">Zrušiť prenos</string>
<string name="pref_show_dynamic_tags_summary">Zobraziť etikety na čítanie pod kontakty</string>
<string name="file_transmission_failed">Nedá sa zdieľať súbor</string>
<string name="file_transmission_cancelled">prenos súboru zrušený</string>
<string name="file_deleted">Súbor zmazaný</string>
<string name="no_application_found_to_open_file">Nebola nájdená aplikácia na otvorenie súboru</string>
<string name="no_application_found_to_open_link">Nebola nájdená aplikácia na otvorenie odkazu</string>
<string name="no_application_found_to_view_contact">Nebola nájdená aplikácia na prezretie kontaktu</string>
<string name="pref_show_dynamic_tags">Dynamické štítky</string>
<string name="pref_show_dynamic_tags_summary">Zobraziť štítky pod kontaktmi</string>
<string name="enable_notifications">Povoliť upozornenia</string>
<string name="account_image_description">Avatar účtu</string>
<string name="copy_omemo_clipboard_description">Skopírovať OMEMO identifikátor do schránky</string>
@ -361,8 +388,12 @@
<string name="sending_x_file">Posielam %s</string>
<string name="offering_x_file">Ponúkam %s</string>
<string name="hide_offline">Skryť neprihlásených</string>
<string name="contact_is_typing">%s píše...</string>
<string name="contact_has_stopped_typing">%s prestal písať</string>
<string name="contacts_are_typing">%s píšu...</string>
<string name="contacts_have_stopped_typing">%s prestali písať</string>
<string name="pref_chat_states">Upozornenia pri písaní</string>
<string name="pref_chat_states_summary">Dajte svojim kontaktom vedieť že im práve píšete správu.</string>
<string name="send_location">Poslať polohu</string>
<string name="show_location">Zobraziť polohu</string>
<string name="location">Poloha</string>
@ -389,37 +420,95 @@
<string name="username">Užívateľské meno</string>
<string name="username_hint">Užívateľské meno</string>
<string name="invalid_username">Toto nie je platné užívateľské meno</string>
<string name="action_add_account_with_certificate">Prihlásiť sa s certifikátom</string>
<string name="action_renew_certificate">Obnoviť certifikát</string>
<string name="error_fetching_omemo_key">Chyba pri načítaní OMEMO kľúča!</string>
<string name="verified_omemo_key_with_certificate">kľúč OMEMO overený certifikátom!</string>
<string name="pref_use_tor">Pripojiť cez Tor</string>
<string name="connected_accounts">%1$dz%2$dúčtov pripojených</string>
<plurals name="x_messages">
<item quantity="one">%dspráva</item>
<item quantity="few">%dsprávy</item>
<item quantity="many">%d správ</item>
<item quantity="other">%dspráv</item>
</plurals>
<string name="load_more_messages">Načítať viac správ</string>
<string name="shared_file_with_x">Súbor zdieľaný s %s</string>
<string name="shared_image_with_x">Obrázok zdieľaný s %s</string>
<string name="shared_images_with_x">Obrázky zdieľané s %s</string>
<string name="shared_text_with_x">Text zdieľaný s %s</string>
<string name="notify_on_all_messages">Oznamovať na všetkých správach</string>
<string name="always">Vždy</string>
<string name="disable">Deaktivovať</string>
<string name="no_accounts">(Žiadne aktivované účty)</string>
<string name="no_application_to_share_uri">Nebola nájdená žiadna aplikácia na zdieľanie URI</string>
<string name="share_uri_with">Zdieľať URI s...</string>
<string name="pref_manually_change_presence_summary">Nastaviť vašu dostupnosť pri úprave vašej status správy.</string>
<string name="presence_online">Online</string>
<string name="presence_dnd">Zaneprázdnený</string>
<string name="gp_disable">Deaktivovať</string>
<string name="pref_broadcast_last_activity">Oznamovať používanie</string>
<string name="pref_privacy">Súkromie</string>
<string name="pref_theme_options">Téma</string>
<string name="pref_theme_options_summary">Zvoľte si farebnú schému</string>
<string name="pref_use_green_background">Zelené pozadie</string>
<string name="pref_use_green_background_summary">Použiť zelené pozadie pre prijaté správy</string>
<string name="pref_delete_omemo_identities">Vymazať OMEMO identifikátory</string>
<string name="pref_delete_omemo_identities_summary">Re-generuje vaše kľúče OMEMO. Všetky vaše kontakty vás budú musieť znova overiť. Použite to ako poslednú možnosť.</string>
<string name="delete_selected_keys">Odstrániť označené kľúče</string>
<string name="all_omemo_keys_have_been_verified">Overili ste všetky kľúče OMEMO vo vašom vlastníctve.</string>
<string name="share_as_barcode">Zdieľať ako qr kód</string>
<string name="share_as_uri">Zdieľať ako XMPP URI</string>
<string name="share_as_http">Zdieľať ako HTTP odkaz</string>
<string name="verify_omemo_keys">Overiť kľúče OMEMO</string>
<string name="pref_automatically_delete_messages_description">Automaticky vymazávať správy z tohto zariadenia, ktoré sú staršie ako nastavené časové obdobie.</string>
<string name="online_right_now">online práve teraz</string>
<string name="attach_record_video">Nahrať video</string>
<string name="copy_to_clipboard">Kopírovať do schránky</string>
<string name="message_copied_to_clipboard">Správa skopírovaná do schránky</string>
<string name="edit_status_message_title">Upraviť status správu</string>
<string name="edit_status_message">Upraviť status správu</string>
<string name="pref_omemo_setting">OMEMO šifrovanie</string>
<string name="pref_omemo_setting_summary_always">OMEMO bude vždy používané pre individuálne a súkromné skupinové rozhovory.</string>
<string name="pref_omemo_setting_summary_default_on">OMEMO bude predvolene zapnuté pre všetky rozhovory.</string>
<string name="pref_font_size">Veľkosť písma</string>
<string name="default_on">Predvolene zapnuté</string>
<string name="default_off">Predvolene vypnuté</string>
<string name="omemo_decryption_failed">Nepodarilo sa dešifrovať OMEMO správu.</string>
<string name="action_share_location">Zdieľať Polohu</string>
<string name="title_activity_share_location">Zdieľať polohu</string>
<string name="title_activity_show_location">Zobraziť polohu</string>
<string name="share">Zdieľať</string>
<string name="search_messages">Prehľadávať správy</string>
<string name="pref_use_share_location_plugin">Plugin na Zdieľanie Polohy</string>
<string name="pref_use_share_location_plugin_summary">Používať Plugin na Zdieľanie Polohy namiesto vstavanej mapy.</string>
<string name="foreground_service_channel_name">Služba v popredí</string>
<string name="notification_group_messages">Správy</string>
<string name="notification_group_calls">Hovory</string>
<string name="messages_channel_name">Správy</string>
<string name="incoming_calls_channel_name">Prichádzajúce hovory</string>
<string name="ongoing_calls_channel_name">Prebiehajúce hovory</string>
<string name="delivery_failed_channel_name">Zlyhané doručenia</string>
<string name="pref_incoming_call_notification_settings">Nastavenia oznámení prichádzajúcich hovorov</string>
<string name="enter_your_name_instructions">Prosím vložte vaše meno, aby ľudia, ktorí vás nemajú v adresári, vedeli kto ste.</string>
<string name="your_name">Vaše meno</string>
<string name="enter_your_name">Vložte vaše meno</string>
<string name="no_name_set_instructions">Pre nastavenie vášho mena, použite tlačidlo Upraviť.</string>
<string name="restore_backup">Obnoviť zálohu</string>
<string name="xmpp_address">XMPP adresa</string>
<string name="attach">Priložiť</string>
<string name="share_backup_files">Zdieľať súbory záloh</string>
<string name="backup">Zálohy</string>
<string name="category_about">O aplikácii</string>
<string name="rtp_state_incoming_call">Prichádzajúci hovor</string>
<string name="rtp_state_incoming_video_call">Prichádzajúci video hovor</string>
<string name="rtp_state_accepting_call">Prijímam hovor</string>
<string name="rtp_state_ending_call">Ukončujem hovor</string>
<string name="answer_call">Prijať</string>
<string name="dismiss_call">Odmietnuť</string>
<string name="rtp_state_finding_device">Vyhľadávanie zariadení</string>
<string name="rtp_state_ringing">Zvoní</string>
<string name="rtp_state_declined_or_busy">Zaneprázdnený</string>
<string name="rtp_state_connectivity_error">Nedá sa pripojiť hovor</string>
<string name="ongoing_call">Prebiehajúci hovor</string>
<string name="ongoing_video_call">Prebiehajúci video hovor</string>
@ -433,5 +522,9 @@
<string name="video_call">Video hovor</string>
<string name="only_one_call_at_a_time">Naraz môžete mať iba jeden hovor.</string>
<string name="return_to_ongoing_call">Vrátiť sa do prebiehajúceho hovoru</string>
<string name="add_to_favorites">Pripnúť na vrch</string>
<string name="remove_from_favorites">Odopnúť z vrchu</string>
<string name="encrypted_with_omemo">Zašifrované s OMEMO</string>
<string name="failed_deliveries">Zlyhané doručenia</string>
<string name="more_options">Viac možnosťí</string>
</resources>

View File

@ -129,6 +129,8 @@
<string name="pref_never_send_crash_summary">Bằng việc gửi báo cáo hoạt động, bạn đang hỗ trợ sự phát triển</string>
<string name="pref_confirm_messages">Xác nhận tin nhắn</string>
<string name="pref_confirm_messages_summary">Báo cho liên hệ của bạn biết khi bạn đã nhận và đọc tin nhắn</string>
<string name="pref_prevent_screenshots">Ngăn chặn chụp màn hình</string>
<string name="pref_prevent_screenshots_summary">Ẩn nội dung ứng dụng trong màn hình chuyển ứng dụng và chặn chụp màn hình</string>
<string name="pref_ui_options">UI</string>
<string name="openpgp_error">OpenKeychain đã có lỗi.</string>
<string name="bad_key_for_encryption">Mã khoá mã hoá bị lỗi.</string>
@ -411,6 +413,7 @@
<string name="audio">âm thanh</string>
<string name="video">video</string>
<string name="image">hình ảnh</string>
<string name="vector_graphic">hình ảnh véc tơ</string>
<string name="pdf_document">tài liệu PDF</string>
<string name="apk">Ứng dụng Android</string>
<string name="vcard">Liên hệ</string>
@ -901,6 +904,7 @@
<string name="rtp_state_connectivity_lost_error">Đã mất kết nối</string>
<string name="rtp_state_retracted">Cuộc gọi đã bị rút lại</string>
<string name="rtp_state_application_failure">Lỗi ứng dụng</string>
<string name="rtp_state_security_error">Vấn đề xác minh</string>
<string name="hang_up">Cúp máy</string>
<string name="ongoing_call">Cuộc gọi đang diễn ra</string>
<string name="ongoing_video_call">Cuộc gọi video đang diễn ra</string>
@ -950,4 +954,6 @@
<string name="no_active_accounts_support_this">Không có tài khoản đang hoạt động nào hỗ trợ tính năng này</string>
<string name="backup_started_message">Việc sao lưu đã được bắt đầu. Bạn sẽ nhận một thông báo khi việc đó đã hoàn tất.</string>
<string name="unable_to_enable_video">Không thể bật video.</string>
</resources>
<string name="plain_text_document">Tài liệu văn bản thuần</string>
</resources>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
<include
domain="sharedpref"
path="."
requireFlags="clientSideEncryption" />
<include
domain="database"
path="."
requireFlags="clientSideEncryption" />
</full-backup-content>

View File

@ -46,30 +46,30 @@ public class PhoneNumberContact extends AbstractPhoneContact {
ContactsContract.Data.PHOTO_URI,
ContactsContract.Data.LOOKUP_KEY,
ContactsContract.CommonDataKinds.Phone.NUMBER};
final Cursor cursor;
try {
cursor = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PROJECTION, null, null, null);
final HashMap<String, PhoneNumberContact> contacts = new HashMap<>();
try (final Cursor cursor = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PROJECTION, null, null, null)){
while (cursor != null && cursor.moveToNext()) {
try {
final PhoneNumberContact contact = new PhoneNumberContact(context, cursor);
final PhoneNumberContact preexisting = contacts.get(contact.getPhoneNumber());
if (preexisting == null || preexisting.rating() < contact.rating()) {
contacts.put(contact.getPhoneNumber(), contact);
}
} catch (final IllegalArgumentException ignored) {
}
}
} catch (final Exception e) {
return ImmutableMap.of();
}
final HashMap<String, PhoneNumberContact> contacts = new HashMap<>();
while (cursor != null && cursor.moveToNext()) {
try {
final PhoneNumberContact contact = new PhoneNumberContact(context, cursor);
final PhoneNumberContact preexisting = contacts.get(contact.getPhoneNumber());
if (preexisting == null || preexisting.rating() < contact.rating()) {
contacts.put(contact.getPhoneNumber(), contact);
}
} catch (final IllegalArgumentException e) {
Log.d(Config.LOGTAG, e.getMessage());
}
}
if (cursor != null) {
cursor.close();
}
return ImmutableMap.copyOf(contacts);
}
public static PhoneNumberContact findByUriOrNumber(Collection<PhoneNumberContact> haystack, Uri uri, String number) {
final PhoneNumberContact byUri = findByUri(haystack, uri);
return byUri != null || number == null ? byUri : findByNumber(haystack, number);
}
public static PhoneNumberContact findByUri(Collection<PhoneNumberContact> haystack, Uri needle) {
for (PhoneNumberContact contact : haystack) {
if (needle.equals(contact.getLookupUri())) {
@ -78,4 +78,13 @@ public class PhoneNumberContact extends AbstractPhoneContact {
}
return null;
}
private static PhoneNumberContact findByNumber(Collection<PhoneNumberContact> haystack, String needle) {
for (PhoneNumberContact contact : haystack) {
if (needle.equals(contact.getPhoneNumber())) {
return contact;
}
}
return null;
}
}

View File

@ -2,6 +2,9 @@ package eu.siacs.conversations.entities;
import android.util.Base64;
import com.google.common.base.Charsets;
import com.google.common.hash.Hashing;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
@ -63,20 +66,15 @@ public class Entry implements Comparable<Entry> {
builder.append(jid.asBareJid().toEscapedString());
}
}
MessageDigest md;
try {
md = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException e) {
return "";
}
byte[] sha1 = md.digest(builder.toString().getBytes());
@SuppressWarnings("deprecation")
final byte[] sha1 = Hashing.sha1().hashString(builder.toString(), Charsets.UTF_8).asBytes();
return new String(Base64.encode(sha1, Base64.DEFAULT)).trim();
}
private static List<Entry> ofPhoneNumberContactsAndContacts(final Collection<PhoneNumberContact> phoneNumberContacts, Collection<Contact> systemContacts) {
ArrayList<Entry> entries = new ArrayList<>();
final ArrayList<Entry> entries = new ArrayList<>();
for(Contact contact : systemContacts) {
PhoneNumberContact phoneNumberContact = PhoneNumberContact.findByUri(phoneNumberContacts, contact.getSystemAccount());
final PhoneNumberContact phoneNumberContact = PhoneNumberContact.findByUri(phoneNumberContacts, contact.getSystemAccount());
if (phoneNumberContact != null && phoneNumberContact.getPhoneNumber() != null) {
Entry entry = findOrCreateByPhoneNumber(entries, phoneNumberContact.getPhoneNumber());
entry.jids.add(contact.getJid().asBareJid());

View File

@ -382,9 +382,13 @@ public class QuickConversationsService extends AbstractQuickConversationsService
if (uri == null) {
continue;
}
PhoneNumberContact phoneNumberContact = PhoneNumberContact.findByUri(contacts, uri);
final String number = getNumber(contact);
final PhoneNumberContact phoneNumberContact = PhoneNumberContact.findByUriOrNumber(contacts, uri, number);
final boolean needsCacheClean;
if (phoneNumberContact != null) {
if (!uri.equals(phoneNumberContact.getLookupUri())) {
Log.d(Config.LOGTAG, "lookupUri has changed from " + uri + " to " + phoneNumberContact.getLookupUri());
}
needsCacheClean = contact.setPhoneContact(phoneNumberContact);
} else {
needsCacheClean = contact.unsetPhoneContact(PhoneNumberContact.class);
@ -396,6 +400,14 @@ public class QuickConversationsService extends AbstractQuickConversationsService
}
}
private static String getNumber(final Contact contact) {
final Jid jid = contact.getJid();
if (jid.getLocal() != null && Config.QUICKSY_DOMAIN.equals(jid.getDomain())) {
return jid.getLocal();
}
return null;
}
private boolean considerSync(final Account account, final Map<String, PhoneNumberContact> contacts, final boolean forced) {
final int hash = contacts.keySet().hashCode();
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": consider sync of " + hash);

View File

@ -2,10 +2,7 @@ package eu.siacs.conversations.ui;
import android.content.Context;
import android.content.Intent;
import androidx.databinding.DataBindingUtil;
import android.os.Bundle;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.appcompat.widget.Toolbar;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Menu;
@ -15,6 +12,10 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;
import androidx.appcompat.widget.Toolbar;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.LinearLayoutManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
@ -25,6 +26,7 @@ import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.ActivityChooseCountryBinding;
import eu.siacs.conversations.ui.adapter.CountryAdapter;
import eu.siacs.conversations.utils.PhoneNumberUtilWrapper;
import eu.siacs.conversations.utils.ThemeHelper;
public class ChooseCountryActivity extends ActionBarActivity implements CountryAdapter.OnCountryClicked {
@ -70,16 +72,17 @@ public class ChooseCountryActivity extends ActionBarActivity implements CountryA
return true;
}
};
private TextView.OnEditorActionListener mSearchDone = (v, actionId, event) -> {
if (countries.size() == 1) {
onCountryClicked(countries.get(0));
}
return true;
};
private TextView.OnEditorActionListener mSearchDone = (v, actionId, event) -> {
if (countries.size() == 1) {
onCountryClicked(countries.get(0));
}
return true;
};
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(ThemeHelper.find(this));
this.binding = DataBindingUtil.setContentView(this, R.layout.activity_choose_country);
setSupportActionBar((Toolbar) this.binding.toolbar);
configureActionBar(getSupportActionBar());
@ -115,9 +118,9 @@ public class ChooseCountryActivity extends ActionBarActivity implements CountryA
private void filterCountries(String needle) {
List<PhoneNumberUtilWrapper.Country> countries = PhoneNumberUtilWrapper.getCountries(this);
Iterator<PhoneNumberUtilWrapper.Country> iterator = countries.iterator();
while(iterator.hasNext()) {
while (iterator.hasNext()) {
final PhoneNumberUtilWrapper.Country country = iterator.next();
if(needle != null && !country.getName().toLowerCase(Locale.getDefault()).contains(needle.toLowerCase(Locale.getDefault()))) {
if (needle != null && !country.getName().toLowerCase(Locale.getDefault()).contains(needle.toLowerCase(Locale.getDefault()))) {
iterator.remove();
}
}

View File

@ -20,7 +20,7 @@ public class EnterNameActivity extends XmppActivity implements XmppConnectionSer
private Account account;
private AtomicBoolean setNick = new AtomicBoolean(false);
private final AtomicBoolean setNick = new AtomicBoolean(false);
@Override
protected void onCreate(final Bundle savedInstanceState) {

View File

@ -14,6 +14,8 @@ import android.view.KeyEvent;
import android.view.View;
import android.widget.EditText;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.atomic.AtomicBoolean;
import eu.siacs.conversations.Config;
@ -126,7 +128,7 @@ public class EnterPhoneNumberActivity extends XmppActivity implements QuickConve
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
public void onSaveInstanceState(@NotNull Bundle savedInstanceState) {
if (this.region != null) {
savedInstanceState.putString("region", this.region);
}

View File

@ -26,6 +26,8 @@ import android.widget.TextView;
import java.lang.ref.WeakReference;
import eu.siacs.conversations.ui.util.StyledAttributes;
public class TextDrawable extends Drawable implements TextWatcher {
private WeakReference<TextView> ref;
private String mText;
@ -62,6 +64,7 @@ public class TextDrawable extends Drawable implements TextWatcher {
*/
public TextDrawable(TextView tv, String initialText, boolean bindToViewsText, boolean bindToViewsPaint) {
this(tv.getPaint(), initialText);
mPaint.setColor(StyledAttributes.getColor(tv.getContext(), android.R.attr.textColorPrimary));
ref = new WeakReference<>(tv);
if (bindToViewsText || bindToViewsPaint) {
if (bindToViewsText) {
@ -157,6 +160,10 @@ public class TextDrawable extends Drawable implements TextWatcher {
setBounds(bounds);
}
public Paint getPaint() {
return mPaint;
}
public void setPaint(Paint paint) {
mPaint = new Paint(paint);
//Since this can change the font used, we need to recalculate bounds.
@ -168,8 +175,8 @@ public class TextDrawable extends Drawable implements TextWatcher {
invalidateSelf();
}
public Paint getPaint() {
return mPaint;
public String getText() {
return mText;
}
public void setText(String text) {
@ -183,10 +190,6 @@ public class TextDrawable extends Drawable implements TextWatcher {
invalidateSelf();
}
public String getText() {
return mText;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout
android:layout_width="match_parent"
@ -49,7 +50,7 @@
android:layout_height="wrap_content"
android:cursorVisible="false"
android:drawableEnd="@drawable/ic_arrow_drop_down_black_18dp"
android:drawableRight="@drawable/ic_arrow_drop_down_black_18dp"
app:drawableTint="?android:attr/textColorPrimary"
android:focusable="false"
android:gravity="bottom|center_horizontal"
android:imeOptions="flagNoExtractUi"

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="pref_notification_grace_period_summary">Doba, počas ktorej bude Quicksy stíšený po detekcii aktivity na inom zariadení.</string>
<string name="pref_never_send_crash_summary">Zaslaním detailov o dôvode zlyhania pomáhate ďalšiemu vývoju aplikácie Quicksy</string>
<string name="pref_broadcast_last_activity_summary">Dajte svojim kontaktom vedieť, keď používate Quicksy</string>
<string name="huawei_protected_apps_summary">Aby ste dostávali oznámenia aj pri vypnutej obrazovke, pridajte Quicksy medzi chránené aplikácie.</string>
<string name="set_profile_picture">Quicksy profilový obrázok</string>
<string name="not_available_in_your_country">Quicksy nie je dostupné vo vašej krajine.</string>
<string name="unable_to_verify_server_identity">Nemôžem overiť identitu servera.</string>
<string name="unknown_security_error">Neznáma bezpečnostná chyba.</string>
<string name="timeout_while_connecting_to_server">Vypršal časový limit pri pripájaní k serveru.</string>
</resources>