diff options
Diffstat (limited to 'src/main')
88 files changed, 2327 insertions, 890 deletions
diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 56ed5c76..d6991f88 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -197,13 +197,18 @@ <provider android:name="android.support.v4.content.FileProvider" - android:authorities="eu.siacs.conversations.files" + android:authorities="${applicationId}.files" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> + <provider + android:authorities="${applicationId}.barcodes" + android:name=".services.BarcodeProvider" + android:exported="false" + android:grantUriPermissions="true"/> </application> diff --git a/src/main/java/eu/siacs/conversations/Config.java b/src/main/java/eu/siacs/conversations/Config.java index 33069439..6d69d36e 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -78,6 +78,10 @@ public final class Config { public static final int MAX_DISPLAY_MESSAGE_CHARS = 4096; + public static final long MILLISECONDS_IN_DAY = 24 * 60 * 60 * 1000; + + public static final long OMEMO_AUTO_EXPIRY = 7 * MILLISECONDS_IN_DAY; + public static final boolean DISABLE_PROXY_LOOKUP = false; //useful to debug ibb public static final boolean DISABLE_HTTP_UPLOAD = false; public static final boolean DISABLE_STRING_PREP = false; // setting to true might increase startup performance @@ -93,11 +97,12 @@ public final class Config { public static final boolean X509_VERIFICATION = false; //use x509 certificates to verify OMEMO keys + public static final boolean ONLY_INTERNAL_STORAGE = false; //use internal storage instead of sdcard to save attachments + public static final boolean IGNORE_ID_REWRITE_IN_MUC = true; public static final boolean PARSE_REAL_JID_FROM_MUC_MAM = false; //dangerous if server doesn’t filter - public static final long MILLISECONDS_IN_DAY = 24 * 60 * 60 * 1000; public static final long MAM_MAX_CATCHUP = MILLISECONDS_IN_DAY / 2; public static final int MAM_MAX_MESSAGES = 500; diff --git a/src/main/java/eu/siacs/conversations/OmemoActivity.java b/src/main/java/eu/siacs/conversations/OmemoActivity.java index c4177cd2..c0c7b298 100644 --- a/src/main/java/eu/siacs/conversations/OmemoActivity.java +++ b/src/main/java/eu/siacs/conversations/OmemoActivity.java @@ -2,6 +2,7 @@ package eu.siacs.conversations; import android.app.AlertDialog; import android.content.DialogInterface; +import android.content.Intent; import android.os.Bundle; import android.view.ContextMenu; import android.view.MenuItem; @@ -12,13 +13,20 @@ import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; +import com.google.zxing.integration.android.IntentIntegrator; +import com.google.zxing.integration.android.IntentResult; + import java.security.cert.X509Certificate; +import java.util.Arrays; import eu.siacs.conversations.crypto.axolotl.FingerprintStatus; +import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession; import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.ui.TrustKeysActivity; import eu.siacs.conversations.ui.XmppActivity; import eu.siacs.conversations.ui.widget.Switch; import eu.siacs.conversations.utils.CryptoHelper; +import eu.siacs.conversations.utils.XmppUri; public abstract class OmemoActivity extends XmppActivity { @@ -26,13 +34,32 @@ public abstract class OmemoActivity extends XmppActivity { private Account mSelectedAccount; private String mSelectedFingerprint; + protected XmppUri mPendingFingerprintVerificationUri = null; + @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu,v,menuInfo); Object account = v.getTag(R.id.TAG_ACCOUNT); Object fingerprint = v.getTag(R.id.TAG_FINGERPRINT); - if (account != null && fingerprint != null && account instanceof Account && fingerprint instanceof String) { + Object fingerprintStatus = v.getTag(R.id.TAG_FINGERPRINT_STATUS);; + if (account != null + && fingerprint != null + && account instanceof Account + && fingerprintStatus != null + && fingerprint instanceof String + && fingerprintStatus instanceof FingerprintStatus) { getMenuInflater().inflate(R.menu.omemo_key_context, menu); + MenuItem purgeItem = menu.findItem(R.id.purge_omemo_key); + MenuItem verifyScan = menu.findItem(R.id.verify_scan); + if (this instanceof TrustKeysActivity) { + purgeItem.setVisible(false); + verifyScan.setVisible(false); + } else { + FingerprintStatus status = (FingerprintStatus) fingerprintStatus; + if (!status.isActive() || status.isVerified()) { + verifyScan.setVisible(false); + } + } this.mSelectedAccount = (Account) account; this.mSelectedFingerprint = (String) fingerprint; } @@ -47,10 +74,29 @@ public abstract class OmemoActivity extends XmppActivity { case R.id.copy_omemo_key: copyOmemoFingerprint(mSelectedFingerprint); break; + case R.id.verify_scan: + new IntentIntegrator(this).initiateScan(Arrays.asList("AZTEC","QR_CODE")); + break; } return true; } + @Override + public void onActivityResult(int requestCode, int resultCode, Intent intent) { + IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent); + if (scanResult != null && scanResult.getFormatName() != null) { + String data = scanResult.getContents(); + XmppUri uri = new XmppUri(data); + if (xmppConnectionServiceBound) { + processFingerprintVerification(uri); + } else { + this.mPendingFingerprintVerificationUri =uri; + } + } + } + + protected abstract void processFingerprintVerification(XmppUri uri); + protected void copyOmemoFingerprint(String fingerprint) { if (copyTextToClipboard(CryptoHelper.prettifyFingerprint(fingerprint.substring(2)), R.string.omemo_fingerprint)) { Toast.makeText( @@ -60,9 +106,17 @@ public abstract class OmemoActivity extends XmppActivity { } } - protected boolean addFingerprintRow(LinearLayout keys, final Account account, final String fingerprint, boolean highlight) { - final FingerprintStatus status = account.getAxolotlService().getFingerprintTrust(fingerprint); - return status != null && addFingerprintRowWithListeners(keys, account, fingerprint, highlight, status, true, true, new CompoundButton.OnCheckedChangeListener() { + protected void addFingerprintRow(LinearLayout keys, final XmppAxolotlSession session, boolean highlight) { + final Account account = session.getAccount(); + final String fingerprint = session.getFingerprint(); + addFingerprintRowWithListeners(keys, + session.getAccount(), + session.getFingerprint(), + highlight, + session.getTrust(), + true, + true, + new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { account.getAxolotlService().setFingerprintTrust(fingerprint, FingerprintStatus.createActive(isChecked)); @@ -70,7 +124,7 @@ public abstract class OmemoActivity extends XmppActivity { }); } - protected boolean addFingerprintRowWithListeners(LinearLayout keys, final Account account, + protected void addFingerprintRowWithListeners(LinearLayout keys, final Account account, final String fingerprint, boolean highlight, FingerprintStatus status, @@ -78,9 +132,6 @@ public abstract class OmemoActivity extends XmppActivity { boolean undecidedNeedEnablement, CompoundButton.OnCheckedChangeListener onCheckedChangeListener) { - if (status.isCompromised()) { - return false; - } View view = getLayoutInflater().inflate(R.layout.contact_key, keys, false); TextView key = (TextView) view.findViewById(R.id.key); TextView keyType = (TextView) view.findViewById(R.id.key_type); @@ -100,6 +151,7 @@ public abstract class OmemoActivity extends XmppActivity { registerForContextMenu(view); view.setTag(R.id.TAG_ACCOUNT,account); view.setTag(R.id.TAG_FINGERPRINT,fingerprint); + view.setTag(R.id.TAG_FINGERPRINT_STATUS,status); boolean x509 = Config.X509_VERIFICATION && status.getTrust() == FingerprintStatus.Trust.VERIFIED_X509; final View.OnClickListener toast; trustToggle.setChecked(status.isTrusted(), false); @@ -184,7 +236,6 @@ public abstract class OmemoActivity extends XmppActivity { key.setText(CryptoHelper.prettifyFingerprint(fingerprint.substring(2))); keys.addView(view); - return true; } public void showPurgeKeyDialog(final Account account, final String fingerprint) { diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java index 702d4ada..09beb22c 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java @@ -25,13 +25,17 @@ import java.security.PrivateKey; import java.security.Security; import java.security.Signature; import java.security.cert.X509Certificate; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Account; @@ -73,6 +77,8 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { private int numPublishTriesOnEmptyPep = 0; private boolean pepBroken = false; + private AtomicBoolean ownPushPending = new AtomicBoolean(false); + @Override public void onAdvancedStreamFeaturesAvailable(Account account) { if (Config.supportOmemo() @@ -88,7 +94,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { for(Jid jid : jids) { if (deviceIds.get(jid) != null) { for (Integer foreignId : this.deviceIds.get(jid)) { - AxolotlAddress address = new AxolotlAddress(jid.toString(), foreignId); + AxolotlAddress address = new AxolotlAddress(jid.toPreppedString(), foreignId); if (fetchStatusMap.getAll(address).containsValue(FetchStatus.ERROR)) { return true; } @@ -106,6 +112,15 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { axolotlStore.preVerifyFingerprint(account, account.getJid().toBareJid().toPreppedString(), fingerprint); } + public boolean hasVerifiedKeys(String name) { + for(XmppAxolotlSession session : this.sessions.getAll(new AxolotlAddress(name,0)).values()) { + if (session.getTrust().isVerified()) { + return true; + } + } + return false; + } + private static class AxolotlAddressMap<T> { protected Map<String, Map<Integer, T>> map; protected final Object MAP_LOCK = new Object(); @@ -172,7 +187,6 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { private void putDevicesForJid(String bareJid, List<Integer> deviceIds, SQLiteAxolotlStore store) { for (Integer deviceId : deviceIds) { AxolotlAddress axolotlAddress = new AxolotlAddress(bareJid, deviceId); - Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Building session for remote address: " + axolotlAddress.toString()); IdentityKey identityKey = store.loadSession(axolotlAddress).getSessionState().getRemoteIdentityKey(); if(Config.X509_VERIFICATION) { X509Certificate certificate = store.getFingerprintCertificate(identityKey.getFingerprint().replaceAll("\\s", "")); @@ -221,6 +235,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { SUCCESS, SUCCESS_VERIFIED, TIMEOUT, + SUCCESS_TRUSTED, ERROR } @@ -297,16 +312,20 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { return new AxolotlAddress(jid.toPreppedString(), 0); } - public Set<XmppAxolotlSession> findOwnSessions() { + public Collection<XmppAxolotlSession> findOwnSessions() { AxolotlAddress ownAddress = getAddressForJid(account.getJid().toBareJid()); - return new HashSet<>(this.sessions.getAll(ownAddress).values()); + ArrayList<XmppAxolotlSession> s = new ArrayList<>(this.sessions.getAll(ownAddress).values()); + Collections.sort(s); + return s; } - private Set<XmppAxolotlSession> findSessionsForContact(Contact contact) { + public Collection<XmppAxolotlSession> findSessionsForContact(Contact contact) { AxolotlAddress contactAddress = getAddressForJid(contact.getJid()); - return new HashSet<>(this.sessions.getAll(contactAddress).values()); + ArrayList<XmppAxolotlSession> s = new ArrayList<>(this.sessions.getAll(contactAddress).values()); + Collections.sort(s); + return s; } private Set<XmppAxolotlSession> findSessionsForConversation(Conversation conversation) { @@ -317,22 +336,6 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { return sessions; } - public Set<String> getFingerprintsForOwnSessions() { - Set<String> fingerprints = new HashSet<>(); - for (XmppAxolotlSession session : findOwnSessions()) { - fingerprints.add(session.getFingerprint()); - } - return fingerprints; - } - - public Set<String> getFingerprintsForContact(final Contact contact) { - Set<String> fingerprints = new HashSet<>(); - for (XmppAxolotlSession session : findSessionsForContact(contact)) { - fingerprints.add(session.getFingerprint()); - } - return fingerprints; - } - private boolean hasAny(Jid jid) { return sessions.hasAny(getAddressForJid(jid)); } @@ -366,23 +369,14 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } public void registerDevices(final Jid jid, @NonNull final Set<Integer> deviceIds) { - if (jid.toBareJid().equals(account.getJid().toBareJid())) { - if (!deviceIds.isEmpty()) { - Log.d(Config.LOGTAG, getLogprefix(account) + "Received non-empty own device list. Resetting publish attempts and pepBroken status."); - pepBroken = false; - numPublishTriesOnEmptyPep = 0; - } - if (deviceIds.contains(getOwnDeviceId())) { - deviceIds.remove(getOwnDeviceId()); - } else { - publishOwnDeviceId(deviceIds); - } - for (Integer deviceId : deviceIds) { - AxolotlAddress ownDeviceAddress = new AxolotlAddress(jid.toBareJid().toPreppedString(), deviceId); - if (sessions.get(ownDeviceAddress) == null) { - buildSessionFromPEP(ownDeviceAddress); - } - } + boolean me = jid.toBareJid().equals(account.getJid().toBareJid()); + if (me && ownPushPending.getAndSet(false)) { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": ignoring own device update because of pending push"); + return; + } + boolean needsPublishing = me && !deviceIds.contains(getOwnDeviceId()); + if (me) { + deviceIds.remove(getOwnDeviceId()); } Set<Integer> expiredDevices = new HashSet<>(axolotlStore.getSubDeviceSessions(jid.toBareJid().toPreppedString())); expiredDevices.removeAll(deviceIds); @@ -401,11 +395,27 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { XmppAxolotlSession session = sessions.get(address); if (session != null && session.getFingerprint() != null) { if (!session.getTrust().isActive()) { + Log.d(Config.LOGTAG,"reactivating device with fingprint "+session.getFingerprint()); session.setTrust(session.getTrust().toActive()); } } } + if (me) { + if (Config.OMEMO_AUTO_EXPIRY != 0) { + needsPublishing |= deviceIds.removeAll(getExpiredDevices()); + } + for (Integer deviceId : deviceIds) { + AxolotlAddress ownDeviceAddress = new AxolotlAddress(jid.toBareJid().toPreppedString(), deviceId); + if (sessions.get(ownDeviceAddress) == null) { + buildSessionFromPEP(ownDeviceAddress); + } + } + if (needsPublishing) { + publishOwnDeviceId(deviceIds); + } + } this.deviceIds.put(jid, deviceIds); + mXmppConnectionService.updateConversationUi(); //update the lock icon mXmppConnectionService.keyStatusUpdated(null); } @@ -418,12 +428,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { deviceIds.add(getOwnDeviceId()); IqPacket publish = mXmppConnectionService.getIqGenerator().publishDeviceIds(deviceIds); Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Wiping all other devices from Pep:" + publish); - mXmppConnectionService.sendIqPacket(account, publish, new OnIqPacketReceived() { - @Override - public void onIqPacketReceived(Account account, IqPacket packet) { - // TODO: implement this! - } - }); + mXmppConnectionService.sendIqPacket(account, publish, null); } public void purgeKey(final String fingerprint) { @@ -444,14 +449,30 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } else { Element item = mXmppConnectionService.getIqParser().getItem(packet); Set<Integer> deviceIds = mXmppConnectionService.getIqParser().deviceIds(item); - if (!deviceIds.contains(getOwnDeviceId())) { - publishOwnDeviceId(deviceIds); - } + registerDevices(account.getJid().toBareJid(),deviceIds); } } }); } + private Set<Integer> getExpiredDevices() { + Set<Integer> devices = new HashSet<>(); + for(XmppAxolotlSession session : findOwnSessions()) { + if (session.getTrust().isActive()) { + long diff = System.currentTimeMillis() - session.getTrust().getLastActivation(); + if (diff > Config.OMEMO_AUTO_EXPIRY) { + long lastMessageDiff = System.currentTimeMillis() - mXmppConnectionService.databaseBackend.getLastTimeFingerprintUsed(account,session.getFingerprint()); + if (lastMessageDiff > Config.OMEMO_AUTO_EXPIRY) { + devices.add(session.getRemoteAddress().getDeviceId()); + session.setTrust(session.getTrust().toInactive()); + Log.d(Config.LOGTAG, "added own device " + session.getFingerprint() + " to list of expired devices. Last message received "+(lastMessageDiff/1000)+"s ago"); + } + } + } + } + return devices; + } + public void publishOwnDeviceId(Set<Integer> deviceIds) { Set<Integer> deviceIdsCopy = new HashSet<>(deviceIds); if (!deviceIdsCopy.contains(getOwnDeviceId())) { @@ -470,9 +491,11 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } deviceIdsCopy.add(getOwnDeviceId()); IqPacket publish = mXmppConnectionService.getIqGenerator().publishDeviceIds(deviceIdsCopy); + ownPushPending.set(true); mXmppConnectionService.sendIqPacket(account, publish, new OnIqPacketReceived() { @Override public void onIqPacketReceived(Account account, IqPacket packet) { + ownPushPending.set(false); if (packet.getType() == IqPacket.TYPE.ERROR) { pepBroken = true; Log.d(Config.LOGTAG, getLogprefix(account) + "Error received while publishing own device id" + packet.findChild("error")); @@ -767,6 +790,8 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { report = FetchStatus.SUCCESS; } else if (own.containsValue(FetchStatus.SUCCESS_VERIFIED) || remote.containsValue(FetchStatus.SUCCESS_VERIFIED)) { report = FetchStatus.SUCCESS_VERIFIED; + } else if (own.containsValue(FetchStatus.SUCCESS_TRUSTED) || remote.containsValue(FetchStatus.SUCCESS_TRUSTED)) { + report = FetchStatus.SUCCESS_TRUSTED; } else if (own.containsValue(FetchStatus.ERROR) || remote.containsValue(FetchStatus.ERROR)) { report = FetchStatus.ERROR; } @@ -824,8 +849,15 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { verifySessionWithPEP(session); } else { FingerprintStatus status = getFingerprintTrust(bundle.getIdentityKey().getFingerprint().replaceAll("\\s","")); - boolean verified = status != null && status.isVerified(); - fetchStatusMap.put(address, verified ? FetchStatus.SUCCESS_VERIFIED : FetchStatus.SUCCESS); + FetchStatus fetchStatus; + if (status != null && status.isVerified()) { + fetchStatus = FetchStatus.SUCCESS_VERIFIED; + } else if (status != null && status.isTrusted()) { + fetchStatus = FetchStatus.SUCCESS_TRUSTED; + } else { + fetchStatus = FetchStatus.SUCCESS; + } + fetchStatusMap.put(address, fetchStatus); finishBuildingSessionsFromPEP(address); } } catch (UntrustedIdentityException | InvalidKeyException e) { @@ -852,7 +884,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Finding devices without session for " + jid); if (deviceIds.get(jid) != null) { for (Integer foreignId : this.deviceIds.get(jid)) { - AxolotlAddress address = new AxolotlAddress(jid.toString(), foreignId); + AxolotlAddress address = new AxolotlAddress(jid.toPreppedString(), foreignId); if (sessions.get(address) == null) { IdentityKey identityKey = axolotlStore.loadSession(address).getSessionState().getRemoteIdentityKey(); if (identityKey != null) { @@ -954,18 +986,14 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { account.getJid().toBareJid(), getOwnDeviceId()); Set<XmppAxolotlSession> remoteSessions = findSessionsForConversation(conversation); - Set<XmppAxolotlSession> ownSessions = findOwnSessions(); + Collection<XmppAxolotlSession> ownSessions = findOwnSessions(); if (remoteSessions.isEmpty()) { return null; } - Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Building axolotl foreign keyElements..."); for (XmppAxolotlSession session : remoteSessions) { - Log.v(Config.LOGTAG, AxolotlService.getLogprefix(account) + session.getRemoteAddress().toString()); axolotlMessage.addDevice(session); } - Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Building axolotl own keyElements..."); for (XmppAxolotlSession session : ownSessions) { - Log.v(Config.LOGTAG, AxolotlService.getLogprefix(account) + session.getRemoteAddress().toString()); axolotlMessage.addDevice(session); } @@ -1040,7 +1068,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } private XmppAxolotlSession getReceivingSession(XmppAxolotlMessage message) { - AxolotlAddress senderAddress = new AxolotlAddress(message.getFrom().toString(), + AxolotlAddress senderAddress = new AxolotlAddress(message.getFrom().toPreppedString(), message.getSenderDeviceId()); XmppAxolotlSession session = sessions.get(senderAddress); if (session == null) { diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/FingerprintStatus.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/FingerprintStatus.java index b594b5de..31b2264b 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/FingerprintStatus.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/FingerprintStatus.java @@ -3,10 +3,13 @@ package eu.siacs.conversations.crypto.axolotl; import android.content.ContentValues; import android.database.Cursor; -public class FingerprintStatus { +public class FingerprintStatus implements Comparable<FingerprintStatus> { + + private static final long DO_NOT_OVERWRITE = -1; private Trust trust = Trust.UNTRUSTED; private boolean active = false; + private long lastActivation = DO_NOT_OVERWRITE; @Override public boolean equals(Object o) { @@ -34,6 +37,9 @@ public class FingerprintStatus { final ContentValues contentValues = new ContentValues(); contentValues.put(SQLiteAxolotlStore.TRUST,trust.toString()); contentValues.put(SQLiteAxolotlStore.ACTIVE,active ? 1 : 0); + if (lastActivation != DO_NOT_OVERWRITE) { + contentValues.put(SQLiteAxolotlStore.LAST_ACTIVATION,lastActivation); + } return contentValues; } @@ -45,6 +51,7 @@ public class FingerprintStatus { status.trust = Trust.UNTRUSTED; } status.active = cursor.getInt(cursor.getColumnIndex(SQLiteAxolotlStore.ACTIVE)) > 0; + status.lastActivation = cursor.getLong(cursor.getColumnIndex(SQLiteAxolotlStore.LAST_ACTIVATION)); return status; } @@ -52,6 +59,15 @@ public class FingerprintStatus { final FingerprintStatus status = new FingerprintStatus(); status.trust = Trust.UNDECIDED; status.active = true; + status.lastActivation = System.currentTimeMillis(); + return status; + } + + public static FingerprintStatus createActiveTrusted() { + final FingerprintStatus status = new FingerprintStatus(); + status.trust = Trust.TRUSTED; + status.active = true; + status.lastActivation = System.currentTimeMillis(); return status; } @@ -92,6 +108,9 @@ public class FingerprintStatus { public FingerprintStatus toActive() { FingerprintStatus status = new FingerprintStatus(); status.trust = trust; + if (!status.active) { + status.lastActivation = System.currentTimeMillis(); + } status.active = true; return status; } @@ -128,6 +147,27 @@ public class FingerprintStatus { return status; } + @Override + public int compareTo(FingerprintStatus o) { + if (active == o.active) { + if (lastActivation > o.lastActivation) { + return -1; + } else if (lastActivation < o.lastActivation) { + return 1; + } else { + return 0; + } + } else if (active){ + return -1; + } else { + return 1; + } + } + + public long getLastActivation() { + return lastActivation; + } + public enum Trust { COMPROMISED, UNDECIDED, diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java index a3647be7..13858b74 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java @@ -21,7 +21,10 @@ import java.util.Set; import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.services.XmppConnectionService; +import eu.siacs.conversations.xmpp.jid.InvalidJidException; +import eu.siacs.conversations.xmpp.jid.Jid; public class SQLiteAxolotlStore implements AxolotlStore { @@ -38,6 +41,7 @@ public class SQLiteAxolotlStore implements AxolotlStore { public static final String TRUSTED = "trusted"; //no longer used public static final String TRUST = "trust"; public static final String ACTIVE = "active"; + public static final String LAST_ACTIVATION = "last_activation"; public static final String OWN = "ownkey"; public static final String CERTIFICATE = "certificate"; @@ -190,7 +194,12 @@ public class SQLiteAxolotlStore implements AxolotlStore { String fingerprint = identityKey.getFingerprint().replaceAll("\\s", ""); FingerprintStatus status = getFingerprintStatus(fingerprint); if (status == null) { - status = FingerprintStatus.createActiveUndecided(); //default for new keys + if (mXmppConnectionService.blindTrustBeforeVerification() && !account.getAxolotlService().hasVerifiedKeys(name)) { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": blindly trusted "+fingerprint+" of "+name); + status = FingerprintStatus.createActiveTrusted(); + } else { + status = FingerprintStatus.createActiveUndecided(); + } } else { status = status.toActive(); } diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java index 572d62c8..725757a3 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java @@ -22,7 +22,7 @@ import org.whispersystems.libaxolotl.protocol.WhisperMessage; import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Account; -public class XmppAxolotlSession { +public class XmppAxolotlSession implements Comparable<XmppAxolotlSession> { private final SessionCipher cipher; private final SQLiteAxolotlStore sqLiteAxolotlStore; private final AxolotlAddress remoteAddress; @@ -132,4 +132,13 @@ public class XmppAxolotlSession { return null; } } + + public Account getAccount() { + return account; + } + + @Override + public int compareTo(XmppAxolotlSession o) { + return getTrust().compareTo(o.getTrust()); + } } diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 77828b03..bb89cf17 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; @@ -340,6 +341,10 @@ public class Account extends AbstractEntity { } } + public State getTrueStatus() { + return this.status; + } + public void setStatus(final State status) { this.status = status; } @@ -489,7 +494,7 @@ public class Account extends AbstractEntity { if (publicKey == null || !(publicKey instanceof DSAPublicKey)) { return null; } - this.otrFingerprint = new OtrCryptoEngineImpl().getFingerprint(publicKey); + this.otrFingerprint = new OtrCryptoEngineImpl().getFingerprint(publicKey).toLowerCase(Locale.US); return this.otrFingerprint; } catch (final OtrCryptoException ignored) { return null; diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java index 55f5443a..b7307a8b 100644 --- a/src/main/java/eu/siacs/conversations/entities/Contact.java +++ b/src/main/java/eu/siacs/conversations/entities/Contact.java @@ -121,7 +121,7 @@ public class Contact implements ListItem, Blockable { } else if (this.presenceName != null && mutualPresenceSubscription()) { return this.presenceName; } else if (jid.hasLocalpart()) { - return jid.getLocalpart(); + return jid.getUnescapedLocalpart(); } else { return jid.getDomainpart(); } @@ -301,7 +301,7 @@ public class Contact implements ListItem, Blockable { for (int i = 0; i < prints.length(); ++i) { final String print = prints.isNull(i) ? null : prints.getString(i); if (print != null && !print.isEmpty()) { - fingerprints.add(prints.getString(i)); + fingerprints.add(prints.getString(i).toLowerCase(Locale.US)); } } } diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 245ff288..ced48913 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -20,6 +20,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; +import java.util.Locale; import eu.siacs.conversations.Config; import eu.siacs.conversations.crypto.PgpDecryptionService; @@ -463,7 +464,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl if (generatedName != null) { return generatedName; } else { - return getJid().getLocalpart(); + return getJid().getUnescapedLocalpart(); } } } else { @@ -627,7 +628,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl return null; } DSAPublicKey remotePubKey = (DSAPublicKey) getOtrSession().getRemotePublicKey(); - this.otrFingerprint = getAccount().getOtrService().getFingerprint(remotePubKey); + this.otrFingerprint = getAccount().getOtrService().getFingerprint(remotePubKey).toLowerCase(Locale.US); } catch (final OtrCryptoException | UnsupportedOperationException ignored) { return null; } diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index e9f16949..20e4c5a5 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -493,7 +493,7 @@ public class Message extends AbstractEntity { !this.getBody().startsWith(ME_COMMAND) && !this.bodyIsHeart() && !message.bodyIsHeart() && - this.isTrusted() == message.isTrusted() + ((this.axolotlFingerprint == null && message.axolotlFingerprint == null) || this.axolotlFingerprint.equals(message.getFingerprint())) ); } @@ -813,7 +813,7 @@ public class Message extends AbstractEntity { public boolean isTrusted() { FingerprintStatus s = conversation.getAccount().getAxolotlService().getFingerprintTrust(axolotlFingerprint); - return s != null && s.isTrustedAndActive(); + return s != null && s.isTrusted(); } private int getPreviousEncryption() { diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index 8e67aa41..bbc3e370 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -3,7 +3,6 @@ package eu.siacs.conversations.entities; import android.annotation.SuppressLint; import java.util.ArrayList; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -395,10 +394,20 @@ public class MucOptions { if (user != null) { synchronized (users) { users.remove(user); - if (membersOnly() && - nonanonymous() && - user.affiliation.ranks(Affiliation.MEMBER) && - user.realJid != null) { + boolean realJidInMuc = false; + for (User u : users) { + if (user.realJid != null && user.realJid.equals(u.realJid)) { + realJidInMuc = true; + break; + } + } + boolean self = user.realJid != null && user.realJid.equals(account.getJid().toBareJid()); + if (membersOnly() + && nonanonymous() + && user.affiliation.ranks(Affiliation.MEMBER) + && user.realJid != null + && !realJidInMuc + && !self) { user.role = Role.NONE; user.avatar = null; user.fullJid = null; @@ -508,8 +517,20 @@ public class MucOptions { } public List<User> getUsers(int max) { - ArrayList<User> users = getUsers(); - return users.subList(0, Math.min(max, users.size())); + ArrayList<User> subset = new ArrayList<>(); + HashSet<Jid> jids = new HashSet<>(); + jids.add(account.getJid().toBareJid()); + synchronized (users) { + for(User user : users) { + if (user.getRealJid() == null || jids.add(user.getRealJid())) { + subset.add(user); + } + if (subset.size() >= max) { + break; + } + } + } + return subset; } public int getUserCount() { diff --git a/src/main/java/eu/siacs/conversations/http/HttpConnectionManager.java b/src/main/java/eu/siacs/conversations/http/HttpConnectionManager.java index 1a417f32..18c60bff 100644 --- a/src/main/java/eu/siacs/conversations/http/HttpConnectionManager.java +++ b/src/main/java/eu/siacs/conversations/http/HttpConnectionManager.java @@ -24,6 +24,7 @@ import eu.siacs.conversations.services.AbstractConnectionManager; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.SSLSocketHelper; +import eu.siacs.conversations.utils.TLSSocketFactory; public class HttpConnectionManager extends AbstractConnectionManager { @@ -77,18 +78,7 @@ public class HttpConnectionManager extends AbstractConnectionManager { new StrictHostnameVerifier()); } try { - final SSLContext sc = SSLSocketHelper.getSSLContext(); - sc.init(null, new X509TrustManager[]{trustManager}, - mXmppConnectionService.getRNG()); - - final SSLSocketFactory sf = sc.getSocketFactory(); - final String[] cipherSuites = CryptoHelper.getOrderedCipherSuites( - sf.getSupportedCipherSuites()); - if (cipherSuites.length > 0) { - sc.getDefaultSSLParameters().setCipherSuites(cipherSuites); - - } - + final SSLSocketFactory sf = new TLSSocketFactory(new X509TrustManager[]{trustManager}, mXmppConnectionService.getRNG()); connection.setSSLSocketFactory(sf); connection.setHostnameVerifier(hostnameVerifier); } catch (final KeyManagementException | NoSuchAlgorithmException ignored) { diff --git a/src/main/java/eu/siacs/conversations/parser/IqParser.java b/src/main/java/eu/siacs/conversations/parser/IqParser.java index 49b0db21..40eec0d2 100644 --- a/src/main/java/eu/siacs/conversations/parser/IqParser.java +++ b/src/main/java/eu/siacs/conversations/parser/IqParser.java @@ -26,6 +26,7 @@ import eu.siacs.conversations.Config; import eu.siacs.conversations.crypto.axolotl.AxolotlService; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; +import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.utils.Xmlns; import eu.siacs.conversations.xml.Element; @@ -319,6 +320,14 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived { } } account.getBlocklist().addAll(jids); + if (packet.getType() == IqPacket.TYPE.SET) { + for(Jid jid : jids) { + Conversation conversation = mXmppConnectionService.find(account,jid); + if (conversation != null) { + mXmppConnectionService.markRead(conversation); + } + } + } } // Update the UI mXmppConnectionService.updateBlocklistUi(OnUpdateBlocklist.Status.BLOCKED); diff --git a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java index 1e50ce9c..63d5782b 100644 --- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java @@ -55,7 +55,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { private static DatabaseBackend instance = null; private static final String DATABASE_NAME = "history"; - private static final int DATABASE_VERSION = 31; + private static final int DATABASE_VERSION = 33; private static String CREATE_CONTATCS_STATEMENT = "create table " + Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, " @@ -132,6 +132,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { + SQLiteAxolotlStore.CERTIFICATE + " BLOB, " + SQLiteAxolotlStore.TRUST + " TEXT, " + SQLiteAxolotlStore.ACTIVE + " NUMBER, " + + SQLiteAxolotlStore.LAST_ACTIVATION + " NUMBER," + SQLiteAxolotlStore.KEY + " TEXT, FOREIGN KEY(" + SQLiteAxolotlStore.ACCOUNT + ") REFERENCES " + Account.TABLENAME + "(" + Account.UUID + ") ON DELETE CASCADE, " @@ -361,12 +362,12 @@ public class DatabaseBackend extends SQLiteOpenHelper { db.execSQL("ALTER TABLE "+ SQLiteAxolotlStore.IDENTITIES_TABLENAME + " ADD COLUMN "+SQLiteAxolotlStore.TRUST + " TEXT"); db.execSQL("ALTER TABLE "+ SQLiteAxolotlStore.IDENTITIES_TABLENAME + " ADD COLUMN "+SQLiteAxolotlStore.ACTIVE + " NUMBER"); HashMap<Integer,ContentValues> migration = new HashMap<>(); - migration.put(0,createFingerprintStatusContentValues(FingerprintStatus.Trust.UNDECIDED,true)); + migration.put(0,createFingerprintStatusContentValues(FingerprintStatus.Trust.TRUSTED,true)); migration.put(1,createFingerprintStatusContentValues(FingerprintStatus.Trust.TRUSTED, true)); migration.put(2,createFingerprintStatusContentValues(FingerprintStatus.Trust.UNTRUSTED, true)); migration.put(3,createFingerprintStatusContentValues(FingerprintStatus.Trust.COMPROMISED, false)); migration.put(4,createFingerprintStatusContentValues(FingerprintStatus.Trust.TRUSTED, false)); - migration.put(5,createFingerprintStatusContentValues(FingerprintStatus.Trust.UNDECIDED, false)); + migration.put(5,createFingerprintStatusContentValues(FingerprintStatus.Trust.TRUSTED, false)); migration.put(6,createFingerprintStatusContentValues(FingerprintStatus.Trust.UNTRUSTED, false)); migration.put(7,createFingerprintStatusContentValues(FingerprintStatus.Trust.VERIFIED_X509, true)); migration.put(8,createFingerprintStatusContentValues(FingerprintStatus.Trust.VERIFIED_X509, false)); @@ -377,6 +378,16 @@ public class DatabaseBackend extends SQLiteOpenHelper { } } + if (oldVersion < 32 && newVersion >= 32) { + db.execSQL("ALTER TABLE "+ SQLiteAxolotlStore.IDENTITIES_TABLENAME + " ADD COLUMN "+SQLiteAxolotlStore.LAST_ACTIVATION + " NUMBER"); + ContentValues defaults = new ContentValues(); + defaults.put(SQLiteAxolotlStore.LAST_ACTIVATION,System.currentTimeMillis()); + db.update(SQLiteAxolotlStore.IDENTITIES_TABLENAME,defaults,null,null); + } + if (oldVersion < 33 && newVersion >= 33) { + String whereClause = SQLiteAxolotlStore.OWN+"=1"; + db.update(SQLiteAxolotlStore.IDENTITIES_TABLENAME,createFingerprintStatusContentValues(FingerprintStatus.Trust.VERIFIED,true),whereClause,null); + } } private static ContentValues createFingerprintStatusContentValues(FingerprintStatus.Trust trust, boolean active) { @@ -780,6 +791,20 @@ public class DatabaseBackend extends SQLiteOpenHelper { } } + public long getLastTimeFingerprintUsed(Account account, String fingerprint) { + String SQL = "select messages.timeSent from accounts join conversations on accounts.uuid=conversations.accountUuid join messages on conversations.uuid=messages.conversationUuid where accounts.uuid=? and messages.axolotl_fingerprint=? order by messages.timesent desc limit 1"; + String[] args = {account.getUuid(), fingerprint}; + Cursor cursor = getReadableDatabase().rawQuery(SQL,args); + long time; + if (cursor.moveToFirst()) { + time = cursor.getLong(0); + } else { + time = 0; + } + cursor.close(); + return time; + } + public Pair<Long,String> getLastClearDate(Account account) { SQLiteDatabase db = this.getReadableDatabase(); String[] columns = {Conversation.ATTRIBUTES}; @@ -1046,6 +1071,7 @@ public class DatabaseBackend extends SQLiteOpenHelper { private Cursor getIdentityKeyCursor(SQLiteDatabase db, Account account, String name, Boolean own, String fingerprint) { String[] columns = {SQLiteAxolotlStore.TRUST, SQLiteAxolotlStore.ACTIVE, + SQLiteAxolotlStore.LAST_ACTIVATION, SQLiteAxolotlStore.KEY}; ArrayList<String> selectionArgs = new ArrayList<>(4); selectionArgs.add(account.getUuid()); @@ -1306,9 +1332,14 @@ public class DatabaseBackend extends SQLiteOpenHelper { return count >= Config.FREQUENT_RESTARTS_THRESHOLD; } - public void clearStartTimeCounter() { - Log.d(Config.LOGTAG,"resetting start time counter"); + public void clearStartTimeCounter(boolean justOne) { SQLiteDatabase db = this.getWritableDatabase(); - db.execSQL("delete from "+START_TIMES_TABLE); + if (justOne) { + db.execSQL("delete from "+START_TIMES_TABLE+" where timestamp in (select timestamp from "+START_TIMES_TABLE+" order by timestamp desc limit 1)"); + Log.d(Config.LOGTAG,"do not count start up after being swiped away"); + } else { + Log.d(Config.LOGTAG,"resetting start time counter"); + db.execSQL("delete from " + START_TIMES_TABLE); + } } } diff --git a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java index 1886d3c0..84330d16 100644 --- a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java @@ -60,7 +60,7 @@ import eu.siacs.conversations.xmpp.pep.Avatar; public class FileBackend { private static final SimpleDateFormat IMAGE_DATE_FORMAT = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US); - public static final String CONVERSATIONS_FILE_PROVIDER = "eu.siacs.conversations.files"; + private static final String FILE_PROVIDER = ".files"; private XmppConnectionService mXmppConnectionService; @@ -152,14 +152,26 @@ public class FileBackend { return true; } - public static String getConversationsFileDirectory() { - return Environment.getExternalStorageDirectory().getAbsolutePath()+"/Conversations/"; + public String getConversationsFileDirectory() { + if (Config.ONLY_INTERNAL_STORAGE) { + return mXmppConnectionService.getFilesDir().getAbsolutePath() + "/Files/"; + } else { + return Environment.getExternalStorageDirectory().getAbsolutePath() + "/Conversations/"; + } + } + + public String getConversationsImageDirectory() { + if (Config.ONLY_INTERNAL_STORAGE) { + return mXmppConnectionService.getFilesDir().getAbsolutePath()+"/Pictures/"; + } else { + return Environment.getExternalStoragePublicDirectory( + Environment.DIRECTORY_PICTURES).getAbsolutePath() + + "/Conversations/"; + } } - public static String getConversationsImageDirectory() { - return Environment.getExternalStoragePublicDirectory( - Environment.DIRECTORY_PICTURES).getAbsolutePath() - + "/Conversations/"; + public static String getConversationsLogsDirectory() { + return Environment.getExternalStorageDirectory().getAbsolutePath()+"/Conversations/"; } public Bitmap resize(Bitmap originalBitmap, int size) { @@ -451,17 +463,27 @@ public class FileBackend { } public Uri getTakePhotoUri() { - File file = new File(getTakePhotoPath()+"IMG_" + this.IMAGE_DATE_FORMAT.format(new Date()) + ".jpg"); + File file; + if (Config.ONLY_INTERNAL_STORAGE) { + file = new File(mXmppConnectionService.getCacheDir().getAbsolutePath(), "Camera/IMG_" + this.IMAGE_DATE_FORMAT.format(new Date()) + ".jpg"); + } else { + file = new File(getTakePhotoPath() + "IMG_" + this.IMAGE_DATE_FORMAT.format(new Date()) + ".jpg"); + } file.getParentFile().mkdirs(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - return FileProvider.getUriForFile(mXmppConnectionService, CONVERSATIONS_FILE_PROVIDER, file); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N || Config.ONLY_INTERNAL_STORAGE) { + return getUriForFile(mXmppConnectionService,file); } else { return Uri.fromFile(file); } } + public static Uri getUriForFile(Context context, File file) { + String packageId = context.getPackageName(); + return FileProvider.getUriForFile(context, packageId + FILE_PROVIDER, file); + } + public static Uri getIndexableTakePhotoUri(Uri original) { - if ("file".equals(original.getScheme())) { + if (Config.ONLY_INTERNAL_STORAGE || "file".equals(original.getScheme())) { return original; } else { List<String> segments = original.getPathSegments(); @@ -707,8 +729,7 @@ public class FileBackend { } public Uri getJingleFileUri(Message message) { - File file = getFile(message); - return Uri.parse("file://" + file.getAbsolutePath()); + return getUriForFile(mXmppConnectionService,getFile(message)); } public void updateFileParams(Message message) { diff --git a/src/main/java/eu/siacs/conversations/services/AbstractConnectionManager.java b/src/main/java/eu/siacs/conversations/services/AbstractConnectionManager.java index 8d02f975..dfe4cb28 100644 --- a/src/main/java/eu/siacs/conversations/services/AbstractConnectionManager.java +++ b/src/main/java/eu/siacs/conversations/services/AbstractConnectionManager.java @@ -55,7 +55,7 @@ public class AbstractConnectionManager { } public boolean hasStoragePermission() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (!Config.ONLY_INTERNAL_STORAGE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { return mXmppConnectionService.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; } else { return true; diff --git a/src/main/java/eu/siacs/conversations/services/AvatarService.java b/src/main/java/eu/siacs/conversations/services/AvatarService.java index 45a6fd81..4b4d1ed3 100644 --- a/src/main/java/eu/siacs/conversations/services/AvatarService.java +++ b/src/main/java/eu/siacs/conversations/services/AvatarService.java @@ -44,6 +44,9 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded { } private Bitmap get(final Contact contact, final int size, boolean cachedOnly) { + if (contact.isSelf()) { + return get(contact.getAccount(),size,cachedOnly); + } final String KEY = key(contact, size); Bitmap avatar = this.mXmppConnectionService.getBitmapCache().get(KEY); if (avatar != null || cachedOnly) { @@ -169,7 +172,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded { if (bitmap != null || cachedOnly) { return bitmap; } - final List<MucOptions.User> users = mucOptions.getUsers(); + final List<MucOptions.User> users = mucOptions.getUsers(5); int count = users.size(); bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); diff --git a/src/main/java/eu/siacs/conversations/services/BarcodeProvider.java b/src/main/java/eu/siacs/conversations/services/BarcodeProvider.java new file mode 100644 index 00000000..9c50b081 --- /dev/null +++ b/src/main/java/eu/siacs/conversations/services/BarcodeProvider.java @@ -0,0 +1,206 @@ +package eu.siacs.conversations.services; + +import android.content.ComponentName; +import android.content.ContentProvider; +import android.content.ContentValues; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.Color; +import android.net.Uri; +import android.os.CancellationSignal; +import android.os.IBinder; +import android.os.ParcelFileDescriptor; +import android.support.annotation.Nullable; +import android.util.Log; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.EncodeHintType; +import com.google.zxing.aztec.AztecWriter; +import com.google.zxing.common.BitMatrix; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.util.Hashtable; + +import eu.siacs.conversations.Config; +import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.utils.CryptoHelper; +import eu.siacs.conversations.xmpp.jid.Jid; + +public class BarcodeProvider extends ContentProvider implements ServiceConnection { + + private static final String AUTHORITY = ".barcodes"; + + private final Object lock = new Object(); + + private XmppConnectionService mXmppConnectionService; + private boolean mBindingInProcess = false; + + @Override + public boolean onCreate() { + File barcodeDirectory = new File(getContext().getCacheDir().getAbsolutePath() + "/barcodes/"); + if (barcodeDirectory.exists() && barcodeDirectory.isDirectory()) { + for (File file : barcodeDirectory.listFiles()) { + if (file.isFile() && !file.isHidden()) { + Log.d(Config.LOGTAG, "deleting old barcode file " + file.getAbsolutePath()); + file.delete(); + } + } + } + return true; + } + + @Nullable + @Override + public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { + return null; + } + + @Nullable + @Override + public String getType(Uri uri) { + return "image/png"; + } + + @Nullable + @Override + public Uri insert(Uri uri, ContentValues values) { + return null; + } + + @Override + public int delete(Uri uri, String selection, String[] selectionArgs) { + return 0; + } + + @Override + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + return 0; + } + + @Override + public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { + return openFile(uri, mode, null); + } + + @Override + public ParcelFileDescriptor openFile(Uri uri, String mode, CancellationSignal signal) throws FileNotFoundException { + Log.d(Config.LOGTAG, "opening file with uri (normal): " + uri.toString()); + String path = uri.getPath(); + if (path != null && path.endsWith(".png") && path.length() >= 5) { + String jid = path.substring(1).substring(0, path.length() - 4); + Log.d(Config.LOGTAG, "account:" + jid); + if (connectAndWait()) { + Log.d(Config.LOGTAG, "connected to background service"); + try { + Account account = mXmppConnectionService.findAccountByJid(Jid.fromString(jid)); + if (account != null) { + String shareableUri = account.getShareableUri(); + String hash = CryptoHelper.getFingerprint(shareableUri); + File file = new File(getContext().getCacheDir().getAbsolutePath() + "/barcodes/" + hash); + if (!file.exists()) { + file.getParentFile().mkdirs(); + file.createNewFile(); + Bitmap bitmap = createAztecBitmap(account.getShareableUri(), 1024); + OutputStream outputStream = new FileOutputStream(file); + bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream); + outputStream.close(); + outputStream.flush(); + } + return ParcelFileDescriptor.open(file,ParcelFileDescriptor.MODE_READ_ONLY); + } + } catch (Exception e) { + throw new FileNotFoundException(); + } + } + } + throw new FileNotFoundException(); + } + + private boolean connectAndWait() { + Intent intent = new Intent(getContext(), XmppConnectionService.class); + intent.setAction(this.getClass().getSimpleName()); + Context context = getContext(); + if (context != null) { + synchronized (this) { + if (mXmppConnectionService == null && !mBindingInProcess) { + Log.d(Config.LOGTAG,"calling to bind service"); + context.startService(intent); + context.bindService(intent, this, Context.BIND_AUTO_CREATE); + this.mBindingInProcess = true; + } + } + try { + waitForService(); + return true; + } catch (InterruptedException e) { + return false; + } + } else { + Log.d(Config.LOGTAG, "context was null"); + return false; + } + } + + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + synchronized (this) { + XmppConnectionService.XmppConnectionBinder binder = (XmppConnectionService.XmppConnectionBinder) service; + mXmppConnectionService = binder.getService(); + mBindingInProcess = false; + synchronized (this.lock) { + lock.notifyAll(); + } + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { + synchronized (this) { + mXmppConnectionService = null; + } + } + + private void waitForService() throws InterruptedException { + if (mXmppConnectionService == null) { + synchronized (this.lock) { + lock.wait(); + } + } else { + Log.d(Config.LOGTAG,"not waiting for service because already initialized"); + } + } + + public static Uri getUriForAccount(Context context, Account account) { + final String packageId = context.getPackageName(); + return Uri.parse("content://" + packageId + AUTHORITY + "/" + account.getJid().toBareJid() + ".png"); + } + + public static Bitmap createAztecBitmap(String input, int size) { + try { + final AztecWriter AZTEC_WRITER = new AztecWriter(); + final Hashtable<EncodeHintType, Object> hints = new Hashtable<>(); + hints.put(EncodeHintType.ERROR_CORRECTION, 10); + final BitMatrix result = AZTEC_WRITER.encode(input, BarcodeFormat.AZTEC, size, size, hints); + final int width = result.getWidth(); + final int height = result.getHeight(); + final int[] pixels = new int[width * height]; + for (int y = 0; y < height; y++) { + final int offset = y * width; + for (int x = 0; x < width; x++) { + pixels[offset + x] = result.get(x, y) ? Color.BLACK : Color.WHITE; + } + } + final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + bitmap.setPixels(pixels, 0, width, 0, 0, width, height); + return bitmap; + } catch (final Exception e) { + return null; + } + } +} diff --git a/src/main/java/eu/siacs/conversations/services/ExportLogsService.java b/src/main/java/eu/siacs/conversations/services/ExportLogsService.java index 87e65931..51eced05 100644 --- a/src/main/java/eu/siacs/conversations/services/ExportLogsService.java +++ b/src/main/java/eu/siacs/conversations/services/ExportLogsService.java @@ -26,7 +26,7 @@ import eu.siacs.conversations.xmpp.jid.Jid; public class ExportLogsService extends Service { private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); - private static final String DIRECTORY_STRING_FORMAT = FileBackend.getConversationsFileDirectory() + "/logs/%s"; + private static final String DIRECTORY_STRING_FORMAT = FileBackend.getConversationsLogsDirectory() + "/logs/%s"; private static final String MESSAGE_STRING_FORMAT = "(%s) %s: %s\n"; private static final int NOTIFICATION_ID = 1; private static AtomicBoolean running = new AtomicBoolean(false); diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java index 6e1d6c4b..47364b30 100644 --- a/src/main/java/eu/siacs/conversations/services/NotificationService.java +++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java @@ -34,6 +34,7 @@ import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.ui.ConversationActivity; import eu.siacs.conversations.ui.ManageAccountActivity; +import eu.siacs.conversations.ui.SettingsActivity; import eu.siacs.conversations.ui.TimePreference; import eu.siacs.conversations.utils.GeoHelper; import eu.siacs.conversations.utils.UIHelper; @@ -591,7 +592,7 @@ public class NotificationService { errors.add(account); } } - if (mXmppConnectionService.getPreferences().getBoolean("keep_foreground_service", false)) { + if (mXmppConnectionService.getPreferences().getBoolean(SettingsActivity.KEEP_FOREGROUND_SERVICE, false)) { notificationManager.notify(FOREGROUND_NOTIFICATION_ID, createForegroundNotification()); } final NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(mXmppConnectionService); diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 1321485d..b9aeffee 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -67,7 +67,6 @@ import eu.siacs.conversations.crypto.PgpEngine; import eu.siacs.conversations.crypto.axolotl.AxolotlService; import eu.siacs.conversations.crypto.axolotl.FingerprintStatus; import eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage; -import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Blockable; import eu.siacs.conversations.entities.Bookmark; @@ -94,6 +93,7 @@ import eu.siacs.conversations.parser.MessageParser; import eu.siacs.conversations.parser.PresenceParser; import eu.siacs.conversations.persistance.DatabaseBackend; import eu.siacs.conversations.persistance.FileBackend; +import eu.siacs.conversations.ui.SettingsActivity; import eu.siacs.conversations.ui.UiCallback; import eu.siacs.conversations.utils.ConversationsFileObserver; import eu.siacs.conversations.utils.CryptoHelper; @@ -335,32 +335,34 @@ public class XmppConnectionService extends Service { } account.pendingConferenceJoins.clear(); scheduleWakeUpCall(Config.PING_MAX_INTERVAL, account.getUuid().hashCode()); - } else if (account.getStatus() == Account.State.OFFLINE || account.getStatus() == Account.State.DISABLED) { - resetSendingToWaiting(account); - if (!account.isOptionSet(Account.OPTION_DISABLED)) { - synchronized (mLowPingTimeoutMode) { - if (mLowPingTimeoutMode.contains(account.getJid().toBareJid())) { - Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": went into offline state during low ping mode. reconnecting now"); - reconnectAccount(account, true, false); - } else { - int timeToReconnect = mRandom.nextInt(20) + 10; - scheduleWakeUpCall(timeToReconnect, account.getUuid().hashCode()); + } else { + if (account.getStatus() == Account.State.OFFLINE || account.getStatus() == Account.State.DISABLED) { + resetSendingToWaiting(account); + if (!account.isOptionSet(Account.OPTION_DISABLED)) { + synchronized (mLowPingTimeoutMode) { + if (mLowPingTimeoutMode.contains(account.getJid().toBareJid())) { + Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": went into offline state during low ping mode. reconnecting now"); + reconnectAccount(account, true, false); + } else { + int timeToReconnect = mRandom.nextInt(10) + 2; + scheduleWakeUpCall(timeToReconnect, account.getUuid().hashCode()); + } } } - } - } else if (account.getStatus() == Account.State.REGISTRATION_SUCCESSFUL) { - databaseBackend.updateAccount(account); - reconnectAccount(account, true, false); - } else if ((account.getStatus() != Account.State.CONNECTING) - && (account.getStatus() != Account.State.NO_INTERNET)) { - resetSendingToWaiting(account); - if (connection != null) { - int next = connection.getTimeToNextAttempt(); - Log.d(Config.LOGTAG, account.getJid().toBareJid() - + ": error connecting account. try again in " - + next + "s for the " - + (connection.getAttempt() + 1) + " time"); - scheduleWakeUpCall(next, account.getUuid().hashCode()); + } else if (account.getStatus() == Account.State.REGISTRATION_SUCCESSFUL) { + databaseBackend.updateAccount(account); + reconnectAccount(account, true, false); + } else if ((account.getStatus() != Account.State.CONNECTING) + && (account.getStatus() != Account.State.NO_INTERNET)) { + resetSendingToWaiting(account); + if (connection != null) { + int next = connection.getTimeToNextAttempt(); + Log.d(Config.LOGTAG, account.getJid().toBareJid() + + ": error connecting account. try again in " + + next + "s for the " + + (connection.getAttempt() + 1) + " time"); + scheduleWakeUpCall(next, account.getUuid().hashCode()); + } } } getNotificationService().updateErrorNotification(); @@ -547,7 +549,7 @@ public class XmppConnectionService extends Service { switch (action) { case ConnectivityManager.CONNECTIVITY_ACTION: if (hasInternetConnection() && Config.RESET_ATTEMPT_COUNT_ON_NETWORK_CHANGE) { - resetAllAttemptCounts(true); + resetAllAttemptCounts(true, false); } break; case ACTION_MERGE_PHONE_CONTACTS: @@ -566,14 +568,14 @@ public class XmppConnectionService extends Service { } break; case ACTION_DISABLE_FOREGROUND: - getPreferences().edit().putBoolean("keep_foreground_service", false).commit(); + getPreferences().edit().putBoolean(SettingsActivity.KEEP_FOREGROUND_SERVICE, false).commit(); toggleForegroundService(); break; case ACTION_DISMISS_ERROR_NOTIFICATIONS: dismissErrorNotifications(); break; case ACTION_TRY_AGAIN: - resetAllAttemptCounts(false); + resetAllAttemptCounts(false, true); interactive = true; break; case ACTION_REPLY_TO_CONVERSATION: @@ -611,103 +613,108 @@ public class XmppConnectionService extends Service { break; } } - this.wakeLock.acquire(); + synchronized (this) { + this.wakeLock.acquire(); + boolean pingNow = ConnectivityManager.CONNECTIVITY_ACTION.equals(action); + HashSet<Account> pingCandidates = new HashSet<>(); + for (Account account : accounts) { + pingNow |= processAccountState(account, + interactive, + "ui".equals(action), + CryptoHelper.getAccountFingerprint(account).equals(pushedAccountHash), + pingCandidates); + } + if (pingNow) { + for (Account account : pingCandidates) { + final boolean lowTimeout = mLowPingTimeoutMode.contains(account.getJid().toBareJid()); + account.getXmppConnection().sendPing(); + Log.d(Config.LOGTAG, account.getJid().toBareJid() + " send ping (action=" + action + ",lowTimeout=" + Boolean.toString(lowTimeout) + ")"); + scheduleWakeUpCall(lowTimeout ? Config.LOW_PING_TIMEOUT : Config.PING_TIMEOUT, account.getUuid().hashCode()); + } + } + if (wakeLock.isHeld()) { + try { + wakeLock.release(); + } catch (final RuntimeException ignored) { + } + } + } + return START_STICKY; + } + private boolean processAccountState(Account account, boolean interactive, boolean isUiAction, boolean isAccountPushed, HashSet<Account> pingCandidates) { boolean pingNow = false; - HashSet<Account> pingCandidates = new HashSet<>(); - - for (Account account : accounts) { - if (!account.isOptionSet(Account.OPTION_DISABLED)) { - if (!hasInternetConnection()) { - account.setStatus(Account.State.NO_INTERNET); + if (!account.isOptionSet(Account.OPTION_DISABLED)) { + if (!hasInternetConnection()) { + account.setStatus(Account.State.NO_INTERNET); + if (statusListener != null) { + statusListener.onStatusChanged(account); + } + } else { + if (account.getStatus() == Account.State.NO_INTERNET) { + account.setStatus(Account.State.OFFLINE); if (statusListener != null) { statusListener.onStatusChanged(account); } - } else { - if (account.getStatus() == Account.State.NO_INTERNET) { - account.setStatus(Account.State.OFFLINE); - if (statusListener != null) { - statusListener.onStatusChanged(account); - } - } - if (account.getStatus() == Account.State.ONLINE) { - synchronized (mLowPingTimeoutMode) { - long lastReceived = account.getXmppConnection().getLastPacketReceived(); - long lastSent = account.getXmppConnection().getLastPingSent(); - long pingInterval = "ui".equals(action) ? Config.PING_MIN_INTERVAL * 1000 : Config.PING_MAX_INTERVAL * 1000; - long msToNextPing = (Math.max(lastReceived, lastSent) + pingInterval) - SystemClock.elapsedRealtime(); - int pingTimeout = mLowPingTimeoutMode.contains(account.getJid().toBareJid()) ? Config.LOW_PING_TIMEOUT * 1000 : Config.PING_TIMEOUT * 1000; - long pingTimeoutIn = (lastSent + pingTimeout) - SystemClock.elapsedRealtime(); - if (lastSent > lastReceived) { - if (pingTimeoutIn < 0) { - Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": ping timeout"); - this.reconnectAccount(account, true, interactive); - } else { - int secs = (int) (pingTimeoutIn / 1000); - this.scheduleWakeUpCall(secs, account.getUuid().hashCode()); + } + if (account.getStatus() == Account.State.ONLINE) { + synchronized (mLowPingTimeoutMode) { + long lastReceived = account.getXmppConnection().getLastPacketReceived(); + long lastSent = account.getXmppConnection().getLastPingSent(); + long pingInterval = isUiAction ? Config.PING_MIN_INTERVAL * 1000 : Config.PING_MAX_INTERVAL * 1000; + long msToNextPing = (Math.max(lastReceived, lastSent) + pingInterval) - SystemClock.elapsedRealtime(); + int pingTimeout = mLowPingTimeoutMode.contains(account.getJid().toBareJid()) ? Config.LOW_PING_TIMEOUT * 1000 : Config.PING_TIMEOUT * 1000; + long pingTimeoutIn = (lastSent + pingTimeout) - SystemClock.elapsedRealtime(); + if (lastSent > lastReceived) { + if (pingTimeoutIn < 0) { + Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": ping timeout"); + this.reconnectAccount(account, true, interactive); + } else { + int secs = (int) (pingTimeoutIn / 1000); + this.scheduleWakeUpCall(secs, account.getUuid().hashCode()); + } + } else { + pingCandidates.add(account); + if (isAccountPushed) { + pingNow = true; + if (mLowPingTimeoutMode.add(account.getJid().toBareJid())) { + Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": entering low ping timeout mode"); } + } else if (msToNextPing <= 0) { + pingNow = true; } else { - pingCandidates.add(account); - if (CryptoHelper.getAccountFingerprint(account).equals(pushedAccountHash)) { - pingNow = true; - if (mLowPingTimeoutMode.add(account.getJid().toBareJid())) { - Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": entering low ping timeout mode"); - } - } else if (msToNextPing <= 0) { - pingNow = true; - } else { - this.scheduleWakeUpCall((int) (msToNextPing / 1000), account.getUuid().hashCode()); - if (mLowPingTimeoutMode.remove(account.getJid().toBareJid())) { - Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": leaving low ping timeout mode"); - } + this.scheduleWakeUpCall((int) (msToNextPing / 1000), account.getUuid().hashCode()); + if (mLowPingTimeoutMode.remove(account.getJid().toBareJid())) { + Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": leaving low ping timeout mode"); } } } - } else if (account.getStatus() == Account.State.OFFLINE) { + } + } else if (account.getStatus() == Account.State.OFFLINE) { + reconnectAccount(account, true, interactive); + } else if (account.getStatus() == Account.State.CONNECTING) { + long secondsSinceLastConnect = (SystemClock.elapsedRealtime() - account.getXmppConnection().getLastConnect()) / 1000; + long secondsSinceLastDisco = (SystemClock.elapsedRealtime() - account.getXmppConnection().getLastDiscoStarted()) / 1000; + long discoTimeout = Config.CONNECT_DISCO_TIMEOUT - secondsSinceLastDisco; + long timeout = Config.CONNECT_TIMEOUT - secondsSinceLastConnect; + if (timeout < 0) { + Log.d(Config.LOGTAG, account.getJid() + ": time out during connect reconnecting (secondsSinceLast="+secondsSinceLastConnect+")"); + account.getXmppConnection().resetAttemptCount(false); reconnectAccount(account, true, interactive); - } else if (account.getStatus() == Account.State.CONNECTING) { - long secondsSinceLastConnect = (SystemClock.elapsedRealtime() - account.getXmppConnection().getLastConnect()) / 1000; - long secondsSinceLastDisco = (SystemClock.elapsedRealtime() - account.getXmppConnection().getLastDiscoStarted()) / 1000; - long discoTimeout = Config.CONNECT_DISCO_TIMEOUT - secondsSinceLastDisco; - long timeout = Config.CONNECT_TIMEOUT - secondsSinceLastConnect; - if (timeout < 0) { - Log.d(Config.LOGTAG, account.getJid() + ": time out during connect reconnecting"); - account.getXmppConnection().resetAttemptCount(); - reconnectAccount(account, true, interactive); - } else if (discoTimeout < 0) { - account.getXmppConnection().sendDiscoTimeout(); - scheduleWakeUpCall((int) Math.min(timeout,discoTimeout), account.getUuid().hashCode()); - } else { - scheduleWakeUpCall((int) Math.min(timeout,discoTimeout), account.getUuid().hashCode()); - } + } else if (discoTimeout < 0) { + account.getXmppConnection().sendDiscoTimeout(); + scheduleWakeUpCall((int) Math.min(timeout,discoTimeout), account.getUuid().hashCode()); } else { - if (account.getXmppConnection().getTimeToNextAttempt() <= 0) { - reconnectAccount(account, true, interactive); - } + scheduleWakeUpCall((int) Math.min(timeout,discoTimeout), account.getUuid().hashCode()); + } + } else { + if (account.getXmppConnection().getTimeToNextAttempt() <= 0) { + reconnectAccount(account, true, interactive); } } - if (mOnAccountUpdate != null) { - mOnAccountUpdate.onAccountUpdate(); - } - } - } - if (pingNow) { - for (Account account : pingCandidates) { - synchronized (mLowPingTimeoutMode) { - final boolean lowTimeout = mLowPingTimeoutMode.contains(account.getJid().toBareJid()); - account.getXmppConnection().sendPing(); - Log.d(Config.LOGTAG, account.getJid().toBareJid() + " send ping (action=" + action + ",lowTimeout=" + Boolean.toString(lowTimeout) + ")"); - scheduleWakeUpCall(lowTimeout ? Config.LOW_PING_TIMEOUT : Config.PING_TIMEOUT, account.getUuid().hashCode()); - } - } - } - if (wakeLock.isHeld()) { - try { - wakeLock.release(); - } catch (final RuntimeException ignored) { } } - return START_STICKY; + return pingNow; } public boolean isDataSaverDisabled() { @@ -761,15 +768,15 @@ public class XmppConnectionService extends Service { } private boolean manuallyChangePresence() { - return getPreferences().getBoolean("manually_change_presence", false); + return getPreferences().getBoolean(SettingsActivity.MANUALLY_CHANGE_PRESENCE, false); } private boolean treatVibrateAsSilent() { - return getPreferences().getBoolean("treat_vibrate_as_silent", false); + return getPreferences().getBoolean(SettingsActivity.TREAT_VIBRATE_AS_SILENT, false); } private boolean awayWhenScreenOff() { - return getPreferences().getBoolean("away_when_screen_off", false); + return getPreferences().getBoolean(SettingsActivity.AWAY_WHEN_SCREEN_IS_OFF, false); } private String getCompressPicturesPreference() { @@ -814,13 +821,13 @@ public class XmppConnectionService extends Service { } } - private void resetAllAttemptCounts(boolean reallyAll) { + private void resetAllAttemptCounts(boolean reallyAll, boolean retryImmediately) { Log.d(Config.LOGTAG, "resetting all attempt counts"); for (Account account : accounts) { if (account.hasErrorStatus() || reallyAll) { final XmppConnection connection = account.getXmppConnection(); if (connection != null) { - connection.resetAttemptCount(); + connection.resetAttemptCount(retryImmediately); } } if (account.setShowErrorNotification(true)) { @@ -868,7 +875,7 @@ public class XmppConnectionService extends Service { this.accounts = databaseBackend.getAccounts(); if (!keepForegroundService() && databaseBackend.startTimeCountExceedsThreshold()) { - getPreferences().edit().putBoolean("keep_foreground_service",true).commit(); + getPreferences().edit().putBoolean(SettingsActivity.KEEP_FOREGROUND_SERVICE,true).commit(); Log.d(Config.LOGTAG,"number of restarts exceeds threshold. enabling foreground service"); } @@ -957,7 +964,7 @@ public class XmppConnectionService extends Service { } private boolean keepForegroundService() { - return getPreferences().getBoolean("keep_foreground_service",false); + return getPreferences().getBoolean(SettingsActivity.KEEP_FOREGROUND_SERVICE,false); } @Override @@ -972,7 +979,7 @@ public class XmppConnectionService extends Service { private void logoutAndSave(boolean stop) { int activeAccounts = 0; - databaseBackend.clearStartTimeCounter(); // regular swipes don't count towards restart counter + databaseBackend.clearStartTimeCounter(true); // regular swipes don't count towards restart counter for (final Account account : accounts) { if (account.getStatus() != Account.State.DISABLED) { activeAccounts++; @@ -2890,8 +2897,6 @@ public class XmppConnectionService extends Service { if (connection == null) { connection = createConnection(account); account.setXmppConnection(connection); - } else { - connection.interrupt(); } if (!account.isOptionSet(Account.OPTION_DISABLED)) { if (!force) { @@ -2900,10 +2905,11 @@ public class XmppConnectionService extends Service { Thread thread = new Thread(connection); connection.setInteractive(interactive); connection.prepareNewConnection(); + connection.interrupt(); thread.start(); scheduleWakeUpCall(Config.CONNECT_DISCO_TIMEOUT, account.getUuid().hashCode()); } else { - disconnect(account, force); + disconnect(account, force || account.getTrueStatus().isError()); account.getRoster().clearPresences(); connection.resetEverything(); account.getAxolotlService().resetBrokenness(); @@ -3606,22 +3612,25 @@ public class XmppConnectionService extends Service { mDatabaseExecutor.execute(new Runnable() { @Override public void run() { - databaseBackend.clearStartTimeCounter(); + databaseBackend.clearStartTimeCounter(false); } }); } - public void verifyFingerprints(Contact contact, List<XmppUri.Fingerprint> fingerprints) { + public boolean verifyFingerprints(Contact contact, List<XmppUri.Fingerprint> fingerprints) { boolean needsRosterWrite = false; + boolean performedVerification = false; final AxolotlService axolotlService = contact.getAccount().getAxolotlService(); for(XmppUri.Fingerprint fp : fingerprints) { if (fp.type == XmppUri.FingerprintType.OTR) { - needsRosterWrite |= contact.addOtrFingerprint(fp.fingerprint); + performedVerification |= contact.addOtrFingerprint(fp.fingerprint); + needsRosterWrite |= performedVerification; } else if (fp.type == XmppUri.FingerprintType.OMEMO) { String fingerprint = "05"+fp.fingerprint.replaceAll("\\s",""); FingerprintStatus fingerprintStatus = axolotlService.getFingerprintTrust(fingerprint); if (fingerprintStatus != null) { if (!fingerprintStatus.isVerified()) { + performedVerification = true; axolotlService.setFingerprintTrust(fingerprint,fingerprintStatus.toVerified()); } } else { @@ -3632,6 +3641,7 @@ public class XmppConnectionService extends Service { if (needsRosterWrite) { syncRosterToDisk(contact.getAccount()); } + return performedVerification; } public boolean verifyFingerprints(Account account, List<XmppUri.Fingerprint> fingerprints) { @@ -3656,6 +3666,10 @@ public class XmppConnectionService extends Service { return verifiedSomething; } + public boolean blindTrustBeforeVerification() { + return getPreferences().getBoolean(SettingsActivity.BLIND_TRUST_BEFORE_VERIFICATION, true); + } + public interface OnMamPreferencesFetched { void onPreferencesFetched(Element prefs); void onPreferencesFetchFailed(); diff --git a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java index 7791372a..42eb49fb 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java @@ -380,7 +380,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers MenuItem invite = menu.findItem(R.id.invite); startConversation.setVisible(true); if (contact != null) { - showContactDetails.setVisible(true); + showContactDetails.setVisible(!contact.isSelf()); } if (user.getRole() == MucOptions.Role.NONE) { invite.setVisible(true); diff --git a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java index a567f151..296a10c2 100644 --- a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java @@ -41,6 +41,7 @@ import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.PgpEngine; import eu.siacs.conversations.crypto.axolotl.AxolotlService; import eu.siacs.conversations.crypto.axolotl.FingerprintStatus; +import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.ListItem; @@ -48,6 +49,7 @@ import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate; import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate; import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.UIHelper; +import eu.siacs.conversations.utils.XmppUri; import eu.siacs.conversations.xmpp.OnKeyStatusUpdated; import eu.siacs.conversations.xmpp.OnUpdateBlocklist; import eu.siacs.conversations.xmpp.XmppConnection; @@ -445,9 +447,12 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp } } if (Config.supportOmemo()) { - for (final String fingerprint : contact.getAccount().getAxolotlService().getFingerprintsForContact(contact)) { - boolean highlight = fingerprint.equals(messageFingerprint); - hasKeys |= addFingerprintRow(keys, contact.getAccount(), fingerprint, highlight); + for (final XmppAxolotlSession session : contact.getAccount().getAxolotlService().findSessionsForContact(contact)) { + if (!session.getTrust().isCompromised()) { + boolean highlight = session.getFingerprint().equals(messageFingerprint); + hasKeys = true; + addFingerprintRow(keys, session, highlight); + } } } if (Config.supportOpenPgp() && contact.getPgpKeyId() != 0) { @@ -524,13 +529,16 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp } public void onBackendConnected() { - if ((accountJid != null) && (contactJid != null)) { - Account account = xmppConnectionService - .findAccountByJid(accountJid); + if (accountJid != null && contactJid != null) { + Account account = xmppConnectionService.findAccountByJid(accountJid); if (account == null) { return; } this.contact = account.getRoster().getContact(contactJid); + if (mPendingFingerprintVerificationUri != null) { + processFingerprintVerification(mPendingFingerprintVerificationUri); + mPendingFingerprintVerificationUri = null; + } populateView(); } } @@ -539,4 +547,15 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp public void onKeyStatusUpdated(AxolotlService.FetchStatus report) { refreshUi(); } + + @Override + protected void processFingerprintVerification(XmppUri uri) { + if (contact != null && contact.getJid().toBareJid().equals(uri.getJid()) && uri.hasFingerprints()) { + if (xmppConnectionService.verifyFingerprints(contact,uri.getFingerprints())) { + Toast.makeText(this,R.string.verified_fingerprints,Toast.LENGTH_SHORT).show(); + } + } else { + Toast.makeText(this,R.string.invalid_barcode,Toast.LENGTH_SHORT).show(); + } + } } diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index feabae11..d298aa28 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -497,6 +497,7 @@ public class ConversationActivity extends XmppActivity case ATTACHMENT_CHOICE_TAKE_PHOTO: Uri uri = xmppConnectionService.getFileBackend().getTakePhotoUri(); intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); mPendingImageUris.clear(); @@ -551,7 +552,7 @@ public class ConversationActivity extends XmppActivity public void attachFile(final int attachmentChoice) { if (attachmentChoice != ATTACHMENT_CHOICE_LOCATION) { - if (!hasStoragePermission(attachmentChoice)) { + if (!Config.ONLY_INTERNAL_STORAGE && !hasStoragePermission(attachmentChoice)) { return; } } @@ -648,7 +649,7 @@ public class ConversationActivity extends XmppActivity } public void startDownloadable(Message message) { - if (!hasStoragePermission(ConversationActivity.REQUEST_START_DOWNLOAD)) { + if (!Config.ONLY_INTERNAL_STORAGE && !hasStoragePermission(ConversationActivity.REQUEST_START_DOWNLOAD)) { this.mPendingDownloadableMessage = message; return; } @@ -1417,9 +1418,11 @@ public class ConversationActivity extends XmppActivity attachImageToConversation(getSelectedConversation(), uri); mPendingImageUris.clear(); } - Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); - intent.setData(uri); - sendBroadcast(intent); + if (!Config.ONLY_INTERNAL_STORAGE) { + Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); + intent.setData(uri); + sendBroadcast(intent); + } } else { mPendingImageUris.clear(); } diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 54b60949..761f8054 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -683,8 +683,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa shareIntent.setType("text/plain"); } else { shareIntent.putExtra(Intent.EXTRA_STREAM, - activity.xmppConnectionService.getFileBackend() - .getJingleFileUri(message)); + activity.xmppConnectionService.getFileBackend().getJingleFileUri(message)); shareIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); String mime = message.getMimeType(); if (mime == null) { @@ -946,15 +945,15 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa private void updateSnackBar(final Conversation conversation) { final Account account = conversation.getAccount(); - final Contact contact = conversation.getContact(); final int mode = conversation.getMode(); + final Contact contact = mode == Conversation.MODE_SINGLE ? conversation.getContact() : null; if (account.getStatus() == Account.State.DISABLED) { showSnackbar(R.string.this_account_is_disabled, R.string.enable, this.mEnableAccountListener); } else if (conversation.isBlocked()) { showSnackbar(R.string.contact_blocked, R.string.unblock, this.mUnblockClickListener); - } else if (!contact.showInRoster() && contact.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) { + } else if (contact != null && !contact.showInRoster() && contact.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) { showSnackbar(R.string.contact_added_you, R.string.add_back, this.mAddBackClickListener); - } else if (contact.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) { + } else if (contact != null && contact.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) { showSnackbar(R.string.contact_asks_for_presence_subscription, R.string.allow, this.mAllowPresenceSubscription); } else if (mode == Conversation.MODE_MULTI && !conversation.getMucOptions().online() diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java index 0f38173b..f48e8a48 100644 --- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java @@ -44,13 +44,16 @@ import eu.siacs.conversations.Config; import eu.siacs.conversations.OmemoActivity; import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.axolotl.AxolotlService; +import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession; import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.services.BarcodeProvider; import eu.siacs.conversations.services.XmppConnectionService.OnCaptchaRequested; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate; import eu.siacs.conversations.ui.adapter.KnownHostsAdapter; import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.UIHelper; +import eu.siacs.conversations.utils.XmppUri; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xmpp.OnKeyStatusUpdated; import eu.siacs.conversations.xmpp.XmppConnection; @@ -251,6 +254,7 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat private TableRow mPushRow; private String mSavedInstanceAccount; private boolean mSavedInstanceInit = false; + private Button mClearDevicesButton; public void refreshUiReal() { invalidateOptionsMenu(); @@ -373,13 +377,24 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat } @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { + public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_BATTERY_OP || requestCode == REQUEST_DATA_SAVER) { updateAccountInformation(mAccount == null); } } + @Override + protected void processFingerprintVerification(XmppUri uri) { + if (mAccount != null && mAccount.getJid().toBareJid().equals(uri.getJid()) && uri.hasFingerprints()) { + if (xmppConnectionService.verifyFingerprints(mAccount,uri.getFingerprints())) { + Toast.makeText(this,R.string.verified_fingerprints,Toast.LENGTH_SHORT).show(); + } + } else { + Toast.makeText(this,R.string.invalid_barcode,Toast.LENGTH_SHORT).show(); + } + } + protected void updateSaveButton() { boolean accountInfoEdited = accountInfoEdited(); @@ -502,6 +517,13 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat this.mNamePort = (LinearLayout) findViewById(R.id.name_port); this.mHostname = (EditText) findViewById(R.id.hostname); this.mHostname.addTextChangedListener(mTextWatcher); + this.mClearDevicesButton = (Button) findViewById(R.id.clear_devices); + this.mClearDevicesButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + showWipePepDialog(); + } + }); this.mPort = (EditText) findViewById(R.id.port); this.mPort.setText("5222"); this.mPort.addTextChangedListener(mTextWatcher); @@ -540,12 +562,14 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat final MenuItem showMoreInfo = menu.findItem(R.id.action_server_info_show_more); final MenuItem changePassword = menu.findItem(R.id.action_change_password_on_server); final MenuItem showPassword = menu.findItem(R.id.action_show_password); - final MenuItem clearDevices = menu.findItem(R.id.action_clear_devices); final MenuItem renewCertificate = menu.findItem(R.id.action_renew_certificate); final MenuItem mamPrefs = menu.findItem(R.id.action_mam_prefs); final MenuItem changePresence = menu.findItem(R.id.action_change_presence); + final MenuItem share = menu.findItem(R.id.action_share); renewCertificate.setVisible(mAccount != null && mAccount.getPrivateKeyAlias() != null); + share.setVisible(mAccount != null && !mInitMode); + if (mAccount != null && mAccount.isOnlineAndConnected()) { if (!mAccount.getXmppConnection().getFeatures().blocking()) { showBlocklist.setVisible(false); @@ -554,17 +578,12 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat changePassword.setVisible(false); } mamPrefs.setVisible(mAccount.getXmppConnection().getFeatures().mam()); - Set<Integer> otherDevices = mAccount.getAxolotlService().getOwnDeviceIds(); - if (otherDevices == null || otherDevices.isEmpty() || !Config.supportOmemo()) { - clearDevices.setVisible(false); - } changePresence.setVisible(manuallyChangePresence()); } else { showQrCode.setVisible(false); showBlocklist.setVisible(false); showMoreInfo.setVisible(false); changePassword.setVisible(false); - clearDevices.setVisible(false); mamPrefs.setVisible(false); changePresence.setVisible(false); } @@ -660,6 +679,10 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat this.mPassword.requestFocus(); } } + if (mPendingFingerprintVerificationUri != null) { + processFingerprintVerification(mPendingFingerprintVerificationUri); + mPendingFingerprintVerificationUri = null; + } updateAccountInformation(init); } @@ -700,15 +723,21 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat case R.id.action_server_info_show_more: changeMoreTableVisibility(!item.isChecked()); break; + case R.id.action_share_barcode: + shareBarcode(); + break; + case R.id.action_share_http: + shareLink(true); + break; + case R.id.action_share_uri: + shareLink(false); + break; case R.id.action_change_password_on_server: gotoChangePassword(null); break; case R.id.action_mam_prefs: editMamPrefs(); break; - case R.id.action_clear_devices: - showWipePepDialog(); - break; case R.id.action_renew_certificate: renewCertificate(); break; @@ -722,6 +751,27 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat return super.onOptionsItemSelected(item); } + private void shareLink(boolean http) { + Intent intent = new Intent(Intent.ACTION_SEND); + intent.setType("text/plain"); + String text; + if (http) { + text = "https://conversations.im/i/"+mAccount.getJid().toBareJid().toString(); + } else { + text = mAccount.getShareableUri(); + } + intent.putExtra(Intent.EXTRA_TEXT,text); + startActivity(Intent.createChooser(intent, getText(R.string.share_with))); + } + + private void shareBarcode() { + Intent intent = new Intent(Intent.ACTION_SEND); + intent.putExtra(Intent.EXTRA_STREAM,BarcodeProvider.getUriForAccount(this,mAccount)); + intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + intent.setType("image/png"); + startActivity(Intent.createChooser(intent, getText(R.string.share_with))); + } + private void changeMoreTableVisibility(boolean visible) { mMoreTable.setVisibility(visible ? View.VISIBLE : View.GONE); } @@ -904,15 +954,21 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat } boolean hasKeys = false; keys.removeAllViews(); - for (final String fingerprint : mAccount.getAxolotlService().getFingerprintsForOwnSessions()) { - if (ownAxolotlFingerprint.equals(fingerprint)) { - continue; + for(XmppAxolotlSession session : mAccount.getAxolotlService().findOwnSessions()) { + if (!session.getTrust().isCompromised()) { + boolean highlight = session.getFingerprint().equals(messageFingerprint); + addFingerprintRow(keys,session,highlight); + hasKeys = true; } - boolean highlight = fingerprint.equals(messageFingerprint); - hasKeys |= addFingerprintRow(keys, mAccount, fingerprint, highlight); } if (hasKeys && Config.supportOmemo()) { keysCard.setVisibility(View.VISIBLE); + Set<Integer> otherDevices = mAccount.getAxolotlService().getOwnDeviceIds(); + if (otherDevices == null || otherDevices.isEmpty()) { + mClearDevicesButton.setVisibility(View.GONE); + } else { + mClearDevicesButton.setVisibility(View.VISIBLE); + } } else { keysCard.setVisibility(View.GONE); } diff --git a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java index 7fcb1e3c..bc80f90a 100644 --- a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java @@ -7,6 +7,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.pm.PackageManager; +import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.preference.ListPreference; @@ -14,8 +15,10 @@ import android.preference.Preference; import android.preference.PreferenceCategory; import android.preference.PreferenceManager; import android.preference.PreferenceScreen; +import android.util.Log; import android.widget.Toast; +import java.io.File; import java.security.KeyStoreException; import java.util.ArrayList; import java.util.Arrays; @@ -35,6 +38,12 @@ import eu.siacs.conversations.xmpp.jid.Jid; public class SettingsActivity extends XmppActivity implements OnSharedPreferenceChangeListener { + public static final String KEEP_FOREGROUND_SERVICE = "enable_foreground_service"; + public static final String AWAY_WHEN_SCREEN_IS_OFF = "away_when_screen_off"; + public static final String TREAT_VIBRATE_AS_SILENT = "treat_vibrate_as_silent"; + public static final String MANUALLY_CHANGE_PRESENCE = "manually_change_presence"; + public static final String BLIND_TRUST_BEFORE_VERIFICATION = "btbv"; + public static final int REQUEST_WRITE_LOGS = 0xbf8701; private SettingsFragment mSettingsFragment; @@ -156,6 +165,26 @@ public class SettingsActivity extends XmppActivity implements } }); + if (Config.ONLY_INTERNAL_STORAGE) { + final Preference cleanCachePreference = mSettingsFragment.findPreference("clean_cache"); + cleanCachePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + cleanCache(); + return true; + } + }); + + final Preference cleanPrivateStoragePreference = mSettingsFragment.findPreference("clean_private_storage"); + cleanPrivateStoragePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + cleanPrivateStorage(); + return true; + } + }); + } + final Preference deleteOmemoPreference = mSettingsFragment.findPreference("delete_omemo_identities"); deleteOmemoPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override @@ -166,6 +195,57 @@ public class SettingsActivity extends XmppActivity implements }); } + private void cleanCache() { + Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + intent.setData(Uri.parse("package:" + getPackageName())); + startActivity(intent); + } + + private void cleanPrivateStorage() { + cleanPrivatePictures(); + cleanPrivateFiles(); + } + + private void cleanPrivatePictures() { + try { + File dir = new File(getFilesDir().getAbsolutePath(), "/Pictures/"); + File[] array = dir.listFiles(); + if (array != null) { + for (int b = 0; b < array.length; b++) { + String name = array[b].getName().toLowerCase(); + if (name.equals(".nomedia")) { + continue; + } + if (array[b].isFile()) { + array[b].delete(); + } + } + } + } catch (Throwable e) { + Log.e("CleanCache", e.toString()); + } + } + + private void cleanPrivateFiles() { + try { + File dir = new File(getFilesDir().getAbsolutePath(), "/Files/"); + File[] array = dir.listFiles(); + if (array != null) { + for (int b = 0; b < array.length; b++) { + String name = array[b].getName().toLowerCase(); + if (name.equals(".nomedia")) { + continue; + } + if (array[b].isFile()) { + array[b].delete(); + } + } + } + } catch (Throwable e) { + Log.e("CleanCache", e.toString()); + } + } + private void deleteOmemoIdentities() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.pref_delete_omemo_identities); @@ -227,10 +307,10 @@ public class SettingsActivity extends XmppActivity implements final List<String> resendPresence = Arrays.asList( "confirm_messages", "xa_on_silent_mode", - "away_when_screen_off", + AWAY_WHEN_SCREEN_IS_OFF, "allow_message_correction", - "treat_vibrate_as_silent", - "manually_change_presence", + TREAT_VIBRATE_AS_SILENT, + MANUALLY_CHANGE_PRESENCE, "last_activity"); if (name.equals("resource")) { String resource = preferences.getString("resource", "mobile") @@ -248,19 +328,18 @@ public class SettingsActivity extends XmppActivity implements } } } - } else if (name.equals("keep_foreground_service")) { - boolean foreground_service = preferences.getBoolean("keep_foreground_service",false); + } else if (name.equals(KEEP_FOREGROUND_SERVICE)) { + boolean foreground_service = preferences.getBoolean(KEEP_FOREGROUND_SERVICE,false); if (!foreground_service) { xmppConnectionService.clearStartTimeCounter(); } xmppConnectionService.toggleForegroundService(); } else if (resendPresence.contains(name)) { if (xmppConnectionServiceBound) { - if (name.equals("away_when_screen_off") - || name.equals("manually_change_presence")) { + if (name.equals(AWAY_WHEN_SCREEN_IS_OFF) || name.equals(MANUALLY_CHANGE_PRESENCE)) { xmppConnectionService.toggleScreenEventReceiver(); } - if (name.equals("manually_change_presence") && !noAccountUsesPgp()) { + if (name.equals(MANUALLY_CHANGE_PRESENCE) && !noAccountUsesPgp()) { Toast.makeText(this, R.string.republish_pgp_keys, Toast.LENGTH_LONG).show(); } xmppConnectionService.refreshAllPresences(); diff --git a/src/main/java/eu/siacs/conversations/ui/SettingsFragment.java b/src/main/java/eu/siacs/conversations/ui/SettingsFragment.java index e4185abc..b5529bad 100644 --- a/src/main/java/eu/siacs/conversations/ui/SettingsFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/SettingsFragment.java @@ -3,6 +3,7 @@ package eu.siacs.conversations.ui; import android.app.Dialog; import android.os.Bundle; import android.preference.Preference; +import android.preference.PreferenceCategory; import android.preference.PreferenceFragment; import android.preference.PreferenceScreen; import android.view.View; @@ -11,6 +12,7 @@ import android.view.ViewParent; import android.widget.FrameLayout; import android.widget.LinearLayout; +import eu.siacs.conversations.Config; import eu.siacs.conversations.R; public class SettingsFragment extends PreferenceFragment { @@ -52,6 +54,16 @@ public class SettingsFragment extends PreferenceFragment { // Load the preferences from an XML resource addPreferencesFromResource(R.xml.preferences); + + // Remove from standard preferences if the flag ONLY_INTERNAL_STORAGE is not true + if (!Config.ONLY_INTERNAL_STORAGE) { + PreferenceCategory mCategory = (PreferenceCategory) findPreference("security_options"); + Preference mPref1 = findPreference("clean_cache"); + Preference mPref2 = findPreference("clean_private_storage"); + mCategory.removePreference(mPref1); + mCategory.removePreference(mPref2); + } + } @Override diff --git a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java index 2d24fbbf..25ce50eb 100644 --- a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java @@ -401,7 +401,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU EnterJidDialog dialog = new EnterJidDialog( this, mKnownHosts, mActivatedAccounts, getString(R.string.create_contact), getString(R.string.create), - prefilledJid, null, !invite.hasFingerprints() + prefilledJid, null, invite == null || !invite.hasFingerprints() ); dialog.setOnEnterJidDialogPositiveListener(new EnterJidDialog.OnEnterJidDialogPositiveListener() { @@ -420,9 +420,11 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU if (contact.showInRoster()) { throw new EnterJidDialog.JidError(getString(R.string.contact_already_exists)); } else { - //contact.addOtrFingerprint(fingerprint); xmppConnectionService.createContact(contact); - switchToConversation(contact); + if (invite != null && invite.hasFingerprints()) { + xmppConnectionService.verifyFingerprints(contact,invite.getFingerprints()); + } + switchToConversation(contact, invite == null ? null : invite.getBody()); return true; } } @@ -561,11 +563,11 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU return xmppConnectionService.findAccountByJid(jid); } - protected void switchToConversation(Contact contact) { + protected void switchToConversation(Contact contact, String body) { Conversation conversation = xmppConnectionService .findOrCreateConversation(contact.getAccount(), contact.getJid(), false); - switchToConversation(conversation); + switchToConversation(conversation, body, false); } public static void populateAccountSpinner(Context context, List<String> accounts, Spinner spinner) { @@ -624,7 +626,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU showCreateConferenceDialog(); return true; case R.id.action_scan_qr_code: - new IntentIntegrator(this).initiateScan(); + new IntentIntegrator(this).initiateScan(Arrays.asList("AZTEC","QR_CODE")); return true; case R.id.action_hide_offline: mHideOfflineContacts = !item.isChecked(); @@ -843,7 +845,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU private boolean handleJid(Invite invite) { Account account = xmppConnectionService.findAccountByJid(invite.getJid()); - if (account != null && invite.hasFingerprints()) { + if (account != null && !account.isOptionSet(Account.OPTION_DISABLED) && invite.hasFingerprints()) { if (xmppConnectionService.verifyFingerprints(account,invite.getFingerprints())) { switchToAccount(account); finish(); @@ -854,7 +856,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU if (invite.isMuc()) { Conversation muc = xmppConnectionService.findFirstMuc(invite.getJid()); if (muc != null) { - switchToConversation(muc); + switchToConversation(muc,invite.getBody(),false); return true; } else { showJoinConferenceDialog(invite.getJid().toBareJid().toString()); @@ -868,7 +870,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU if (invite.hasFingerprints()) { xmppConnectionService.verifyFingerprints(contact,invite.getFingerprints()); } - switchToConversation(contact); + switchToConversation(contact,invite.getBody()); return true; } else { if (mMenuSearchView != null) { @@ -1054,10 +1056,14 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU activity.conference_context_id = acmi.position; } else if (mResContextMenu == R.menu.contact_context) { activity.contact_context_id = acmi.position; - final Blockable contact = (Contact) activity.contacts.get(acmi.position); + final Contact contact = (Contact) activity.contacts.get(acmi.position); final MenuItem blockUnblockItem = menu.findItem(R.id.context_contact_block_unblock); + final MenuItem showContactDetailsItem = menu.findItem(R.id.context_contact_details); + if (contact.isSelf()) { + showContactDetailsItem.setVisible(false); + } XmppConnection xmpp = contact.getAccount().getXmppConnection(); - if (xmpp != null && xmpp.getFeatures().blocking()) { + if (xmpp != null && xmpp.getFeatures().blocking() && !contact.isSelf()) { if (contact.isBlocked()) { blockUnblockItem.setTitle(R.string.unblock_contact); } else { diff --git a/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java b/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java index 26836395..1f7951e4 100644 --- a/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java @@ -1,7 +1,12 @@ package eu.siacs.conversations.ui; +import android.app.ActionBar; import android.content.Intent; import android.os.Bundle; +import android.util.Log; +import android.view.Gravity; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; @@ -10,9 +15,13 @@ import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; +import com.google.zxing.integration.android.IntentIntegrator; +import com.google.zxing.integration.android.IntentResult; + import org.whispersystems.libaxolotl.IdentityKey; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -23,9 +32,9 @@ import eu.siacs.conversations.OmemoActivity; import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.axolotl.AxolotlService; import eu.siacs.conversations.crypto.axolotl.FingerprintStatus; -import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.utils.XmppUri; import eu.siacs.conversations.xmpp.OnKeyStatusUpdated; import eu.siacs.conversations.xmpp.jid.InvalidJidException; import eu.siacs.conversations.xmpp.jid.Jid; @@ -64,6 +73,7 @@ public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdat finish(); } }; + private Toast mUseCameraHintToast = null; @Override protected void refreshUiReal() { @@ -102,6 +112,61 @@ public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdat } } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.trust_keys, menu); + mUseCameraHintToast = Toast.makeText(this,R.string.use_camera_icon_to_scan_barcode,Toast.LENGTH_LONG); + ActionBar actionBar = getActionBar(); + mUseCameraHintToast.setGravity(Gravity.TOP | Gravity.END, 0 ,actionBar == null ? 0 : actionBar.getHeight()); + mUseCameraHintToast.show(); + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.action_scan_qr_code: + if (hasPendingKeyFetches()) { + Toast.makeText(this, R.string.please_wait_for_keys_to_be_fetched, Toast.LENGTH_SHORT).show(); + } else { + new IntentIntegrator(this).initiateScan(Arrays.asList("AZTEC","QR_CODE")); + return true; + } + } + return super.onOptionsItemSelected(item); + } + + @Override + protected void onStop() { + super.onStop(); + if (mUseCameraHintToast != null) { + mUseCameraHintToast.cancel(); + } + } + + @Override + protected void processFingerprintVerification(XmppUri uri) { + if (mConversation != null + && mAccount != null + && uri.hasFingerprints() + && mAccount.getAxolotlService().getCryptoTargets(mConversation).contains(uri.getJid())) { + boolean performedVerification = xmppConnectionService.verifyFingerprints(mAccount.getRoster().getContact(uri.getJid()),uri.getFingerprints()); + boolean keys = reloadFingerprints(); + if (performedVerification && !keys && !hasNoOtherTrustedKeys() && !hasPendingKeyFetches()) { + Toast.makeText(this,R.string.all_omemo_keys_have_been_verified, Toast.LENGTH_SHORT).show(); + finishOk(); + return; + } else if (performedVerification) { + Toast.makeText(this,R.string.verified_fingerprints,Toast.LENGTH_SHORT).show(); + } + } else { + reloadFingerprints(); + Log.d(Config.LOGTAG,"xmpp uri was: "+uri.getJid()+" has Fingerprints: "+Boolean.toString(uri.hasFingerprints())); + Toast.makeText(this,R.string.barcode_does_not_contain_fingerprints_for_this_conversation,Toast.LENGTH_SHORT).show(); + } + populateView(); + } + private void populateView() { setTitle(getString(R.string.trust_omemo_fingerprints)); ownKeys.removeAllViews(); @@ -216,8 +281,13 @@ public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdat if (this.mAccount != null && intent != null) { String uuid = intent.getStringExtra("conversation"); this.mConversation = xmppConnectionService.findConversationByUuid(uuid); - reloadFingerprints(); - populateView(); + if (this.mPendingFingerprintVerificationUri != null) { + processFingerprintVerification(this.mPendingFingerprintVerificationUri); + this.mPendingFingerprintVerificationUri = null; + } else { + reloadFingerprints(); + populateView(); + } } } @@ -236,15 +306,22 @@ public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdat @Override public void onKeyStatusUpdated(final AxolotlService.FetchStatus report) { + final boolean keysToTrust = reloadFingerprints(); if (report != null) { lastFetchReport = report; runOnUiThread(new Runnable() { @Override public void run() { + if (mUseCameraHintToast != null && !keysToTrust) { + mUseCameraHintToast.cancel(); + } switch (report) { case ERROR: Toast.makeText(TrustKeysActivity.this,R.string.error_fetching_omemo_key,Toast.LENGTH_SHORT).show(); break; + case SUCCESS_TRUSTED: + Toast.makeText(TrustKeysActivity.this,R.string.blindly_trusted_omemo_keys,Toast.LENGTH_LONG).show(); + break; case SUCCESS_VERIFIED: Toast.makeText(TrustKeysActivity.this, Config.X509_VERIFICATION ? R.string.verified_omemo_key_with_certificate : R.string.all_omemo_keys_have_been_verified, @@ -255,7 +332,6 @@ public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdat }); } - boolean keysToTrust = reloadFingerprints(); if (keysToTrust || hasPendingKeyFetches() || hasNoOtherTrustedKeys()) { refreshUi(); } else { diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java index d961497c..583fab78 100644 --- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java @@ -44,7 +44,6 @@ import android.os.SystemClock; import android.preference.PreferenceManager; import android.text.InputType; import android.util.DisplayMetrics; -import android.util.Log; import android.util.Pair; import android.view.MenuItem; import android.view.View; @@ -55,10 +54,8 @@ import android.widget.Toast; import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; -import com.google.zxing.WriterException; +import com.google.zxing.aztec.AztecWriter; import com.google.zxing.common.BitMatrix; -import com.google.zxing.qrcode.QRCodeWriter; -import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import net.java.otr4j.session.SessionID; @@ -81,6 +78,7 @@ import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.MucOptions; import eu.siacs.conversations.entities.Presences; import eu.siacs.conversations.services.AvatarService; +import eu.siacs.conversations.services.BarcodeProvider; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.services.XmppConnectionService.XmppConnectionBinder; import eu.siacs.conversations.utils.CryptoHelper; @@ -994,7 +992,7 @@ public abstract class XmppActivity extends Activity { } protected boolean manuallyChangePresence() { - return getPreferences().getBoolean("manually_change_presence", false); + return getPreferences().getBoolean(SettingsActivity.MANUALLY_CHANGE_PRESENCE, false); } protected void unregisterNdefPushMessageCallback() { @@ -1061,7 +1059,7 @@ public abstract class XmppActivity extends Activity { Point size = new Point(); getWindowManager().getDefaultDisplay().getSize(size); final int width = (size.x < size.y ? size.x : size.y); - Bitmap bitmap = createQrCodeBitmap(uri, width); + Bitmap bitmap = BarcodeProvider.createAztecBitmap(uri, width); ImageView view = new ImageView(this); view.setBackgroundColor(Color.WHITE); view.setImageBitmap(bitmap); @@ -1071,31 +1069,6 @@ public abstract class XmppActivity extends Activity { } } - protected Bitmap createQrCodeBitmap(String input, int size) { - Log.d(Config.LOGTAG,"qr code requested size: "+size); - try { - final QRCodeWriter QR_CODE_WRITER = new QRCodeWriter(); - final Hashtable<EncodeHintType, Object> hints = new Hashtable<>(); - hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M); - final BitMatrix result = QR_CODE_WRITER.encode(input, BarcodeFormat.QR_CODE, size, size, hints); - final int width = result.getWidth(); - final int height = result.getHeight(); - final int[] pixels = new int[width * height]; - for (int y = 0; y < height; y++) { - final int offset = y * width; - for (int x = 0; x < width; x++) { - pixels[offset + x] = result.get(x, y) ? Color.BLACK : Color.TRANSPARENT; - } - } - final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - Log.d(Config.LOGTAG,"output size: "+width+"x"+height); - bitmap.setPixels(pixels, 0, width, 0, 0, width, height); - return bitmap; - } catch (final WriterException e) { - return null; - } - } - protected Account extractAccount(Intent intent) { String jid = intent != null ? intent.getStringExtra(EXTRA_ACCOUNT) : null; try { diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java index 6a392ee1..66c60ca5 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -138,7 +138,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie } } - private void displayStatus(ViewHolder viewHolder, Message message, int type, boolean darkBackground) { + private void displayStatus(ViewHolder viewHolder, Message message, int type, boolean darkBackground, boolean inValidSession) { String filesize = null; String info = null; boolean error = false; @@ -218,8 +218,8 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie .getAccount().getAxolotlService().getFingerprintTrust( message.getFingerprint()); - if(status == null || (!status.isTrustedAndActive())) { - viewHolder.indicator.setColorFilter(activity.getWarningTextColor()); + if(status == null || (type == SENT ? !status.isTrusted() : (!status.isVerified() && inValidSession))) { + viewHolder.indicator.setColorFilter(0xffc64545); viewHolder.indicator.setAlpha(1.0f); } else { viewHolder.indicator.clearColorFilter(); @@ -551,7 +551,8 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie @Override public View getView(int position, View view, ViewGroup parent) { final Message message = getItem(position); - final boolean isInValidSession = message.isValidInSession(); + final boolean omemoEncryption = message.getEncryption() == Message.ENCRYPTION_AXOLOTL; + final boolean isInValidSession = message.isValidInSession() && (!omemoEncryption || message.isTrusted()); final Conversation conversation = message.getConversation(); final Account account = conversation.getAccount(); final int type = getItemViewType(position); @@ -758,11 +759,15 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie } else { viewHolder.message_box.setBackgroundResource(R.drawable.message_bubble_received_warning); viewHolder.encryption.setVisibility(View.VISIBLE); - viewHolder.encryption.setText(CryptoHelper.encryptionTypeToText(message.getEncryption())); + if (omemoEncryption && !message.isTrusted()) { + viewHolder.encryption.setText(R.string.not_trusted); + } else { + viewHolder.encryption.setText(CryptoHelper.encryptionTypeToText(message.getEncryption())); + } } } - displayStatus(viewHolder, message, type, darkBackground); + displayStatus(viewHolder, message, type, darkBackground, isInValidSession); return view; } @@ -866,12 +871,16 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie mime = "*/*"; } Uri uri; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N || Config.ONLY_INTERNAL_STORAGE) { try { - uri = FileProvider.getUriForFile(activity, FileBackend.CONVERSATIONS_FILE_PROVIDER, file); + uri = FileBackend.getUriForFile(activity, file); } catch (IllegalArgumentException e) { - Toast.makeText(activity,activity.getString(R.string.no_permission_to_access_x,file.getAbsolutePath()), Toast.LENGTH_SHORT).show(); - return; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + Toast.makeText(activity, activity.getString(R.string.no_permission_to_access_x, file.getAbsolutePath()), Toast.LENGTH_SHORT).show(); + return; + } else { + uri = Uri.fromFile(file); + } } openIntent.setDataAndType(uri, mime); openIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); diff --git a/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java b/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java index 38ebced1..f1a9d8c4 100644 --- a/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java @@ -206,9 +206,13 @@ public final class CryptoHelper { } public static String getAccountFingerprint(Account account) { + return getFingerprint(account.getJid().toBareJid().toString()); + } + + public static String getFingerprint(String value) { try { MessageDigest md = MessageDigest.getInstance("SHA-256"); - return bytesToHex(md.digest(account.getJid().toBareJid().toString().getBytes("UTF-8"))); + return bytesToHex(md.digest(value.getBytes("UTF-8"))); } catch (Exception e) { return ""; } diff --git a/src/main/java/eu/siacs/conversations/utils/TLSSocketFactory.java b/src/main/java/eu/siacs/conversations/utils/TLSSocketFactory.java new file mode 100644 index 00000000..9d8a4111 --- /dev/null +++ b/src/main/java/eu/siacs/conversations/utils/TLSSocketFactory.java @@ -0,0 +1,69 @@ +package eu.siacs.conversations.utils; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.X509TrustManager; + +public class TLSSocketFactory extends SSLSocketFactory { + + private final SSLSocketFactory internalSSLSocketFactory; + + public TLSSocketFactory(X509TrustManager[] trustManager, SecureRandom random) throws KeyManagementException, NoSuchAlgorithmException { + SSLContext context = SSLContext.getInstance("TLS"); + context.init(null, trustManager, random); + this.internalSSLSocketFactory = context.getSocketFactory(); + } + + @Override + public String[] getDefaultCipherSuites() { + return CryptoHelper.getOrderedCipherSuites(internalSSLSocketFactory.getDefaultCipherSuites()); + } + + @Override + public String[] getSupportedCipherSuites() { + return internalSSLSocketFactory.getSupportedCipherSuites(); + } + + @Override + public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { + return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose)); + } + + @Override + public Socket createSocket(String host, int port) throws IOException { + return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port)); + } + + @Override + public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException { + return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort)); + } + + @Override + public Socket createSocket(InetAddress host, int port) throws IOException { + return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port)); + } + + @Override + public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { + return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort)); + } + + private static Socket enableTLSOnSocket(Socket socket) { + if(socket != null && (socket instanceof SSLSocket)) { + try { + SSLSocketHelper.setSecurity((SSLSocket) socket); + } catch (NoSuchAlgorithmException e) { + //ignoring + } + } + return socket; + } +}
\ No newline at end of file diff --git a/src/main/java/eu/siacs/conversations/utils/XmppUri.java b/src/main/java/eu/siacs/conversations/utils/XmppUri.java index 1fc9812a..e16377cf 100644 --- a/src/main/java/eu/siacs/conversations/utils/XmppUri.java +++ b/src/main/java/eu/siacs/conversations/utils/XmppUri.java @@ -16,6 +16,7 @@ public class XmppUri { protected String jid; protected boolean muc; protected List<Fingerprint> fingerprints = new ArrayList<>(); + private String body; public static final String OMEMO_URI_PARAM = "omemo-sid-"; public static final String OTR_URI_PARAM = "otr-fingerprint"; @@ -55,13 +56,14 @@ public class XmppUri { muc = segments.size() > 1 && "j".equalsIgnoreCase(segments.get(0)); } else if ("xmpp".equalsIgnoreCase(scheme)) { // sample: xmpp:foo@bar.com - muc = "join".equalsIgnoreCase(uri.getQuery()); + muc = isMuc(uri.getQuery()); if (uri.getAuthority() != null) { jid = uri.getAuthority(); } else { jid = uri.getSchemeSpecificPart().split("\\?")[0]; } this.fingerprints = parseFingerprints(uri.getQuery()); + this.body = parseBody(uri.getQuery()); } else if ("imto".equalsIgnoreCase(scheme)) { // sample: imto://xmpp/foo@bar.com try { @@ -85,7 +87,7 @@ public class XmppUri { String[] parts = pair.split("=",2); if (parts.length == 2) { String key = parts[0].toLowerCase(Locale.US); - String value = parts[1]; + String value = parts[1].toLowerCase(Locale.US); if (OTR_URI_PARAM.equals(key)) { fingerprints.add(new Fingerprint(FingerprintType.OTR,value)); } @@ -102,6 +104,30 @@ public class XmppUri { return fingerprints; } + protected String parseBody(String query) { + for(String pair : query == null ? new String[0] : query.split(";")) { + final String[] parts = pair.split("=",2); + if (parts.length == 2 && "body".equals(parts[0].toLowerCase(Locale.US))) { + try { + return URLDecoder.decode(parts[1],"UTF-8"); + } catch (UnsupportedEncodingException e) { + return null; + } + } + } + return null; + } + + protected boolean isMuc(String query) { + for(String pair : query == null ? new String[0] : query.split(";")) { + final String[] parts = pair.split("=",2); + if (parts.length == 1 && "join".equals(parts[0])) { + return true; + } + } + return false; + } + public Jid getJid() { try { return this.jid == null ? null :Jid.fromString(this.jid.toLowerCase()); @@ -110,6 +136,10 @@ public class XmppUri { } } + public String getBody() { + return body; + } + public List<Fingerprint> getFingerprints() { return this.fingerprints; } diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index d6a3b2cb..128e1187 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -218,7 +218,10 @@ public class XmppConnection implements Runnable { mXmppConnectionService = service; } - protected void changeStatus(final Account.State nextStatus) { + protected synchronized void changeStatus(final Account.State nextStatus) { + if (Thread.currentThread().isInterrupted()) { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": not changing status to "+nextStatus+" because thread was interrupted"); + } if (account.getStatus() != nextStatus) { if ((nextStatus == Account.State.OFFLINE) && (account.getStatus() != Account.State.CONNECTING) @@ -262,6 +265,7 @@ public class XmppConnection implements Runnable { break; } try { + Socket localSocket; shouldAuthenticate = needsBinding = !account.isOptionSet(Account.OPTION_REGISTER); tagReader = new XmlReader(wakeLock); tagWriter = new TagWriter(); @@ -276,8 +280,15 @@ public class XmppConnection implements Runnable { destination = account.getHostname(); } Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": connect to " + destination + " via Tor"); - socket = SocksSocketFactory.createSocketOverTor(destination, account.getPort()); - startXmpp(); + localSocket = SocksSocketFactory.createSocketOverTor(destination, account.getPort()); + try { + startXmpp(localSocket); + } catch (InterruptedException e) { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": thread was interrupted before beginning stream"); + return; + } catch (Exception e) { + throw new IOException(e.getMessage()); + } } else if (extended && account.getHostname() != null && !account.getHostname().isEmpty()) { InetSocketAddress address = new InetSocketAddress(account.getHostname(), account.getPort()); @@ -288,33 +299,47 @@ public class XmppConnection implements Runnable { if (features.encryptionEnabled) { try { final TlsFactoryVerifier tlsFactoryVerifier = getTlsFactoryVerifier(); - socket = tlsFactoryVerifier.factory.createSocket(); - socket.connect(address, Config.SOCKET_TIMEOUT * 1000); - final SSLSession session = ((SSLSocket) socket).getSession(); + localSocket = tlsFactoryVerifier.factory.createSocket(); + localSocket.connect(address, Config.SOCKET_TIMEOUT * 1000); + final SSLSession session = ((SSLSocket) localSocket).getSession(); if (!tlsFactoryVerifier.verifier.verify(account.getServer().getDomainpart(), session)) { Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": TLS certificate verification failed"); throw new SecurityException(); } } catch (KeyManagementException e) { features.encryptionEnabled = false; - socket = new Socket(); + localSocket = new Socket(); } } else { - socket = new Socket(); - socket.connect(address, Config.SOCKET_TIMEOUT * 1000); + localSocket = new Socket(); + localSocket.connect(address, Config.SOCKET_TIMEOUT * 1000); } } catch (IOException e) { throw new UnknownHostException(); } - startXmpp(); + try { + startXmpp(localSocket); + } catch (InterruptedException e) { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": thread was interrupted before beginning stream"); + return; + } catch (Exception e) { + throw new IOException(e.getMessage()); + } } else if (DNSHelper.isIp(account.getServer().toString())) { - socket = new Socket(); + localSocket = new Socket(); try { - socket.connect(new InetSocketAddress(account.getServer().toString(), 5222), Config.SOCKET_TIMEOUT * 1000); + localSocket.connect(new InetSocketAddress(account.getServer().toString(), 5222), Config.SOCKET_TIMEOUT * 1000); } catch (IOException e) { throw new UnknownHostException(); } - startXmpp(); + try { + startXmpp(localSocket); + } catch (InterruptedException e) { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": thread was interrupted before beginning stream"); + return; + } catch (Exception e) { + throw new IOException(e.getMessage()); + } } else { final Bundle result = DNSHelper.getSRVRecord(account.getServer(), mXmppConnectionService); final ArrayList<Parcelable> values = result.getParcelableArrayList("values"); @@ -350,32 +375,37 @@ public class XmppConnection implements Runnable { } if (!features.encryptionEnabled) { - socket = new Socket(); - socket.connect(addr, Config.SOCKET_TIMEOUT * 1000); + localSocket = new Socket(); + localSocket.connect(addr, Config.SOCKET_TIMEOUT * 1000); } else { final TlsFactoryVerifier tlsFactoryVerifier = getTlsFactoryVerifier(); - socket = tlsFactoryVerifier.factory.createSocket(); + localSocket = tlsFactoryVerifier.factory.createSocket(); - if (socket == null) { + if (localSocket == null) { throw new IOException("could not initialize ssl socket"); } - SSLSocketHelper.setSecurity((SSLSocket) socket); - SSLSocketHelper.setSNIHost(tlsFactoryVerifier.factory, (SSLSocket) socket, account.getServer().getDomainpart()); - SSLSocketHelper.setAlpnProtocol(tlsFactoryVerifier.factory, (SSLSocket) socket, "xmpp-client"); + SSLSocketHelper.setSecurity((SSLSocket) localSocket); + SSLSocketHelper.setSNIHost(tlsFactoryVerifier.factory, (SSLSocket) localSocket, account.getServer().getDomainpart()); + SSLSocketHelper.setAlpnProtocol(tlsFactoryVerifier.factory, (SSLSocket) localSocket, "xmpp-client"); - socket.connect(addr, Config.SOCKET_TIMEOUT * 1000); + localSocket.connect(addr, Config.SOCKET_TIMEOUT * 1000); - if (!tlsFactoryVerifier.verifier.verify(account.getServer().getDomainpart(), ((SSLSocket) socket).getSession())) { + if (!tlsFactoryVerifier.verifier.verify(account.getServer().getDomainpart(), ((SSLSocket) localSocket).getSession())) { Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": TLS certificate verification failed"); throw new SecurityException(); } } - - if (startXmpp()) + if (startXmpp(localSocket)) { break; // successfully connected to server that speaks xmpp + } else { + localSocket.close(); + } } catch (final SecurityException e) { throw e; + } catch (InterruptedException e) { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": thread was interrupted before beginning stream"); + return; } catch (final Throwable e) { Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": " + e.getMessage() + "(" + e.getClass().getName() + ")"); if (!iterator.hasNext()) { @@ -385,8 +415,10 @@ public class XmppConnection implements Runnable { } } processStream(); - } catch (final java.lang.SecurityException e) { + } catch (final java.lang.SecurityException e) { this.changeStatus(Account.State.MISSING_INTERNET_PERMISSION); + } catch (final RegistrationNotSupportedException e) { + this.changeStatus(Account.State.REGISTRATION_NOT_SUPPORTED); } catch (final IncompatibleServerException e) { this.changeStatus(Account.State.INCOMPATIBLE_SERVER); } catch (final SecurityException e) { @@ -410,12 +442,16 @@ public class XmppConnection implements Runnable { this.changeStatus(Account.State.OFFLINE); this.attempt = Math.max(0, this.attempt - 1); } finally { - forceCloseSocket(); - if (wakeLock.isHeld()) { - try { - wakeLock.release(); - } catch (final RuntimeException ignored) { + if (!Thread.currentThread().isInterrupted()) { + forceCloseSocket(); + if (wakeLock.isHeld()) { + try { + wakeLock.release(); + } catch (final RuntimeException ignored) { + } } + } else { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": not force closing socket and releasing wake lock because thread was interrupted"); } } } @@ -423,27 +459,18 @@ public class XmppConnection implements Runnable { /** * Starts xmpp protocol, call after connecting to socket * @return true if server returns with valid xmpp, false otherwise - * @throws IOException Unknown tag on connect - * @throws XmlPullParserException Bad Xml - * @throws NoSuchAlgorithmException Other error */ - private boolean startXmpp() throws IOException, XmlPullParserException, NoSuchAlgorithmException { + private boolean startXmpp(Socket socket) throws Exception { + if (Thread.currentThread().isInterrupted()) { + throw new InterruptedException(); + } + this.socket = socket; tagWriter.setOutputStream(socket.getOutputStream()); tagReader.setInputStream(socket.getInputStream()); tagWriter.beginDocument(); sendStartStream(); - Tag nextTag; - while ((nextTag = tagReader.readTag()) != null) { - if (nextTag.isStart("stream")) { - return true; - } else { - throw new IOException("unknown tag on connect"); - } - } - if (socket.isConnected()) { - socket.close(); - } - return false; + final Tag tag = tagReader.readTag(); + return tag != null && tag.isStart("stream"); } private static class TlsFactoryVerifier { @@ -812,10 +839,8 @@ public class XmppConnection implements Runnable { } else { throw new IncompatibleServerException(); } - } else if (!this.streamFeatures.hasChild("register") - && account.isOptionSet(Account.OPTION_REGISTER)) { - forceCloseSocket(); - changeStatus(Account.State.REGISTRATION_NOT_SUPPORTED); + } else if (!this.streamFeatures.hasChild("register") && account.isOptionSet(Account.OPTION_REGISTER)) { + throw new RegistrationNotSupportedException(); } else if (this.streamFeatures.hasChild("mechanisms") && shouldAuthenticate && (features.encryptionEnabled || Config.ALLOW_NON_TLS_CONNECTIONS)) { @@ -950,7 +975,7 @@ public class XmppConnection implements Runnable { } public void resetEverything() { - resetAttemptCount(); + resetAttemptCount(true); resetStreamId(); clearIqCallbacks(); mStanzaQueue.clear(); @@ -1359,30 +1384,6 @@ public class XmppConnection implements Runnable { } } - public void waitForPush() { - if (tagWriter.isActive()) { - tagWriter.finish(); - new Thread(new Runnable() { - @Override - public void run() { - try { - while(!tagWriter.finished()) { - Thread.sleep(10); - } - socket.close(); - Log.d(Config.LOGTAG,account.getJid().toBareJid()+": closed tcp without closing stream"); - changeStatus(Account.State.OFFLINE); - } catch (IOException | InterruptedException e) { - Log.d(Config.LOGTAG,account.getJid().toBareJid()+": error while closing socket for waitForPush()"); - } - } - }).start(); - } else { - forceCloseSocket(); - Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": closed tcp without closing stream (no waiting)"); - } - } - private void forceCloseSocket() { if (socket != null) { try { @@ -1526,9 +1527,11 @@ public class XmppConnection implements Runnable { this.sendPacket(new InactivePacket()); } - public void resetAttemptCount() { + public void resetAttemptCount(boolean resetConnectTime) { this.attempt = 0; - this.lastConnect = 0; + if (resetConnectTime) { + this.lastConnect = 0; + } } public void setInteractive(boolean interactive) { @@ -1567,6 +1570,10 @@ public class XmppConnection implements Runnable { } + private class RegistrationNotSupportedException extends IOException { + + } + public enum Identity { FACEBOOK, SLACK, diff --git a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java index 20f1feb4..f551dd20 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java @@ -21,6 +21,8 @@ public final class Jid { private final String domainpart; private final String resourcepart; + private static final char[] JID_ESCAPING_CHARS = {' ','"','&','\'','/',':','<','>','@','\\'}; + // It's much more efficient to store the ful JID as well as the parts instead of figuring them // all out every time (since some characters are displayed but aren't used for comparisons). private final String displayjid; @@ -29,6 +31,18 @@ public final class Jid { return localpart; } + public String getUnescapedLocalpart() { + if (localpart == null || !localpart.contains("\\")) { + return localpart; + } else { + String localpart = this.localpart; + for(char c : JID_ESCAPING_CHARS) { + localpart = localpart.replace(String.format ("\\%02x", (int)c),String.valueOf(c)); + } + return localpart; + } + } + public String getDomainpart() { return IDN.toUnicode(domainpart); } diff --git a/src/main/res/drawable-hdpi/ic_action_camera.png b/src/main/res/drawable-hdpi/ic_action_camera.png Binary files differnew file mode 100644 index 00000000..60f9f100 --- /dev/null +++ b/src/main/res/drawable-hdpi/ic_action_camera.png diff --git a/src/main/res/drawable-hdpi/ic_camera_alt_white_24dp.png b/src/main/res/drawable-hdpi/ic_camera_alt_white_24dp.png Binary files differnew file mode 100644 index 00000000..497c88ca --- /dev/null +++ b/src/main/res/drawable-hdpi/ic_camera_alt_white_24dp.png diff --git a/src/main/res/drawable-mdpi/ic_action_camera.png b/src/main/res/drawable-mdpi/ic_action_camera.png Binary files differnew file mode 100644 index 00000000..75d6b8c2 --- /dev/null +++ b/src/main/res/drawable-mdpi/ic_action_camera.png diff --git a/src/main/res/drawable-mdpi/ic_camera_alt_white_24dp.png b/src/main/res/drawable-mdpi/ic_camera_alt_white_24dp.png Binary files differnew file mode 100644 index 00000000..e8305220 --- /dev/null +++ b/src/main/res/drawable-mdpi/ic_camera_alt_white_24dp.png diff --git a/src/main/res/drawable-xhdpi/ic_action_camera.png b/src/main/res/drawable-xhdpi/ic_action_camera.png Binary files differnew file mode 100644 index 00000000..31b4b221 --- /dev/null +++ b/src/main/res/drawable-xhdpi/ic_action_camera.png diff --git a/src/main/res/drawable-xhdpi/ic_camera_alt_white_24dp.png b/src/main/res/drawable-xhdpi/ic_camera_alt_white_24dp.png Binary files differnew file mode 100644 index 00000000..be9fb226 --- /dev/null +++ b/src/main/res/drawable-xhdpi/ic_camera_alt_white_24dp.png diff --git a/src/main/res/drawable-xxhdpi/ic_action_camera.png b/src/main/res/drawable-xxhdpi/ic_action_camera.png Binary files differnew file mode 100644 index 00000000..e7b99102 --- /dev/null +++ b/src/main/res/drawable-xxhdpi/ic_action_camera.png diff --git a/src/main/res/drawable-xxhdpi/ic_camera_alt_white_24dp.png b/src/main/res/drawable-xxhdpi/ic_camera_alt_white_24dp.png Binary files differnew file mode 100644 index 00000000..c8e69dce --- /dev/null +++ b/src/main/res/drawable-xxhdpi/ic_camera_alt_white_24dp.png diff --git a/src/main/res/drawable-xxxhdpi/ic_camera_alt_white_24dp.png b/src/main/res/drawable-xxxhdpi/ic_camera_alt_white_24dp.png Binary files differnew file mode 100644 index 00000000..777658e9 --- /dev/null +++ b/src/main/res/drawable-xxxhdpi/ic_camera_alt_white_24dp.png diff --git a/src/main/res/layout/activity_edit_account.xml b/src/main/res/layout/activity_edit_account.xml index ea4d49c8..6c26a162 100644 --- a/src/main/res/layout/activity_edit_account.xml +++ b/src/main/res/layout/activity_edit_account.xml @@ -610,6 +610,14 @@ android:orientation="vertical" android:showDividers="middle"> </LinearLayout> + <Button + android:id="@+id/clear_devices" + style="?android:attr/borderlessButtonStyle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/clear_other_devices" + android:layout_gravity="center_horizontal" + android:textColor="@color/accent"/> </LinearLayout> </LinearLayout> </ScrollView> diff --git a/src/main/res/menu/editaccount.xml b/src/main/res/menu/editaccount.xml index 9ab1788b..c67e5c47 100644 --- a/src/main/res/menu/editaccount.xml +++ b/src/main/res/menu/editaccount.xml @@ -1,5 +1,21 @@ <menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/action_share" + android:title="@string/share_uri_with" + android:icon="?attr/icon_share" + android:showAsAction="always"> + <menu> + <item + android:id="@+id/action_share_barcode" + android:title="@string/share_as_barcode"/> + <item + android:id="@+id/action_share_uri" + android:title="@string/share_as_uri"/> + <item android:id="@+id/action_share_http" + android:title="@string/share_as_http"/> + </menu> + </item> + <item android:id="@+id/action_change_presence" android:showAsAction="always" @@ -44,10 +60,6 @@ android:title="@string/change_password"/> <item - android:id="@+id/action_clear_devices" - android:showAsAction="never" - android:title="@string/clear_other_devices"/> - <item android:id="@+id/action_settings" android:orderInCategory="100" android:showAsAction="never" diff --git a/src/main/res/menu/omemo_key_context.xml b/src/main/res/menu/omemo_key_context.xml index 2e2fc5da..1e825902 100644 --- a/src/main/res/menu/omemo_key_context.xml +++ b/src/main/res/menu/omemo_key_context.xml @@ -1,6 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item + android:id="@+id/verify_scan" + android:title="@string/scan_qr_code" + /> + <item android:id="@+id/purge_omemo_key" android:title="@string/purge_key"/> <item diff --git a/src/main/res/menu/trust_keys.xml b/src/main/res/menu/trust_keys.xml new file mode 100644 index 00000000..90304767 --- /dev/null +++ b/src/main/res/menu/trust_keys.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + + <item + android:id="@+id/action_scan_qr_code" + android:title="@string/scan_qr_code" + android:showAsAction="always" + android:icon="?attr/icon_scan_qr_code"/> +</menu>
\ No newline at end of file diff --git a/src/main/res/values-ar/strings.xml b/src/main/res/values-ar/strings.xml index b54de99c..5de991c3 100644 --- a/src/main/res/values-ar/strings.xml +++ b/src/main/res/values-ar/strings.xml @@ -100,7 +100,6 @@ <string name="accept">قبول</string> <string name="error">حدث خطأ ما</string> <string name="pref_grant_presence_updates">منح تحديثات الظهور</string> - <string name="pref_grant_presence_updates_summary">اسأل واقبل السؤال عن تحديثات الظهور</string> <string name="your_account">حسابك</string> <string name="keys">مفاتيح</string> <string name="send_presence_updates">ارسال تحديثات الظهور</string> @@ -223,7 +222,6 @@ <string name="no_application_found_to_open_file">لا يوجد تطبيق متاح لعرض الملف</string> <string name="could_not_verify_fingerprint">لا يمكن التحقق من البصمة</string> <string name="manually_verify">تأكيد يدوي</string> - <string name="are_you_sure_verify_fingerprint">هل ترغب في تأكيد بصمات OTR لجهات اتصالك ؟</string> <string name="pref_show_dynamic_tags">عرض العلامات التلقائية</string> <string name="pref_show_dynamic_tags_summary">عرض العلامات للقراءة فقط أسفل بيانات جهات الإتصال </string> <string name="enable_notifications">تفعيل الإشعارات</string> diff --git a/src/main/res/values-bg/strings.xml b/src/main/res/values-bg/strings.xml index d7cd734a..f0054b7c 100644 --- a/src/main/res/values-bg/strings.xml +++ b/src/main/res/values-bg/strings.xml @@ -122,14 +122,14 @@ <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_ui_options">Потр. интерфейс</string> <string name="openpgp_error">OpenKeychain докладва за грешка</string> <string name="error_decrypting_file">В/И грешка при дешифроването на файла</string> <string name="accept">Приемане</string> <string name="error">Възникна грешка</string> <string name="pref_grant_presence_updates">Позволяване на актуализации на присъствието</string> - <string name="pref_grant_presence_updates_summary">Предварително позволяване и изискване на абониране за актуализации на присъствието за контакти, създадено от Вас</string> + <string name="pref_grant_presence_updates_summary">Предварително позволяване и изискване на абонамент за присъствието за контактите, създадени от Вас</string> <string name="subscriptions">Абонаменти</string> <string name="your_account">Вашият профил</string> <string name="keys">Ключове</string> @@ -339,8 +339,8 @@ <string name="url_copied_to_clipboard">Адресът е копиран</string> <string name="message_copied_to_clipboard">Съобщението е копирано</string> <string name="image_transmission_failed">Неуспешно прехвърляне на изображението</string> - <string name="scan_qr_code">Сканиране на QR кода</string> - <string name="show_qr_code">Показване на QR кода</string> + <string name="scan_qr_code">Сканиране на 2-измерен баркод</string> + <string name="show_qr_code">Показване на 2-измерен баркод</string> <string name="show_block_list">Показване на списъка с блокирани</string> <string name="account_details">Подробности за профила</string> <string name="verify_otr">Проверка на OTR</string> @@ -380,7 +380,7 @@ <string name="no_application_found_to_open_file">Няма намерено приложение за отваряне на файла</string> <string name="could_not_verify_fingerprint">Неуспешна проверка на отпечатъка</string> <string name="manually_verify">Ръчна проверка</string> - <string name="are_you_sure_verify_fingerprint">Сигурни ли сте, че искате да проверите отпечатъка OTR на контактите си?</string> + <string name="are_you_sure_verify_fingerprint">Наистина ли искате да потвърдите отпечатъка OTR на контакта си?</string> <string name="pref_show_dynamic_tags">Динамични етикети</string> <string name="pref_show_dynamic_tags_summary">Показване на етикети, предназначени само за четене под контактите</string> <string name="enable_notifications">Включване на известията</string> @@ -473,7 +473,7 @@ <string name="contact_is_typing">%s пише…</string> <string name="contact_has_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> @@ -666,4 +666,20 @@ <string name="data_saver_enabled">Съхранението на данни е включено</string> <string name="data_saver_enabled_explained">Операционната Ви система не позволява на Conversations да се свързва с Интернет когато работи на заден фон. За да получавате известия за новите съобщения, трябва да дадете на Conversations неограничен достъп когато съхранението на данни е включено.\nConversations ще продължи да се опитва да записва данните когато е възможно.</string> <string name="device_does_not_support_data_saver">Устройството Ви не поддържа изключването на съхранението на данни за Conversations.</string> + <string name="error_unable_to_create_temporary_file">Неуспешно създаване на временен файл</string> + <string name="this_device_has_been_verified">Това устройство е потвърдено</string> + <string name="copy_fingerprint">Копиране на отпечатъка</string> + <string name="all_omemo_keys_have_been_verified">Всички ключове OMEMO са потвърдени</string> + <string name="barcode_does_not_contain_fingerprints_for_this_conversation">Баркодът не съдържа отпечатъци за този разговор.</string> + <string name="verified_fingerprints">Потвърдени отпечатъци</string> + <string name="use_camera_icon_to_scan_barcode">Използвайте камерата, за да сканирате баркода на контакт</string> + <string name="please_wait_for_keys_to_be_fetched">Моля, изчакайте получаването на ключовете</string> + <string name="share_as_barcode">Споделяне като баркод</string> + <string name="share_as_uri">Споделяне като адрес на XMPP</string> + <string name="share_as_http">Споделяне като връзка в Интернет</string> + <string name="pref_blind_trust_before_verification">Доверяване на сляпо преди потвърждение</string> + <string name="pref_blind_trust_before_verification_summary">Автоматично доверяване на всички нови устройства на контактите, които не са били потвърдени преди, и питане за ръчно одобрение всеки път, когато потвърден контакт добави ново устройство.</string> + <string name="blindly_trusted_omemo_keys">Приети на сляпо ключове OMEMO</string> + <string name="not_trusted">Неприети</string> + <string name="invalid_barcode">Грешен 2-измерен баркод</string> </resources> diff --git a/src/main/res/values-ca/strings.xml b/src/main/res/values-ca/strings.xml index b2f051e9..6f5791aa 100644 --- a/src/main/res/values-ca/strings.xml +++ b/src/main/res/values-ca/strings.xml @@ -98,13 +98,11 @@ <string name="pref_never_send_crash">Mai enviïs informes d\'errors</string> <string name="pref_never_send_crash_summary">Enviant traces d\'execució d\'ajudes al futur desenvolupament del Conversations.</string> <string name="pref_confirm_messages">Confirmant missatges</string> - <string name="pref_confirm_messages_summary">Deixeu que el seu contacte sàpiga quan heu rebut i llegit un missatge</string> <string name="openpgp_error">OpenKeychain ha reportat un error</string> <string name="error_decrypting_file">I/O Error al desxifrar un arxiu</string> <string name="accept">Acceptar</string> <string name="error">Un error ha passat</string> <string name="pref_grant_presence_updates">Concedir actualitzacions</string> - <string name="pref_grant_presence_updates_summary">Preventivament atorgar i preguntar per les subscripcions als contactes creats</string> <string name="subscriptions">Subscripcions</string> <string name="your_account">El teu compte</string> <string name="keys">Claus</string> @@ -273,8 +271,6 @@ <string name="url_copied_to_clipboard">URL copiada al portapapers</string> <string name="message_copied_to_clipboard">Missatge copiat al portapapers</string> <string name="image_transmission_failed">Transmissió de l\'imatge fallada</string> - <string name="scan_qr_code">Escanejar el codi QR</string> - <string name="show_qr_code">Mostrar el codi QR</string> <string name="show_block_list">Mostra la llista de bloqueig</string> <string name="account_details">Detalls del compte</string> <string name="verify_otr">Verificar OTR</string> @@ -310,7 +306,6 @@ <string name="no_application_found_to_open_file">Cap aplicació trobada a l\'obrir l\'arxiu</string> <string name="could_not_verify_fingerprint">No s\'ha pogut verificar l\'empremta dactilar</string> <string name="manually_verify">Verificat manualment</string> - <string name="are_you_sure_verify_fingerprint">Estàs segur que vols verificar l\'empremta digital OTR dels teus contactes?</string> <string name="pref_show_dynamic_tags">Mostrar etiquetes dinàmiques</string> <string name="pref_show_dynamic_tags_summary">Mostra etiquetes de nomès lectura per sota dels noms dels contactes</string> <string name="enable_notifications">Habilitar notificació</string> @@ -386,7 +381,6 @@ <string name="disable_account">Deshabilita el compte</string> <string name="contact_has_stopped_typing">%s ha deixat d\'escriure</string> <string name="pref_chat_states">Notificacions d\'escriptura</string> - <string name="pref_chat_states_summary">Permet el teu contacte saber quan estàs escrivint un missatge nou</string> <string name="send_location">Enviar localització</string> <string name="show_location">Mostrar localització</string> <string name="no_application_found_to_display_location">No s\'ha trobat cap aplicació per mostrar la localització</string> diff --git a/src/main/res/values-cs/strings.xml b/src/main/res/values-cs/strings.xml index 80fe5d12..c18a6346 100644 --- a/src/main/res/values-cs/strings.xml +++ b/src/main/res/values-cs/strings.xml @@ -122,14 +122,12 @@ <string name="pref_never_send_crash">Neodesílat detaily o pádu aplikace</string> <string name="pref_never_send_crash_summary">Zasláním detailů o důvodu selhání pomůžete dalšímu vývoji aplikace Konverzace</string> <string name="pref_confirm_messages">Potvrzovat zprávy</string> - <string name="pref_confirm_messages_summary">Oznamovat kontaktům, že zpráva byla přijata a přečtena</string> <string name="pref_ui_options">UI</string> <string name="openpgp_error">OpenKeychain nahlásil chybu</string> <string name="error_decrypting_file">I/O chyba dešifrování souboru</string> <string name="accept">Přijmout</string> <string name="error">Došlo k chybě</string> <string name="pref_grant_presence_updates">Povolit aktualizace stavu</string> - <string name="pref_grant_presence_updates_summary">Aktivně povolovat a žádat o zasílání změn stavu pro vytvářené kontakty</string> <string name="subscriptions">Odběry</string> <string name="your_account">Váš účet</string> <string name="keys">Klíče</string> @@ -339,8 +337,6 @@ <string name="url_copied_to_clipboard">URL zkopírováno do schránky</string> <string name="message_copied_to_clipboard">Zpráva zkopírována do schránky</string> <string name="image_transmission_failed">Přenos obrázku selhal</string> - <string name="scan_qr_code">Skenovat QR kód</string> - <string name="show_qr_code">Zobrazit QR kód</string> <string name="show_block_list">Zobrazit seznam blokovaných</string> <string name="account_details">Detaily účtu</string> <string name="verify_otr">Ověřit OTR</string> @@ -380,7 +376,6 @@ <string name="no_application_found_to_open_file">Nebyla nalezena aplikace umožňující otevření souboru</string> <string name="could_not_verify_fingerprint">Ověření otisku se nezdařilo</string> <string name="manually_verify">Ruční ověření</string> - <string name="are_you_sure_verify_fingerprint">Opravdu si přejete ověřit OTR otisk kontaktu?</string> <string name="pref_show_dynamic_tags">Zobrazit dynamické tagy</string> <string name="pref_show_dynamic_tags_summary">Zobrazit tagy pro čtení pod kontakty</string> <string name="enable_notifications">Povolit upozornění</string> @@ -473,7 +468,6 @@ <string name="contact_is_typing">%s píše...</string> <string name="contact_has_stopped_typing">%s přestal(a) psát</string> <string name="pref_chat_states">Upozornění při psaní</string> - <string name="pref_chat_states_summary">Oznamovat kontaktům že píšete novou zprávu</string> <string name="send_location">Poslat pozici</string> <string name="show_location">Zobrazit pozici</string> <string name="no_application_found_to_display_location">Nebyla nalezena aplikace pro zobrazení pozice</string> @@ -668,4 +662,9 @@ <string name="error_message">Chybová zpráva</string> <string name="data_saver_enabled">Zapnuta úspora dat</string> <string name="data_saver_enabled_explained">Váš operační systém zabraňuje aplikaci Conversations v přístupu na Internet, pokud tato běží na pozadí. Pro příjem upozornění na nové zprávy musíte Conversations povolit neomezený přístup při zapnuté úspoře dat.\nConversations se bude i přesto snažit omezovat přenos dat.</string> + <string name="device_does_not_support_data_saver">Tento přístroj nepodporuje vypnutí šetření dat pro aplikaci Conversations.</string> + <string name="error_unable_to_create_temporary_file">Nelze vytvořit dočasný soubor</string> + <string name="this_device_has_been_verified">Tento přístroj byl ověřen</string> + <string name="copy_fingerprint">Kopírovat identifikátor</string> + <string name="all_omemo_keys_have_been_verified">Všechny OMEMO klíče byly ověřeny</string> </resources> diff --git a/src/main/res/values-de/strings.xml b/src/main/res/values-de/strings.xml index a3c94429..93414f04 100644 --- a/src/main/res/values-de/strings.xml +++ b/src/main/res/values-de/strings.xml @@ -4,8 +4,8 @@ <string name="action_add">Neue Unterhaltung</string> <string name="action_accounts">Konten verwalten</string> <string name="action_end_conversation">Unterhaltung beenden</string> - <string name="action_contact_details">Kontakt-Details</string> - <string name="action_muc_details">Konferenz-Details</string> + <string name="action_contact_details">Kontaktdetails</string> + <string name="action_muc_details">Konferenzdetails</string> <string name="action_secure">Verschlüsselte Unterhaltung</string> <string name="action_add_account">Konto hinzufügen</string> <string name="action_edit_contact">Namen bearbeiten</string> @@ -17,8 +17,8 @@ <string name="action_unblock_domain">Domain entsperren</string> <string name="title_activity_manage_accounts">Konten verwalten</string> <string name="title_activity_settings">Einstellungen</string> - <string name="title_activity_conference_details">Konferenz-Details</string> - <string name="title_activity_contact_details">Kontakt-Details</string> + <string name="title_activity_conference_details">Konferenzdetails</string> + <string name="title_activity_contact_details">Kontaktdetails</string> <string name="title_activity_sharewith">Mit Unterhaltung teilen</string> <string name="title_activity_start_conversation">Unterhaltung beginnen</string> <string name="title_activity_choose_contact">Kontakt auswählen</string> @@ -220,7 +220,7 @@ <string name="reception_failed">Empfang fehlgeschlagen</string> <string name="your_fingerprint">Dein Fingerabdruck</string> <string name="otr_fingerprint">OTR-Fingerabdruck</string> - <string name="otr_fingerprint_selected_message">OTR Fingerabdruck der Nachricht</string> + <string name="otr_fingerprint_selected_message">OTR-Fingerabdruck der Nachricht</string> <string name="openpgp_key_id">OpenPGP Schlüssel-ID</string> <string name="omemo_fingerprint">OMEMO-Fingerabdruck</string> <string name="omemo_fingerprint_x509">v\\OMEMO-Fingerabdruck</string> @@ -239,14 +239,14 @@ <string name="enter_contact">Kontakt eingeben</string> <string name="join_conference">Konferenz beitreten</string> <string name="delete_contact">Kontakt löschen</string> - <string name="view_contact_details">Kontakt-Details anzeigen</string> + <string name="view_contact_details">Kontaktdetails anzeigen</string> <string name="block_contact">Kontakt sperren</string> <string name="unblock_contact">Kontakt entsperren</string> <string name="create">Erstellen</string> <string name="select">Auswählen</string> <string name="contact_already_exists">Der Kontakt existiert bereits</string> <string name="join">Beitreten</string> - <string name="conference_address">Konferenz-Adresse</string> + <string name="conference_address">Konferenzadresse</string> <string name="conference_address_example">raum@conference.beispiel.de/Nickname</string> <string name="save_as_bookmark">Zur Kontaktliste hinzufügen</string> <string name="delete_bookmark">Von Kontaktliste entfernen</string> @@ -313,7 +313,7 @@ <string name="pref_use_indicate_received_summary">Empfangene Nachrichten werden mit einem grünen Häkchen markiert. Bitte beachte, dass dies nicht in allen Fällen funktioniert.</string> <string name="pref_use_send_button_to_indicate_status_summary">\"Senden\"-Schaltfläche einfärben, um den Online-Status des Kontakts anzuzeigen</string> <string name="pref_expert_options_other">Sonstiges</string> - <string name="pref_conference_name">Konferenz-Name</string> + <string name="pref_conference_name">Konferenzname</string> <string name="pref_conference_name_summary">Thema von Konferenzen anstatt JID als Namen verwenden</string> <string name="pref_autojoin">Konferenzen automatisch beitreten</string> <string name="pref_autojoin_summary">Autojoin-Flag in Konferenzlesezeichen beachten</string> @@ -338,11 +338,11 @@ <string name="message_text">Nachrichtentext</string> <string name="url_copied_to_clipboard">URL in Zwischenablage kopiert</string> <string name="message_copied_to_clipboard">Nachricht in Zwischenablage kopiert</string> - <string name="image_transmission_failed">Bild-Übertragung fehlgeschlagen</string> - <string name="scan_qr_code">QR-Code scannen</string> - <string name="show_qr_code">QR-Code anzeigen</string> + <string name="image_transmission_failed">Bildübertragung fehlgeschlagen</string> + <string name="scan_qr_code">Barcode scannen</string> + <string name="show_qr_code">Barcode anzeigen</string> <string name="show_block_list">Sperrliste anzeigen</string> - <string name="account_details">Konto-Details</string> + <string name="account_details">Kontodetails</string> <string name="verify_otr">OTR prüfen</string> <string name="remote_fingerprint">Fingerabdruck der Gegenseite</string> <string name="scan">Scannen</string> @@ -385,7 +385,7 @@ <string name="pref_show_dynamic_tags_summary">Schreibgeschütze Tags unterhalb der Kontakte anzeigen</string> <string name="enable_notifications">Benachrichtigungen aktivieren</string> <string name="conference_with">Konferenz erstellen mit…</string> - <string name="no_conference_server_found">Kein Konferenz-Server gefunden</string> + <string name="no_conference_server_found">Kein Konferenzserver gefunden</string> <string name="conference_creation_failed">Erstellen der Konferenz fehlgeschlagen!</string> <string name="secret_accepted">Schlüssel akzeptiert!</string> <string name="reset">Zurücksetzen</string> @@ -410,7 +410,7 @@ <string name="otr_session_not_started">Sende eine Nachricht, um eine verschlüsselte Unterhaltung zu beginnen</string> <string name="ask_question">Frage stellen</string> <string name="smp_explain_question">Falls du mit deinem Kontakt ein gemeinsames Geheimnis hast (z.B. ein Insider-Witz oder was ihr zuletzt gemeinsam zum Mittag gegessen habt), kann dies zur gegenseitigen Überprüfung des Fingerabdrucks genutzt werden.\n\nDu stellst eine Frage oder gibst einen Hinweis und dein Kontakt gibt eine eindeutige Antwort.</string> - <string name="smp_explain_answer">Dein Kontakt möchte deinen Fingerabdruck mit Hilfe eines gemeinsamen Schlüssels überprüfen. Dein Kontakt hat dazu folgende Frage gestellt.</string> + <string name="smp_explain_answer">Dein Kontakt möchte deinen Fingerabdruck mit Hilfe eines gemeinsamen Geheimnisses überprüfen. Dein Kontakt hat dazu folgende Frage gestellt.</string> <string name="shared_secret_hint_should_not_be_empty">Deine Frage darf nicht leer sein.</string> <string name="shared_secret_can_not_be_empty">Dein gemeinsamer Schlüssel darf nicht leer sein</string> <string name="manual_verification_explanation">Vergleiche den angezeigten Fingerabdruck sorgfältig mit dem deines Kontakts.\nDu kannst dazu einen sicheren Kommunikationsweg (z.B. verschlüsselte E-Mail oder Telefonanruf) zum Austausch nutzen.</string> @@ -438,13 +438,13 @@ <string name="could_not_change_role">Rolle von %s konnte nicht geändert werden</string> <string name="public_conference">Öffentlich zugängliche Konferenz</string> <string name="private_conference">Private Konferenz nur für Mitglieder</string> - <string name="conference_options">Konferenz-Optionen</string> + <string name="conference_options">Konferenzoptionen</string> <string name="members_only">Privat, nur Mitglieder</string> <string name="non_anonymous">De-anonymisiert</string> <string name="moderated">Moderiert</string> <string name="you_are_not_participating">Du bist kein Mitglied</string> - <string name="modified_conference_options">Konferenz-Optionen wurden modifiziert!</string> - <string name="could_not_modify_conference_options">Konferenz-Optionen konnten nicht modifiziert werden</string> + <string name="modified_conference_options">Konferenzoptionen wurden modifiziert!</string> + <string name="could_not_modify_conference_options">Konferenzoptionen konnten nicht modifiziert werden</string> <string name="never">Niemals</string> <string name="thirty_minutes">30 Minuten</string> <string name="one_hour">1 Stunde</string> @@ -473,7 +473,7 @@ <string name="contact_is_typing">%s schreibt…</string> <string name="contact_has_stopped_typing">%s schreibt nicht mehr</string> <string name="pref_chat_states">Tipp-Benachrichtigung</string> - <string name="pref_chat_states_summary">Informiere deine Kontakte, wenn du eine Nachricht eintippst.</string> + <string name="pref_chat_states_summary">Informiere deine Kontakte, wenn du eine Nachricht schreibst</string> <string name="send_location">Standort senden</string> <string name="show_location">Standort anzeigen</string> <string name="no_application_found_to_display_location">Keine App für die Standort-Anzeige gefunden</string> @@ -508,8 +508,8 @@ <string name="username">Benutzername</string> <string name="username_hint">Benutzername</string> <string name="invalid_username">Ungültiger Benutzername</string> - <string name="conference_name">Konferenz-Name</string> - <string name="invalid_conference_name">Dies ist kein gültiger Konferenz-Name</string> + <string name="conference_name">Konferenzname</string> + <string name="invalid_conference_name">Dies ist kein gültiger Konferenzname</string> <string name="download_failed_server_not_found">Download fehlgeschlagen: Server nicht gefunden</string> <string name="download_failed_file_not_found">Download fehlgeschlagen: Datei nicht gefunden</string> <string name="download_failed_could_not_connect">Download fehlgeschlagen: keine Verbindung zum Host</string> @@ -527,7 +527,7 @@ <string name="pref_xa_on_silent_mode_summary">Setzt deinen Status auf \"nicht verfügbar\", solange dein Gerät lautlos ist</string> <string name="pref_treat_vibrate_as_silent">Vibration als Lautlos behandeln</string> <string name="pref_treat_vibrate_as_silent_summary">Setzt deinen Status auf \"nicht verfügbar\", solange das Gerät auf Vibration geschaltet ist</string> - <string name="pref_show_connection_options">Erweiterte Verbindungs-Optionen</string> + <string name="pref_show_connection_options">Erweiterte Verbindungsoptionen</string> <string name="pref_show_connection_options_summary">Hostname- und Port-Optionen bei Kontoeinrichtung anzeigen</string> <string name="hostname_example">xmpp.domain.de</string> <string name="action_add_account_with_certificate">Konto mit Zertifikat hinzufügen</string> @@ -542,11 +542,11 @@ <string name="certificate_chain_is_not_trusted">Zertifikat wird nicht vertraut</string> <string name="jid_does_not_match_certificate">Jabber-ID stimmt nicht dem Zertifikat überein</string> <string name="action_renew_certificate">Zertifikat erneuern</string> - <string name="error_fetching_omemo_key">Kann OMEMO Schlüssel nicht empfangen!</string> - <string name="verified_omemo_key_with_certificate">OMEMO Schlüssel mit Zertifikat bestätigt!</string> + <string name="error_fetching_omemo_key">Kann OMEMO-Schlüssel nicht empfangen!</string> + <string name="verified_omemo_key_with_certificate">OMEMO-Schlüssel mit Zertifikat bestätigt!</string> <string name="device_does_not_support_certificates">Dein Gerät unterstützt das Auswählen von Client-Zertifikaten nicht!</string> <string name="pref_connection_options">Verbindung</string> - <string name="pref_use_tor">Über TOR verbinden</string> + <string name="pref_use_tor">Über Tor verbinden</string> <string name="pref_use_tor_summary">Alle Verbindungen über das Tor-Netzwerk tunneln. Benötigt Orbot</string> <string name="account_settings_hostname">Hostname</string> <string name="account_settings_port">Port</string> @@ -664,6 +664,22 @@ <string name="show_error_message">Zeige Fehlermeldung</string> <string name="error_message">Fehlermeldung</string> <string name="data_saver_enabled">Datensparmodus aktiv</string> - <string name="data_saver_enabled_explained">Dein Betriebssystem verbietet Conversations im Hintergrund den Zugang zum Internet. Um Benachrichtigungen erhalten zu können, solltest du Conversations den Zugang erlauben, wenn der Datensparmodus aktiv ist. Conversations wird dennoch versuchen, so viel Daten wie möglich einzusparen.</string> + <string name="data_saver_enabled_explained">Dein Betriebssystem verbietet Conversations im Hintergrund den Zugang zum Internet. Um Benachrichtigungen erhalten zu können, solltest du Conversations den Zugang erlauben, wenn der Datensparmodus aktiv ist. Conversations wird dennoch versuchen, so viele Daten wie möglich einzusparen.</string> <string name="device_does_not_support_data_saver">Dein Gerät unterstützt den Datensparmodus für Conversations nicht.</string> + <string name="error_unable_to_create_temporary_file">Temporäre Datei kann nicht erstellt werden</string> + <string name="this_device_has_been_verified">Dieses Gerät wurde verifiziert</string> + <string name="copy_fingerprint">Fingerabdruck kopieren</string> + <string name="all_omemo_keys_have_been_verified">Alle OMEMO-Schlüssel wurden verifiziert</string> + <string name="barcode_does_not_contain_fingerprints_for_this_conversation">Barcode enthält keine Fingerabdrücke für diese Unterhaltung.</string> + <string name="verified_fingerprints">Überprüfte Fingerabdrücke</string> + <string name="use_camera_icon_to_scan_barcode">Nutze Kamera, um Barcodes deiner Kontakte zu scannen</string> + <string name="please_wait_for_keys_to_be_fetched">Bitte warten bis Schlüssel abgerufen werden …</string> + <string name="share_as_barcode">Als Barcode teilen</string> + <string name="share_as_uri">Als XMPP URI teilen</string> + <string name="share_as_http">Als HTTP Link teilen</string> + <string name="pref_blind_trust_before_verification">Blind vertrauen vor der Überprüfung</string> + <string name="pref_blind_trust_before_verification_summary">Vertraue automatisch allen neuen Geräten von Kontakten, die noch nicht überprüft wurden und zeige eine Aufforderung zur manuellen Bestätigung an, wenn ein verifizierter Kontakt ein neues Gerät hinzufügt.</string> + <string name="blindly_trusted_omemo_keys">Blind vertraute OMEMO-Schlüssel</string> + <string name="not_trusted">Nicht vertraut</string> + <string name="invalid_barcode">Ungültiger Barcode</string> </resources> diff --git a/src/main/res/values-el/strings.xml b/src/main/res/values-el/strings.xml index 1c2fd858..7f419332 100644 --- a/src/main/res/values-el/strings.xml +++ b/src/main/res/values-el/strings.xml @@ -98,13 +98,11 @@ <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="openpgp_error">Το OpenKeychain ανέφερε κάποιο σφάλμα</string> <string name="error_decrypting_file">Σφάλμα εισόδου/εξόδου κατά την αποκρυπτογράφηση αρχείου</string> <string name="accept">Αποδοχή</string> <string name="error">Έχει συμβεί κάποιο σφάλμα</string> <string name="pref_grant_presence_updates">Χορήγηση ενημερώσεων παρουσίας</string> - <string name="pref_grant_presence_updates_summary">Ερήμην χορήγηση και παράκληση για συνδρομή παρουσίας στις επαφές που δημιουργείτε</string> <string name="subscriptions">Συνδρομές</string> <string name="your_account">Ο λογαριασμός σας</string> <string name="keys">Κλειδιά</string> @@ -273,8 +271,6 @@ <string name="url_copied_to_clipboard">Η διεύθυνση URL αντιγράφηκε στο πρόχειρο</string> <string name="message_copied_to_clipboard">Το μήνυμα αντιγράφηκε στο πρόχειρο</string> <string name="image_transmission_failed">Η μετάδοση της εικόνας απέτυχε</string> - <string name="scan_qr_code">Σάρωση κωδικού QR</string> - <string name="show_qr_code">Εμφάνιση κωδικού QR</string> <string name="show_block_list">Εμφάνιση λίστας αποκλεισμένων</string> <string name="account_details">Λεπτομέρειες λογαριασμού</string> <string name="verify_otr">Επαλήθευση OTR</string> @@ -310,7 +306,6 @@ <string name="no_application_found_to_open_file">Δεν βρέθηκε εφαρμογή για να ανοίξει το αρχείο</string> <string name="could_not_verify_fingerprint">Δεν ήταν δυνατή η επαλήθευση του αποτυπώματος</string> <string name="manually_verify">Χειροκίνητη επαλήθευση</string> - <string name="are_you_sure_verify_fingerprint">Είστε βέβαιοι ότι θέλετε να επαληθεύσετε το αποτύπωμα OTR της επαφής σας;</string> <string name="pref_show_dynamic_tags">Εμφάνιση δυναμικών ετικετών</string> <string name="pref_show_dynamic_tags_summary">Εμφάνιση ετικετών μόνο για ανάγνωση κάτω από τις επαφές</string> <string name="enable_notifications">Ενεργοποίηση ειδοποιήσεων</string> @@ -386,7 +381,6 @@ <string name="disable_account">Απενεργοποίηση λογαριασμού</string> <string name="contact_has_stopped_typing">Ο χρήστης %s σταμάτησε να γράφει</string> <string name="pref_chat_states">Ειδοποιήσεις πληκτρολόγησης</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> diff --git a/src/main/res/values-es/strings.xml b/src/main/res/values-es/strings.xml index 640b088e..6cd291aa 100644 --- a/src/main/res/values-es/strings.xml +++ b/src/main/res/values-es/strings.xml @@ -122,7 +122,7 @@ <string name="pref_never_send_crash">Nunca informar de errores</string> <string name="pref_never_send_crash_summary">Si envías registros de error ayudas al desarrollo de Conversations</string> <string name="pref_confirm_messages">Confirmar mensajes</string> - <string name="pref_confirm_messages_summary">Permitir a tus contactos saber cuando recibes y lees un mensaje</string> + <string name="pref_confirm_messages_summary">Permitir a tus contactos saber cuando has recibido y leído sus mensajes</string> <string name="pref_ui_options">Pantalla</string> <string name="openpgp_error">OpenKeychain reportó un error</string> <string name="error_decrypting_file">Error descifrando archivo</string> @@ -380,7 +380,7 @@ <string name="no_application_found_to_open_file">No se ha encontrado ninguna aplicación para abrir el archivo</string> <string name="could_not_verify_fingerprint">No se puede verificar el contacto</string> <string name="manually_verify">Verificar manualmente</string> - <string name="are_you_sure_verify_fingerprint">¿Estás seguro de que quieres verificar el contacto?</string> + <string name="are_you_sure_verify_fingerprint">¿Estás seguro de que quieres verificar la huella digital OTR de tu contacto?</string> <string name="pref_show_dynamic_tags">Mostrar etiquetas</string> <string name="pref_show_dynamic_tags_summary">Mostrar información en forma de etiquetas debajo de los contactos</string> <string name="enable_notifications">Habilitar notificaciones</string> @@ -473,7 +473,7 @@ <string name="contact_is_typing">%s está escribiendo...</string> <string name="contact_has_stopped_typing">%s ha dejado de escribir</string> <string name="pref_chat_states">Notificación de escritura</string> - <string name="pref_chat_states_summary">Permitir a tus contactos saber cuando estás escribiendo un nuevo mensaje</string> + <string name="pref_chat_states_summary">Permitir a tus contactos saber cuando estás escribiendo un mensaje</string> <string name="send_location">Enviar ubicación</string> <string name="show_location">Mostrar ubicación</string> <string name="no_application_found_to_display_location">No se ha encontrado ninguna aplicación para mostrar la ubicación</string> @@ -666,4 +666,20 @@ <string name="data_saver_enabled">Optimización de datos habilitado</string> <string name="data_saver_enabled_explained">Tu sistema operativo está restringiendo a Conversations acceder a internet cuando está en segundo plano. Para recibir notificaciones de nuevos mensajes deberías permitir a Conversations acceder a internet cuando la optimización de datos está habilitada.\nConversations realizará igualmente optimizaciones para ahorrar datos cuando sea posible.</string> <string name="device_does_not_support_data_saver">Tu dispositivo no soporta la opción de deshabilitar la optimización de datos para Conversations</string> + <string name="error_unable_to_create_temporary_file">No se ha podido crear el fichero temporal</string> + <string name="this_device_has_been_verified">Este dispositivo ha sido verificado</string> + <string name="copy_fingerprint">Copiar huella digital</string> + <string name="all_omemo_keys_have_been_verified">Todas las huellas digitales OMEMO han sido verificadas</string> + <string name="barcode_does_not_contain_fingerprints_for_this_conversation">El código QR no contiene huellas digitales para esta conversación.</string> + <string name="verified_fingerprints">Huellas digitales verificadas</string> + <string name="use_camera_icon_to_scan_barcode">Usa la cámara para escanear el código QR del contacto</string> + <string name="please_wait_for_keys_to_be_fetched">Por favor, espera a que las claves sean recuperadas</string> + <string name="share_as_barcode">Compartir como código QR</string> + <string name="share_as_uri">Compartir como XMPP URI</string> + <string name="share_as_http">Compartir como link HTTP</string> + <string name="pref_blind_trust_before_verification">Confianza ciega antes de verificación</string> + <string name="pref_blind_trust_before_verification_summary">Automáticamente confiar en los nuevos dispositivos de tus contactos que no han sido verificados antes y solicita confirmación manual cada vez que un contacto verificado añade un dispositivo nuevo.</string> + <string name="blindly_trusted_omemo_keys">Huellas digitales OMEMO de confianza ciega</string> + <string name="not_trusted">No confiables</string> + <string name="invalid_barcode">Código QR inválido</string> </resources> diff --git a/src/main/res/values-eu/strings.xml b/src/main/res/values-eu/strings.xml index 6d26330d..be7a915e 100644 --- a/src/main/res/values-eu/strings.xml +++ b/src/main/res/values-eu/strings.xml @@ -122,14 +122,12 @@ <string name="pref_never_send_crash">Gelditze txostenik ez bidali inoiz</string> <string name="pref_never_send_crash_summary">Akats harraskak bidaliz Conversationsen garapenean laguntzen duzu</string> <string name="pref_confirm_messages">Mezuak egiaztatu</string> - <string name="pref_confirm_messages_summary">Zure kontaktuak mezu bat noiz jaso eta irakurri duzun jakin dezan baimendu</string> <string name="pref_ui_options">Erabiltzaile-interfazea</string> <string name="openpgp_error">OpenKeychainek akats baten berri eman du</string> <string name="error_decrypting_file">Sarrera/Irteera akatsa fitxategia desenkriptatzerakoan</string> <string name="accept">Onartu</string> <string name="error">Akats bat gertatu da</string> <string name="pref_grant_presence_updates">Presentzia eguneraketak eman</string> - <string name="pref_grant_presence_updates_summary">Prebentiboki presentzia eguneraketak eman eta eskatu sortu dituzun kontaktuetarako</string> <string name="subscriptions">Harpidetzak</string> <string name="your_account">Zure kontua</string> <string name="keys">Gakoak</string> @@ -331,6 +329,7 @@ <string name="check_x_filesize_on_host">Egiaztatu %1$sren neurria %2$s ostalarian</string> <string name="message_options">Mezuaren aukerak</string> <string name="copy_text">Testua kopiatu</string> + <string name="select_text">Testua hautatu</string> <string name="copy_original_url">Jatorrizko URLa kopiatu</string> <string name="send_again">Berriro bidali</string> <string name="file_url">Fitxategiaren URLa</string> @@ -338,8 +337,6 @@ <string name="url_copied_to_clipboard">URLa arbelera kopiatu da</string> <string name="message_copied_to_clipboard">Mezua arbelera kopiatu da</string> <string name="image_transmission_failed">Irudiaren transmisioak huts egin du</string> - <string name="scan_qr_code">QR kodea eskaneatu</string> - <string name="show_qr_code">QR kodea erakutsi</string> <string name="show_block_list">Blokeatutakoen zerrenda ikusi</string> <string name="account_details">Kontuaren xehetasunak</string> <string name="verify_otr">OTR egiaztatu</string> @@ -379,7 +376,6 @@ <string name="no_application_found_to_open_file">Fitxategia ireki dezakeen aplikaziorik ez da aurkitu</string> <string name="could_not_verify_fingerprint">Hatz-marka ezin izan da egiaztatu</string> <string name="manually_verify">Eskuz egiaztatu</string> - <string name="are_you_sure_verify_fingerprint">Ziur al zaude zure kontaktuaren OTR hatz-marka egiaztatu nahi duzulaz?</string> <string name="pref_show_dynamic_tags">Etiketa dinamikoak erakutsi</string> <string name="pref_show_dynamic_tags_summary">Irakurtzeko soilik diren etiketak erakutsi kontaktuen azpian</string> <string name="enable_notifications">Jakinarazpenak gaitu</string> @@ -472,7 +468,6 @@ <string name="contact_is_typing">%s idazten ari da...</string> <string name="contact_has_stopped_typing">%s(e)k idazteari utzi dio</string> <string name="pref_chat_states">Idazketa jakinarazpenak</string> - <string name="pref_chat_states_summary">Zure kontaktuak mezu berri bat noiz idazten ari zaren jakin dezan baimendu</string> <string name="send_location">Kokapena partekatu</string> <string name="show_location">Kokapena erakutsi</string> <string name="no_application_found_to_display_location">Kokapena erakutsi dezakeen aplikaziorik ez da aurkitu</string> @@ -660,4 +655,9 @@ <string name="pref_delete_omemo_identities_summary">Zure OMEMO gakoak birsortu. Zure kontaktu guztiak zu egiaztatu beharko zaituzte berriz. Soilik azken aukera bezala erabili hau.</string> <string name="delete_selected_keys">Hautatutako gakoak ezabatu</string> <string name="error_publish_avatar_offline">Konektatuta egon behar zara zure profileko argazkia argitaratzeko.</string> + <string name="show_error_message">Akatsaren mezua erakutsi</string> + <string name="error_message">Akatsaren mezua</string> + <string name="data_saver_enabled">Datuen aurreztailea gaituta</string> + <string name="data_saver_enabled_explained">Zure sistema eragileak Conversations atzeko planoan dagoenean Internetera konekta dadin mugatzen ari da. Mezu berrien jakinarazpenak jasotzeko Conversationsi mugagabeko sarrera eman beharko zenioke Datuen aurreztailea piztuta dagoenean.\nConversationsek datuak aurrezteko esfortzua egiten jarraituko du ahal duenean.</string> + <string name="device_does_not_support_data_saver">Zure gailuak ez du Datuen aurreztailea ezgaitzea baimentzen Conversationserako</string> </resources> diff --git a/src/main/res/values-fr/strings.xml b/src/main/res/values-fr/strings.xml index af305570..290125dc 100644 --- a/src/main/res/values-fr/strings.xml +++ b/src/main/res/values-fr/strings.xml @@ -122,14 +122,14 @@ <string name="pref_never_send_crash">Ne pas envoyer de rapports d\'erreurs</string> <string name="pref_never_send_crash_summary">En envoyant des logs vous aidez le développement de Conversations.</string> <string name="pref_confirm_messages">Confirmation de lecture</string> - <string name="pref_confirm_messages_summary">Informer le contact lorsque vous avez reçu et lu un message.</string> + <string name="pref_confirm_messages_summary">Faites savoir à vos contacts quand vous avez reçu et lu leurs messages</string> <string name="pref_ui_options">Interface</string> <string name="openpgp_error">OpenKeychain a signalé une erreur</string> <string name="error_decrypting_file">Erreur d\'E/S lors du déchiffrement du fichier</string> <string name="accept">Accepter</string> <string name="error">Une erreur s\'est produite</string> <string name="pref_grant_presence_updates">Autoriser les màj de disponibilité</string> - <string name="pref_grant_presence_updates_summary">Autoriser et demander par avance les mises à jour de disponibilité des contacts ajoutés.</string> + <string name="pref_grant_presence_updates_summary">Accordez et demandez par avance les abonnements de présence aux contacts que vous avez ajoutés</string> <string name="subscriptions">Publications</string> <string name="your_account">Votre compte</string> <string name="keys">Clefs</string> @@ -339,8 +339,8 @@ <string name="url_copied_to_clipboard">URL copiée dans le presse-papier</string> <string name="message_copied_to_clipboard">Message copié dans le presse-papier</string> <string name="image_transmission_failed">Échec lors de l\'envoi de l\'image</string> - <string name="scan_qr_code">Scanner un code QR</string> - <string name="show_qr_code">Afficher le code QR</string> + <string name="scan_qr_code">Scanner le Code-barres 2D</string> + <string name="show_qr_code">Montrer le Code-barres 2D</string> <string name="show_block_list">Afficher la liste des contacts bloqués</string> <string name="account_details">Détails du compte</string> <string name="verify_otr">Vérifier l\'OTR</string> @@ -380,7 +380,7 @@ <string name="no_application_found_to_open_file">Aucune application disponible pour ouvrir le fichier</string> <string name="could_not_verify_fingerprint">Impossible de vérifier l\'empreinte</string> <string name="manually_verify">Vérifier manuellement</string> - <string name="are_you_sure_verify_fingerprint">Êtes-vous sûr de vouloir vérifier l\'empreinte OTR de vos contacts ?</string> + <string name="are_you_sure_verify_fingerprint">Êtes-vous sûr de vouloir vérifier l\'empreinte OTR de votre contact?</string> <string name="pref_show_dynamic_tags">Afficher les tags dynamiques</string> <string name="pref_show_dynamic_tags_summary">Afficher des tags en lecture seule en dessous des contacts.</string> <string name="enable_notifications">Activer les notifications</string> @@ -473,7 +473,7 @@ <string name="contact_is_typing">%s est en train d\'écrire</string> <string name="contact_has_stopped_typing">%s a arrêté d\'écrire</string> <string name="pref_chat_states">Notifications d\'écriture</string> - <string name="pref_chat_states_summary">Informer votre contact lorsque vous êtes en train d\'écrire un message.</string> + <string name="pref_chat_states_summary">Faites savoir à vos contacts quand vous leur écrivez des message</string> <string name="send_location">Envoyer la position</string> <string name="show_location">Afficher la position</string> <string name="no_application_found_to_display_location">Aucune application trouvée pour afficher la position</string> @@ -665,4 +665,21 @@ <string name="error_message">Message d\'erreur</string> <string name="data_saver_enabled">Économie de données activée</string> <string name="data_saver_enabled_explained">Votre système d\'exploitation empêche Conversations d’accéder à Internet en arrière plan. Pour recevoir les notifications de nouveaux messages, vous devez autoriser, quand le mode d\'économie de données est actif, à ce que Conversations ai un plein accès au réseau.\n Conversations essaiera autant que possible d\'économiser la data.</string> + <string name="device_does_not_support_data_saver">Votre appareil ne prend pas en charge la désactivation de l\'économiseur de données pour Conversations.</string> + <string name="error_unable_to_create_temporary_file">Impossible de créer un fichier temporaire</string> + <string name="this_device_has_been_verified">Cet appareil a été vérifié</string> + <string name="copy_fingerprint">Copier l\'empreinte</string> + <string name="all_omemo_keys_have_been_verified">Toutes les clés OMEMO ont étés vérifiées</string> + <string name="barcode_does_not_contain_fingerprints_for_this_conversation">Le Code-barres ne contient pas d\'empreintes pour cette conversation.</string> + <string name="verified_fingerprints">Empreintes vérifiées</string> + <string name="use_camera_icon_to_scan_barcode">Utilisez l\'appareil photo pour scanner le code-barres d\'un contact</string> + <string name="please_wait_for_keys_to_be_fetched">Veuillez attendre que les clés soient récupérées</string> + <string name="share_as_barcode">Partager par Code-barres</string> + <string name="share_as_uri">Partager par URI XMPP</string> + <string name="share_as_http">Partager par lien HTTP</string> + <string name="pref_blind_trust_before_verification">Faire Aveuglement Confiance Avant La Vérification</string> + <string name="pref_blind_trust_before_verification_summary">Faire automatiquement confiance à tous les nouveaux appareils des contacts qui n\'ont pas étés vérifiés avant et demandez une confirmation manuelle à chaque fois qu\'un contact vérifié ajoute un nouveau appareil.</string> + <string name="blindly_trusted_omemo_keys">Faire aveuglement confiance aux clés OMEMO</string> + <string name="not_trusted">Non approuvée</string> + <string name="invalid_barcode">Code-barres 2D invalide</string> </resources> diff --git a/src/main/res/values-gl/strings.xml b/src/main/res/values-gl/strings.xml index ea60f29c..82507c7b 100644 --- a/src/main/res/values-gl/strings.xml +++ b/src/main/res/values-gl/strings.xml @@ -67,7 +67,6 @@ <string name="accept">Aceptar</string> <string name="error">Produciuse un erro</string> <string name="pref_grant_presence_updates">Suscripción de presencia</string> - <string name="pref_grant_presence_updates_summary">Por defecto otorgar e pedir suscripcións de presencia dos contactos que creaches</string> <string name="subscriptions">Suscripcións</string> <string name="your_account">A túa conta</string> <string name="keys">Chaves</string> diff --git a/src/main/res/values-id/strings.xml b/src/main/res/values-id/strings.xml index 6ba858c7..78c17a2a 100644 --- a/src/main/res/values-id/strings.xml +++ b/src/main/res/values-id/strings.xml @@ -113,14 +113,12 @@ <string name="pref_never_send_crash">Jangan kirim laporan kerusakan</string> <string name="pref_never_send_crash_summary">Dengan mengirimkan kesalahan Anda membantu pengembangan Aplikasi Conversations</string> <string name="pref_confirm_messages">Konfirmasi Pesan</string> - <string name="pref_confirm_messages_summary">Biarkan kontak Anda tahu kapan Anda telah menerima dan membaca pesan</string> <string name="pref_ui_options">UI</string> <string name="openpgp_error">OpenKeychain melaporkan kesalahan</string> <string name="error_decrypting_file">I/O Error menerjemahkan berkas</string> <string name="accept">Terima</string> <string name="error">Sebuah kesalahan terjadi</string> <string name="pref_grant_presence_updates">Memberikan perubahan kehadiran</string> - <string name="pref_grant_presence_updates_summary">Terlebih dahulu meminta dan berlangganan kehadiran untuk kontak Anda buat</string> <string name="subscriptions">Langganan</string> <string name="your_account">Akun anda</string> <string name="keys">Kunci</string> @@ -298,8 +296,6 @@ <string name="url_copied_to_clipboard">URL disalin ke clipboard</string> <string name="message_copied_to_clipboard">Pesan disalin ke clipboard</string> <string name="image_transmission_failed">pengiriman gambar gagal</string> - <string name="scan_qr_code">Pindai kode QR</string> - <string name="show_qr_code">Tampilkan kode QR</string> <string name="show_block_list">Tampilkan daftar blokir</string> <string name="account_details">Detil akun</string> <string name="verify_otr">Verifikasi OTR</string> @@ -336,7 +332,6 @@ <string name="no_application_found_to_open_file">Tidak ditemukan aplikasi untuk membuka berkas</string> <string name="could_not_verify_fingerprint">Tidak dapat verifikasi fingerprint</string> <string name="manually_verify">Verifikasi secara manual</string> - <string name="are_you_sure_verify_fingerprint">Yakin untuk memferifikasi OTR fingerprint kontak Anda?</string> <string name="pref_show_dynamic_tags">Tampilkan tag dinamis</string> <string name="pref_show_dynamic_tags_summary">Tampilan read-only tag di bawah kontak</string> <string name="enable_notifications">Aktifkan notifikasi</string> @@ -418,7 +413,6 @@ <string name="contact_is_typing">%s sedang mengetik…</string> <string name="contact_has_stopped_typing">%s telah berhenti mengetik</string> <string name="pref_chat_states">Notifikasi ketik pesan</string> - <string name="pref_chat_states_summary">Biarkan kontak Anda tahu ketika Anda sedang menulis pesan baru</string> <string name="send_location">Kirim lokasi</string> <string name="show_location">Tampilkan lokasi</string> <string name="no_application_found_to_display_location">Tidak ada aplikasi ditemukan untuk menampilkan lokasi</string> diff --git a/src/main/res/values-it/strings.xml b/src/main/res/values-it/strings.xml index d409b53f..e462e92a 100644 --- a/src/main/res/values-it/strings.xml +++ b/src/main/res/values-it/strings.xml @@ -122,14 +122,12 @@ <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 dell’errore aiuterai lo sviluppo di Conversations</string> <string name="pref_confirm_messages">Conferma Messaggi</string> - <string name="pref_confirm_messages_summary">Fai sapere ai tuoi contatti quando hai ricevuto il messaggio e l’hai letto</string> <string name="pref_ui_options">Interfaccia Utente</string> <string name="openpgp_error">OpenKeychain ha riportato un errore</string> <string name="error_decrypting_file">Errore di I/O nel decifrare il file</string> <string name="accept">Accetta</string> <string name="error">Si è verificato un errore</string> <string name="pref_grant_presence_updates">Concedi aggiornamenti della presenza</string> - <string name="pref_grant_presence_updates_summary">Concedi e chiedi preventivamente la sottoscrizione della presenza ai contatti che hai creato</string> <string name="subscriptions">Sottoscrizioni</string> <string name="your_account">Il tuo utente</string> <string name="keys">Chiavi</string> @@ -331,6 +329,7 @@ <string name="check_x_filesize_on_host">Controlla %1$s dimensione su %2$s</string> <string name="message_options">Opzioni del messaggio</string> <string name="copy_text">Copia testo</string> + <string name="select_text">Seleziona testo</string> <string name="copy_original_url">Copia URL originale</string> <string name="send_again">Invia di nuovo</string> <string name="file_url">URL del file</string> @@ -338,8 +337,6 @@ <string name="url_copied_to_clipboard">URL copiato</string> <string name="message_copied_to_clipboard">Messaggio copiato</string> <string name="image_transmission_failed">Trasmissione dell’immagine fallita</string> - <string name="scan_qr_code">Scansiona codice QR</string> - <string name="show_qr_code">Mostra codice QR</string> <string name="show_block_list">Mostra la black list</string> <string name="account_details">Dettagli utente</string> <string name="verify_otr">Verifica OTR</string> @@ -379,7 +376,6 @@ <string name="no_application_found_to_open_file">Nessuna applicazione trovata per aprire il file</string> <string name="could_not_verify_fingerprint">Impronta non verificata</string> <string name="manually_verify">Verifica manuale</string> - <string name="are_you_sure_verify_fingerprint">Sei sicuro di voler verificare l’impronta OTR del contatto?</string> <string name="pref_show_dynamic_tags">Mostra tag dinamici</string> <string name="pref_show_dynamic_tags_summary">Mostra tag in sola lettura sotto i contatti</string> <string name="enable_notifications">Abilita le notifiche</string> @@ -472,7 +468,6 @@ <string name="contact_is_typing">%s sta digitando...</string> <string name="contact_has_stopped_typing">%s ha smesso di digitare</string> <string name="pref_chat_states">Notifiche di composizione</string> - <string name="pref_chat_states_summary">Permetti al tuo contatto di vedere quando stai digitando</string> <string name="send_location">Invia la posizione</string> <string name="show_location">Mostra la posizione</string> <string name="no_application_found_to_display_location">Non è stata trovata alcuna applicazione per mostrare la posizione</string> @@ -660,4 +655,9 @@ <string name="pref_delete_omemo_identities_summary">Rigenera le tue chiavi OMEMO. I tuoi contatti dovranno verificare un\'altra volta la tua identità. Solo come ultima possibilità.</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> + <string name="show_error_message">Mostra messaggio di errore</string> + <string name="error_message">Messaggio di errore</string> + <string name="data_saver_enabled">Risparmio dati attivato</string> + <string name="data_saver_enabled_explained">Il tuo sistema operativo sta limitando l\'accesso internet a Conversations quando è in background. Per ricevere le notifiche di nuovi messaggi dovresti consentire l\'accesso senza limiti a Conversations quando il Risparmio dati è attivo.\nConversations cercherà comunque di risparmiare dati quando possibile.</string> + <string name="device_does_not_support_data_saver">Il tuo dispositivo non supporta la disattivazione del Risparmio dati per Conversations.</string> </resources> diff --git a/src/main/res/values-iw/strings.xml b/src/main/res/values-iw/strings.xml index 8ed4739f..a02b3c23 100644 --- a/src/main/res/values-iw/strings.xml +++ b/src/main/res/values-iw/strings.xml @@ -104,13 +104,11 @@ <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="openpgp_error">אפליקציית OpenKeychain דיווחה על שגיאה</string> <string name="error_decrypting_file">שגיאת I/O פענוח קובץ</string> <string name="accept">קבל</string> <string name="error">אירעה שגיאה</string> <string name="pref_grant_presence_updates">הענק עדכוני נוכחות</string> - <string name="pref_grant_presence_updates_summary">הענק ובקש הרשמות נוכחות מראש עבור אנשי קשר שיצרת</string> <string name="subscriptions">הרשמות</string> <string name="your_account">החשבון שלך</string> <string name="keys">מפתחות</string> @@ -291,8 +289,6 @@ <string name="url_copied_to_clipboard">הקישור הועתק</string> <string name="message_copied_to_clipboard">ההודעה הועתקה</string> <string name="image_transmission_failed">שליחת התמונה נכשלה</string> - <string name="scan_qr_code">סרוק ברקוד QR</string> - <string name="show_qr_code">הראה ברקוד QR</string> <string name="show_block_list">הראה רשימת חסומים</string> <string name="account_details">פרטי חשבון</string> <string name="verify_otr">אמת OTR</string> @@ -328,7 +324,6 @@ <string name="no_application_found_to_open_file">אין אפליקציה מתאימה לפתיחת הקובץ</string> <string name="could_not_verify_fingerprint">אימות טביעת האצבע נכשל</string> <string name="manually_verify">אימות ידני</string> - <string name="are_you_sure_verify_fingerprint">האם אתה בטוח שברצונך לאמת טביעת אצבע OTR זו?</string> <string name="pref_show_dynamic_tags">הראה תגים דומיים</string> <string name="pref_show_dynamic_tags_summary">הראה תגי read-only מתחת לאנשי הקשר</string> <string name="enable_notifications">אפשר התראות</string> @@ -417,7 +412,6 @@ <string name="contact_is_typing">%s מקליד/ה כעת…</string> <string name="contact_has_stopped_typing">%s הפסיק/ה להקליד</string> <string name="pref_chat_states">התראות הקלדה</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> diff --git a/src/main/res/values-ja/strings.xml b/src/main/res/values-ja/strings.xml index 5e5230d7..1aa424f6 100644 --- a/src/main/res/values-ja/strings.xml +++ b/src/main/res/values-ja/strings.xml @@ -122,7 +122,7 @@ <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_ui_options">UI</string> <string name="openpgp_error">OpenKeychain がエラーを報告しました</string> <string name="error_decrypting_file">ファイルの復号化中に I/O エラー</string> @@ -339,8 +339,8 @@ <string name="url_copied_to_clipboard">URL をクリップボードにコピーしました</string> <string name="message_copied_to_clipboard">メッセージをクリップボードにコピーしました</string> <string name="image_transmission_failed">画像の転送に失敗しました</string> - <string name="scan_qr_code">QR コードをスキャン</string> - <string name="show_qr_code">QR コードを表示</string> + <string name="scan_qr_code">2D バーコードをスキャン</string> + <string name="show_qr_code">2D バーコードを表示</string> <string name="show_block_list">ブロックリストを表示</string> <string name="account_details">アカウントの詳細</string> <string name="verify_otr">OTR を検証</string> @@ -473,7 +473,7 @@ <string name="contact_is_typing">%s は入力中…</string> <string name="contact_has_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> @@ -663,4 +663,20 @@ <string name="data_saver_enabled">データセーバーを有効にしました</string> <string name="data_saver_enabled_explained">お使いのオペレーティングシステムは、Conversationsがバックグラウンドのときにインターネットにアクセスすることを制限しています。新しいメッセージの通知を受信するには、データセーバーがオンになっているとき、Conversationsに無制限のアクセスを許可する必要があります。\nConversationsは可能なときにデータを保存するための努力をします。</string> <string name="device_does_not_support_data_saver">お使いのデバイスは、Conversationsのデータセーバーを無効にすることはできません。</string> + <string name="error_unable_to_create_temporary_file">一時ファイルを作成できません</string> + <string name="this_device_has_been_verified">このデバイスは検証済です</string> + <string name="copy_fingerprint">フィンガープリントをコピー</string> + <string name="all_omemo_keys_have_been_verified">すべての OMEMO 鍵は検証済です</string> + <string name="barcode_does_not_contain_fingerprints_for_this_conversation">バーコードに、この会話のフィンガープリントが含まれていません。</string> + <string name="verified_fingerprints">フィンガープリントを検証しました</string> + <string name="use_camera_icon_to_scan_barcode">カメラを使用して連絡先のバーコードをスキャンします</string> + <string name="please_wait_for_keys_to_be_fetched">キーが取得されるのをお待ちください</string> + <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_summary">以前に確認されていない連絡先の新しいデバイスをすべて自動的に信頼し、確認済の連絡先が新しいデバイスを追加するたびに手動で確認するよう促します。</string> + <string name="blindly_trusted_omemo_keys">OMEMO 鍵を白紙信託しました</string> + <string name="not_trusted">信頼されていない</string> + <string name="invalid_barcode">不正な 2D バーコード</string> </resources> diff --git a/src/main/res/values-ko/strings.xml b/src/main/res/values-ko/strings.xml index 1860cbc2..88202e68 100644 --- a/src/main/res/values-ko/strings.xml +++ b/src/main/res/values-ko/strings.xml @@ -71,12 +71,16 @@ <string name="send_failed">전송 실패 </string> <string name="send_rejected">거부됨 </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">이 대화의 모든 메세지를 삭제하시겠습니까? 경고: 이것은 다른 기기나 서버에 있는 메세지에는 영향을 미치지 않습니다. </string> <string name="delete_messages">메세지 삭제 </string> <string name="also_end_conversation">나중에 이 대화 끝내기 </string> + <string name="choose_presence">기기 선택</string> <string name="send_unencrypted_message">암호화하지 않은 메세지 전송</string> + <string name="send_message_to_x">%s 에게 매세지 보내기 </string> <string name="send_otr_message">OTR 암호화된 메세지 전송 </string> <string name="send_omemo_message">OMEMO로 암호화된 메세지</string> <string name="send_omemo_x509_message">v\\OMEMO로 암호화된 메세지 전송</string> @@ -100,19 +104,27 @@ <string name="pref_xmpp_resource_summary">이 클라이언트가 자신을 알아보는 이름</string> <string name="pref_accept_files">파일 수락 </string> <string name="pref_accept_files_summary">이 크기보다 작은 파일을 자동으로 수락 </string> + <string name="pref_attachments">첨부파일</string> + <string name="pref_return_to_previous">빠른 공유</string> + <string name="pref_notification_settings">알림 </string> <string name="pref_notifications">알림 </string> <string name="pref_notifications_summary">새 메세지 도착시 알림 </string> <string name="pref_vibrate">진동 </string> + <string name="pref_vibrate_summary">새 메세지 도착시 진동</string> + <string name="pref_led">LED 알림</string> + <string name="pref_led_summary">새 메세지 도착시 LED 깜빡이기</string> + <string name="pref_sound">알림음</string> + <string name="pref_sound_summary">새 메세지 도착시 알림음 재생</string> + <string name="pref_advanced_options">고급</string> <string name="pref_never_send_crash">충돌 보고서 보내지 않음 </string> <string name="pref_never_send_crash_summary">Stack trace 정보를 보냄으로서 Conversations의 개발에 기여할 수 있습니다 </string> <string name="pref_confirm_messages">메세지 확인 </string> - <string name="pref_confirm_messages_summary">메세지를 수신하고 읽었는지를 연락처에게 알려줌 </string> + <string name="pref_ui_options">UI</string> <string name="openpgp_error">OpenKeychain이 오류를 보고합니다 </string> <string name="error_decrypting_file">파일 복호화 입출력 오류 </string> <string name="accept">수락 </string> <string name="error">오류가 발생했습니다 </string> <string name="pref_grant_presence_updates">프레즌스 업데이트 허가 </string> - <string name="pref_grant_presence_updates_summary">당신이 추가한 연락처의 프레즌스 구독을 선제적으로 허가 및 요청함 </string> <string name="subscriptions">구독 </string> <string name="your_account">당신의 계정 </string> <string name="keys">키 </string> @@ -301,8 +313,6 @@ <string name="url_copied_to_clipboard">URL이 클립보드에 복사되었습니다 </string> <string name="message_copied_to_clipboard">메세지가 클립보드에 복사되었습니다 </string> <string name="image_transmission_failed">이미지 전송 실패 </string> - <string name="scan_qr_code">QR코드 스캔 </string> - <string name="show_qr_code">QR코드 보기 </string> <string name="show_block_list">차단 목록 보기 </string> <string name="account_details">계정 정보 </string> <string name="verify_otr">OTR 검증 </string> @@ -339,7 +349,6 @@ <string name="no_application_found_to_open_file">파일을 열기 위한 앱이 발견되지 않았습니다 </string> <string name="could_not_verify_fingerprint">핑거프린트를 검증할 수 없습니다 </string> <string name="manually_verify">수동 검증 </string> - <string name="are_you_sure_verify_fingerprint">연락처의 OTR 핑거프린트를 검증하시겠습니까? </string> <string name="pref_show_dynamic_tags">동적 태그 표시 </string> <string name="pref_show_dynamic_tags_summary">연락처 밑에 읽기 전용 태그 표시 </string> <string name="enable_notifications">알림 사용 </string> @@ -430,7 +439,6 @@ <string name="contact_is_typing">%s 이(가) 입력중입니다...</string> <string name="contact_has_stopped_typing">%s 이(가) 입력을 중단했습니다 </string> <string name="pref_chat_states">입력 알림 </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> diff --git a/src/main/res/values-nb-rNO/strings.xml b/src/main/res/values-nb-rNO/strings.xml index 55671015..b030242d 100644 --- a/src/main/res/values-nb-rNO/strings.xml +++ b/src/main/res/values-nb-rNO/strings.xml @@ -106,13 +106,11 @@ <string name="pref_never_send_crash">Aldri send feilrettingsrapporter</string> <string name="pref_never_send_crash_summary">Ved å sende inn stabelsporinger hjelper du den pågående utviklingen av Conversations</string> <string name="pref_confirm_messages">Bekreft meldinger</string> - <string name="pref_confirm_messages_summary">La din kontakt få vite når du har mottatt og lest en melding</string> <string name="openpgp_error">Feilmelding fra OpenKeychain</string> <string name="error_decrypting_file">I/O-feil ved dekryptering av fil</string> <string name="accept">Godta</string> <string name="error">En feil har inntruffet</string> <string name="pref_grant_presence_updates">Tillat oppdateringer for tilstedeværelse</string> - <string name="pref_grant_presence_updates_summary">Gi og spør om tilstandsabbonementer på forhånd for kontakter du har opprettet</string> <string name="subscriptions">Abonnement</string> <string name="your_account">Din konto</string> <string name="keys">Nøkler</string> @@ -301,8 +299,6 @@ <string name="url_copied_to_clipboard">Nettadresse kopiert til utklippstavle</string> <string name="message_copied_to_clipboard">Melding kopiert til utklippstavle</string> <string name="image_transmission_failed">Bildeoverføring feilet</string> - <string name="scan_qr_code">Skann QR-kode</string> - <string name="show_qr_code">Vis QR-kode</string> <string name="show_block_list">Vis blokkeringsliste</string> <string name="account_details">Kontodetaljer</string> <string name="verify_otr">Bekreft OTR</string> @@ -339,7 +335,6 @@ <string name="no_application_found_to_open_file">Fant inget program til åpning av fil</string> <string name="could_not_verify_fingerprint">Kunne ikke bekrefte fingeravtrykk</string> <string name="manually_verify">Bekreft manuelt</string> - <string name="are_you_sure_verify_fingerprint">Bekreft verifisering av din kontakts OTR-fingeravtrykk.</string> <string name="pref_show_dynamic_tags">Vis dynamiske merkelapper</string> <string name="pref_show_dynamic_tags_summary">Vis \"bare-les\"-merkelapper under kontakter</string> <string name="enable_notifications">Aktiver varslinger</string> @@ -430,7 +425,6 @@ <string name="contact_is_typing">%s skriver…</string> <string name="contact_has_stopped_typing">%s har sluttet å skrive</string> <string name="pref_chat_states">Varsler for skriving</string> - <string name="pref_chat_states_summary">La din kontakt få vite når du skriver en ny melding</string> <string name="send_location">Send plasseringsdata</string> <string name="show_location">Vis plasseringsdata</string> <string name="no_application_found_to_display_location">Ingen programmer funnet til visning av plasseringsdata</string> diff --git a/src/main/res/values-nl/strings.xml b/src/main/res/values-nl/strings.xml index 0ce91361..2088d45e 100644 --- a/src/main/res/values-nl/strings.xml +++ b/src/main/res/values-nl/strings.xml @@ -122,14 +122,14 @@ <string name="pref_never_send_crash">Verstuur nooit crashrapportages</string> <string name="pref_never_send_crash_summary">Door crashrapportages te versturen help je de ontwikkeling van Conversations</string> <string name="pref_confirm_messages">Bevestig berichten</string> - <string name="pref_confirm_messages_summary">Laat je contacten weten wanneer je berichten hebt ontvangen en gelezen</string> + <string name="pref_confirm_messages_summary">Laat je contacten weten wanneer je hun berichten ontvangen en gelezen hebt</string> <string name="pref_ui_options">Gebruikersomgeving</string> <string name="openpgp_error">OpenKeychain rapporteerde een fout</string> <string name="error_decrypting_file">I/O-fout tijdens ontsleutelen van bestand</string> <string name="accept">Aanvaarden</string> <string name="error">Er is een fout opgetreden</string> <string name="pref_grant_presence_updates">Verleen toestemming voor aanwezigheidsupdates</string> - <string name="pref_grant_presence_updates_summary">Op voorhand toestemming voor aanwezigheidsabonnementen verlenen en vragen aan contacten die je hebt aangemaakt</string> + <string name="pref_grant_presence_updates_summary">Op voorhand toestemming voor aanwezigheidsupdates verlenen en vragen aan contacten die je hebt aangemaakt</string> <string name="subscriptions">Abonnementen</string> <string name="your_account">Je account</string> <string name="keys">Sleutels</string> @@ -339,8 +339,8 @@ <string name="url_copied_to_clipboard">URL gekopieerd naar klembord</string> <string name="message_copied_to_clipboard">Bericht gekopieerd naar klembord</string> <string name="image_transmission_failed">Versturen van afbeelding mislukt</string> - <string name="scan_qr_code">QR-code scannen</string> - <string name="show_qr_code">QR-code tonen</string> + <string name="scan_qr_code">2D-barcode scannen</string> + <string name="show_qr_code">2D-barcode tonen</string> <string name="show_block_list">Geblokkeerde contacten weergeven</string> <string name="account_details">Accountgegevens</string> <string name="verify_otr">OTR bevestigen</string> @@ -380,7 +380,6 @@ <string name="no_application_found_to_open_file">Geen applicatie om bestand te openen</string> <string name="could_not_verify_fingerprint">Kon vingerafdruk niet bevestigen</string> <string name="manually_verify">Handmatig bevestigen</string> - <string name="are_you_sure_verify_fingerprint">Ben je zeker dat je de OTR-vingerafdruk van je contact wil bevestigen?</string> <string name="pref_show_dynamic_tags">Toon dynamische tags</string> <string name="pref_show_dynamic_tags_summary">Toon enkel-lezen tags onder contacten</string> <string name="enable_notifications">Meldingen inschakelen</string> @@ -473,7 +472,6 @@ <string name="contact_is_typing">%s is aan het typen…</string> <string name="contact_has_stopped_typing">%s is gestopt met typen</string> <string name="pref_chat_states">\'Aan het typen\' meldingen</string> - <string name="pref_chat_states_summary">Laat je contacten weten wanneer je een nieuw bericht aan het schrijven bent</string> <string name="send_location">Locatie versturen</string> <string name="show_location">Locatie weergeven</string> <string name="no_application_found_to_display_location">Geen applicatie om locatie weer te geven</string> @@ -666,4 +664,9 @@ <string name="data_saver_enabled">Gegevensbesparing ingeschakeld</string> <string name="data_saver_enabled_explained">Je besturingssysteem verhindert Conversations toegang tot het internet wanneer Conversations zich in de achtergrond bevindt. Om meldingen van nieuwe berichten te krijgen moet je Conversations onbeperkte toegang geven wanneer gegevensbesparing is ingeschakeld.\nConversations zal nog steeds proberen wanneer mogelijk gegevens te besparen.</string> <string name="device_does_not_support_data_saver">Je apparaat ondersteunt het uitschakelen van gegevensbesparing voor Conversations niet.</string> + <string name="error_unable_to_create_temporary_file">Kan tijdelijk bestand niet aanmaken</string> + <string name="this_device_has_been_verified">Dit apparaat is geverifieerd</string> + <string name="copy_fingerprint">Vingerafdruk kopiëren</string> + <string name="all_omemo_keys_have_been_verified">Alle OMEMO-sleutels zijn geverifieerd</string> + <string name="verified_fingerprints">Geverifieerde vingerafdrukken</string> </resources> diff --git a/src/main/res/values-pl/strings.xml b/src/main/res/values-pl/strings.xml index 7cbb7655..eeb43c6c 100644 --- a/src/main/res/values-pl/strings.xml +++ b/src/main/res/values-pl/strings.xml @@ -78,7 +78,9 @@ <string name="clear_histor_msg">Czy na pewno usunąć wszystkie wiadomości powiązane z konwersacją?\n\n<b>Uwaga:</b> Działanie nie wpływa na wiadomości przechowywane na innych urządzeniach lub serwerach.</string> <string name="delete_messages">Usuń wiadomości</string> <string name="also_end_conversation">po czym zakończ tę rozmowę</string> + <string name="choose_presence">Wybierz urządzenie</string> <string name="send_unencrypted_message">Wyślij wiadomość bez szyfrowania</string> + <string name="send_message_to_x">Wyślij wiadomość do %s</string> <string name="send_otr_message">Wyślij zaszyfrowaną wiadomość (OTR)</string> <string name="send_omemo_message">Wyślij wiadomość zaszyfrowaną OMEMO</string> <string name="send_omemo_x509_message">Wyślij wiadomość zaszyfrowaną v\\OMEMO</string> @@ -114,18 +116,17 @@ <string name="pref_led_summary">Migaj lampką powiadamiającą gdy nadejdzie wiadomość</string> <string name="pref_sound">Dzwonek</string> <string name="pref_sound_summary">Odtwórz dźwięk gdy nadejdzie wiadomość</string> + <string name="pref_notification_grace_period">Czas Bez Powiadomień</string> <string name="pref_advanced_options">Zaawansowane</string> <string name="pref_never_send_crash">Nie wysyłaj raportów awarii</string> <string name="pref_never_send_crash_summary">Wysyłając ślady stosu pomagasz rozwijać Conversations</string> <string name="pref_confirm_messages">Potwierdzenia wiadomości</string> - <string name="pref_confirm_messages_summary">Powiadamiaj kontakty o otrzymaniu lub przeczytaniu wiadomości</string> <string name="pref_ui_options">UI</string> <string name="openpgp_error">Wystąpił błąd OpenKeychain</string> <string name="error_decrypting_file">Błąd podczas deszyfrowania pliku</string> <string name="accept">Akceptuj</string> <string name="error">Wystąpił błąd</string> <string name="pref_grant_presence_updates">Zezwól na powiadomienia obecności</string> - <string name="pref_grant_presence_updates_summary">Automatycznie zezwalaj i pytaj o powiadomienia obecności, kiedy utworzysz kontakt</string> <string name="subscriptions">Subskrypcje</string> <string name="your_account">Twoje konto</string> <string name="keys">Klucze</string> @@ -238,6 +239,7 @@ <string name="contact_already_exists">Kontakt już istnieje</string> <string name="join">Dołącz</string> <string name="conference_address">Adres konferencji</string> + <string name="conference_address_example">konferencja@konferencje.example.com/nick</string> <string name="save_as_bookmark">Dodaj jako zakładkę</string> <string name="delete_bookmark">Usuń zakładkę</string> <string name="bookmark_already_exists">Zakładka już istnieje</string> @@ -272,6 +274,7 @@ <string name="conference_requires_password">Konferencja jest zabezpieczona hasłem</string> <string name="enter_password">Wprowadź hasło</string> <string name="missing_presence_updates">Kontakt nie udostępnia powiadomień o obecności</string> + <string name="missing_presence_subscription">Brakuje subskrypcji obecności</string> <string name="request_presence_updates">Poproś kontakt o udostępnienie powiadomień o obecności.\n\n<small>Pozwoli to na ustalenie klienta, z którego korzysta rozmówca.</small></string> <string name="request_now">Zażądaj teraz</string> <string name="delete_fingerprint">Usuń odcisk klucza</string> @@ -319,6 +322,7 @@ <string name="check_x_filesize_on_host">Sprawdź wielkość %1$s na %2$s</string> <string name="message_options">Opcje wiadomości</string> <string name="copy_text">Skopiuj tekst</string> + <string name="select_text">Zaznacz tekst</string> <string name="copy_original_url">Skopiuj oryginalny URL</string> <string name="send_again">Wyślij ponownie</string> <string name="file_url">URL pliku</string> @@ -326,8 +330,6 @@ <string name="url_copied_to_clipboard">URL obrazu został skopiowany do schowka</string> <string name="message_copied_to_clipboard">Wiadomość została skopiowana do schowka</string> <string name="image_transmission_failed">Błąd podczas przesyłania obrazu</string> - <string name="scan_qr_code">Zeskanuj kod QR</string> - <string name="show_qr_code">Pokaż kod QR</string> <string name="show_block_list">Wyświetl listę banów</string> <string name="account_details">Szczegóły konta</string> <string name="verify_otr">Weryfikuj OTR</string> @@ -365,7 +367,6 @@ <string name="no_application_found_to_open_file">Nie odnaleziono aplikacji skojarzonej z typem pliku</string> <string name="could_not_verify_fingerprint">Weryfikacja odcisku klucza nieudana</string> <string name="manually_verify">Weryfikuj ręcznie</string> - <string name="are_you_sure_verify_fingerprint">Czy na pewno chcesz zweryfikować odcisk klucza OTR kontaktu?</string> <string name="pref_show_dynamic_tags">Etykiety kontaktów</string> <string name="pref_show_dynamic_tags_summary">Wyświetlaj etykiety pod kontaktami</string> <string name="enable_notifications">Włącz powiadomienia</string> @@ -457,7 +458,6 @@ <string name="contact_is_typing">%s pisze...</string> <string name="contact_has_stopped_typing">%s przestał(a) pisać</string> <string name="pref_chat_states">Powiadomienia pisania</string> - <string name="pref_chat_states_summary">Powiadamiaj rozmówcę, kiedy rozpoczynasz nową wiadomość</string> <string name="send_location">Wyślij lokalizację</string> <string name="show_location">Pokaż lokalizację</string> <string name="no_application_found_to_display_location">Nie odnaleziono aplikacji do wyświetlenia lokalizacji</string> @@ -599,4 +599,29 @@ <string name="secure_password_generated">Zostało wygenerowane bezpieczne hasło</string> <string name="device_does_not_support_battery_op">Twoje urządzenie nie pozwala na wyłączenie optymalizacji baterii</string> <string name="show_password">Pokaż hasło</string> + <string name="pref_delete_omemo_identities_summary">Wygeneruj jeszcze raz klucze OMEMO. Wszystkie Twoje kontakty będą musiały zweryfikować Twoje nowe klucze. Użyj tego tylko w ostateczności.</string> + <string name="delete_selected_keys">Usuń zaznaczone klucze</string> + <string name="error_publish_avatar_offline">Musisz być połączony/na, aby opublikować swój awatar.</string> + <string name="show_error_message">Pokaż komunikaty błędów</string> + <string name="error_message">Komunikat o Błędzie</string> + <string name="data_saver_enabled">Oszczędzanie danych jest włączone</string> + <string name="data_saver_enabled_explained">Twój system operacyjny blokuje dostęp do internetu Conversations, kiedy jest w tle. Aby dostawać powiadomienia dla nowych wiadomości powinieneś/powinnaś dać Conversations nieograniczony dostęp do internetu, kiedy Oszczędzanie danych jest włączone. +Conversations będzie wciąż ograniczał transfer danych, kiedy tylko to jest możliwe.</string> + <string name="device_does_not_support_data_saver">Twoje urządzenie nie wspiera wyłączenia Oszczędzania danych dla Conversations.</string> + <string name="error_unable_to_create_temporary_file">Niemożna utworzyć pliku tymczasowego</string> + <string name="this_device_has_been_verified">To urządzenie zostało zweryfikowane</string> + <string name="copy_fingerprint">Skopiuj odcisk</string> + <string name="all_omemo_keys_have_been_verified">Wszystkie odciski OMEMO zostały zweryfikowane</string> + <string name="barcode_does_not_contain_fingerprints_for_this_conversation">Kod kreskowy nie zawiera odcisków dla tej rozmowy.</string> + <string name="verified_fingerprints">Zaufane odciski</string> + <string name="use_camera_icon_to_scan_barcode">Użyj aparatu, aby zeskanować kod kreskowy kontaktu.</string> + <string name="please_wait_for_keys_to_be_fetched">Proszę czekać na ściągnięcie kluczy</string> + <string name="share_as_barcode">Udostępnij przez Kod Kreskowy</string> + <string name="share_as_uri">Udostępnij przez URI XMPP</string> + <string name="share_as_http">Udostępnij przez link HTTP</string> + <string name="pref_blind_trust_before_verification">Ślepo Ufaj Przed Weryfikacją</string> + <string name="pref_blind_trust_before_verification_summary">Automatycznie ufaj wszystkim nowym urządzeniom kontaktów, którzy nie zostali zweryfikowani wcześniej, i poproś o ręczne potwierdzenie za każdym, kiedy zweryfikowany kontakt dodaje nowe urządzenie.</string> + <string name="blindly_trusted_omemo_keys">Ślepo ufaj kluczom OMEMO</string> + <string name="not_trusted">Niezaufane</string> + <string name="invalid_barcode">Nieprawidłowy kod kreskowy 2D</string> </resources> diff --git a/src/main/res/values-pt-rBR/strings.xml b/src/main/res/values-pt-rBR/strings.xml index 502ffd54..dd818d0a 100644 --- a/src/main/res/values-pt-rBR/strings.xml +++ b/src/main/res/values-pt-rBR/strings.xml @@ -121,21 +121,21 @@ <string name="pref_advanced_options">Avançado</string> <string name="pref_never_send_crash">Nunca enviar relatórios de erros</string> <string name="pref_never_send_crash_summary">Ao enviar os stack traces você está colaborando com o desenvolvimento do Conversations.</string> - <string name="pref_confirm_messages">Confirmação de mensangens</string> - <string name="pref_confirm_messages_summary">Permite que um contato saiba quando você recebeu e leu uma mensagem.</string> + <string name="pref_confirm_messages">Confirmação de mensagens</string> + <string name="pref_confirm_messages_summary">Permite que seus contatos saibam quando você recebeu e leu as mensagens deles.</string> <string name="pref_ui_options">IU</string> <string name="openpgp_error">O OpenKeychain informou um erro</string> <string name="error_decrypting_file">Ocorreu um erro de E/S na descriptografia o arquivo</string> <string name="accept">Aceitar</string> <string name="error">Ocorreu um erro</string> - <string name="pref_grant_presence_updates">Permitir atualizações de presença</string> - <string name="pref_grant_presence_updates_summary">Permite e solicita atualizações de presença aos contatos que você criar</string> + <string name="pref_grant_presence_updates">Fornecer atualizações de presença</string> + <string name="pref_grant_presence_updates_summary">Permite e solicita, antecipadamente, atualizações de presença aos contatos que você criou</string> <string name="subscriptions">Inscrições</string> <string name="your_account">Sua conta</string> <string name="keys">Chaves</string> <string name="send_presence_updates">Enviar atualizações de presença</string> <string name="receive_presence_updates">Receber atualizações de presença</string> - <string name="ask_for_presence_updates">Pedir por atualizações de presença</string> + <string name="ask_for_presence_updates">Solicitar atualizações de presença</string> <string name="attach_choose_picture">Selecionar uma imagem</string> <string name="attach_take_picture">Tirar uma foto</string> <string name="preemptively_grant">Autorizar antecipadamente as solicitações de inscrição</string> @@ -283,6 +283,7 @@ <string name="conference_requires_password">Essa conferencia requer uma senha</string> <string name="enter_password">Digite a senha</string> <string name="missing_presence_updates">Sem atualizações de presença do contato</string> + <string name="missing_presence_subscription">Sem requisição de presença</string> <string name="request_presence_updates">Por favor, primeiro solicite atualizações de presençado seu contato.\n\n<small>Isso determinará qual(is) cliente(s) o seu contato está usando.</small></string> <string name="request_now">Solicitar agora</string> <string name="delete_fingerprint">Excluir impressão digital</string> @@ -338,8 +339,8 @@ <string name="url_copied_to_clipboard">A URL foi copiada para a área de transferência</string> <string name="message_copied_to_clipboard">A mensagem foi copiada para a área de transferência</string> <string name="image_transmission_failed">Não foi possível enviar a imagem</string> - <string name="scan_qr_code">Escanear QR code</string> - <string name="show_qr_code">Exibir QR code</string> + <string name="scan_qr_code">Capturar código de barras 2D</string> + <string name="show_qr_code">Exibir código de barras 2D</string> <string name="show_block_list">Exibir a lista de bloqueios</string> <string name="account_details">Detalhes da conta</string> <string name="verify_otr">Verificar OTR</string> @@ -379,7 +380,7 @@ <string name="no_application_found_to_open_file">Não foi encontrado nenhum aplicativo para abrir o arquivo</string> <string name="could_not_verify_fingerprint">Não foi possível verificar a impressão digital</string> <string name="manually_verify">Verificado manualmente</string> - <string name="are_you_sure_verify_fingerprint">Deseja realmente verificar as impressões digitais OTR dos seus contatos?</string> + <string name="are_you_sure_verify_fingerprint">Tem certeza que deseja verificar as impressões digitais OTR do seu contato?</string> <string name="pref_show_dynamic_tags">Exibir etiquetas dinâmicas</string> <string name="pref_show_dynamic_tags_summary">Exibe etiquetas de somente-leitura abaixo dos contatos.</string> <string name="enable_notifications">Habilitar notificações</string> @@ -472,7 +473,7 @@ <string name="contact_is_typing">%s está digitando...</string> <string name="contact_has_stopped_typing">%s parou de digitar</string> <string name="pref_chat_states">Notificações de digitação</string> - <string name="pref_chat_states_summary">Permite que seus contatos vejam quando você estiver digitando uma nova mensagem.</string> + <string name="pref_chat_states_summary">Permite aos seus usuários saberem quando você está escrevendo mensagens para eles</string> <string name="send_location">Enviar localização</string> <string name="show_location">Exibir localização</string> <string name="no_application_found_to_display_location">Não foi encontrado nenhum aplicativo para exibir a localização</string> @@ -645,12 +646,12 @@ <string name="payment_required">É necessário efetuar pagamento</string> <string name="missing_internet_permission">Permissões de Internet ausentes</string> <string name="me">Eu</string> - <string name="contact_asks_for_presence_subscription">O contato está solicitando atualizações de presença</string> + <string name="contact_asks_for_presence_subscription">O contato está requisitando acompanhar sua presença</string> <string name="allow">Permitir</string> <string name="no_permission_to_access_x">Sem permissão para acessar %s</string> <string name="remote_server_not_found">O servidor remoto não foi encontrado</string> <string name="unable_to_update_account">Não foi possível atualizar a conta</string> - <string name="missing_presence_subscription_with_x">Sem permissão para atualizações de presença de %s.</string> + <string name="missing_presence_subscription_with_x">Sem requisição de atualizações de presença com %s.</string> <string name="missing_keys_from_x">Sem chaves OMEMO para %s.</string> <string name="missing_omemo_keys">Chaves OMEMO ausentes</string> <string name="wrong_conference_configuration">Essa conferência não é privada nem anônima.</string> @@ -662,4 +663,18 @@ <string name="error_publish_avatar_offline">É necessário estar conectado para publicar o avatar.</string> <string name="show_error_message">Exibir a mensagem de erro</string> <string name="error_message">Mensagem de erro</string> + <string name="data_saver_enabled">Economia de dados habilitada</string> + <string name="data_saver_enabled_explained">O seu sistema operacional está restringindo o acesso à internet em segundo plano pelo Conversations. Para receber notificações de novas mensagens você deve permitir que o Conversations tenha acesso irrestrito quando a economia de dados estiver ativada.\nO Conversations fará um esforço para economizar dados sempre que possível.</string> + <string name="device_does_not_support_data_saver">O seu dispositivo não permite que a economia de dados seja desativada para o Conversations.</string> + <string name="error_unable_to_create_temporary_file">Não foi possível criar o arquivo temporário</string> + <string name="this_device_has_been_verified">Este dispositivo foi verificado</string> + <string name="copy_fingerprint">Copiar impressão digital</string> + <string name="all_omemo_keys_have_been_verified">Todas as chaves OMEMO foram verificadas</string> + <string name="barcode_does_not_contain_fingerprints_for_this_conversation">O código de barras não contém impressões digitais para esta conversa.</string> + <string name="verified_fingerprints">Impressões digitais verificadas</string> + <string name="use_camera_icon_to_scan_barcode">Use a câmera para capturar o código de barras de um contato</string> + <string name="share_as_barcode">Compartilhar como código de barras</string> + <string name="share_as_uri">Compartilhar como uma URI XMPP</string> + <string name="share_as_http">Compartilhar como um link HTTP</string> + <string name="not_trusted">Não confiável</string> </resources> diff --git a/src/main/res/values-pt/strings.xml b/src/main/res/values-pt/strings.xml index 9d5bd169..09ab0747 100644 --- a/src/main/res/values-pt/strings.xml +++ b/src/main/res/values-pt/strings.xml @@ -78,7 +78,9 @@ <string name="clear_histor_msg">Deseja remover todas as mensagens nesta conversa?\n\n<b>Aviso:<b> Isto não irá influenciar mensagens guardadas noutros dispositivos ou servidores.</string> <string name="delete_messages">Remover mensagens</string> <string name="also_end_conversation">Terminar esta conversa depois</string> + <string name="choose_presence">Escolher dispositivo</string> <string name="send_unencrypted_message">Enviar mensagem não cifrada</string> + <string name="send_message_to_x">Enviar mensagem para %s</string> <string name="send_otr_message">Enviar mensagem cifrada com OTR</string> <string name="send_omemo_message">Enviar mensagem cifrada com OMEMO</string> <string name="send_omemo_x509_message">Enviar mensagem cifrada com v\\OMEMO</string> @@ -118,14 +120,12 @@ <string name="pref_never_send_crash">Nunca enviar relatórios de falhas</string> <string name="pref_never_send_crash_summary">Ao enviar os stack traces você está a ajudar ao desenvolvimento contínuo de Conversations</string> <string name="pref_confirm_messages">Confirmar mensagens</string> - <string name="pref_confirm_messages_summary">Permitir que um contacto saiba quando você recebeu e leu uma mensagem</string> <string name="pref_ui_options">Interface do Utilizador</string> <string name="openpgp_error">O OpenKeychain reportou um erro</string> <string name="error_decrypting_file">Erro de I/O ao decifrar o ficheiro</string> <string name="accept">Aceitar</string> <string name="error">Ocorreu um erro</string> <string name="pref_grant_presence_updates">Permitir atualizações de presença</string> - <string name="pref_grant_presence_updates_summary">Conceder ou pedir subscrição de presença antecipadamente para contactos que tenha criado.</string> <string name="subscriptions">Subscrições</string> <string name="your_account">A sua conta</string> <string name="keys">Chaves</string> @@ -318,6 +318,7 @@ <string name="check_x_filesize_on_host">Verifique o tamanho de %1$s em %2$s</string> <string name="message_options">Opções de mensagem</string> <string name="copy_text">Copiar texto</string> + <string name="select_text">Selecionar texto</string> <string name="copy_original_url">Copiar o URL original</string> <string name="send_again">Enviar novamente</string> <string name="file_url">URL do ficheiro</string> @@ -325,8 +326,6 @@ <string name="url_copied_to_clipboard">URL copiado para a área de transferência</string> <string name="message_copied_to_clipboard">Mensagem copiada para a área de transferência</string> <string name="image_transmission_failed">A transmissão da imagem falhou</string> - <string name="scan_qr_code">Ler código QR</string> - <string name="show_qr_code">Mostrar código QR</string> <string name="show_block_list">Mostar lista de bloqueios</string> <string name="account_details">Detalhes da conta</string> <string name="verify_otr">Verificar OTR</string> @@ -348,6 +347,7 @@ <string name="conversations_foreground_service">Conversations</string> <string name="pref_keep_foreground_service">Manter o serviço em primeiro plano</string> <string name="pref_keep_foreground_service_summary">Previne o sistema operativo de terminar a sua conexão</string> + <string name="pref_export_logs">Exportar histórico</string> <string name="notification_export_logs_title">A escrever os logs para o cartão SD</string> <string name="choose_file">Escolher ficheiro</string> <string name="receiving_x_file">A receber %1$s (%2$d%% concluído)</string> @@ -364,7 +364,6 @@ <string name="no_application_found_to_open_file">Não foi encontrada nenhuma aplicação para abrir o ficheiro</string> <string name="could_not_verify_fingerprint">Não foi possível verificar a impressão digital</string> <string name="manually_verify">Verificar manualmente</string> - <string name="are_you_sure_verify_fingerprint">Tem a certeza que quer verificar a impressão digital OTR do seu contacto?</string> <string name="pref_show_dynamic_tags">Mostrar tags dinâmicas</string> <string name="pref_show_dynamic_tags_summary">Mostrar tags read-only debaixo dos contactos</string> <string name="enable_notifications">Ativar notificações</string> @@ -456,7 +455,6 @@ <string name="contact_is_typing">%s está a escrever...</string> <string name="contact_has_stopped_typing">%s parou de escrever</string> <string name="pref_chat_states">Notificações de escrita</string> - <string name="pref_chat_states_summary">Permitir que um contacto saiba quando está a escrever uma nova mensagem</string> <string name="send_location">Enviar localização</string> <string name="show_location">Exibir localização</string> <string name="no_application_found_to_display_location">Não foi encontrada nenhuma aplicação para mostrar a localização</string> @@ -576,4 +574,5 @@ <string name="security_error_invalid_file_access">Erro de segurança: Acesso ao ficheiro inválido</string> <string name="no_application_to_share_uri">Não foi encontrada nenhuma aplicação para partilhar o URI</string> <string name="share_uri_with">Partilhar URI com...</string> + <string name="create_account">Criar conta</string> </resources> diff --git a/src/main/res/values-ro-rRO/strings.xml b/src/main/res/values-ro-rRO/strings.xml index ede0a8dc..5590cd29 100644 --- a/src/main/res/values-ro-rRO/strings.xml +++ b/src/main/res/values-ro-rRO/strings.xml @@ -339,8 +339,8 @@ <string name="url_copied_to_clipboard">URL copiat in memorie</string> <string name="message_copied_to_clipboard">Mesaj copiat in memorie</string> <string name="image_transmission_failed">Transmisia imaginii a esuat</string> - <string name="scan_qr_code">Scaneaza cod QR</string> - <string name="show_qr_code">Arata codul QR</string> + <string name="scan_qr_code">Scaneaza cod de bare 2D</string> + <string name="show_qr_code">Arata cod de bare 2D</string> <string name="show_block_list">Arata lista blocata</string> <string name="account_details">Detalii cont</string> <string name="verify_otr">Verifica OTR</string> @@ -670,4 +670,20 @@ Emitent</string> <string name="data_saver_enabled">Economizorul de date este activat</string> <string name="data_saver_enabled_explained">Sistemul de operare restrictioneaza accesul la Internet pentru Conversations atunci cand este in fundal. Pentru a primi in continuare notificari de mesaje noi trebuie sa acordati acces ne restrictionat pentru Conversations atunci cand Economizorul de date este activ.\nConversations totusi face eforturi sa economiseasca datele atunci cand este posibil.</string> <string name="device_does_not_support_data_saver">Dispozitivul nu suporta dezactivarea Economizorului de date pentru Conversations.</string> + <string name="error_unable_to_create_temporary_file">Nu se poate crea un fisier temporar</string> + <string name="this_device_has_been_verified">Acest dispozitiv a fost verificat</string> + <string name="copy_fingerprint">Copiaza amprenta</string> + <string name="all_omemo_keys_have_been_verified">Toate cheile OMEMO au fost verificate</string> + <string name="barcode_does_not_contain_fingerprints_for_this_conversation">Codul de bare nu contine amprente pentru aceasta conversatie.</string> + <string name="verified_fingerprints">Amprente verificate</string> + <string name="use_camera_icon_to_scan_barcode">Foloseste camera pentru a scana codul de bare al contactului</string> + <string name="please_wait_for_keys_to_be_fetched">Asteptati cat se preiau cheile</string> + <string name="share_as_barcode">Partajeaza un cod de bare</string> + <string name="share_as_uri">Partajeaza ca adresa XMPP</string> + <string name="share_as_http">Partajeaza ca legatura HTTP</string> + <string name="pref_blind_trust_before_verification">Incredere Oarba Inainte de Verificare</string> + <string name="pref_blind_trust_before_verification_summary">Ai incredere in toate dispozitivele noi ale contactelor care nu au fost verificate anterior, si cere confirmare manuala de fiecare data cand un contact adauga un dispozitiv nou.</string> + <string name="blindly_trusted_omemo_keys">Incredere oarba in aceste chei OMEMO</string> + <string name="not_trusted">De neincredere</string> + <string name="invalid_barcode">Cod de bare 2D invalid</string> </resources> diff --git a/src/main/res/values-ru/strings.xml b/src/main/res/values-ru/strings.xml index 25bf34a8..3a88a444 100644 --- a/src/main/res/values-ru/strings.xml +++ b/src/main/res/values-ru/strings.xml @@ -122,14 +122,12 @@ <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_ui_options">Интерфейс</string> <string name="openpgp_error">Возникла ошибка в OpenKeychain</string> <string name="error_decrypting_file">Ошибка расшифровки файла</string> <string name="accept">Принять</string> <string name="error">Произошла ошибка</string> <string name="pref_grant_presence_updates">Предоставлять обновления</string> - <string name="pref_grant_presence_updates_summary">Разрешить и запрашивать статус присутствия для созданных вами контактов</string> <string name="subscriptions">Подписки</string> <string name="your_account">Ваш аккаунт</string> <string name="keys">Ключи</string> @@ -340,8 +338,6 @@ <string name="url_copied_to_clipboard">Ссылка скопирована в буфер обмена</string> <string name="message_copied_to_clipboard">Сообщение скопировано в буфер обмена</string> <string name="image_transmission_failed">Передача изображения не удалась</string> - <string name="scan_qr_code">Поиск QR-кода</string> - <string name="show_qr_code">Показать QR-код</string> <string name="show_block_list">Показать чёрный список</string> <string name="account_details">Сведения об учётной записи</string> <string name="verify_otr">Подтвердить OTR</string> @@ -381,7 +377,6 @@ <string name="no_application_found_to_open_file">Не найдено приложения для открытия файла</string> <string name="could_not_verify_fingerprint">Не удалось подтвердить отпечаток</string> <string name="manually_verify">Ручная проверка</string> - <string name="are_you_sure_verify_fingerprint">Вы точно хотите подтвердить OTR-отпечатки ваших контактов?</string> <string name="pref_show_dynamic_tags">Показывать динамические тэги</string> <string name="pref_show_dynamic_tags_summary">Отображать теги только для чтения под контактами</string> <string name="enable_notifications">Включить уведомления</string> @@ -474,7 +469,6 @@ <string name="contact_is_typing">%s печатает…</string> <string name="contact_has_stopped_typing">%s прекратил набор</string> <string name="pref_chat_states">Оповещения о наборе</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> @@ -670,4 +664,7 @@ <string name="error_publish_avatar_offline">Вы должны подключиться для публикации аватара.</string> <string name="show_error_message">Текст ошибки</string> <string name="error_message">Текст ошибки</string> + <string name="this_device_has_been_verified">Это устройство было подтверждено</string> + <string name="copy_fingerprint">Копировать отпечаток</string> + <string name="all_omemo_keys_have_been_verified">Все OMEMO-ключи были подтверждены</string> </resources> diff --git a/src/main/res/values-sk/strings.xml b/src/main/res/values-sk/strings.xml index a1c3e89c..a57d3b9d 100644 --- a/src/main/res/values-sk/strings.xml +++ b/src/main/res/values-sk/strings.xml @@ -101,13 +101,11 @@ <string name="pref_never_send_crash">Neodosielať detaily o zlyhaní aplikácie</string> <string name="pref_never_send_crash_summary">Zaslaním detailov o dôvode zlyhania pomáhate ďalšiemu vývoju aplikácie Conversations</string> <string name="pref_confirm_messages">Potvrdzovať správy</string> - <string name="pref_confirm_messages_summary">Oznámi kontaktom, že správa bola prijatá a prečítaná</string> <string name="openpgp_error">OpenKeychain nahlásil chybu</string> <string name="error_decrypting_file">I/O chyba dešifrovania súboru</string> <string name="accept">Prijať</string> <string name="error">Došlo k chybe</string> <string name="pref_grant_presence_updates">Povoliť aktualizáciu stavu</string> - <string name="pref_grant_presence_updates_summary">Aktívne povoliť a žiadať o zasielanie zmien stavu pre vytvorené kontakty</string> <string name="subscriptions">Odbery</string> <string name="your_account">Váš účet</string> <string name="keys">Kľúče</string> @@ -289,8 +287,6 @@ <string name="url_copied_to_clipboard">URL skopírovaný do schránky</string> <string name="message_copied_to_clipboard">Správa skopírovaná do schránky</string> <string name="image_transmission_failed">Zlyhal prenos obrázku</string> - <string name="scan_qr_code">Skenovať kód QR</string> - <string name="show_qr_code">Zobraziť kód QR</string> <string name="show_block_list">Zobraziť zoznam blokovaných</string> <string name="account_details">Detaily účtu</string> <string name="verify_otr">Overiť OTR</string> @@ -326,7 +322,6 @@ <string name="no_application_found_to_open_file">Nenašla sa žiadna aplikácia na otvorenie súboru</string> <string name="could_not_verify_fingerprint">Nepodarilo sa overiť identifikátor</string> <string name="manually_verify">Overiť manuálne</string> - <string name="are_you_sure_verify_fingerprint">Ste si istý, že chcete overiť OTR identifikátor vašich kontaktov? </string> <string name="pref_show_dynamic_tags">Zobraziť dynamické etikety</string> <string name="pref_show_dynamic_tags_summary">Zobraziť etikety na čítanie pod kontakty</string> <string name="enable_notifications">Povoliť upozornenia</string> @@ -405,7 +400,6 @@ <string name="disable_account">Vypnúť účet</string> <string name="contact_has_stopped_typing">%s prestal písať</string> <string name="pref_chat_states">Upozornenia pri písaní</string> - <string name="pref_chat_states_summary">Upozorniť kontakt, keď píšete novú správu</string> <string name="send_location">Poslať polohu</string> <string name="show_location">Zobraziť polohu</string> <string name="no_application_found_to_display_location">Nenašla sa aplikácia na zobrazenie polohy</string> diff --git a/src/main/res/values-sr/strings.xml b/src/main/res/values-sr/strings.xml index 6b914e23..f8cb5622 100644 --- a/src/main/res/values-sr/strings.xml +++ b/src/main/res/values-sr/strings.xml @@ -62,8 +62,8 @@ <string name="crash_report_message">Слањем контратрага помажете текући развој Конверзације\n<b>Упозорење:</b> Ово ће да искористи ваш ИксМПП налог за слање контратрага програмеру.</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="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> @@ -122,14 +122,12 @@ <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_ui_options">Сучеље</string> <string name="openpgp_error">Отворени кључарник је пријавио грешку</string> <string name="error_decrypting_file">У/И грешка дешифровања фајла</string> <string name="accept">Прихвати</string> <string name="error">Десила се грешка</string> <string name="pref_grant_presence_updates">Дозволи ажурирања присутности</string> - <string name="pref_grant_presence_updates_summary">Унапред дозволи и питај за претплату на присутност за контакте које направите</string> <string name="subscriptions">Претплате</string> <string name="your_account">Ваш налог</string> <string name="keys">Кључеви</string> @@ -339,8 +337,8 @@ <string name="url_copied_to_clipboard">УРЛ је копиран на клипборд</string> <string name="message_copied_to_clipboard">Порука је копирана на клипборд</string> <string name="image_transmission_failed">Пренос слике није успео</string> - <string name="scan_qr_code">Очитај бар-кôд</string> - <string name="show_qr_code">Прикажи бар-кôд</string> + <string name="scan_qr_code">Очитај 2Д бар-кôд</string> + <string name="show_qr_code">Прикажи 2Д бар-кôд</string> <string name="show_block_list">Прикажи списак блокираних</string> <string name="account_details">Детаљи налога</string> <string name="verify_otr">Овери ОТР</string> @@ -380,7 +378,6 @@ <string name="no_application_found_to_open_file">Нема апликације која може да отвори фајл</string> <string name="could_not_verify_fingerprint">Не могох да оверим отисак</string> <string name="manually_verify">Овери ручно</string> - <string name="are_you_sure_verify_fingerprint">Желите ли заиста да оверите ОТР отисак вашег контакта?</string> <string name="pref_show_dynamic_tags">Прикажи динамичке ознаке</string> <string name="pref_show_dynamic_tags_summary">Приказ ознака испод контаката</string> <string name="enable_notifications">Укључи обавештења</string> @@ -473,7 +470,6 @@ <string name="contact_is_typing">%s куца…</string> <string name="contact_has_stopped_typing">%s престаде да куца</string> <string name="pref_chat_states">Обавештења о куцању</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> @@ -533,12 +529,12 @@ <string name="pref_show_connection_options_summary">Приказ домаћина и порта у поставкама налога</string> <string name="hostname_example">xmpp.primer.com</string> <string name="action_add_account_with_certificate">Додај налог сертификатом</string> - <string name="unable_to_parse_certificate">Не могох да рашчланим сертификат</string> + <string name="unable_to_parse_certificate">Не могу да рашчланим сертификат</string> <string name="authenticate_with_certificate">Оставите празно за аутентификацију сертификатом</string> <string name="mam_prefs">Поставке архивисања</string> <string name="server_side_mam_prefs">Серверске поставке архивисања</string> <string name="fetching_mam_prefs">Добављам поставке архивисања, сачекајте…</string> - <string name="unable_to_fetch_mam_prefs">Не могох да добавим поставке архивисања</string> + <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> @@ -639,7 +635,7 @@ <string name="pref_theme_dark">Тамна тема</string> <string name="pref_use_green_background">Зелена позадина</string> <string name="pref_use_green_background_summary">Зелена позадина за примљене поруке</string> - <string name="unable_to_connect_to_keychain">Не могох да се повежем са Отвореним кључарником</string> + <string name="unable_to_connect_to_keychain">Не могу да се повежем са Отвореним кључарником</string> <string name="this_device_is_no_longer_in_use">Овај уређај више није у употреби</string> <string name="type_pc">Рачунар</string> <string name="type_phone">Мобилни телефон</string> @@ -653,7 +649,7 @@ <string name="allow">Дозволи</string> <string name="no_permission_to_access_x">Нема дозвола за приступ %s</string> <string name="remote_server_not_found">Удаљени сервер није нађен</string> - <string name="unable_to_update_account">Не могох да се ажурирам налог</string> + <string name="unable_to_update_account">Не могу да ажурирам налог</string> <string name="missing_presence_subscription_with_x">Нема претплате на присутност са %s.</string> <string name="missing_keys_from_x">Нема ОМЕМО кључева у %s.</string> <string name="missing_omemo_keys">Нема ОМЕМО кључева</string> @@ -666,4 +662,11 @@ <string name="error_publish_avatar_offline">Морате бити повезани да бисте објавили ваш аватар.</string> <string name="show_error_message">Прикажи поруку грешке</string> <string name="error_message">Порука грешке</string> + <string name="error_unable_to_create_temporary_file">Не могу да направим привремени фајл</string> + <string name="this_device_has_been_verified">Овај уређај је оверен.</string> + <string name="copy_fingerprint">Копирај отисак</string> + <string name="all_omemo_keys_have_been_verified">Сви ОМЕМО кључеви су оверени</string> + <string name="share_as_barcode">Подели као бар-кôд</string> + <string name="share_as_uri">Подели као ИксМПП УРИ</string> + <string name="share_as_http">Подели као ХТТП везу</string> </resources> diff --git a/src/main/res/values-sv/strings.xml b/src/main/res/values-sv/strings.xml index 3487e0ba..92288264 100644 --- a/src/main/res/values-sv/strings.xml +++ b/src/main/res/values-sv/strings.xml @@ -122,14 +122,14 @@ <string name="pref_never_send_crash">Skicka aldrig krasch-rapporter</string> <string name="pref_never_send_crash_summary">Genom att skicka in stack traces hjälper du utvecklarna av Conversations</string> <string name="pref_confirm_messages">Bekräfta meddelanden</string> - <string name="pref_confirm_messages_summary">Låter dina kontakter veta när du har tagit emot och läst ett meddelande</string> + <string name="pref_confirm_messages_summary">Låt dina kontakter veta när du har mottagit och läst deras meddelanden</string> <string name="pref_ui_options">Gränssnitt</string> <string name="openpgp_error">OpenKeychain rapporterade ett fel</string> <string name="error_decrypting_file">I/O-fel vid avkryptering av fil</string> <string name="accept">Acceptera</string> <string name="error">Ett fel har inträffat</string> <string name="pref_grant_presence_updates">Tillåt tillänglighetsuppdateringar</string> - <string name="pref_grant_presence_updates_summary">Tillåt i förväg och be om tillgänglighetsuppdateringar för kontakter du skapat</string> + <string name="pref_grant_presence_updates_summary">Tillåt och be om abonnemangsbegäran i förväg för kontakter du har skapat</string> <string name="subscriptions">Abonnemang</string> <string name="your_account">Ditt konto</string> <string name="keys">Nycklar</string> @@ -339,8 +339,8 @@ <string name="url_copied_to_clipboard">URL kopierad till urklipp</string> <string name="message_copied_to_clipboard">Meddelande kopierat till urklipp</string> <string name="image_transmission_failed">Bildöverföring lyckades inte</string> - <string name="scan_qr_code">Skanna QR-kod</string> - <string name="show_qr_code">Visa QR-kod</string> + <string name="scan_qr_code">Scanna 2D-streckkod</string> + <string name="show_qr_code">Visa 2D-streckkod</string> <string name="show_block_list">Visa blockeringslista</string> <string name="account_details">Kontodetaljer</string> <string name="verify_otr">Verifiera OTR</string> @@ -380,7 +380,7 @@ <string name="no_application_found_to_open_file">Ingen applikation kunde hittas för att öppna filen</string> <string name="could_not_verify_fingerprint">Kunde inte verifiera fingeravtryck</string> <string name="manually_verify">Verifiera manuellt</string> - <string name="are_you_sure_verify_fingerprint">Är du säker på att du vill verifiera din kontakts OTR-fingeravtryck</string> + <string name="are_you_sure_verify_fingerprint">Är du säker på att du vill verifiera din kontakts OTR-fingeravtryck?</string> <string name="pref_show_dynamic_tags">Visa dynamiska taggar</string> <string name="pref_show_dynamic_tags_summary">Visa skrivskyddade taggar under kontakter</string> <string name="enable_notifications">Aktivera notifieringar</string> @@ -473,7 +473,7 @@ <string name="contact_is_typing">%s skriver...</string> <string name="contact_has_stopped_typing">%s har slutat skriva</string> <string name="pref_chat_states">Skriv-notifieringar</string> - <string name="pref_chat_states_summary">Låter dina kontakter veta när du skriver ett nytt meddelande</string> + <string name="pref_chat_states_summary">Låt dina kontakter veta när du skriver meddelande till dem</string> <string name="send_location">Skicka position</string> <string name="show_location">Visa position</string> <string name="no_application_found_to_display_location">Kunde inte hitta applikation för att visa position</string> @@ -666,4 +666,20 @@ <string name="data_saver_enabled">Databesparing</string> <string name="data_saver_enabled_explained">Ditt operativsystem begränsar Internet-access för Conversations i när den är i bakgrunden. För att få notifieringar vid nya meddelanden behöver du ge Conversations obegränsad access när databesparing är påslaget.\nConversations kommer ändå försöka minska dataanvändningen när det är möjligt.</string> <string name="device_does_not_support_data_saver">Din enhet stödjer inte att deaktivera databesparing för Conversations.</string> + <string name="error_unable_to_create_temporary_file">Kunde inte skapa tillfällig fil</string> + <string name="this_device_has_been_verified">Denna enhet har verifierats</string> + <string name="copy_fingerprint">Kopiera fingeravtryck</string> + <string name="all_omemo_keys_have_been_verified">Alla OMEMO nycklar har verifierats</string> + <string name="barcode_does_not_contain_fingerprints_for_this_conversation">Streckkoden innehåller inte fingeravtryck för den här konversationen.</string> + <string name="verified_fingerprints">Verifierade fingeravtryck</string> + <string name="use_camera_icon_to_scan_barcode">Använd kameran för att scanna en kontakts streckkod</string> + <string name="please_wait_for_keys_to_be_fetched">Vänta medans nycklar hämtas</string> + <string name="share_as_barcode">Dela som streckkod</string> + <string name="share_as_uri">Dela som XMPP URI</string> + <string name="share_as_http">Dela som HTTP länk</string> + <string name="pref_blind_trust_before_verification">Blint förtroende före verifiering</string> + <string name="pref_blind_trust_before_verification_summary">Lita automatiskt på alla nya enheter för kontakter som inte har blivit verifierade tidigare, och be om manuell bekräftelse varje gång en verifierad kontakt lägger till en ny enhet.</string> + <string name="blindly_trusted_omemo_keys">Lita blint på OMEMO-nycklar</string> + <string name="not_trusted">Ej betrodd</string> + <string name="invalid_barcode">Ogiltig 2D-streckkod</string> </resources> diff --git a/src/main/res/values-tr-rTR/strings.xml b/src/main/res/values-tr-rTR/strings.xml index 768822b7..364b2c0e 100644 --- a/src/main/res/values-tr-rTR/strings.xml +++ b/src/main/res/values-tr-rTR/strings.xml @@ -1,12 +1,12 @@ <?xml version='1.0' encoding='UTF-8'?> <resources> <string name="action_settings">Ayarlar</string> - <string name="action_add">Yeni sohbet</string> + <string name="action_add">Yeni konuşma</string> <string name="action_accounts">Hesapları yönet</string> - <string name="action_end_conversation">Sohbeti sonlandır</string> + <string name="action_end_conversation">Konuşmayı sonlandır</string> <string name="action_contact_details">Kişi bilgileri</string> - <string name="action_muc_details">Grup sohbet bilgileri</string> - <string name="action_secure">Güvenli sohbet</string> + <string name="action_muc_details">Toplantı bilgileri</string> + <string name="action_secure">Güvenli konuşma</string> <string name="action_add_account">Hesap ekle</string> <string name="action_edit_contact">İsmi düzenle</string> <string name="action_add_phone_book">Telefon rehberine ekle</string> @@ -17,36 +17,36 @@ <string name="action_unblock_domain">Alan adını engellemekten vazgeç</string> <string name="title_activity_manage_accounts">Hesapları yönet</string> <string name="title_activity_settings">Ayarlar</string> - <string name="title_activity_conference_details">Grup sohbet bilgileri</string> + <string name="title_activity_conference_details">Toplantı bilgileri</string> <string name="title_activity_contact_details">Kişi bilgileri</string> - <string name="title_activity_sharewith">Sohbetle paylaş</string> - <string name="title_activity_start_conversation">Sohbeti başlat</string> + <string name="title_activity_sharewith">Konuşmayla paylaş</string> + <string name="title_activity_start_conversation">Konuşmayı başlat</string> <string name="title_activity_choose_contact">Kişi seç</string> <string name="title_activity_block_list">Listeyi blokla</string> <string name="just_now">şimdi</string> <string name="minute_ago">1 dakika önce</string> <string name="minutes_ago">%d dakika önc</string> - <string name="unread_conversations">okunmamış sohbetler</string> + <string name="unread_conversations">okunmamış konuşmalar</string> <string name="sending">gönderiyor…</string> <string name="message_decrypting">İleti deşifre ediliyor. Lütfen bekleyin…</string> - <string name="pgp_message">OpenPGP şifreli mesaj</string> + <string name="pgp_message">OpenPGP şifreli ileti</string> <string name="nick_in_use">Rumuz kullanılıyor</string> <string name="admin">Yönetici</string> <string name="owner">Sahip</string> <string name="moderator">Moderatör</string> <string name="participant">Katılımcı</string> <string name="visitor">Ziyaretçi</string> - <string name="remove_contact_text">%s kişisini listenizden silmek istiyor musunuz? Bu kişiyle yaptığınız sohbetler silinmeyecektir.</string> + <string name="remove_contact_text">%s kişisini listenizden silmek istiyor musunuz? Bu kişiyle yaptığınız konuşmalar silinmeyecektir.</string> <string name="block_contact_text">%s kişisinin size ileti göndermesini engellemek istiyor musunuz?</string> <string name="unblock_contact_text">% kişisinin size ileti göndermesine koyduğunuz engellemeyi kaldırmak ve size ileti göndermesine izin vermek istiyor musunuz?</string> - <string name="block_domain_text">%s üzerinden gelen bütün kişileri engellemek istiyor musunuz? </string> + <string name="block_domain_text">%s üzerinden gelen tüm kişileri engellemek istiyor musunuz? </string> <string name="unblock_domain_text">%s üzerinden gelen kişilerdeki engellemeyi kaldırmak istiyor musunuz?</string> <string name="contact_blocked">Kişi engellendi</string> - <string name="remove_bookmark_text">%s yer imini silmek istiyor musunuz? Bu yer imiyle ilintili sohbet silinmeyecektir.</string> + <string name="remove_bookmark_text">%s yer imini silmek istiyor musunuz? Bu yer imiyle ilintili konuşma silinmeyecektir.</string> <string name="register_account">Sunucuda yeni bir hesap oluştur</string> <string name="change_password_on_server">Sunucudaki şifreni değiştir</string> <string name="share_with">Paylaş...</string> - <string name="start_conversation">Sohbet başlat</string> + <string name="start_conversation">Konuşma başlat</string> <string name="invite_contact">Kişi davet et</string> <string name="contacts">Kişiler</string> <string name="cancel">İptal et</string> @@ -74,13 +74,13 @@ <string name="preparing_images">Resimler iletilmek üzere hazırlanıyor</string> <string name="sharing_files_please_wait">Dosyalar Paylaşılıyor. Lütfen bekleyin...</string> <string name="action_clear_history">Geçmişi sil</string> - <string name="clear_conversation_history">Sohbet geçmişini sil</string> - <string name="clear_histor_msg">Bu sohbetteki bütün iletileri silmek istiyor musunuz?\n\n<b>Uyarı:</b>Başka cihazlardaki ya da sunuculardaki iletiler bundan etkilenmeyecektir.</string> + <string name="clear_conversation_history">Konuşma geçmişini sil</string> + <string name="clear_histor_msg">Bu konuşmadaki tüm iletileri silmek istiyor musunuz?\n\n<b>Uyarı:</b>Başka aygıtlardaki ya da sunuculardaki iletiler bundan etkilenmeyecektir.</string> <string name="delete_messages">İletileri sil</string> - <string name="also_end_conversation">Sonrasında bu sohbeti sonlandır</string> - <string name="choose_presence">Cihaz seç</string> + <string name="also_end_conversation">Sonrasında bu konuşmayı sonlandır</string> + <string name="choose_presence">Aygıt seç</string> <string name="send_unencrypted_message">Şifrelenmemiş ileti gönder</string> - <string name="send_message_to_x">%s kişisine mesaj gönder</string> + <string name="send_message_to_x">%s kişisine ileti gönder</string> <string name="send_otr_message">OTR ile şifrelenmiş ileti gönder</string> <string name="send_omemo_message">OMEMO ile şifrelenmiş ileti gönder</string> <string name="send_omemo_x509_message">v\\OMEMO ile şifrelenmiş ileti gönder</string> @@ -96,17 +96,17 @@ <string name="offering">sunuluyor…</string> <string name="waiting">bekliyor…</string> <string name="no_pgp_key">Herhangi bir OpenPGP anahtarı bulunamadı</string> - <string name="contact_has_no_pgp_key">Kişi ortak anahtarını yayınlamadığı için Conversations iletilerinizi şifreleyemiyor.\n\n<small>Lütfen kişiden OpenPGP’yi ayarlamasını isteyin.</small></string> + <string name="contact_has_no_pgp_key">Kişi ortak anahtarını yayımlamadığı için Conversations iletilerinizi şifreleyemiyor.\n\n<small>Lütfen kişiden OpenPGP’yi ayarlamasını isteyin.</small></string> <string name="no_pgp_keys">Herhangi bir OpenPGP anahtarı bulunamadı</string> - <string name="contacts_have_no_pgp_keys">Kişiler ortak anahtarlarını yayınlamadığı için Conversations iletilerinizi şifreleyemiyor.\n\n<small>Lütfen kişilerden OpenPGP’yi ayarlamalarını isteyin.</small></string> + <string name="contacts_have_no_pgp_keys">Kişiler ortak anahtarlarını yayımlamadığı için Conversations iletilerinizi şifreleyemiyor.\n\n<small>Lütfen kişilerden OpenPGP’yi ayarlamalarını isteyin.</small></string> <string name="pref_general">Genel</string> <string name="pref_xmpp_resource">XMPP kaynağı</string> <string name="pref_xmpp_resource_summary">İstemci kimliği</string> <string name="pref_accept_files">Dosyaları kabul et</string> - <string name="pref_accept_files_summary">…‘den küçük olan dosyaları otomatik olarak kabul et</string> + <string name="pref_accept_files_summary">…‘den küçük olan dosyaları kendiliğinden kabul et</string> <string name="pref_attachments">Ekler</string> <string name="pref_return_to_previous">Hızlı Paylaşım</string> - <string name="pref_return_to_previous_summary">Bir şey paylaştıktan sonra bir grup sohbetine dönmek yerine önceki etkinliğe dön</string> + <string name="pref_return_to_previous_summary">Bir şey paylaştıktan sonra bir grup konuşmasına dönmek yerine önceki etkinliğe dön</string> <string name="pref_notification_settings">Bildirim</string> <string name="pref_notifications">Bildirimler</string> <string name="pref_notifications_summary">Yeni ileti geldiğinde bildir</string> @@ -117,12 +117,12 @@ <string name="pref_sound">Zil sesi</string> <string name="pref_sound_summary">Yeni bir ileti geldiğinde sesli bildir</string> <string name="pref_notification_grace_period">Mühlet</string> - <string name="pref_notification_grace_period_summary">Başka bir cihaz üstünde etkinlik algılandığında Conversations\'ın sessiz kalma süresi</string> + <string name="pref_notification_grace_period_summary">Başka bir aygıt üstünde etkinlik algılandığında Conversations\'ın sessiz kalma süresi</string> <string name="pref_advanced_options">Gelişmiş</string> <string name="pref_never_send_crash">Asla çöküş raporu gönderme</string> <string name="pref_never_send_crash_summary">Çöküş raporu göndermeniz Conversations\n’ın geliştirilmesine katkıda bulunacaktır.</string> <string name="pref_confirm_messages">İletileri onayla</string> - <string name="pref_confirm_messages_summary">Karşı tarafa ileti alındı ve okundu raporu gönder.</string> + <string name="pref_confirm_messages_summary">Onların iletilerini aldığınızda ve okuduğunuzda, kişilerinizin bunu bilmesini sağlayın</string> <string name="pref_ui_options">Arabirim</string> <string name="openpgp_error">OpenKeychain bir hata bildirdi</string> <string name="error_decrypting_file">Dosyanın deşifresinde G/Ç hatası</string> @@ -133,9 +133,9 @@ <string name="subscriptions">Abonelikler</string> <string name="your_account">Hesabınız</string> <string name="keys">Anahtarlar</string> - <string name="send_presence_updates">Çevrimiçi durum bildirimi gönder</string> - <string name="receive_presence_updates">Çevrimiçi durum bildirimi al</string> - <string name="ask_for_presence_updates">Çevrimiçi durum bildirimi iste</string> + <string name="send_presence_updates">Çevrim içi durum bildirimi gönder</string> + <string name="receive_presence_updates">Çevrim içi durum bildirimi al</string> + <string name="ask_for_presence_updates">Çevrim içi durum bildirimi iste</string> <string name="attach_choose_picture">Resim seç</string> <string name="attach_take_picture">Resim çek</string> <string name="preemptively_grant">Abonelik isteğini peşinen kabul et</string> @@ -146,9 +146,9 @@ <string name="error_security_exception_during_image_copy">Bu resmi seçmek için kullandığınız uygulama, dosyayı okuyabilmemiz için izin vermiyor. \n\n<small>Resim seçmek için farklı bir dosya yöneticisi kullanın.</small></string> <string name="account_status_unknown">Bilinmeyen</string> <string name="account_status_disabled">Geçici olarak devre dışı</string> - <string name="account_status_online">Çevrimiçi</string> + <string name="account_status_online">Çevrim içi</string> <string name="account_status_connecting">Bağlanıyor\u2026</string> - <string name="account_status_offline">Çevrimdışı</string> + <string name="account_status_offline">Çevrim dışı</string> <string name="account_status_unauthorized">Yetkisiz</string> <string name="account_status_not_found">Sunucu bulunamadı</string> <string name="account_status_no_internet">Bağlantı yok</string> @@ -167,13 +167,13 @@ <string name="mgmt_account_edit">Hesabı düzenle</string> <string name="mgmt_account_delete">Hesabı sil</string> <string name="mgmt_account_disable">Geçici olarak devre dışı bırak</string> - <string name="mgmt_account_publish_avatar">Avatar yayınla</string> - <string name="mgmt_account_publish_pgp">OpenPGP genel anahtarını yayınla</string> - <string name="openpgp_has_been_published">OpenPGP genel anahtar yayınlandı.</string> - <string name="republish_pgp_keys">OpenPGP genel anahtarınızı yeniden yayınlamayı unutmayın!</string> + <string name="mgmt_account_publish_avatar">Avatar yayımla</string> + <string name="mgmt_account_publish_pgp">OpenPGP genel anahtarını yayımla</string> + <string name="openpgp_has_been_published">OpenPGP genel anahtar yayımlandı.</string> + <string name="republish_pgp_keys">OpenPGP genel anahtarınızı yeniden yayımlamayı unutmayın!</string> <string name="mgmt_account_enable">Hesabı etkinleştir</string> <string name="mgmt_account_are_you_sure">Emin misiniz?</string> - <string name="mgmt_account_delete_confirm_text">Hesabınızı silerseniz bütün sohbet geçmişiniz silinecek</string> + <string name="mgmt_account_delete_confirm_text">Hesabınızı silerseniz tüm konuşma geçmişiniz silinecek</string> <string name="attach_record_voice">Ses kaydet</string> <string name="account_settings_jabber_id">Jabber ID</string> <string name="account_settings_password">Parola</string> @@ -185,13 +185,13 @@ <string name="invalid_jid">Jabber ID geçersiz</string> <string name="error_out_of_memory">Yetersiz bellek. Görüntü dosyası çok büyük.</string> <string name="add_phone_book_text">%s kişisini listenize eklemek ister misiniz?</string> - <string name="contact_status_online">çevrimiçi</string> - <string name="contact_status_free_to_chat">sohbet için uygun</string> + <string name="contact_status_online">çevrim içi</string> + <string name="contact_status_free_to_chat">konuşma için uygun</string> <string name="contact_status_away">uzakta</string> <string name="contact_status_extended_away">uzun süredir uzakta</string> <string name="contact_status_do_not_disturb">rahatsız etmeyin</string> - <string name="contact_status_offline">çevrimdışı</string> - <string name="muc_details_conference">Grup Sohbet</string> + <string name="contact_status_offline">çevrim dışı</string> + <string name="muc_details_conference">Toplantı</string> <string name="muc_details_other_members">Diğer Üyeler</string> <string name="server_info_show_more">Sunucu bilgisi</string> <string name="server_info_mam">XEP-0313: MAM</string> @@ -214,7 +214,7 @@ <string name="last_seen_day">en son 1 gün önce görüldü</string> <string name="last_seen_days">en son %d gün önce görüldü</string> <string name="never_seen">hiç görülmedi</string> - <string name="install_openkeychain">Şifreli mesaj. Deşifre etmek için lütfen OpenKeychain kurun.</string> + <string name="install_openkeychain">Şifreli ileti. Deşifre etmek için lütfen OpenKeychain kurun.</string> <string name="unknown_otr_fingerprint">Bilinmeyen OTR parmak izi</string> <string name="openpgp_messages_found">OpenPGP ile şifrelenmiş iletiler bulundu</string> <string name="reception_failed">Alınamadı</string> @@ -227,17 +227,17 @@ <string name="omemo_fingerprint_selected_message">İletinin OMEMO parmak izi</string> <string name="omemo_fingerprint_x509_selected_message">v\\İletinin OMEMO parmak izi</string> <string name="this_device_omemo_fingerprint">OMEMO parmak iziniz</string> - <string name="other_devices">Diğer cihazlar</string> + <string name="other_devices">Diğer aygıtlar</string> <string name="trust_omemo_fingerprints">OMEMO parmak izlerine güven</string> <string name="fetching_keys">Anahtarları alıyor…</string> <string name="done">Tamam</string> <string name="verify">Doğrula</string> <string name="decrypt">Deşifre et</string> - <string name="conferences">Grup Sohbetleri</string> + <string name="conferences">Toplantılar</string> <string name="search">Ara</string> <string name="create_contact">Kişi Oluştur</string> <string name="enter_contact">Kişi Girin</string> - <string name="join_conference">Grup Sohbete Katıl</string> + <string name="join_conference">Toplantıya Katıl</string> <string name="delete_contact">Kişi Sil</string> <string name="view_contact_details">Kişi bilgilerini görüntüle</string> <string name="block_contact">Kişiyi engelle</string> @@ -246,31 +246,31 @@ <string name="select">Seç</string> <string name="contact_already_exists">Kişi zaten mevcut</string> <string name="join">Katıl</string> - <string name="conference_address">Grup sohbet adresi</string> - <string name="conference_address_example">oda@conference.ornek.com/nick</string> + <string name="conference_address">Toplantı adresi</string> + <string name="conference_address_example">oda@toplanti.ornek.com/nick</string> <string name="save_as_bookmark">Yer imi olarak kaydet</string> <string name="delete_bookmark">Yer imini sil</string> <string name="bookmark_already_exists">Bu yer imi zaten mevcut</string> <string name="you">Siz</string> - <string name="action_edit_subject">Grup sohbet konusunu düzenle</string> - <string name="edit_subject_hint">Bu grup sohbetin konusu</string> - <string name="joining_conference">Grup sohbete katiliyor</string> + <string name="action_edit_subject">Toplantı konusunu düzenle</string> + <string name="edit_subject_hint">Bu toplantının konusu</string> + <string name="joining_conference">Toplantıya katılıyor...</string> <string name="leave">Ayrıl</string> <string name="contact_added_you">Kişi sizi listesine ekledi</string> <string name="add_back">Siz de ekleyin</string> <string name="contact_has_read_up_to_this_point">%s buraya kadar okudu</string> - <string name="publish">Yayınla</string> + <string name="publish">Yayımla</string> <string name="touch_to_choose_picture">Galeriden resim seçmek için avatara dokun</string> - <string name="publish_avatar_explanation">Lütfen dikkat: Çevrimiçi durum bildirimi güncellemelerinize abone olan herkes bu resmi görebilir.</string> - <string name="publishing">Yayınlanıyor…</string> - <string name="error_publish_avatar_server_reject">Sunucu yayınladığınız resmi reddetti</string> + <string name="publish_avatar_explanation">Lütfen dikkat: Çevrim içi durum bildirimi güncellemelerinize abone olan herkes bu resmi görebilir.</string> + <string name="publishing">Yayımlanıyor…</string> + <string name="error_publish_avatar_server_reject">Sunucu yayımladığınızı reddetti</string> <string name="error_publish_avatar_converting">Resim dönüştürülürken hata oluştu</string> <string name="error_saving_avatar">vatar diske kaydedilemedi</string> <string name="or_long_press_for_default">(Veya varsayılan değerlere dönmek için uzun süre basılı tutun)</string> - <string name="error_publish_avatar_no_server_support">Sunucunuz avatar yayınlanmasını desteklemiyor</string> + <string name="error_publish_avatar_no_server_support">Sunucunuz avatar yayımlanmasını desteklemiyor</string> <string name="private_message">fısıldandı</string> <string name="private_message_to">%s kişisine</string> - <string name="send_private_message_to">%s kişisine özel mesaj gönder</string> + <string name="send_private_message_to">%s kişisine özel ileti gönder</string> <string name="connect">Bağlan</string> <string name="account_already_exists">Bu hesap zaten mevcut</string> <string name="next">Sonraki</string> @@ -280,19 +280,19 @@ <string name="disable_notifications">Bildirimleri kapat</string> <string name="disable_notifications_for_this_conversation">Bu sohbet için bildirimleri kapat</string> <string name="enable">Etkinleştir</string> - <string name="conference_requires_password">Grup sohbet için parola gerekiyor</string> + <string name="conference_requires_password">Toplantı için parola gerekiyor</string> <string name="enter_password">Parolayı gir</string> - <string name="missing_presence_updates">Kişinin çevrimiçi durum bildirimi güncellemesi kayıp</string> + <string name="missing_presence_updates">Kişinin çevrim içi durum bildirimi güncellemesi kayıp</string> <string name="missing_presence_subscription">Durum bildirimi aboneliği eksik.</string> - <string name="request_presence_updates">Lütfen öncelikle kişiden çevrimiçi durum güncellemelerini isteyin.\n\n<small>Bu bilgi kişinin kullandığı istemcinin belirlenmesinde kullanılacaktır.</small></string> + <string name="request_presence_updates">Lütfen öncelikle kişiden çevrim içi durum güncellemelerini isteyin.\n\n<small>Bu bilgi kişinin kullandığı istemcinin belirlenmesinde kullanılacaktır.</small></string> <string name="request_now">Şimdi iste</string> <string name="delete_fingerprint">Parmak izini sil</string> <string name="sure_delete_fingerprint">Bu parmak izini silmek istediğinizden emin misiniz?</string> <string name="ignore">Yok say</string> - <string name="without_mutual_presence_updates"><b>Uyarı:</b> Karşılıklı çevrimiçi durum bildirimi güncellemeleri olmaksızın bunu göndermeniz beklenmedik sorunlara sebep olabilir.\n\n\n\n<small>Çevrimiçi durum bildirimi aboneliklerinizi kontrol etmek için kişi bilgilerine gidin.</small></string> + <string name="without_mutual_presence_updates"><b>Uyarı:</b> Karşılıklı çevrim içi durum bildirimi güncellemeleri olmaksızın bunu göndermeniz beklenmedik sorunlara neden olabilir.\n\n\n\n<small>Çevrim içi durum bildirimi aboneliklerinizi denetlemek için kişi bilgilerine gidin.</small></string> <string name="pref_security_settings">Güvenlik</string> <string name="pref_force_encryption">Uçtan uca şifrelemeye zorla</string> - <string name="pref_force_encryption_summary">Her zaman şifrelenmiş ileti gönder (Conversations hariç)</string> + <string name="pref_force_encryption_summary">Her zaman şifrelenmiş ileti gönder (toplantılar dışında)</string> <string name="pref_allow_message_correction">İleti düzeltmeye izin ver</string> <string name="pref_allow_message_correction_summary">Kişilerinizin geçmiş iletilerini düzeltmelerine izin ver</string> <string name="pref_dont_save_encrypted">Şifrelenmiş iletileri kaydetme</string> @@ -306,29 +306,29 @@ <string name="title_pref_quiet_hours_end_time">Bitiş zamanı</string> <string name="title_pref_enable_quiet_hours">Sessiz saatleri etkinleştir</string> <string name="pref_quiet_hours_summary">Bildirimler sessiz saatler boyunca sessize alınacaktır</string> - <string name="pref_use_larger_font">Fontu büyüt</string> - <string name="pref_use_larger_font_summary">Uygulamanın tamamında daha büyük font kullan+</string> + <string name="pref_use_larger_font">Yazı tipini büyüt</string> + <string name="pref_use_larger_font_summary">Uygulamanın tümünde büyük yazı tipi kullan</string> <string name="pref_use_send_button_to_indicate_status">Gönder düğmesi durum bildirsin</string> <string name="pref_use_indicate_received">İleti alındısı iste</string> - <string name="pref_use_indicate_received_summary">Alınan mesajlar, eğer destekleniyorsa, yeşil bir tikle işaretlenecektir.</string> + <string name="pref_use_indicate_received_summary">Alınan iletiler, eğer destekleniyorsa, yeşil bir tikle işaretlenecektir.</string> <string name="pref_use_send_button_to_indicate_status_summary">Gönder butonunu kişinin durumuna göre renklendir</string> <string name="pref_expert_options_other">Diğer</string> - <string name="pref_conference_name">Grup sohbet ismi</string> - <string name="pref_conference_name_summary">Grup sohbetleri tanımlamak için JID yerine odanın konusunu kullan</string> - <string name="pref_autojoin">Grup sohbet\'e otomatik olarak katıl</string> - <string name="pref_autojoin_summary">Grup sohbet yer imlerinde otomatik katıl bayrağına riayet et</string> + <string name="pref_conference_name">Toplantı adı</string> + <string name="pref_conference_name_summary">Toplantıları tanımlamak için JID yerine odanın konusunu kullan</string> + <string name="pref_autojoin">Toplantılara kendiliğinden katıl</string> + <string name="pref_autojoin_summary">Toplantı yer imlerinde kendiliğinden katıl seçeneğine uy</string> <string name="toast_message_otr_fingerprint">OTR parmak izi panoya kopyalandı!</string> <string name="toast_message_omemo_fingerprint">OMEMO parmak izi panoya kopyalandı!</string> - <string name="conference_banned">Grup sohbetinden atıldınız</string> - <string name="conference_members_only">Bu grup sohbet sadece üyelere açıktır</string> - <string name="conference_kicked">Grup sohbetinden atıldınız</string> - <string name="conference_shutdown">Grup sohbet sona erdi</string> - <string name="conference_unknown_error">Artık bu grup sohbet içerisinde değilsiniz.</string> + <string name="conference_banned">Bu toplantıda engellendiniz</string> + <string name="conference_members_only">Bu toplantı yalnızca üyelere açıktır</string> + <string name="conference_kicked">Bu toplantıdan atıldınız</string> + <string name="conference_shutdown">Toplantı sona erdi</string> + <string name="conference_unknown_error">Artık bu toplantı içerisinde değilsiniz.</string> <string name="using_account">%s hesabını kullanarak</string> - <string name="checking_x">HTTP sunucusundaki %s \'leri kontrol ediyor</string> + <string name="checking_x">HTTP sunucusundaki %s denetleniyor</string> <string name="not_connected_try_again">Bağlı değilsiniz. Daha sonra yeniden deneyin</string> - <string name="check_x_filesize">%s boyutunu kontrol edin</string> - <string name="check_x_filesize_on_host">%2$s üzerindeki %1$s boyutunu kontrol edin</string> + <string name="check_x_filesize">%s boyutunu denetle</string> + <string name="check_x_filesize_on_host">%2$s üzerindeki %1$s boyutunu denetle</string> <string name="message_options">İleti seçenekleri</string> <string name="copy_text">Metni kopyala</string> <string name="select_text">Metni seç</string> @@ -339,8 +339,8 @@ <string name="url_copied_to_clipboard">Panoya kopyalanan URL</string> <string name="message_copied_to_clipboard">Panoya kopyalanan ileti</string> <string name="image_transmission_failed">Resim aktarılamadı</string> - <string name="scan_qr_code">QR kodunu tara</string> - <string name="show_qr_code">QR kodunu göster</string> + <string name="scan_qr_code">2B Barkod Tara</string> + <string name="show_qr_code">2B Barkod Göster</string> <string name="show_block_list">Engellenenler listesini göster</string> <string name="account_details">Hesap bilgileri</string> <string name="verify_otr">OTR doğrula</string> @@ -380,22 +380,22 @@ <string name="no_application_found_to_open_file">Dosyayı açacak bir uygulama bulunamadı</string> <string name="could_not_verify_fingerprint">Parmak izi doğrulanamadı</string> <string name="manually_verify">Bizzat doğrula</string> - <string name="are_you_sure_verify_fingerprint">Kişilerin OTR parmak izlerini doğrulamak istediğinizden emin misiniz?</string> - <string name="pref_show_dynamic_tags">Dinamik etiketleri göster</string> + <string name="are_you_sure_verify_fingerprint">Kişinizin OTR parmak izini doğrulamak istediğinize emin misiniz?</string> + <string name="pref_show_dynamic_tags">Canlı etiketleri göster</string> <string name="pref_show_dynamic_tags_summary">Kişilerin görünmeyen salt okunur etiketlerini göster</string> <string name="enable_notifications">Bildirimleri etkinleştir</string> - <string name="conference_with">… ile grup sohbet başlat</string> - <string name="no_conference_server_found">Bir grup sohbet sunucusu bulunamadı</string> - <string name="conference_creation_failed">Grup sohbet başlatılamadı!</string> + <string name="conference_with">… ile toplantı başlat</string> + <string name="no_conference_server_found">Bir toplantı sunucusu bulunamadı</string> + <string name="conference_creation_failed">Toplantı başlatılamadı!</string> <string name="secret_accepted">Gizli bilgi kabul edildi!</string> <string name="reset">Sıfırla</string> <string name="account_image_description">Hesap avatarı</string> <string name="copy_otr_clipboard_description">OTR parmak izini panoya kopyala</string> <string name="copy_omemo_clipboard_description">OMEMO parmak izini panoya kopyala</string> <string name="regenerate_omemo_key">OMEMO anahtarını yeniden oluştur</string> - <string name="wipe_omemo_pep">PEP’teki diğer cihazları sil</string> - <string name="clear_other_devices">Cihazları sil</string> - <string name="clear_other_devices_desc">OMEMO bildirimindeki diğer cihazların hepsini silmek istediğinizden emin misiniz? Cihazlarınız yeniden bağlandıklarında kendilerini yeniden bildirecekler ama bu süre zarfındaki iletileri alamayabilirler.</string> + <string name="wipe_omemo_pep">PEP’teki diğer aygıtları sil</string> + <string name="clear_other_devices">Aygıtları sil</string> + <string name="clear_other_devices_desc">OMEMO bildirimindeki diğer aygıtların hepsini silmek istediğinizden emin misiniz? Aygıtlarınız yeniden bağlandıklarında kendilerini yeniden bildirecekler ama bu süre zarfındaki iletileri alamayabilirler.</string> <string name="purge_key">Anahtarı sil</string> <string name="purge_key_desc_part1">Bu anahtarı silmek istediğinizden emin misiniz?</string> <string name="purge_key_desc_part2">Anahtar geri dönüşü olmayacak şekilde zedelenmiş kabul edilecek bir daha onunla bir oturum başlatamayacaksınız.</string> @@ -409,8 +409,8 @@ <string name="could_not_change_password">Parola değiştirilemedi</string> <string name="otr_session_not_started">Şifreli bir konuşma başlatmak için ileti gönder</string> <string name="ask_question">Soru sor</string> - <string name="smp_explain_question">Karşınızdaki kişiyle, ikinizden başka kimsenin bilmediği ortak bir sırrınız varsa (aranızdaki bir şaka ya da sadece en son buluştuğunuzda ne yediğiniz gibi) bunu birbirinizin parmak izlerini doğrulamak için kullanabilirsiniz. \n\n Karşınızdaki kişiye bir ipucu veya soru sorabilirsiniz. Cevabın harf duyarlı olması gerekmektedir.</string> - <string name="smp_explain_answer">Kişi parmak izinizi onaylamak için sadece ikinizin bildiği bir şeyi sormak istiyor. Kişi sırrınız hakkında aşağıdaki ipucu veya soruyu gönderdi.</string> + <string name="smp_explain_question">Karşınızdaki kişiyle, ikinizden başka kimsenin bilmediği ortak bir sırrınız varsa (aranızdaki bir şaka ya da yalnızca en son buluştuğunuzda ne yediğiniz gibi) bunu birbirinizin parmak izlerini doğrulamak için kullanabilirsiniz. \n\n Karşınızdaki kişiye bir ipucu veya soru sorabilirsiniz. Yanıtın harf duyarlı olması gerekmektedir.</string> + <string name="smp_explain_answer">Kişi parmak izinizi onaylamak için yalnızca ikinizin bildiği bir şeyi sormak istiyor. Kişi sırrınız hakkında aşağıdaki ipucu veya soruyu gönderdi.</string> <string name="shared_secret_hint_should_not_be_empty">İpucunuz boş kalamaz</string> <string name="shared_secret_can_not_be_empty">Sırrınız boş kalamaz</string> <string name="manual_verification_explanation">Aşağıdaki parmak izini, karşınızdaki kişinin parmak iziyle dikkatlice karşılaştırın. \n\nŞifreli eposta veya telefon gibi güvenilir bir iletişim kanalı üzerinden bilgi alışverişi yapabilirsiniz.</string> @@ -418,11 +418,11 @@ <string name="current_password">Mevcut parola</string> <string name="new_password">Yeni parola</string> <string name="password_should_not_be_empty">Parola boş kalamaz</string> - <string name="enable_all_accounts">Bütün hesapları etkinleştir</string> - <string name="disable_all_accounts">Bütün hesapları devre dışı bırak</string> + <string name="enable_all_accounts">Tüm hesapları etkinleştir</string> + <string name="disable_all_accounts">Tüm hesapları devre dışı bırak</string> <string name="perform_action_with">Kullanarak tamamla</string> <string name="no_affiliation">Ortaklık yok</string> - <string name="no_role">Çevrimdışı</string> + <string name="no_role">Çevrim dışı</string> <string name="outcast">Bağlantısız</string> <string name="member">Üye</string> <string name="advanced_mode">Gelişmiş kip</string> @@ -430,21 +430,21 @@ <string name="remove_membership">Üyeliği geri çevir</string> <string name="grant_admin_privileges">Yönetici imtiyazlarını kabul et</string> <string name="remove_admin_privileges">Yönetici imtiyazlarını geri çevir</string> - <string name="remove_from_room">Grup sohbetten at</string> + <string name="remove_from_room">Toplantıdan at</string> <string name="could_not_change_affiliation">%s kişisinin ortaklığı değiştirilemedi</string> - <string name="ban_from_conference">Grup sohbetten at</string> - <string name="removing_from_public_conference">%s kişisini herkese açık grup sohbetten atmaya çalışıyorsunuz. Bunu ancak bu kullanıcıyı daimi men ederek yapabilirsiniz.</string> + <string name="ban_from_conference">Toplantıdan engelle</string> + <string name="removing_from_public_conference">%s kişisini herkese açık toplantıdan atmaya çalışıyorsunuz. Bunu yalnızca bu kullanıcıyı süresiz engelleyerek yapabilirsiniz.</string> <string name="ban_now">Şimdi men et</string> <string name="could_not_change_role">%s kişisinin rolü değiştirilemedi</string> - <string name="public_conference">Herkese açık grup sohbet</string> - <string name="private_conference">Özel, sadece üyelere açık grup sohbet</string> - <string name="conference_options">Grup sohbet seçenekleri</string> - <string name="members_only">Özel, sadece üyeler</string> + <string name="public_conference">Herkese açık toplantı</string> + <string name="private_conference">Özel, yalnızca üyelere açık toplantı</string> + <string name="conference_options">Toplantı seçenekleri</string> + <string name="members_only">Özel, yalnızca üyeler</string> <string name="non_anonymous">Anonim olmayan</string> <string name="moderated">Denetli</string> <string name="you_are_not_participating">Katılımcı değilsiniz</string> - <string name="modified_conference_options">Değiştirilmiş grup sohbet seçenekleri!</string> - <string name="could_not_modify_conference_options">Grup sohbet seçenekleri değiştirilemedi</string> + <string name="modified_conference_options">Değiştirilmiş toplantı seçenekleri!</string> + <string name="could_not_modify_conference_options">Toplantı seçenekleri değiştirilemedi</string> <string name="never">Hiçbir zaman</string> <string name="thirty_minutes">30 dakika</string> <string name="one_hour">1 saat</string> @@ -465,24 +465,24 @@ <string name="received_x_file">%s alındı</string> <string name="disable_foreground_service">Ön planda çalışmasını devre dışı bırak</string> <string name="touch_to_open_conversations">Conversations’ı başlatmak için dokunun</string> - <string name="avatar_has_been_published">Avatar yayınlandı!</string> + <string name="avatar_has_been_published">Avatar yayımlandı!</string> <string name="sending_x_file">%s gönderiliyor</string> <string name="offering_x_file">%s sunuluyor</string> - <string name="hide_offline">Çevrimdışı gizle</string> + <string name="hide_offline">Çevrim dışıları gizle</string> <string name="disable_account">Hesabı devre dışı bırak</string> <string name="contact_is_typing">%s yazıyor…</string> <string name="contact_has_stopped_typing">%s yazmayı bıraktı</string> <string name="pref_chat_states">Yazma bildirimleri</string> - <string name="pref_chat_states_summary">Karşınızdaki kişi sizin yeni bir ileti yazdığınızı görsün</string> + <string name="pref_chat_states_summary">Siz onlara ileti yazarken kişilerinizin bunu bilmesini sağlayın</string> <string name="send_location">Yer bildirimi gönder</string> <string name="show_location">Yer bildirimi göster</string> <string name="no_application_found_to_display_location">Yer bildirimi için bir uygulama bulunamadı</string> <string name="location">Yer</string> <string name="received_location">Bildirilen yer</string> <string name="title_undo_swipe_out_conversation">Sohbet sonlandı</string> - <string name="title_undo_swipe_out_muc">Grup sohbetten ayrıldı</string> + <string name="title_undo_swipe_out_muc">Toplantıdan ayrıldı</string> <string name="pref_dont_trust_system_cas_title">Sistem sertifikalarına güvenmeyin</string> - <string name="pref_dont_trust_system_cas_summary">Bütün sertifikalar bizzat onaylanmalıdır</string> + <string name="pref_dont_trust_system_cas_summary">Tüm sertifikalar bizzat onaylanmalıdır</string> <string name="pref_remove_trusted_certificates_title">Sertifikaları kaldır</string> <string name="pref_remove_trusted_certificates_summary">Bizzat onaylanmış sertifikaları sil</string> <string name="toast_no_trusted_certs">Bizzat onaylanmış sertifika yok</string> @@ -502,12 +502,12 @@ <string name="choose_quick_action">Kısayolu seç</string> <string name="search_for_contacts_or_groups">Kişi veya gruplarda ara</string> <string name="send_private_message">Özel ileti gönder</string> - <string name="user_has_left_conference">%s görüşmeden ayrıldı!</string> + <string name="user_has_left_conference">%s toplantıdan ayrıldı!</string> <string name="username">Kullanıcı adı</string> <string name="username_hint">Kullanıcı adı</string> <string name="invalid_username">Kullanıcı adı geçerli değil</string> - <string name="conference_name">Grup sohbet ismi</string> - <string name="invalid_conference_name">Bu grup sohbet adı geçerli değil</string> + <string name="conference_name">Toplantı adı</string> + <string name="invalid_conference_name">Bu toplantı adı geçerli değil</string> <string name="download_failed_server_not_found">İndirme başarısız: Sunucu bulunamadı</string> <string name="download_failed_file_not_found">İndirme başarısız: Dosya bulunamadı</string> <string name="download_failed_could_not_connect">İndirme başarısız: Sunucuya bağlanılamadı</string> @@ -520,11 +520,11 @@ <string name="server_info_broken">Bozuk</string> <string name="pref_presence_settings">Durum</string> <string name="pref_away_when_screen_off">Ekran kapandığında uzakta</string> - <string name="pref_away_when_screen_off_summary">Ekran kapandığında çevrimiçi durum bildiriminizi uzakta olarak değiştirir</string> + <string name="pref_away_when_screen_off_summary">Ekran kapandığında çevrim içi durum bildiriminizi uzakta olarak değiştirir</string> <string name="pref_xa_on_silent_mode">Sessiz moddayken erişilemez</string> <string name="pref_xa_on_silent_mode_summary">Telefonunuz sessizdeyken, durum bildiriminizi müsait değil olarak değiştirir</string> <string name="pref_treat_vibrate_as_silent">titreş modunu sessiz mod olarak değerlendir</string> - <string name="pref_treat_vibrate_as_silent_summary">cihazınız titreşim modundaysa durum bildiriminizi müsahit değil olarak değiştirir</string> + <string name="pref_treat_vibrate_as_silent_summary">Aygıtınız titreşim kipindeyken durum bildiriminizi uygun değil olarak değiştirir</string> <string name="pref_show_connection_options">Genişletilmiş bağlantı seçenekleri</string> <string name="pref_show_connection_options_summary">Hesap oluştururken sunucu adıyla port seçeneğini göster</string> <string name="hostname_example">xmpp.ornek.com</string> @@ -542,10 +542,10 @@ <string name="action_renew_certificate">Sertifikayı yenile</string> <string name="error_fetching_omemo_key">OMEMO anahtarı alınırken hata oluştu!</string> <string name="verified_omemo_key_with_certificate">Sertifikalı OMEMO anahtarı onaylandı!</string> - <string name="device_does_not_support_certificates">Cihazınız seçilen istemci sertifikalarını desteklemiyor!</string> + <string name="device_does_not_support_certificates">Aygıtınız seçilen istemci sertifikalarını desteklemiyor!</string> <string name="pref_connection_options">Bağlantı</string> <string name="pref_use_tor">Tor üzerinden bağlan</string> - <string name="pref_use_tor_summary">Bütün bağlantıları Tor ağı üzerinden aktar. Orbot gerekir.</string> + <string name="pref_use_tor_summary">Tüm bağlantıları Tor ağı üzerinden aktar. Orbot gerekir.</string> <string name="account_settings_hostname">Sunucu adı</string> <string name="account_settings_port">Port</string> <string name="hostname_or_onion">Sunucu- veya .onion-Address</string> @@ -562,7 +562,7 @@ <string name="shared_text_with_x">%s ile paylaşılan metin</string> <string name="no_storage_permission">Conversations’ın harici depolama alanına erişmesi gerek </string> <string name="sync_with_contacts">Kişilerle senkronize et</string> - <string name="sync_with_contacts_long">Conversations XMPP listenizi telefon rehberinizle eşleştirerek kişilerin tam isimlerini ve avatarlarını göstermek istiyor. \n\n Conversations telefon rehberinizi sadece okuyacak ve onları sunucunuza yüklemeden eşleştirecek. \n\n Şimdi telefon rehberinize erişilmesine izin vermeniz istenecek.\n\n</string> + <string name="sync_with_contacts_long">Conversations XMPP listenizi telefon rehberinizle eşleştirerek kişilerin tam isimlerini ve avatarlarını göstermek istiyor.\n\nConversations telefon rehberinizi yalnızca okuyacak ve onları sunucunuza yüklemeden eşleştirecek.\n\nŞimdi telefon rehberinize erişilmesine izin vermeniz istenecek.</string> <string name="certificate_information">Sertifika Bilgisi</string> <string name="certificate_subject">Konu</string> <string name="certificate_issuer">Veren</string> @@ -572,23 +572,23 @@ <string name="certicate_info_not_available">(mevcut değil)</string> <string name="certificate_not_found">Sertifika bulunamadı</string> <string name="notify_on_all_messages">Tüm iletilerde uyar</string> - <string name="notify_only_when_highlighted">Sadece işaretliyse uyar</string> + <string name="notify_only_when_highlighted">Yalnızca vurguluysa uyar</string> <string name="notify_never">Uyarılar devre dışı</string> <string name="notify_paused">Uyarılar geçici olarak durduruldu</string> <string name="pref_picture_compression">Resimleri sıkıştır</string> <string name="pref_picture_compression_summary">Resimleri yeniden boyutlandır ve sıkıştır</string> <string name="always">Her zaman</string> - <string name="automatically">Otomatik olarak</string> + <string name="automatically">Kendiliğinden</string> <string name="battery_optimizations_enabled">Pil optimizasyonu devrede</string> - <string name="battery_optimizations_enabled_explained">Cihazınız Conversations üzerinde yoğun pil optimizasyonu yaptığı için bildirimlerde gecikmeler olabilir hatta bazı ileti kayıpları yaşanabilir.\nBu durumla karşılaşamamak için devre dışı bırakmanız önerilir. </string> - <string name="battery_optimizations_enabled_dialog">Cihazınız Conversations üzerinde yoğun pil optimizasyonu yaptığı için bildirimlerde gecikmeler olabilir hatta bazı ileti kayıpları yaşanabilir.\n Şimdi bunları devre dışı bırakmanız istenecek.</string> + <string name="battery_optimizations_enabled_explained">Aygıtınız Conversations üzerinde yoğun pil iyileştirmesi yaptığı için bildirimlerde gecikmeler olabilir üstelik bazı ileti kayıpları yaşanabilir.\nBu durumla karşılaşamamak için devre dışı bırakmanız önerilir. </string> + <string name="battery_optimizations_enabled_dialog">Aygıtınız Conversations üzerinde yoğun pil iyileştirmesi yaptığı için bildirimlerde gecikmeler olabilir üstelik bazı ileti kayıpları yaşanabilir.\n Şimdi bunları devre dışı bırakmanız istenecek.</string> <string name="disable">Devre dışı</string> <string name="selection_too_large">Seçilen alan çok büyük</string> - <string name="no_accounts">(Aktif hesap bulunmuyor)</string> + <string name="no_accounts">(Etkin hesap bulunmuyor)</string> <string name="this_field_is_required">Bu alan zorunludur</string> <string name="correct_message">ileti düzelt</string> <string name="send_corrected_message">Düzeltilmiş iletiyi gönder</string> - <string name="no_keys_just_confirm">Bu kişiye zaten güveniyor durumdasınız. \"tamam\" seçeneğini işaretleyerek, sadece %s \'in bu grup sohbete katılabileceğini teyid ediyorsunuz.</string> + <string name="no_keys_just_confirm">Bu kişiye zaten güveniyor durumdasınız. \"Tamam\"ı seçerek, yalnızca %s\'in bu toplantıya katılabileceğini onaylıyorsunuz.</string> <string name="select_image_and_crop">Resmi seçip kırpın</string> <string name="this_account_is_disabled">Bu hesabı devre dışı bıraktınız</string> <string name="security_error_invalid_file_access">Güvenlik hatası: Geçersiz dosya erişimi</string> @@ -604,37 +604,37 @@ <string name="pref_manually_change_presence_summary">Durumunuzu değiştirmek için avatarınıza dokunun</string> <string name="change_presence">Durum Değiştir</string> <string name="status_message">Durum iletisi</string> - <string name="all_accounts_on_this_device">Bu cihazdaki tüm hesaplara uygula</string> + <string name="all_accounts_on_this_device">Bu aygıttaki tüm hesaplara uygula</string> <string name="presence_chat">Sohbet için uygun</string> - <string name="presence_online">Çevrimiçi</string> + <string name="presence_online">Çevrim içi</string> <string name="presence_away">Uzakta</string> <string name="presence_xa">Mevcut Değil</string> <string name="presence_dnd">Meşgul</string> <string name="secure_password_generated">Güvenli bir parola oluşturuldu</string> - <string name="device_does_not_support_battery_op">Cihazınız pil optimizasyonunu devre dışı bırakmayı desteklemiyor</string> + <string name="device_does_not_support_battery_op">Aygıtınız pil iyileştirmesini devre dışı bırakmayı desteklemiyor</string> <string name="show_password">Parola göster</string> - <string name="registration_please_wait">Hesap oluşturulamadı: Sonra tekrar deneyin</string> + <string name="registration_please_wait">Hesap oluşturulamadı: Sonra yeniden deneyin</string> <string name="registration_password_too_weak">Kayıt Başarısız: Parola çok zayıf</string> - <string name="create_conference">Grup Sohbet başlat</string> - <string name="join_or_create_conference">Grup Sohbete katıl veya başlat</string> + <string name="create_conference">Toplantı başlat</string> + <string name="join_or_create_conference">Toplantıya katıl veya başlat</string> <string name="conference_subject">Konu</string> <string name="choose_participants">Katılımcıları seç</string> - <string name="creating_conference">Grup Sohbet başlatılıyor...</string> + <string name="creating_conference">Toplantı başlatılıyor...</string> <string name="invite_again">Yeniden davet et</string> <string name="gp_short">Kısa</string> <string name="gp_medium">Orta</string> <string name="gp_long">Uzun</string> - <string name="pref_broadcast_last_activity">Son kullanıcı etkileşimini yayınla</string> + <string name="pref_broadcast_last_activity">Son kullanıcı etkileşimini yayımla</string> <string name="pref_broadcast_last_activity_summary">Tüm kişileriniz ne zaman Conversations kullandığınızı görsün</string> <string name="pref_privacy">Mahremiyet</string> - <string name="pref_theme_options">Tema</string> + <string name="pref_theme_options">Gövde</string> <string name="pref_theme_options_summary">Renk paletini seçin</string> - <string name="pref_theme_light">Açık tema</string> - <string name="pref_theme_dark">Koyu tema</string> + <string name="pref_theme_light">Açık gövde</string> + <string name="pref_theme_dark">Koyu gövde</string> <string name="pref_use_green_background">Yeşil arka plan</string> <string name="pref_use_green_background_summary">Gelen iletiler için yeşil arka plan kullan</string> <string name="unable_to_connect_to_keychain">OpenKeychain\'e bağlanılamıyor</string> - <string name="this_device_is_no_longer_in_use">Bu cihaz artık kullanılmıyor</string> + <string name="this_device_is_no_longer_in_use">Bu aygıt artık kullanılmıyor</string> <string name="type_pc">Bilgisayar</string> <string name="type_phone">Mobil telefon</string> <string name="type_tablet">Tablet</string> @@ -651,15 +651,32 @@ <string name="missing_presence_subscription_with_x">%s ile durum bildirimi aboneliği eksik.</string> <string name="missing_keys_from_x">%s den eksik OMEMO anahtarları var.</string> <string name="missing_omemo_keys">Eksik OMEMO anahtarları var.</string> - <string name="wrong_conference_configuration">Bu özel ve anonim olmayan bir sohbet.</string> - <string name="this_conference_has_no_members">Bu konferansta herhangi bir üye yok. </string> + <string name="wrong_conference_configuration">Bu özel ve adsız olmayan bir toplantı.</string> + <string name="this_conference_has_no_members">Bu toplantıda herhangi bir üye yok.</string> <string name="report_jid_as_spammer">Bu kişiyi istenmeyen ileti gönderen olarak rapor et.</string> <string name="pref_delete_omemo_identities">OMEMO kimiliğini sil</string> - <string name="pref_delete_omemo_identities_summary">OMEMO anahtarını tekrar oluştur. Tüm kişilerinizin sizi tekrar doğrulaması gerekecek. Bunu sadece son çare olarak kullanın.</string> + <string name="pref_delete_omemo_identities_summary">OMEMO anahtarını yeniden oluştur. Tüm kişilerinizin sizi yeniden doğrulaması gerekecek. Bunu yalnızca son çare olarak kullanın.</string> <string name="delete_selected_keys">Seçilen anahtarları sil</string> - <string name="error_publish_avatar_offline">Avatarınızı yayınlamak için bağlı olmalısınız.</string> - <string name="show_error_message">Hata mesajını göster</string> - <string name="error_message">Hata mesajı</string> - <string name="data_saver_enabled">Veri tasarrufu aktif</string> - <string name="data_saver_enabled_explained">İşletim sisteminiz Conversations arka planda çalışırken Internet erişimini sınırlıyor. Yeni ileti alındığında uyarı gelmesi için Conversations\'a veri tasarrufu aktif durumdayken sınırsız erişim vermeniz gerekiyor.\nConversations mümkün olan durumlarda veri tasarrufu için çaba harcar.</string> + <string name="error_publish_avatar_offline">Avatarınızı yayımlamak için bağlı olmalısınız.</string> + <string name="show_error_message">Hata iletisini göster</string> + <string name="error_message">Hata İletisi</string> + <string name="data_saver_enabled">Veri tasarrufu etkin</string> + <string name="data_saver_enabled_explained">İşletim sisteminiz Conversations arka planda çalışırken İnternet erişimini sınırlıyor. Yeni ileti alındığında uyarı gelmesi için Conversations\'a veri tasarrufu etkin durumdayken sınırsız erişim vermeniz gerekiyor.\nConversations mümkün olan durumlarda veri tasarrufu için çaba harcar.</string> + <string name="device_does_not_support_data_saver">Aygıtınız Conversations için Veri tasarrufunu devre dışı bırakmayı desteklemiyor</string> + <string name="error_unable_to_create_temporary_file">Geçici dosya oluşturulamıyor</string> + <string name="this_device_has_been_verified">Bu aygıt doğrulandı</string> + <string name="copy_fingerprint">Parmak izini kopyala</string> + <string name="all_omemo_keys_have_been_verified">Tüm OMEMO anahtarları doğrulandı</string> + <string name="barcode_does_not_contain_fingerprints_for_this_conversation">Barkod, bu konuşma için parmak izlerini içermiyor.</string> + <string name="verified_fingerprints">Doğrulanmış parmak izleri</string> + <string name="use_camera_icon_to_scan_barcode">Bir kişinin barkodunu taramak için kamerayı kullan</string> + <string name="please_wait_for_keys_to_be_fetched">Anahtarların alınması için lütfen bekle</string> + <string name="share_as_barcode">Barkod olarak paylaş</string> + <string name="share_as_uri">XMPP URI\'si olarak paylaş</string> + <string name="share_as_http">HTTP bağlantısı olarak paylaş</string> + <string name="pref_blind_trust_before_verification">Doğrulamadan Önce Kör Güven</string> + <string name="pref_blind_trust_before_verification_summary">Kişilerin daha önce doğrulanmamış tüm yeni aygıtlarına kendiliğinden güven ve doğrulanmış kişi her yeni aygıt eklediğinde elle doğrulama iste.</string> + <string name="blindly_trusted_omemo_keys">Körü körüne güvenilen OMEMO anahtarları</string> + <string name="not_trusted">Güvenilmeyen</string> + <string name="invalid_barcode">Geçersiz 2D barkod</string> </resources> diff --git a/src/main/res/values-uk/strings.xml b/src/main/res/values-uk/strings.xml index 576c7310..421bf980 100644 --- a/src/main/res/values-uk/strings.xml +++ b/src/main/res/values-uk/strings.xml @@ -121,14 +121,12 @@ <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_ui_options">Інтерфейс користувача</string> <string name="openpgp_error">OpenKeychain відзвітував про помилку</string> <string name="error_decrypting_file">Помилка вводу-виводу при розшифруванні файлу</string> <string name="accept">Прийняти</string> <string name="error">Сталася помилка</string> <string name="pref_grant_presence_updates">Давати оновлення про присутність</string> - <string name="pref_grant_presence_updates_summary">Попередньо давати та запитувати підписку на присутність для контактів, які Ви створюєте</string> <string name="subscriptions">Підписки</string> <string name="your_account">Ваш обліковий запис</string> <string name="keys">Ключі</string> @@ -335,8 +333,6 @@ <string name="url_copied_to_clipboard">URL скопійовано до комірки обміну</string> <string name="message_copied_to_clipboard">Повідомлення скопійовано до комірки обміну</string> <string name="image_transmission_failed">Передача зображення не відбулася</string> - <string name="scan_qr_code">Сканувати QR код</string> - <string name="show_qr_code">Показати QR код</string> <string name="show_block_list">Показати список блокування</string> <string name="account_details">Деталі облікового запису</string> <string name="verify_otr">Перевірити OTR</string> @@ -374,7 +370,6 @@ <string name="no_application_found_to_open_file">Не знайдено програми для відкриття файла</string> <string name="could_not_verify_fingerprint">Не можу перевірити відбиток</string> <string name="manually_verify">Перевірити вручну</string> - <string name="are_you_sure_verify_fingerprint">Ви впевнені, що хочете перевірити OTR відбитки Ваших контактів?</string> <string name="pref_show_dynamic_tags">Показати динамічні мітки</string> <string name="pref_show_dynamic_tags_summary">Показувати мітки \"лише для читання\" під контактами</string> <string name="enable_notifications">Увікнути сповіщення</string> @@ -467,7 +462,6 @@ <string name="contact_is_typing">%s друкує…</string> <string name="contact_has_stopped_typing">%s припинив друкувати</string> <string name="pref_chat_states">Сповіщення про набір</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> diff --git a/src/main/res/values-v21/themes.xml b/src/main/res/values-v21/themes.xml index 7cac79c2..f7ab3e92 100644 --- a/src/main/res/values-v21/themes.xml +++ b/src/main/res/values-v21/themes.xml @@ -61,6 +61,7 @@ <item name="attr/icon_settings">@drawable/ic_settings_black_24dp</item> <item name="attr/icon_import_export">@drawable/ic_import_export_white_24dp</item> <item name="attr/icon_share">@drawable/ic_share_white_24dp</item> + <item name="attr/icon_scan_qr_code">@drawable/ic_camera_alt_white_24dp</item> <item name="attr/icon_notifications">@drawable/ic_notifications_black54_24dp</item> <item name="attr/icon_notifications_off">@drawable/ic_notifications_off_black54_24dp</item> @@ -128,6 +129,7 @@ <item name="attr/icon_settings">@drawable/ic_settings_white_24dp</item> <item name="attr/icon_import_export">@drawable/ic_import_export_white_24dp</item> <item name="attr/icon_share">@drawable/ic_share_white_24dp</item> + <item name="attr/icon_scan_qr_code">@drawable/ic_camera_alt_white_24dp</item> <item name="attr/icon_notifications">@drawable/ic_notifications_white_24dp</item> <item name="attr/icon_notifications_off">@drawable/ic_notifications_off_white_24dp</item> diff --git a/src/main/res/values-vi/strings.xml b/src/main/res/values-vi/strings.xml index 0a1f24b6..dd2a1d02 100644 --- a/src/main/res/values-vi/strings.xml +++ b/src/main/res/values-vi/strings.xml @@ -106,13 +106,11 @@ <string name="pref_never_send_crash">Không bao giờ gửi báo cáo dừng chạy</string> <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ợ nhóm phát triển của Conversations</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="openpgp_error">OpenKeychain đã báo cáo một lỗi</string> <string name="error_decrypting_file">Tập tin giải mã lỗi I/O</string> <string name="accept">Chấp thuận</string> <string name="error">Đã có lỗi xảy ra</string> <string name="pref_grant_presence_updates">Trao quyền cập nhật hiện diện</string> - <string name="pref_grant_presence_updates_summary">Ưu tiên trao quyền và hỏi đăng ký hiện diện cho các liên hệ bạn đã tạo</string> <string name="subscriptions">Đăng ký</string> <string name="your_account">Tài khoản của bạn</string> <string name="keys">Các khoá</string> @@ -301,8 +299,6 @@ <string name="url_copied_to_clipboard">Đã chép URL vào clipboard</string> <string name="message_copied_to_clipboard">Đã chép tin nhắn vào clipboard</string> <string name="image_transmission_failed">Thất bại khi chuyển hình</string> - <string name="scan_qr_code">Quét mã QR</string> - <string name="show_qr_code">Hiện mã QR</string> <string name="show_block_list">Quét danh sách chặn</string> <string name="account_details">Chi tiết tài khoản</string> <string name="verify_otr">Xác minh OTR</string> @@ -339,7 +335,6 @@ <string name="no_application_found_to_open_file">Không tìm thấy ứng dụng nào để mở tập tin</string> <string name="could_not_verify_fingerprint">Không thể xác minh dấu vân tay</string> <string name="manually_verify">Xác minh thủ công</string> - <string name="are_you_sure_verify_fingerprint">Có chắc là bạn muốn xác minh dấu vân tay OTR của liên hệ không?</string> <string name="pref_show_dynamic_tags">Hiện các nhãn động</string> <string name="pref_show_dynamic_tags_summary">Hiện nhãn chỉ đọc bên dưới các liên hệ</string> <string name="enable_notifications">Bật thông báo</string> @@ -430,7 +425,6 @@ <string name="contact_is_typing">%s đang gõ...</string> <string name="contact_has_stopped_typing">%s đã ngừng gõ</string> <string name="pref_chat_states">Thông báo đang gõ</string> - <string name="pref_chat_states_summary">Báo cho liên hệ biết khi bạn đang viết tin nhắn mới</string> <string name="send_location">Gửi vị trí</string> <string name="show_location">Hiện vị trí</string> <string name="no_application_found_to_display_location">Không thấy ứng dụng nào có thể hiện vị trí</string> diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index 89e5a9c6..e0705cb0 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -122,14 +122,12 @@ <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_ui_options">UI</string> <string name="openpgp_error">OpenKeychain 报告了一个错误</string> <string name="error_decrypting_file">解密文件时出现 I/O 错误</string> <string name="accept">接受</string> <string name="error">产生了一个错误</string> <string name="pref_grant_presence_updates">同意更新在线联系人</string> - <string name="pref_grant_presence_updates_summary">预先同意并请求更新您的联系人</string> <string name="subscriptions">关注</string> <string name="your_account">你的账号</string> <string name="keys">密钥</string> @@ -331,6 +329,7 @@ <string name="check_x_filesize_on_host">在 %2$s 上检查 %1$s 的大小</string> <string name="message_options">消息选项</string> <string name="copy_text">拷贝文本</string> + <string name="select_text">选择文本</string> <string name="copy_original_url">拷贝原始URL</string> <string name="send_again">再次发送</string> <string name="file_url">文件 </string> @@ -338,8 +337,6 @@ <string name="url_copied_to_clipboard">已经拷贝 URL 到剪贴板</string> <string name="message_copied_to_clipboard">消息已经拷贝到剪贴板</string> <string name="image_transmission_failed">图片传送失败</string> - <string name="scan_qr_code">扫描二维码</string> - <string name="show_qr_code">显示二维码</string> <string name="show_block_list">显示屏蔽列表</string> <string name="account_details">账户详情</string> <string name="verify_otr">验证 OTR</string> @@ -379,7 +376,6 @@ <string name="no_application_found_to_open_file">没有可以打开此文件的应用</string> <string name="could_not_verify_fingerprint">不能验证指纹</string> <string name="manually_verify">手工验证</string> - <string name="are_you_sure_verify_fingerprint">你确认验证你的联系人的 OTR 指纹?</string> <string name="pref_show_dynamic_tags">显示动态标签</string> <string name="pref_show_dynamic_tags_summary">在联系人下方显示只读标签</string> <string name="enable_notifications">启用通知</string> @@ -472,7 +468,6 @@ <string name="contact_is_typing">%s 正在输入</string> <string name="contact_has_stopped_typing">%s 已停止输入</string> <string name="pref_chat_states">键盘输入通知</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> @@ -659,4 +654,9 @@ <string name="pref_delete_omemo_identities_summary">重新生成你的 OMEMO 密钥。你的所有联系人不得不对你进行再认证。请将此作为最后的办法。</string> <string name="delete_selected_keys">删除选择的密钥</string> <string name="error_publish_avatar_offline">你需要连接才能发布头像</string> + <string name="show_error_message">显示出错消息</string> + <string name="error_message">出错消息</string> + <string name="data_saver_enabled">省流量模式已激活</string> + <string name="data_saver_enabled_explained">您的操作系统禁止本程序在后台运行时访问互联网。为了收到新消息提示,您需要在省流量模式下允许本程序不受限制地访问互联网。\n本程序仍会尽可能节省流量。</string> + <string name="device_does_not_support_data_saver">该设备不支持禁用省流量模式</string> </resources> diff --git a/src/main/res/values-zh-rTW/strings.xml b/src/main/res/values-zh-rTW/strings.xml index 00557f09..e8df9d29 100644 --- a/src/main/res/values-zh-rTW/strings.xml +++ b/src/main/res/values-zh-rTW/strings.xml @@ -5,126 +5,173 @@ <string name="action_accounts">管理帳戶</string> <string name="action_end_conversation">結束對話</string> <string name="action_contact_details">聯絡人詳情</string> + <string name="action_muc_details">討論群組詳情</string> <string name="action_secure">安全對話</string> <string name="action_add_account">新增帳戶</string> <string name="action_edit_contact">編輯姓名</string> + <string name="action_add_phone_book">添加到地址薄</string> <string name="action_delete_contact">從列表中刪除</string> + <string name="action_block_contact">遮罩連絡人</string> + <string name="action_unblock_contact">解除連絡人遮罩</string> + <string name="action_block_domain">遮罩功能變數名稱</string> + <string name="action_unblock_domain">解除功能變數名稱遮罩</string> <string name="title_activity_manage_accounts">管理帳戶</string> - <string name="title_activity_conference_details">群組詳情</string> - <string name="title_activity_contact_details">聯絡人詳情</string> - <string name="title_activity_sharewith">分享對話</string> - <string name="title_activity_start_conversation">開始對話</string> - <string name="title_activity_choose_contact">選擇聯絡人</string> + <string name="title_activity_settings">設置</string> + <string name="title_activity_conference_details">討論群組詳情</string> + <string name="title_activity_contact_details">連絡人詳情</string> + <string name="title_activity_sharewith">分享會話</string> + <string name="title_activity_start_conversation">開始會話</string> + <string name="title_activity_choose_contact">選擇連絡人</string> + <string name="title_activity_block_list">遮罩列表</string> <string name="just_now">剛剛</string> <string name="minute_ago">1 分鐘前</string> - <string name="minutes_ago">%d 分鐘前</string> - <string name="unread_conversations">未讀對話</string> + <string name="minutes_ago">%d分鐘前</string> + <string name="unread_conversations">未讀會話</string> <string name="sending">正在發送…</string> - <string name="nick_in_use">該用戶名稱已被使用</string> + <string name="message_decrypting">解密信息中. 請稍候…</string> + <string name="pgp_message">OpenPGP 加密的信息</string> + <string name="nick_in_use">該名稱已存在</string> <string name="admin">管理員</string> - <string name="owner">擁有人</string> + <string name="owner">所有者</string> <string name="moderator">版主</string> - <string name="participant">成員</string> + <string name="participant">參與者</string> <string name="visitor">訪客</string> - <string name="remove_contact_text">你確定要將 %s 從聯絡人清單中移除嗎?與該聯絡人的對話將不會被清除。</string> - <string name="remove_bookmark_text">你確定要將 %s 從書籤清單中移除嗎?與該聯絡人的對話將不會被清除。</string> + <string name="remove_contact_text">將 %s 從列表中移除? 與該連絡人的會話消息不會清除.</string> + <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="contact_blocked">連絡人已遮罩</string> + <string name="remove_bookmark_text">從書簽中移除 %s ?相關會話消息不會被清除 .</string> <string name="register_account">在伺服器上註冊新帳戶</string> + <string name="change_password_on_server">在伺服器上改變密碼</string> <string name="share_with">分享</string> - <string name="start_conversation">開始對話</string> - <string name="invite_contact">邀請聯絡人</string> - <string name="contacts">聯絡人</string> + <string name="start_conversation">開始會話</string> + <string name="invite_contact">邀請連絡人</string> + <string name="contacts">連絡人</string> <string name="cancel">取消</string> - <string name="add">新增</string> + <string name="set">設置</string> + <string name="add">添加</string> <string name="edit">編輯</string> <string name="delete">刪除</string> - <string name="save">儲存</string> - <string name="ok">好的</string> - <string name="crash_report_title">Conversations 停止運行</string> - <string name="crash_report_message">發送「堆疊追蹤」給 Conversations 的開發人員能幫助改進本程式。\n<b>警告:</b> 你的 XMPP 帳戶將被用作發送有關訊息之用。</string> + <string name="block">遮罩</string> + <string name="unblock">解除遮罩</string> + <string name="save">保存</string> + <string name="ok">完成</string> + <string name="crash_report_title">Conversations 崩潰</string> + <string name="crash_report_message">發送堆疊跟蹤資訊到 Conversations 的開發人員\n<b>警告:</b> 該操作將用您的 XMPP 帳戶發送堆疊跟蹤給開發人員。</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="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="send_rejected">拒絕</string> - <string name="preparing_image">準備傳輸圖片</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_messages">刪除訊息</string> - <string name="send_otr_message">發送 OTR 加密訊息</string> - <string name="send_pgp_message">發送 OpenPGP 加密訊息</string> - <string name="your_nick_has_been_changed">用戶名稱修改成功</string> + <string name="clear_conversation_history">清除會話記錄</string> + <string name="clear_histor_msg">刪除該會話中所有資訊?\n\n<b>注:</b> 該操作不會影響其他設備或伺服器保存的資訊。</string> + <string name="delete_messages">刪除消息</string> + <string name="also_end_conversation">結束此會話以後</string> + <string name="choose_presence">選擇設備</string> + <string name="send_unencrypted_message">發送未加密的資訊</string> + <string name="send_message_to_x">發信息給 %s</string> + <string name="send_otr_message">發送 OTR 加密資訊</string> + <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="decryption_failed">解密失敗,可能是私密金鑰不正確。</string> <string name="openkeychain_required">OpenKeychain</string> - <string name="openkeychain_required_long">Conversations 使用一個名為 <b>OpenKeychain</b> 的第三方程式來加密、解碼訊息以及管理您的公鑰。\n\nOpenKeychain 以 GPLv3 釋出,並可在 F-Droid 和 Google Play 上下載。\n\n<small>(之後請重新啟動 Conversations。)</small></string> - <string name="restart">重新啟動</string> + <string name="openkeychain_required_long">Conversations 使用了協力廠商app <b>OpenKeychain</b> 來加密、解密資訊並管理您的金鑰。\n\nOpenKeychain 遵循 GPLv3 並且可以在 F-Droid 和 Google Play 上獲取。\n\n<small>(之後請重啟 Conversations)</small></string> + <string name="restart">重啟</string> <string name="install">安裝</string> - <string name="offering">提供中…</string> - <string name="waiting">等待中…</string> - <string name="no_pgp_key">找不到 OpenPGP 鑰匙</string> - <string name="contact_has_no_pgp_key">Conversations 不能將你的訊息加密,因為聯絡人沒有公佈他/她的公鑰。\n\n<small>請通知聯絡人設定 OpenPGP。</small></string> - <string name="no_pgp_keys">找不到多條 OpenPGP 鑰匙</string> - <string name="contacts_have_no_pgp_keys">Conversations 不能將你的訊息加密,因為多位聯絡人沒有公佈他/她的公鑰。\n\n<small>請通知聯絡人設定 OpenPGP。</small></string> - <string name="pref_general">一般</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">Conversations 無法加密資訊,因為連絡人未提供他/她的公開金鑰。\n\n<small>請通知連絡人設置 OpenPGP。</small></string> + <string name="no_pgp_keys">未找到 OpenPGP 金鑰</string> + <string name="contacts_have_no_pgp_keys">因您的連絡人未公佈公開金鑰,Conversations未能成功加密您的資訊.\n\n<small>請通知連絡人設置OpenPGP.</small></string> + <string name="pref_general">常規</string> <string name="pref_xmpp_resource">XMPP 資源</string> - <string name="pref_xmpp_resource_summary">客戶端標示名稱</string> + <string name="pref_xmpp_resource_summary">用戶端標識名稱</string> <string name="pref_accept_files">接收文件</string> <string name="pref_accept_files_summary">自動接收小於 … 的文件</string> + <string name="pref_attachments">附件</string> + <string name="pref_return_to_previous">快速分享</string> + <string name="pref_return_to_previous_summary">分享後立即回到之前活動的應用程式,而非打開會話</string> + <string name="pref_notification_settings">通知</string> <string name="pref_notifications">通知</string> - <string name="pref_notifications_summary">收到新訊息時通知</string> + <string name="pref_notifications_summary">收到新消息時通知</string> <string name="pref_vibrate">震動</string> - <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="openpgp_error">OpenKeychain 回報了一個錯誤</string> - <string name="error_decrypting_file">解密文件時出現 I/O 錯誤</string> + <string name="pref_vibrate_summary">收到新消息時震動</string> + <string name="pref_led">LED 燈提示</string> + <string name="pref_led_summary">收到新消息時閃爍通知燈</string> + <string name="pref_sound">鈴聲</string> + <string name="pref_sound_summary">收到新消息時響鈴</string> + <string name="pref_notification_grace_period">靜默期限</string> + <string name="pref_notification_grace_period_summary">發現在其它設備上的活動後,Conversations保持安靜的時間</string> + <string name="pref_advanced_options">高級</string> + <string name="pref_never_send_crash">總不發送崩潰報告</string> + <string name="pref_never_send_crash_summary">發送堆疊跟蹤説明 Conversations 開發人員</string> + <string name="pref_confirm_messages">確認消息</string> + <string name="pref_ui_options">UI</string> + <string name="openpgp_error">OpenKeychain 報告了一個錯誤</string> + <string name="error_decrypting_file">解密檔時出現 I/O 錯誤</string> <string name="accept">接受</string> - <string name="error">發生了一個錯誤</string> - <string name="pref_grant_presence_updates">同意更新狀態訊息</string> - <string name="pref_grant_presence_updates_summary">預先更新狀態訊息並關注聯絡人的狀態訊息</string> + <string name="error">產生了一個錯誤</string> + <string name="pref_grant_presence_updates">同意更新線上連絡人</string> <string name="subscriptions">關注</string> - <string name="your_account">你的帳戶</string> - <string name="keys">鑰匙</string> - <string name="send_presence_updates">發送狀態訊息</string> - <string name="receive_presence_updates">接收狀態訊息</string> - <string name="ask_for_presence_updates">關注狀態訊息</string> + <string name="your_account">你的帳號</string> + <string name="keys">金鑰</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="error_not_an_image_file">您選擇的文件不是圖片</string> - <string name="error_compressing_image">轉換圖片時發生錯誤</string> - <string name="error_file_not_found">找不到文件</string> - <string name="error_io_exception">一般的 I/O 錯誤。是存儲空間不足嗎?</string> - <string name="error_security_exception_during_image_copy">你用來選擇圖片的 app 沒有給予足夠權限我們去讀取文件。\n\n<small>請使用另一文件管理器來選擇圖片</small></string> + <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">常規的 I/O 錯誤。可能是存儲空間不足?</string> + <string name="error_security_exception_during_image_copy">您用來選擇圖片的 app 沒有給予足夠許可權支持我們讀取檔。\n\n<small>請使用另一檔案管理員選擇圖片</small></string> <string name="account_status_unknown">未知</string> - <string name="account_status_disabled">暫時停用</string> - <string name="account_status_online">在線</string> + <string name="account_status_disabled">暫時不可用</string> + <string name="account_status_online">線上</string> <string name="account_status_connecting">連接中\u2026</string> <string name="account_status_offline">離線</string> <string name="account_status_unauthorized">未授權</string> <string name="account_status_not_found">未找到伺服器</string> - <string name="account_status_no_internet">未連接網絡</string> + <string name="account_status_no_internet">未連接網路</string> <string name="account_status_regis_fail">註冊失敗</string> - <string name="account_status_regis_conflict">該用戶名稱已被使用</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_regis_not_sup">伺服器不支援註冊</string> + <string name="account_status_security_error">安全錯誤</string> + <string name="account_status_policy_violation">違反政策</string> + <string name="account_status_incompatible_server">伺服器不相容</string> + <string name="account_status_stream_error">流錯誤</string> + <string name="encryption_choice_unencrypted">未加密</string> <string name="encryption_choice_otr">OTR</string> <string name="encryption_choice_pgp">OpenPGP</string> - <string name="mgmt_account_edit">編輯帳戶</string> - <string name="mgmt_account_delete">刪除帳戶</string> - <string name="mgmt_account_disable">暫時停用</string> + <string name="encryption_choice_omemo">OMEMO</string> + <string name="mgmt_account_edit">編輯帳號</string> + <string name="mgmt_account_delete">刪除帳號</string> + <string name="mgmt_account_disable">暫時不可用</string> <string name="mgmt_account_publish_avatar">發佈頭像</string> - <string name="mgmt_account_publish_pgp">發布 OpenPGP 公共鑰匙</string> + <string name="mgmt_account_publish_pgp">發佈 OpenPGP 公開金鑰</string> + <string name="openpgp_has_been_published">OpenPGP 公開金鑰已發佈</string> + <string name="republish_pgp_keys">記得重新發佈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="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">Jabber ID</string> <string name="account_settings_password">密碼</string> @@ -134,97 +181,482 @@ <string name="confirm_password">確認密碼</string> <string name="passwords_do_not_match">密碼不一致</string> <string name="invalid_jid">該 Jabber ID 無效</string> - <string name="error_out_of_memory">空間不足,圖片過大</string> + <string name="error_out_of_memory">空間不足。圖片過大</string> + <string name="add_phone_book_text">是否添加 %s 到地址薄?</string> <string name="contact_status_online">線上</string> - <string name="contact_status_free_to_chat">目前有空</string> + <string name="contact_status_free_to_chat">自由暢聊</string> <string name="contact_status_away">離開</string> <string name="contact_status_extended_away">長時間離開</string> <string name="contact_status_do_not_disturb">請勿打擾</string> <string name="contact_status_offline">離線</string> - <string name="muc_details_conference">群組</string> + <string name="muc_details_conference">討論群組</string> <string name="muc_details_other_members">其他成員</string> - <string name="server_info_carbon_messages">XEP-0280: Message Carbons</string> - <string name="server_info_stream_management">XEP-0198: Stream Management</string> - <string name="server_info_available">支援</string> - <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="never_seen">未曾上線</string> - <string name="install_openkeychain">加密的訊息。請安裝 OpenKeychain 以解密。</string> - <string name="unknown_otr_fingerprint">未知的 OTR 指紋</string> - <string name="openpgp_messages_found">發現以 OpenPGP 加密的訊息</string> + <string name="server_info_show_more">伺服器資訊</string> + <string name="server_info_mam">XEP-0313: MAM</string> + <string name="server_info_carbon_messages">XEP-0280: 消息複寫</string> + <string name="server_info_csi">XEP-0352: 用戶端狀態指示</string> + <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_pep">XEP-0163: PEP (替身 / OMEMO)</string> + <string name="server_info_http_upload">XEP-0363: HTTP 文件上傳</string> + <string name="server_info_push">XEP-0357: Push</string> + <string name="server_info_available">有效</string> + <string name="server_info_unavailable">無效</string> + <string name="missing_public_keys">缺少公開金鑰通知</string> + <string name="last_seen_now">剛剛查看過</string> + <string name="last_seen_min">1 分鐘前查看過</string> + <string name="last_seen_mins">%d 分鐘前查看過</string> + <string name="last_seen_hour">1 小時前查看過</string> + <string name="last_seen_hours">%d 小時前查看過</string> + <string name="last_seen_day">1 天前查看過</string> + <string name="last_seen_days">%d 天前查看過</string> + <string name="never_seen">未曾查看</string> + <string name="install_openkeychain">加密信息. 請安裝 OpenKeychain 以解密。</string> + <string name="unknown_otr_fingerprint">未知 OTR 指紋</string> + <string name="openpgp_messages_found">發現 OpenPGP 加密資訊</string> <string name="reception_failed">接收失敗</string> <string name="your_fingerprint">你的指紋</string> <string name="otr_fingerprint">OTR 指紋</string> + <string name="otr_fingerprint_selected_message">消息的 OTR 指紋</string> + <string name="openpgp_key_id">OpenPGP 金鑰 ID</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">消息的 OMEMO 指紋</string> + <string name="this_device_omemo_fingerprint">自己的 OMEMO 指紋</string> + <string name="other_devices">其他設備</string> + <string name="trust_omemo_fingerprints">信任的 OMEMO 指紋</string> + <string name="fetching_keys">獲取金鑰中</string> + <string name="done">完成</string> <string name="verify">驗證</string> <string name="decrypt">解密</string> - <string name="conferences">群組</string> + <string name="conferences">討論群組</string> <string name="search">查找</string> - <string name="create_contact">新增聯絡人</string> - <string name="join_conference">加入群組</string> - <string name="delete_contact">刪除聯絡人</string> - <string name="view_contact_details">查看聯絡人詳細訊息</string> - <string name="create">新增</string> - <string name="contact_already_exists">聯絡人已存在</string> + <string name="create_contact">創建連絡人</string> + <string name="enter_contact">輸入連絡人</string> + <string name="join_conference">加入討論群組</string> + <string name="delete_contact">刪除連絡人</string> + <string name="view_contact_details">查看連絡人詳細資訊</string> + <string name="block_contact">遮罩連絡人</string> + <string name="unblock_contact">解除連絡人遮罩</string> + <string name="create">創建</string> + <string name="select">選擇</string> + <string name="contact_already_exists">連絡人已存在</string> <string name="join">加入</string> - <string name="conference_address">群組地址</string> - <string name="save_as_bookmark">儲存為書籤</string> - <string name="delete_bookmark">刪除書籤</string> - <string name="bookmark_already_exists">該書籤已存在</string> + <string name="conference_address">討論群組地址</string> + <string name="conference_address_example">room@conference.example.com/nick</string> + <string name="save_as_bookmark">保存為書簽</string> + <string name="delete_bookmark">刪除書簽</string> + <string name="bookmark_already_exists">該書簽已存在</string> <string name="you">你</string> - <string name="action_edit_subject">編輯群組主題</string> + <string name="action_edit_subject">編輯討論群組主題</string> + <string name="edit_subject_hint">討論群組主題</string> + <string name="joining_conference">加入討論群組…</string> <string name="leave">離開</string> - <string name="contact_added_you">聯絡人已新增你到聯絡人列表</string> - <string name="add_back">新增為聯絡人</string> - <string name="contact_has_read_up_to_this_point">%s 讀到此處</string> + <string name="contact_added_you">連絡人已添加你到連絡人列表</string> + <string name="add_back">反向添加</string> + <string name="contact_has_read_up_to_this_point">%s 已讀此句</string> <string name="publish">發佈</string> - <string name="touch_to_choose_picture">點擊頭像可選擇頭像</string> - <string name="publish_avatar_explanation">請注意: 所有關注你狀態訊息的人將看到該圖像。</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="touch_to_choose_picture">點擊頭像可從相冊中選擇頭像 </string> + <string name="publish_avatar_explanation">請注意: 所有關注您最新動態的人將看到該圖像。</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="account_already_exists">該帳號已存在</string> <string name="next">下一步</string> - <string name="server_info_session_established">已建立連接</string> - <string name="additional_information">其他訊息</string> - <string name="skip">略過</string> + <string name="server_info_session_established">當前會話已建立</string> + <string name="additional_information">其他資訊</string> + <string name="skip">忽略</string> <string name="disable_notifications">關閉通知</string> - <string name="disable_notifications_for_this_conversation">關閉該對話消息</string> + <string name="disable_notifications_for_this_conversation">關閉該會話消息</string> <string name="enable">打開通知</string> - <string name="conference_requires_password">群組設有密碼</string> + <string name="conference_requires_password">討論群組設有密碼</string> <string name="enter_password">輸入密碼</string> - <string name="missing_presence_updates">缺少聯絡人狀態訊息</string> - <string name="request_presence_updates">請先發送關注狀態訊息請求。\n\n<small>這將用來判斷您的聯絡人所用的客戶端類型。</small></string> + <string name="missing_presence_updates">缺少線上連絡人更新</string> + <string name="missing_presence_subscription">缺少線上訂閱</string> + <string name="request_presence_updates">請先發送更新線上連絡人的請求。\n\n<small>以判斷您的連絡人所用的用戶端類型。</small></string> <string name="request_now">現在發送請求</string> <string name="delete_fingerprint">刪除指紋</string> - <string name="sure_delete_fingerprint">你確定刪除該指紋嗎?</string> + <string name="sure_delete_fingerprint">是否確定刪除該指紋?</string> <string name="ignore">忽略</string> - <string name="without_mutual_presence_updates"><b>警告:</b> 在沒有互相關注狀態訊息的情況下發送或會引起不能預計的問題。\n\n<small>請檢視聯絡人詳情頁面以確認你們的關注狀態。</small></string> - <string name="pref_force_encryption">強制要求端到端加密</string> - <string name="pref_force_encryption_summary">總是發送加密訊息 (群組訊息除外)</string> - <string name="pref_dont_save_encrypted">不儲存加密訊息</string> - <string name="pref_dont_save_encrypted_summary">警告: 此操作或會導致訊息丟失</string> - <string name="pref_expert_options_summary">請小心設定</string> - <string name="pref_use_larger_font">增加字體大小</string> - <string name="pref_use_larger_font_summary">讓整個 app 界面使用更大號的字體</string> - <string name="pref_use_send_button_to_indicate_status">用「發送」按鈕顯示狀態訊息</string> - <string name="pref_use_indicate_received">要求讀取收據</string> - <string name="pref_use_indicate_received_summary">已被讀取的訊息會以綠色勾號表示。請注意,這個功能未必每次有效。</string> - <string name="pref_use_send_button_to_indicate_status_summary">將「發送」按鈕設成不同顏色,以表示不同的狀態訊息。</string> + <string name="without_mutual_presence_updates"><b>警告:</b>在沒有相互更新線上連絡人的情況下發送將會出現未知問題。\n\n<small>前往連絡人詳情以驗證您訂閱的線上連絡人。</small></string> + <string name="pref_security_settings">安全</string> + <string name="pref_force_encryption">強制要求端對端加密</string> + <string name="pref_force_encryption_summary"> 總是發送加密資訊(討論群組資訊除外)</string> + <string name="pref_allow_message_correction">允許更正消息</string> + <string name="pref_allow_message_correction_summary">允許您的連絡人追回編輯他們的資訊</string> + <string name="pref_dont_save_encrypted">不保存加密資訊</string> + <string name="pref_dont_save_encrypted_summary">警告:此操作將會導致資訊丟失</string> + <string name="pref_expert_options">高級設置</string> + <string name="pref_expert_options_summary">請謹慎使用</string> + <string name="title_activity_about">關於 Conversations</string> + <string name="pref_about_conversations_summary">編譯及許可證資訊</string> + <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="pref_quiet_hours_summary">在靜默時間段內通知將保持靜音</string> + <string name="pref_use_larger_font"> 放大字體</string> + <string name="pref_use_larger_font_summary">整個 app 介面使用較大的字體</string> + <string name="pref_use_send_button_to_indicate_status">發送按鈕顯示狀態</string> + <string name="pref_use_indicate_received">請求消息回復</string> + <string name="pref_use_indicate_received_summary">如果支援消息將會以綠色對勾標識</string> + <string name="pref_use_send_button_to_indicate_status_summary">發送按鈕採用其他顏色以示發送狀態的區別</string> <string name="pref_expert_options_other">其他</string> - <string name="pref_conference_name">群組名稱</string> - <string name="pref_conference_name_summary">使用群組的名稱而不是 JID 來識別之。 </string> + <string name="pref_conference_name">討論群組名稱</string> + <string name="pref_conference_name_summary">用討論群組的主題來標示討論群組而不是 JID</string> + <string name="pref_autojoin">自動加入討論群組</string> + <string name="pref_autojoin_summary">將討論群組加入到自動加入書簽</string> + <string name="toast_message_otr_fingerprint">OTR 指紋已拷貝到剪貼板!</string> + <string name="toast_message_omemo_fingerprint">OMEMO 指紋已拷貝到剪貼板!</string> + <string name="conference_banned">你被此討論群組遮罩</string> + <string name="conference_members_only">此討論群組只允許成員加入</string> + <string name="conference_kicked">你被從此討論群組踢出</string> + <string name="conference_shutdown">討論群組已被關閉</string> + <string name="conference_unknown_error">你已不屬於此討論群組</string> + <string name="using_account">用帳戶 %s</string> + <string name="checking_x">正在 HTTP 伺服器中檢查 %s</string> + <string name="not_connected_try_again">你沒有連接。請稍後重試</string> + <string name="check_x_filesize">檢查 %s 大小</string> + <string name="check_x_filesize_on_host">在 %2$s 上檢查 %1$s 的大小</string> + <string name="message_options">消息選項</string> + <string name="copy_text">拷貝文本</string> + <string name="select_text">選擇文本</string> + <string name="copy_original_url">拷貝原始URL</string> + <string name="send_again">再次發送</string> + <string name="file_url">文件 </string> + <string name="message_text">消息文本</string> + <string name="url_copied_to_clipboard">已經拷貝 URL 到剪貼板</string> + <string name="message_copied_to_clipboard">消息已經拷貝到剪貼板</string> + <string name="image_transmission_failed">圖片傳送失敗</string> + <string name="show_block_list">顯示幕蔽列表</string> + <string name="account_details">帳戶詳情</string> + <string name="verify_otr">驗證 OTR</string> + <string name="remote_fingerprint">遠程指紋</string> + <string name="scan">掃描</string> + <string name="smp">Socialist Millionaire Protocol</string> + <string name="shared_secret_hint">提示或問題</string> + <string name="shared_secret_secret">共知的秘密</string> + <string name="confirm">確認</string> + <string name="in_progress">處理中</string> + <string name="respond">回應</string> + <string name="failed">失敗</string> + <string name="secrets_do_not_match">秘密不符</string> + <string name="try_again">再試一遍</string> + <string name="finish">完成</string> + <string name="verified">驗證通過!</string> + <string name="smp_requested">連絡人請求 SMP 驗證</string> + <string name="no_otr_session_found">沒有找到 OTR 會話</string> + <string name="conversations_foreground_service">Conversations</string> + <string name="pref_keep_foreground_service">保持前臺服務</string> + <string name="pref_keep_foreground_service_summary">防止作業系統中斷你的連接</string> + <string name="pref_export_logs">匯出歷史記錄</string> + <string name="pref_export_logs_summary">將 conversations 的歷史日誌寫到 SD 卡</string> + <string name="notification_export_logs_title">正在將日誌寫入 SD 卡</string> + <string name="choose_file">選擇檔</string> + <string name="receiving_x_file">接收中 %1$s (已完成 %2$d%%)</string> + <string name="download_x_file">下載 %s</string> + <string name="delete_x_file">刪除 %s</string> + <string name="file">文件</string> + <string name="open_x_file"> 打開 %s</string> + <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="file_transmission_failed">檔傳送失敗</string> + <string name="file_deleted">檔已經刪除</string> + <string name="no_application_found_to_open_file">沒有可以打開此檔的應用</string> + <string name="could_not_verify_fingerprint">不能驗證指紋</string> + <string name="manually_verify">手工驗證</string> + <string name="pref_show_dynamic_tags">顯示動態標籤</string> + <string name="pref_show_dynamic_tags_summary">在連絡人下方顯示唯讀標籤</string> + <string name="enable_notifications">啟用通知</string> + <string name="conference_with">與…創建討論群組</string> + <string name="no_conference_server_found">無法找到討論群組伺服器</string> + <string name="conference_creation_failed">討論群組創建失敗!</string> + <string name="secret_accepted">秘密被接受!</string> + <string name="reset">重置</string> + <string name="account_image_description">帳戶頭像</string> + <string name="copy_otr_clipboard_description">拷貝 OTR 指紋到剪貼板</string> + <string name="copy_omemo_clipboard_description">拷貝 OMEMO 指紋到剪貼板</string> + <string name="regenerate_omemo_key">重新生成 OMEMO 金鑰</string> + <string name="wipe_omemo_pep">從 PEP 中清除其他設備</string> + <string name="clear_other_devices">清除設備</string> + <string name="clear_other_devices_desc">你想清除所有其他設備的 OMEMO 通告?下次你的設備連接,將會重新收到通告,但也許將不會收到當時你發送的消息。</string> + <string name="purge_key">清除金鑰</string> + <string name="purge_key_desc_part1">是否確認清除該金鑰?</string> + <string name="purge_key_desc_part2">這是不可逆的損壞,你不能用此再建立一個會話了。</string> + <string name="error_no_keys_to_trust_server_error">此連絡人沒有可用的金鑰。\n從伺服器獲取金鑰失敗。也許你的連絡人所在伺服器發生問題。</string> + <string name="error_no_keys_to_trust">此連絡人沒有可用的金鑰。如果你曾經清除過他們的金鑰,那麼需要他們生成新的金鑰。</string> + <string name="error_trustkeys_title">錯誤</string> + <string name="fetching_history_from_server">從伺服器獲取歷史記錄</string> + <string name="no_more_history_on_server">伺服器上沒有更多歷史記錄</string> + <string name="updating">更新中…</string> + <string name="password_changed">密碼已修改!</string> + <string name="could_not_change_password">不能修改密碼</string> + <string name="otr_session_not_started">發送消息來開始加密聊天</string> + <string name="ask_question">提出問題</string> + <string name="smp_explain_question">如果你和你的連絡人有一個共知的秘密(比如一個內部笑話或者僅僅只是上次見面時吃的午餐) 你可以使用這個秘密來驗證彼此的指紋。\n\n你的連絡人將以大小寫敏感的方式給出答案,你可以給出提示或問題。</string> + <string name="smp_explain_answer">你的連絡人可以通過一個你們共知的秘密來驗證指紋。你的連絡人給出了如下的提示或問題。</string> + <string name="shared_secret_hint_should_not_be_empty">你的提示不能為空</string> + <string name="shared_secret_can_not_be_empty">你共知的秘密不能為空</string> + <string name="manual_verification_explanation">請仔細核對下面顯示出來的你的連絡人的指紋。\n你可以使用任何可信賴的聯繫方式,比如加密郵件或電話,來交換這些指紋資訊。</string> + <string name="change_password">修改密碼</string> + <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="perform_action_with">選擇一個操作</string> + <string name="no_affiliation">沒有從屬關係</string> + <string name="no_role">離線</string> + <string name="outcast">拋棄</string> + <string name="member">成員</string> + <string name="advanced_mode">高級模式</string> + <string name="grant_membership">已授予的成員</string> + <string name="remove_membership">吊銷的成員</string> + <string name="grant_admin_privileges">授予管理員許可權</string> + <string name="remove_admin_privileges">吊銷管理員許可權</string> + <string name="remove_from_room">從討論群組移出</string> + <string name="could_not_change_affiliation">不能修改 %s 的從屬關係</string> + <string name="ban_from_conference">遮罩出討論群組</string> + <string name="removing_from_public_conference">你正嘗試將 %s 移出一個公共的討論群組。唯一的方式是永遠遮罩這個使用者</string> + <string name="ban_now">現在遮罩</string> + <string name="could_not_change_role">不能修改 %s 的角色</string> + <string name="public_conference">公開訪問的討論群組</string> + <string name="private_conference">私密,只有成員可以加入的討論群組</string> + <string name="conference_options">討論群組選項</string> + <string name="members_only">私密,只有成員可以加入</string> + <string name="non_anonymous">非匿名</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="never">從不</string> + <string name="thirty_minutes">30 分鐘</string> + <string name="one_hour">1 個小時</string> + <string name="two_hours">2 個小時</string> + <string name="eight_hours">8 個小時</string> + <string name="until_further_notice">直到新的通知</string> + <string name="pref_input_options">輸入</string> + <string name="pref_enter_is_send">回車是發送</string> + <string name="pref_enter_is_send_summary">用回車鍵來發送消息</string> + <string name="pref_display_enter_key">顯示回車鍵</string> + <string name="pref_display_enter_key_summary">改變表情鍵為回車鍵</string> + <string name="audio">音訊</string> + <string name="video">視頻</string> + <string name="image">圖像</string> + <string name="pdf_document">PDF 文檔</string> + <string name="apk">Android App</string> + <string name="vcard">連絡人</string> + <string name="received_x_file">已經收到 %s</string> + <string name="disable_foreground_service">禁用前臺服務</string> + <string name="touch_to_open_conversations">輕觸打開 Conversations</string> + <string name="avatar_has_been_published">頭像已經發佈!</string> + <string name="sending_x_file">發送中 %s</string> + <string name="offering_x_file">提供中 %s</string> + <string name="hide_offline">隱藏離線連絡人</string> + <string name="disable_account">禁用帳戶</string> + <string name="contact_is_typing">%s 正在輸入</string> + <string name="contact_has_stopped_typing">%s 已停止輸入</string> + <string name="pref_chat_states">鍵盤輸入通知</string> + <string name="send_location">發送位置</string> + <string name="show_location">顯示位置</string> + <string name="no_application_found_to_display_location">無法找到顯示位置的應用</string> + <string name="location">位置</string> + <string name="received_location">位置已收到</string> + <string name="title_undo_swipe_out_conversation">Conversation 已關閉</string> + <string name="title_undo_swipe_out_muc">離開討論群組</string> + <string name="pref_dont_trust_system_cas_title">不相信系統 CA</string> + <string name="pref_dont_trust_system_cas_summary">所有證書必須人工通過</string> + <string name="pref_remove_trusted_certificates_title">移除證書</string> + <string name="pref_remove_trusted_certificates_summary">刪除人工通過的證書</string> + <string name="toast_no_trusted_certs">沒有人工通過的證書</string> + <string name="dialog_manage_certs_title">移除證書</string> + <string name="dialog_manage_certs_positivebutton">刪除選項</string> + <string name="dialog_manage_certs_negativebutton">取消</string> + <plurals name="toast_delete_certificates"> + <item quantity="other">%d 個證書已被刪除</item> + </plurals> + <plurals name="select_contact"> + <item quantity="other">選擇 %d 個連絡人</item> + </plurals> + <string name="pref_quick_action_summary">以快速動作替代發送按鈕</string> + <string name="pref_quick_action">快速動作</string> + <string name="none">無</string> + <string name="recently_used">最近使用過的</string> + <string name="choose_quick_action">選擇快速動作</string> + <string name="search_for_contacts_or_groups">搜索連絡人或群組</string> + <string name="send_private_message">發送私密消息</string> + <string name="user_has_left_conference">%s 已離開討論群組!</string> + <string name="username">用戶名</string> + <string name="username_hint">用戶名</string> + <string name="invalid_username">該用戶名無效</string> + <string name="conference_name">討論群組名稱</string> + <string name="invalid_conference_name">該討論群組名稱無效</string> + <string name="download_failed_server_not_found">下載失敗:未找到伺服器</string> + <string name="download_failed_file_not_found">下載失敗:未找到文件</string> + <string name="download_failed_could_not_connect">下載失敗:無法連接到伺服器</string> + <string name="download_failed_could_not_write_file">下載失敗:不能寫入檔</string> + <string name="pref_use_white_background">使用白色背景</string> + <string name="pref_use_white_background_summary">收到的消息將顯示為白底黑字</string> + <string name="account_status_tor_unavailable">Tor network 不可用</string> + <string name="account_status_bind_failure">綁定失敗</string> + <string name="account_status_host_unknown">伺服器不能為功能變數名稱做出回應</string> + <string name="server_info_broken">損壞</string> + <string name="pref_presence_settings">存在</string> + <string name="pref_away_when_screen_off">關閉螢幕時離開</string> + <string name="pref_away_when_screen_off_summary">當螢幕關閉時將標記您的資源為離開狀態</string> + <string name="pref_xa_on_silent_mode">靜音模式時不可用</string> + <string name="pref_xa_on_silent_mode_summary">當設備進入靜音模式時把資源標識改為不可用</string> + <string name="pref_treat_vibrate_as_silent">靜音模式開啟振動</string> + <string name="pref_treat_vibrate_as_silent_summary">當設備進入振動模式時把資源標識改為不可用</string> + <string name="pref_show_connection_options">高級連接設置</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> + <string name="authenticate_with_certificate">留空以認證 w/ 證書</string> + <string name="mam_prefs">壓縮設置</string> + <string name="server_side_mam_prefs">服務端壓縮設置</string> + <string name="fetching_mam_prefs">正在獲取壓縮設置。請稍後...</string> + <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="jid_does_not_match_certificate">Jabber ID 與證書不匹配</string> + <string name="action_renew_certificate">更新證書</string> + <string name="error_fetching_omemo_key">獲取 OMEMO 金鑰錯誤!</string> + <string name="verified_omemo_key_with_certificate">請用證書驗證 OMEMO 金鑰!</string> + <string name="device_does_not_support_certificates">您的設備不支援設備證書選擇!</string> + <string name="pref_connection_options">連接</string> + <string name="pref_use_tor">通過 Tor 連接</string> + <string name="pref_use_tor_summary">所有連接使用 Tor 網路傳輸,需要 Orbot</string> + <string name="account_settings_hostname">主機名稱</string> + <string name="account_settings_port">埠</string> + <string name="hostname_or_onion">伺服器 - 或者 .orion 地址</string> + <string name="not_a_valid_port">該埠號無效</string> + <string name="not_valid_hostname">該主機名稱無效</string> + <string name="connected_accounts">%2$d 個中的 %1$d 個帳戶已連接</string> + <plurals name="x_messages"> + <item quantity="other">%d 條消息</item> + </plurals> + <string name="load_more_messages">載入更多消息</string> + <string name="shared_file_with_x">用 %s 分享文件</string> + <string name="shared_image_with_x">用 %s 分享圖片</string> + <string name="shared_images_with_x">圖片分享自 %s</string> + <string name="shared_text_with_x">用 %s 分享文本</string> + <string name="no_storage_permission">Conversations 需要訪問外部存儲</string> + <string name="sync_with_contacts">與連絡人同步</string> + <string name="sync_with_contacts_long">Conversations 會匹配你的 XMPP 花名冊與你的連絡人,以顯示他們的全名和頭像。\n\nConversations 只會讀取你的連絡人並在本地匹配,不會上傳到你的伺服器。\n\n現在將要詢問你是否給予訪問你連絡人的許可權。</string> + <string name="certificate_information">證書詳情</string> + <string name="certificate_subject">主題</string> + <string name="certificate_issuer">發行人</string> + <string name="certificate_cn">通用名稱</string> + <string name="certificate_o">組織</string> + <string name="certificate_sha1">SHA-1</string> + <string name="certicate_info_not_available">(不可用)</string> + <string name="certificate_not_found">未發現證書</string> + <string name="notify_on_all_messages">為所有資訊顯示通知</string> + <string name="notify_only_when_highlighted">僅當高亮時顯示通知</string> + <string name="notify_never">禁用通知</string> + <string name="notify_paused">暫停通知</string> + <string name="pref_picture_compression">壓縮圖片</string> + <string name="pref_picture_compression_summary">裁剪並壓縮圖片</string> + <string name="always">總是</string> + <string name="automatically">自動</string> + <string name="battery_optimizations_enabled">啟用節電模式</string> + <string name="battery_optimizations_enabled_explained">你的設備正在為Conversations進行電池優化,這可能導致通知的延遲甚至消息的丟失。 +建議不要這樣做</string> + <string name="battery_optimizations_enabled_dialog">你的設備正在為Conversations進行電池優化,這可能導致通知的延遲甚至消息的丟失。 +你將會被提示禁用該功能。</string> + <string name="disable">禁用</string> + <string name="selection_too_large">選擇區域過大</string> + <string name="no_accounts">(沒有啟動的帳戶)</string> + <string name="this_field_is_required">必填</string> + <string name="correct_message">更正消息</string> + <string name="send_corrected_message">發送更正後的消息</string> + <string name="no_keys_just_confirm">你已信任此連絡人。選擇“完成”表示 %s 將成為此討論群組的一部分。</string> + <string name="select_image_and_crop">選擇照片並裁剪</string> + <string name="this_account_is_disabled">你已經禁用了此帳戶</string> + <string name="security_error_invalid_file_access">安全錯誤:檔存取權限無效</string> + <string name="no_application_to_share_uri">沒有可以分享此連結的應用</string> + <string name="share_uri_with">分享連結...</string> + <string name="welcome_text">XMPP 是一個獨立協議的提供者。你可以用這個用戶端連接任何你選擇的 XMPP 伺服器。\n為了讓你更便捷,我們讓你可以在 conversations.im¹ 上方便的註冊帳號;特意為使用 Conversations 的人準備。</string> + <string name="magic_create_text">我們將會引導你完成在 conversations.im¹ 上註冊帳號的過程。\n當獲得了 conversations.im 提供的帳號以後,你可以通過添加使用其他提供商的好友的完整 Jabber ID 來與他們聯絡。</string> + <string name="your_full_jid_will_be">您完整的 Jabble ID 是:%s </string> + <string name="create_account">創建帳戶</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> + <string name="change_presence">變更狀態</string> + <string name="status_message">狀態資訊</string> + <string name="all_accounts_on_this_device">為本設備上的所有帳戶設置</string> + <string name="presence_chat">免費聊天室</string> + <string name="presence_online">線上</string> + <string name="presence_away">離開</string> + <string name="presence_xa">離線</string> + <string name="presence_dnd">忙碌</string> + <string name="secure_password_generated">安全密碼已生成</string> + <string name="device_does_not_support_battery_op">該設備不支援禁用電池優化</string> + <string name="show_password">顯示密碼</string> + <string name="registration_please_wait">註冊失敗:請重試</string> + <string name="registration_password_too_weak">註冊失敗:密碼太弱</string> + <string name="create_conference">創建討論群組</string> + <string name="join_or_create_conference">加入創建討論群組</string> + <string name="conference_subject">主題</string> + <string name="choose_participants">選擇成員</string> + <string name="creating_conference">正在創建討論群組…</string> + <string name="invite_again">重新邀請</string> + <string name="gp_short">短</string> + <string name="gp_medium">中</string> + <string name="gp_long">長</string> + <string name="pref_broadcast_last_activity">廣播最後打開該應用的時間</string> + <string name="pref_broadcast_last_activity_summary">讓你的所有連絡人知道你使用Conversations的時間</string> + <string name="pref_privacy">隱私</string> + <string name="pref_theme_options">主題</string> + <string name="pref_theme_options_summary">選擇調色板</string> + <string name="pref_theme_light">明亮主題</string> + <string name="pref_theme_dark">黑暗主題</string> + <string name="pref_use_green_background">綠色背景</string> + <string name="pref_use_green_background_summary">接收到的消息使用綠色背景</string> + <string name="unable_to_connect_to_keychain">無法連接到 OpenKeychain</string> + <string name="this_device_is_no_longer_in_use">此設備不再使用</string> + <string name="type_pc">電腦</string> + <string name="type_phone">行動電話</string> + <string name="type_tablet">平板</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="allow">允許</string> + <string name="no_permission_to_access_x">沒有訪問 %s 的許可</string> + <string name="remote_server_not_found">找不到遠端伺服器</string> + <string name="unable_to_update_account">無法更新帳戶</string> + <string name="missing_presence_subscription_with_x">缺少與 %s 的線上訂閱。</string> + <string name="missing_keys_from_x">缺少來自 %s 的 OMEMO 金鑰。</string> + <string name="missing_omemo_keys">缺少 OMEMO 金鑰</string> + <string name="wrong_conference_configuration">這不是一個私密,非匿名的會議室。</string> + <string name="this_conference_has_no_members">這個會議室中沒有成員。</string> + <string name="report_jid_as_spammer">報告這個 JID 發送不想要的消息。</string> + <string name="pref_delete_omemo_identities">刪除 OMEMO 身份</string> + <string name="pref_delete_omemo_identities_summary">重新生成你的 OMEMO 金鑰。你的所有連絡人不得不對你進行再認證。請將此作為最後的辦法。</string> + <string name="delete_selected_keys">刪除選擇的金鑰</string> + <string name="error_publish_avatar_offline">你需要連接才能發佈頭像</string> + <string name="show_error_message">顯示出錯消息</string> + <string name="error_message">出錯消息</string> + <string name="data_saver_enabled">省流量模式已啟動</string> + <string name="data_saver_enabled_explained">您的作業系統禁止本程式在後臺運行時訪問互聯網。為了收到新消息提示,您需要在省流量模式下允許本程式不受限制地訪問互聯網。\n本程式仍會盡可能節省流量。</string> + <string name="device_does_not_support_data_saver">該設備不支援禁用省流量模式</string> </resources> diff --git a/src/main/res/values/attrs.xml b/src/main/res/values/attrs.xml index e402901c..39787f36 100644 --- a/src/main/res/values/attrs.xml +++ b/src/main/res/values/attrs.xml @@ -48,6 +48,7 @@ <attr name="icon_settings" format="reference"/> <attr name="icon_share" format="reference"/> <attr name="icon_import_export" format="reference"/> + <attr name="icon_scan_qr_code" format="reference"/> <attr name="icon_notifications" format="reference"/> <attr name="icon_notifications_off" format="reference"/> diff --git a/src/main/res/values/ids.xml b/src/main/res/values/ids.xml index 7daad46d..142e4d66 100644 --- a/src/main/res/values/ids.xml +++ b/src/main/res/values/ids.xml @@ -2,4 +2,5 @@ <resources> <item type="id" name="TAG_ACCOUNT"/> <item type="id" name="TAG_FINGERPRINT"/> + <item type="id" name="TAG_FINGERPRINT_STATUS"/> </resources>
\ No newline at end of file diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 7a528d77..638b6bd6 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -123,14 +123,14 @@ <string name="pref_never_send_crash">Never send crash reports</string> <string name="pref_never_send_crash_summary">By sending in stack traces you are helping the ongoing development of Conversations</string> <string name="pref_confirm_messages">Confirm Messages</string> - <string name="pref_confirm_messages_summary">Let your contact know when you have received and read a message</string> + <string name="pref_confirm_messages_summary">Let your contacts know when you have received and read their messages</string> <string name="pref_ui_options">UI</string> <string name="openpgp_error">OpenKeychain reported an error</string> <string name="error_decrypting_file">I/O Error decrypting file</string> <string name="accept">Accept</string> <string name="error">An error has occurred</string> <string name="pref_grant_presence_updates">Grant presence updates</string> - <string name="pref_grant_presence_updates_summary">Preemptively grant and ask for presence subscription for contacts you created</string> + <string name="pref_grant_presence_updates_summary">Preemptively grant and request presence subscriptions for contacts you have created</string> <string name="subscriptions">Subscriptions</string> <string name="your_account">Your account</string> <string name="keys">Keys</string> @@ -372,8 +372,8 @@ <string name="url_copied_to_clipboard">URL copied to clipboard</string> <string name="message_copied_to_clipboard">Message copied to clipboard</string> <string name="image_transmission_failed">Image transmission failed</string> - <string name="scan_qr_code">Scan QR code</string> - <string name="show_qr_code">Show QR code</string> + <string name="scan_qr_code">Scan 2D Barcode</string> + <string name="show_qr_code">Show 2D Barcode</string> <string name="show_block_list">Show block list</string> <string name="account_details">Account details</string> <string name="verify_otr">Verify OTR</string> @@ -413,7 +413,7 @@ <string name="no_application_found_to_open_file">No application found to open file</string> <string name="could_not_verify_fingerprint">Could not verify fingerprint</string> <string name="manually_verify">Manually verify</string> - <string name="are_you_sure_verify_fingerprint">Are you sure that you want to verify your contacts OTR fingerprint?</string> + <string name="are_you_sure_verify_fingerprint">Are you sure that you want to verify your contact’s OTR fingerprint?</string> <string name="pref_show_dynamic_tags">Show dynamic tags</string> <string name="pref_show_dynamic_tags_summary">Display read-only tags underneath contacts</string> <string name="enable_notifications">Enable notifications</string> @@ -506,7 +506,7 @@ <string name="contact_is_typing">%s is typing…</string> <string name="contact_has_stopped_typing">%s has stopped typing</string> <string name="pref_chat_states">Typing notifications</string> - <string name="pref_chat_states_summary">Let your contact know when you are writing a new message</string> + <string name="pref_chat_states_summary">Let your contacts know when you are writing messages to them</string> <string name="send_location">Send location</string> <string name="show_location">Show location</string> <string name="no_application_found_to_display_location">No application found to display location</string> @@ -704,4 +704,20 @@ <string name="this_device_has_been_verified">This device has been verified</string> <string name="copy_fingerprint">Copy fingerprint</string> <string name="all_omemo_keys_have_been_verified">All OMEMO keys have been verified</string> + <string name="barcode_does_not_contain_fingerprints_for_this_conversation">Barcode does not contain fingerprints for this conversation.</string> + <string name="verified_fingerprints">Verified fingerprints</string> + <string name="use_camera_icon_to_scan_barcode">Use the camera to scan a contact’s barcode</string> + <string name="please_wait_for_keys_to_be_fetched">Please wait for keys to be fetched</string> + <string name="share_as_barcode">Share as Barcode</string> + <string name="share_as_uri">Share as XMPP URI</string> + <string name="share_as_http">Share as HTTP link</string> + <string name="pref_blind_trust_before_verification">Blind Trust Before Verification</string> + <string name="pref_blind_trust_before_verification_summary">Automatically trust all new devices of contacts that haven’t been verified before, and prompt for manual confirmation each time a verified contact adds a new device.</string> + <string name="blindly_trusted_omemo_keys">Blindly trusted OMEMO keys</string> + <string name="not_trusted">Untrusted</string> + <string name="invalid_barcode">Invalid 2D barcode</string> + <string name="pref_clean_cache_summary">Clean cache folder (used by Camera Application)</string> + <string name="pref_clean_cache">Clean cache</string> + <string name="pref_clean_private_storage">Clean private storage</string> + <string name="pref_clean_private_storage_summary">Clean private storage where files are kept (They can be re-downloaded from the server)</string> </resources> diff --git a/src/main/res/values/themes.xml b/src/main/res/values/themes.xml index 46ea691b..8ac3793b 100644 --- a/src/main/res/values/themes.xml +++ b/src/main/res/values/themes.xml @@ -58,6 +58,7 @@ <item name="attr/icon_settings">@drawable/ic_action_settings</item> <item name="attr/icon_import_export">@drawable/ic_stat_communication_import_export</item> <item name="attr/icon_share">@drawable/ic_action_share</item> + <item name="attr/icon_scan_qr_code">@drawable/ic_action_camera</item> <item name="attr/icon_notifications">@drawable/ic_notifications_black54_24dp</item> <item name="attr/icon_notifications_off">@drawable/ic_notifications_off_black54_24dp</item> @@ -122,6 +123,7 @@ <item name="attr/icon_settings">@drawable/ic_action_settings_white</item> <item name="attr/icon_import_export">@drawable/ic_stat_communication_import_export</item> <item name="attr/icon_share">@drawable/ic_action_share</item> + <item name="attr/icon_scan_qr_code">@drawable/ic_action_camera</item> <item name="attr/icon_notifications">@drawable/ic_notifications_white80</item> <item name="attr/icon_notifications_off">@drawable/ic_notifications_off_white80</item> diff --git a/src/main/res/xml/file_paths.xml b/src/main/res/xml/file_paths.xml index 2a8bc766..6a5e2609 100644 --- a/src/main/res/xml/file_paths.xml +++ b/src/main/res/xml/file_paths.xml @@ -1,4 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <paths> <external-path name="external" path="/"/> + <files-path path="Pictures/" name="pics" /> + <files-path path="Files/" name="files" /> + <cache-path path="Camera/" name="cam" /> </paths>
\ No newline at end of file diff --git a/src/main/res/xml/preferences.xml b/src/main/res/xml/preferences.xml index cee43491..751f3bec 100644 --- a/src/main/res/xml/preferences.xml +++ b/src/main/res/xml/preferences.xml @@ -163,7 +163,13 @@ android:key="expert" android:summary="@string/pref_expert_options_summary" android:title="@string/pref_expert_options"> - <PreferenceCategory android:title="@string/pref_security_settings"> + <PreferenceCategory android:title="@string/pref_security_settings" + android:key="security_options"> + <CheckBoxPreference + android:defaultValue="true" + android:key="btbv" + android:title="@string/pref_blind_trust_before_verification" + android:summary="@string/pref_blind_trust_before_verification_summary"/> <CheckBoxPreference android:defaultValue="false" android:key="dont_save_encrypted" @@ -184,6 +190,14 @@ android:title="@string/pref_allow_message_correction" android:summary="@string/pref_allow_message_correction_summary"/> <Preference + android:key="clean_cache" + android:summary="@string/pref_clean_cache_summary" + android:title="@string/pref_clean_cache"/> + <Preference + android:key="clean_private_storage" + android:summary="@string/pref_clean_private_storage_summary" + android:title="@string/pref_clean_private_storage"/> + <Preference android:key="delete_omemo_identities" android:title="@string/pref_delete_omemo_identities" android:summary="@string/pref_delete_omemo_identities_summary"/> @@ -254,7 +268,7 @@ android:title="@string/pref_use_indicate_received"/> <CheckBoxPreference android:defaultValue="false" - android:key="keep_foreground_service" + android:key="enable_foreground_service" android:summary="@string/pref_keep_foreground_service_summary" android:title="@string/pref_keep_foreground_service"/> <Preference |