Compare commits

...

56 Commits

Author SHA1 Message Date
MajorCrazed
7e9153bd81 remove force disable 2017-11-06 16:56:30 +01:00
MajorCrazed
15fa44c1b1 remove comment 2017-11-06 16:43:02 +01:00
MajorCrazed
7ffe1b8bae move force variable to BluetoothDisableEvent 2017-11-02 13:31:21 +01:00
MajorCrazed
bb8713ddcb enable bluetooth by default 2017-11-02 13:30:54 +01:00
MajorCrazed
1e9afd14db set the reason to enable or disable bluetooth 2017-11-01 17:36:36 +01:00
MajorCrazed
86ea6eae63 handle different reasons why bluetooth should be enabled 2017-11-01 17:35:11 +01:00
MajorCrazed
56ba639084 enum to set the reason why bluetooth is enabled 2017-11-01 17:33:12 +01:00
MajorCrazed
8c16c2107f disable bluetooth after adding contact 2017-10-29 23:31:21 +01:00
MajorCrazed
cefe2b09e0 add option to force enable or disable bluetooth adapter 2017-10-29 23:30:47 +01:00
akwizgran
e6b1597fa7 Upgraded Gradle to 3.5. 2017-10-26 18:07:20 +01:00
akwizgran
8937d3cd9c Updated translations. 2017-10-24 17:01:11 +01:00
akwizgran
51f320d147 Merge branch '992-wake-lock-tag' into 'master'
Change wake lock tag

Closes #992 and #1087

See merge request !612
2017-10-24 13:36:26 +00:00
goapunk
e402a894bb Change wake lock tag
Signed-off-by: goapunk <noobie@goapunks.net>
2017-10-24 13:45:27 +02:00
Torsten Grote
9b577f1219 Merge branch 'remove-location-permission' into 'master'
Remove unused location permission

See merge request !611
2017-10-18 16:31:56 +00:00
akwizgran
220f678403 Removed unused location permission. 2017-10-18 14:05:11 +01:00
akwizgran
4173fc4daa Merge branch '1045-preference-divider' into 'master'
Don't use a custom widget to separate preference categories

Closes #1045

See merge request !609
2017-10-17 17:03:13 +00:00
Torsten Grote
c6756d2145 Merge branch 'gradle-plugin-2.3.3' into 'master'
Upgrade Gradle plugin and build tools

See merge request !610
2017-10-17 16:14:53 +00:00
akwizgran
6731f6eeb5 Added checksum for Gradle download. 2017-10-17 17:01:46 +01:00
akwizgran
6f7f8b40e3 Upgraded Gradle plugin and build tools. 2017-10-17 15:31:28 +01:00
akwizgran
1a83b2c99b Bumped version number for beta release. 2017-10-17 09:41:11 +01:00
akwizgran
f641fae1c7 Added new translations. 2017-10-16 17:10:53 +01:00
akwizgran
deb43d9872 Updated translations. 2017-10-16 17:08:07 +01:00
akwizgran
cee4e1305e Merge branch 'extend-expiry' into 'master'
Extend expiry and show a green snackbar about it once

See merge request !606
2017-10-12 17:03:26 +00:00
akwizgran
a1f989c43c Use black text for the expiry extension notice. 2017-10-12 17:51:57 +01:00
akwizgran
b67abadbac Use a setting to record whether update notice has been shown 2017-10-12 17:51:57 +01:00
Torsten Grote
8c29c85696 Extend expiry and show a green snackbar about it once 2017-10-12 17:51:57 +01:00
akwizgran
4fe4c298d7 Don't use a custom widget to separate preference categories. 2017-10-11 17:35:05 +01:00
akwizgran
13d35229d5 Merge branch '1091-reduce-polling-queries' into 'master'
Reduce number of DB queries used when polling for connections

Closes #1091

See merge request !604
2017-10-11 13:45:14 +00:00
Torsten Grote
f0137b41b6 Merge branch 'accept-sdk-license-agreement-for-ci' into 'master'
Accept build tools license agreement for CI runner

See merge request !607
2017-10-11 13:24:25 +00:00
akwizgran
b221d21903 Accept all SDK license agreements for CI runner. 2017-10-11 14:18:02 +01:00
Torsten Grote
8bac202626 Add Hindi, Finnish and Basque translations 2017-10-10 10:04:22 -03:00
Torsten Grote
973151c949 Merge branch 'report-bluetooth-and-wifi-support' into 'master'
Report Bluetooth LE and Wi-Fi Direct support in crash reports and feedback

See merge request !605
2017-10-10 12:16:29 +00:00
akwizgran
ed26ab78a5 Merge branch '158-permission-requests' into 'master'
Add permission requests for Android 6+

Closes #158

See merge request !601
2017-10-10 10:40:14 +00:00
akwizgran
8454b2d235 Code cleanup, shortened button text to help with layout. 2017-10-10 11:33:07 +01:00
akwizgran
91d0f89f60 Removed unused import. 2017-10-10 11:08:40 +01:00
akwizgran
e074672e86 Reduce DB queries for looking up transport properties. 2017-10-10 10:59:39 +01:00
akwizgran
6c1901fe5b Reduced DB queries when polling for LAN connections. 2017-10-09 15:20:03 +01:00
goapunk
49052be627 Add permission requests for Android 6+
* Add request for the camera

Signed-off-by: goapunk <noobie@goapunks.net>
2017-10-04 13:17:51 +02:00
Torsten Grote
5b5b540630 Merge branch '299-disable-bluetooth-at-shutdown' into 'master'
Disable Bluetooth at shutdown if we enabled it

See merge request !602
2017-10-03 15:38:22 +00:00
akwizgran
9993bac3a1 Disable Bluetooth at shutdown if we enabled it. 2017-10-03 15:59:07 +01:00
akwizgran
3c95988693 Merge branch '539-clear-notifications' into 'master'
Don't show dismissed notifications again when items are removed

Closes #539

See merge request !600
2017-10-02 14:46:54 +00:00
akwizgran
fc5c3b470e Merge branch 'patch-1' into 'master'
Contacts, on your side

See merge request !594
2017-10-02 13:14:00 +00:00
akwizgran
53f05a72ba Removed logging. 2017-09-29 15:31:25 +01:00
akwizgran
2c10ae7d06 Clear notifications when dismissed.
Also fixed an issue with notifications alerting again when items
were removed.
2017-09-29 15:23:27 +01:00
akwizgran
6b9010c557 Merge branch '703-create-test-data' into 'master'
Add an option to debug builds to create fake test data

Closes #703

See merge request !595
2017-09-28 10:37:03 +00:00
Torsten Grote
1bf0fdfa81 Add an option to debug builds to create fake test data 2017-09-27 13:55:29 -03:00
Torsten Grote
237759aac0 Add Simplified Chinese translation 2017-09-27 13:32:07 -03:00
akwizgran
2a141e0a97 Merge branch 'disableAaptCruncher' into 'master'
Disable PNG crunching for reproducibility

See merge request !596
2017-09-27 16:04:23 +00:00
akwizgran
d6900be68e Merge branch '1051-fix-pink' into 'master'
Fix pink navigation drawer items with current support library

Closes #1051

See merge request !598
2017-09-27 16:02:22 +00:00
Torsten Grote
a35d7c7204 Fix pink navigation drawer items with current support library 2017-09-27 12:09:06 -03:00
Torsten Grote
86287f9241 Merge branch 'spongy-castle-158' into 'master'
Upgrade Spongy Castle to 1.58

See merge request !597
2017-09-27 15:01:15 +00:00
akwizgran
0b2e3dd96f Upgrade Spongy Castle to 1.58. 2017-09-27 15:54:37 +01:00
Torsten Grote
90aa1d1ce7 Disable PNG crunching for reproducibility
This can help to prevent non-determinism introduced by the crunching
process.

More information:
e48f9f0773

With enabled and disabled crunching,
the size of the signed release APK was 17809681 bytes.

Related to #164
2017-09-27 11:35:25 -03:00
Allan Nordhøy
5c51259269 "Connection aborted!" no und 2017-09-19 19:39:57 +00:00
Allan Nordhøy
7eefa07052 Contact connections → contacts
by us → on your side
2017-09-19 18:56:22 +00:00
akwizgran
eb9d0c00a8 Report Bluetooth LE and Wi-Fi Direct support. 2017-08-16 12:21:13 +01:00
108 changed files with 3601 additions and 569 deletions

View File

@@ -7,8 +7,7 @@ cache:
before_script:
- export GRADLE_USER_HOME=$PWD/.gradle
# - export ANDROID_COMPILE_SDK=`sed -n 's,.*compileSdkVersion\s*\([0-9][0-9]*\).*,\1,p' app/build.gradle`
# - echo y | android --silent update sdk --no-ui --filter android-${ANDROID_COMPILE_SDK}
- echo y | /opt/android-sdk/tools/bin/sdkmanager "build-tools;23.0.3"
test:
script:

View File

@@ -7,13 +7,13 @@ apply plugin: 'de.undercouch.download'
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
buildToolsVersion '25.0.0'
defaultConfig {
minSdkVersion 14
targetSdkVersion 22
versionCode 1610
versionName "0.16.10"
versionCode 1611
versionName "0.16.11"
consumerProguardFiles 'proguard-rules.txt'
}
@@ -24,7 +24,7 @@ android {
}
dependencies {
compile project(':bramble-core')
compile project(path: ':bramble-core', configuration: 'default')
compile fileTree(dir: 'libs', include: '*.jar')
provided 'javax.annotation:jsr250-api:1.0'
}

View File

@@ -11,8 +11,6 @@
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_LOGS"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<!-- Since API 23, this is needed to add contacts via Bluetooth -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<application
android:allowBackup="false"

View File

@@ -39,7 +39,7 @@ public class AndroidPluginModule {
EventBus eventBus) {
Context appContext = app.getApplicationContext();
DuplexPluginFactory bluetooth = new DroidtoothPluginFactory(ioExecutor,
androidExecutor, appContext, random, backoffFactory);
androidExecutor, appContext, random, eventBus, backoffFactory);
DuplexPluginFactory tor = new TorPluginFactory(ioExecutor, appContext,
locationUtils, reporter, eventBus, torSocketFactory,
backoffFactory);

View File

@@ -8,20 +8,26 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.widget.ArrayAdapter;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BluetoothEnableDisableReason;
import org.briarproject.bramble.api.plugin.PluginException;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.plugin.event.DisableBluetoothEvent;
import org.briarproject.bramble.api.plugin.event.EnableBluetoothEvent;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.util.AndroidUtils;
@@ -30,6 +36,7 @@ import org.briarproject.bramble.util.StringUtils;
import java.io.Closeable;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
@@ -63,7 +70,7 @@ import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
class DroidtoothPlugin implements DuplexPlugin {
class DroidtoothPlugin implements DuplexPlugin, EventListener {
private static final Logger LOG =
Logger.getLogger(DroidtoothPlugin.class.getName());
@@ -79,6 +86,8 @@ class DroidtoothPlugin implements DuplexPlugin {
private volatile boolean running = false;
private volatile boolean wasEnabledByUs = false;
private volatile ArrayList<BluetoothEnableDisableReason>
enableDisableReasons = new ArrayList<>();
private volatile BluetoothStateReceiver receiver = null;
private volatile BluetoothServerSocket socket = null;
@@ -149,10 +158,8 @@ class DroidtoothPlugin implements DuplexPlugin {
bind();
} else {
// Enable Bluetooth if settings allow
if (callback.getSettings().getBoolean(PREF_BT_ENABLE, false)) {
wasEnabledByUs = true;
if (adapter.enable()) LOG.info("Enabling Bluetooth");
else LOG.info("Could not enable Bluetooth");
if (callback.getSettings().getBoolean(PREF_BT_ENABLE, true)) {
enableAdapter(BluetoothEnableDisableReason.COMMUNICATION);
} else {
LOG.info("Not enabling Bluetooth");
}
@@ -243,13 +250,42 @@ class DroidtoothPlugin implements DuplexPlugin {
return new DroidtoothTransportConnection(this, s);
}
private void enableAdapter(BluetoothEnableDisableReason reason) {
if (adapter != null && !adapter.isEnabled()) {
if (adapter.enable()) {
LOG.info("Enabling Bluetooth");
wasEnabledByUs = true;
if(!enableDisableReasons.contains(reason)) {
enableDisableReasons.add(reason);
}
} else {
LOG.info("Could not enable Bluetooth");
}
}
}
@Override
public void stop() {
running = false;
if (receiver != null) appContext.unregisterReceiver(receiver);
tryToClose(socket);
// Disable Bluetooth if we enabled it and it's still enabled
if (wasEnabledByUs && adapter.isEnabled()) {
disableAdapter(true);
}
private void disableAdapter(boolean force){
disableAdapter(null, force);
}
private void disableAdapter(BluetoothEnableDisableReason reason,
boolean force) {
if (adapter != null && adapter.isEnabled() && wasEnabledByUs
&& (enableDisableReasons.contains(reason) || force)) {
if(enableDisableReasons.contains(reason)){
enableDisableReasons.remove(reason);
}
if (adapter.disable()) LOG.info("Disabling Bluetooth");
else LOG.info("Could not disable Bluetooth");
}
@@ -347,8 +383,7 @@ class DroidtoothPlugin implements DuplexPlugin {
@Override
public DuplexTransportConnection createConnection(ContactId c) {
if (!isRunning()) return null;
TransportProperties p = callback.getRemoteProperties().get(c);
if (p == null) return null;
TransportProperties p = callback.getRemoteProperties(c);
String address = p.get(PROP_ADDRESS);
if (StringUtils.isNullOrEmpty(address)) return null;
String uuid = p.get(PROP_UUID);
@@ -413,6 +448,35 @@ class DroidtoothPlugin implements DuplexPlugin {
return StringUtils.macToString(mac);
}
@Override
public void eventOccurred(Event e) {
if (e instanceof EnableBluetoothEvent) {
EnableBluetoothEvent enable = (EnableBluetoothEvent) e;
enableAdapterAsync(enable.getReason());
} else if (e instanceof DisableBluetoothEvent) {
DisableBluetoothEvent disable = (DisableBluetoothEvent) e;
disableAdapterAsync(disable.getReason());
}
}
private void enableAdapterAsync(final BluetoothEnableDisableReason reason) {
ioExecutor.execute(new Runnable() {
@Override
public void run() {
enableAdapter(reason);
}
});
}
private void disableAdapterAsync(final BluetoothEnableDisableReason reason) {
ioExecutor.execute(new Runnable() {
@Override
public void run() {
disableAdapter(reason, false);
}
});
}
private class BluetoothStateReceiver extends BroadcastReceiver {
@Override

View File

@@ -2,6 +2,7 @@ package org.briarproject.bramble.plugin.droidtooth;
import android.content.Context;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
@@ -31,15 +32,18 @@ public class DroidtoothPluginFactory implements DuplexPluginFactory {
private final AndroidExecutor androidExecutor;
private final Context appContext;
private final SecureRandom secureRandom;
private final EventBus eventBus;
private final BackoffFactory backoffFactory;
public DroidtoothPluginFactory(Executor ioExecutor,
AndroidExecutor androidExecutor, Context appContext,
SecureRandom secureRandom, BackoffFactory backoffFactory) {
SecureRandom secureRandom, EventBus eventBus,
BackoffFactory backoffFactory) {
this.ioExecutor = ioExecutor;
this.androidExecutor = androidExecutor;
this.appContext = appContext;
this.secureRandom = secureRandom;
this.eventBus = eventBus;
this.backoffFactory = backoffFactory;
}
@@ -57,7 +61,10 @@ public class DroidtoothPluginFactory implements DuplexPluginFactory {
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE);
return new DroidtoothPlugin(ioExecutor, androidExecutor, appContext,
secureRandom, backoff, callback, MAX_LATENCY);
DroidtoothPlugin plugin = new DroidtoothPlugin(ioExecutor,
androidExecutor, appContext, secureRandom, backoff, callback,
MAX_LATENCY);
eventBus.addListener(plugin);
return plugin;
}
}

View File

@@ -55,6 +55,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
@@ -84,13 +85,13 @@ import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_NEVER;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_WIFI;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_PORT;
import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION;
import static org.briarproject.bramble.util.PrivacyUtils.scrubOnion;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private static final String PROP_ONION = "onion";
private static final String[] EVENTS = {
"CIRC", "ORCONN", "HS_DESC", "NOTICE", "WARN", "ERR"
};
@@ -148,7 +149,8 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
cookieFile = new File(torDirectory, ".tor/control_auth_cookie");
Object o = appContext.getSystemService(POWER_SERVICE);
PowerManager pm = (PowerManager) o;
wakeLock = pm.newWakeLock(PARTIAL_WAKE_LOCK, "TorPlugin");
// This tag will prevent Huawei's powermanager from killing us.
wakeLock = pm.newWakeLock(PARTIAL_WAKE_LOCK, "LocationManagerService");
wakeLock.setReferenceCounted(false);
}
@@ -538,16 +540,21 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
public void poll(Collection<ContactId> connected) {
if (!isRunning()) return;
backoff.increment();
// TODO: Pass properties to connectAndCallBack()
for (ContactId c : callback.getRemoteProperties().keySet())
if (!connected.contains(c)) connectAndCallBack(c);
Map<ContactId, TransportProperties> remote =
callback.getRemoteProperties();
for (Entry<ContactId, TransportProperties> e : remote.entrySet()) {
ContactId c = e.getKey();
if (!connected.contains(c)) connectAndCallBack(c, e.getValue());
}
}
private void connectAndCallBack(final ContactId c) {
private void connectAndCallBack(final ContactId c,
final TransportProperties p) {
ioExecutor.execute(new Runnable() {
@Override
public void run() {
DuplexTransportConnection d = createConnection(c);
if (!isRunning()) return;
DuplexTransportConnection d = createConnection(p);
if (d != null) {
backoff.reset();
callback.outgoingConnectionCreated(c, d);
@@ -559,8 +566,11 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
@Override
public DuplexTransportConnection createConnection(ContactId c) {
if (!isRunning()) return null;
TransportProperties p = callback.getRemoteProperties().get(c);
if (p == null) return null;
return createConnection(callback.getRemoteProperties(c));
}
@Nullable
private DuplexTransportConnection createConnection(TransportProperties p) {
String onion = p.get(PROP_ONION);
if (StringUtils.isNullOrEmpty(onion)) return null;
if (!ONION.matcher(onion).matches()) {

View File

@@ -0,0 +1,6 @@
package org.briarproject.bramble.api.plugin;
public enum BluetoothEnableDisableReason {
COMMUNICATION,
ADD_CONTACT
}

View File

@@ -4,5 +4,10 @@ public interface LanTcpConstants {
TransportId ID = new TransportId("org.briarproject.bramble.lan");
// a transport property (shared with contacts)
String PROP_IP_PORTS = "ipPorts";
// a local setting
String PREF_LAN_IP_PORTS = "ipPorts";
}

View File

@@ -29,6 +29,11 @@ public interface PluginCallback {
*/
Map<ContactId, TransportProperties> getRemoteProperties();
/**
* Returns the plugin's remote transport properties for the given contact.
*/
TransportProperties getRemoteProperties(ContactId c);
/**
* Merges the given settings with the namespaced settings
*/

View File

@@ -4,6 +4,8 @@ public interface TorConstants {
TransportId ID = new TransportId("org.briarproject.bramble.tor");
String PROP_ONION = "onion";
int SOCKS_PORT = 59050;
int CONTROL_PORT = 59051;
@@ -16,4 +18,5 @@ public interface TorConstants {
int PREF_TOR_NETWORK_NEVER = 0;
int PREF_TOR_NETWORK_WIFI = 1;
int PREF_TOR_NETWORK_ALWAYS = 2;
}

View File

@@ -0,0 +1,16 @@
package org.briarproject.bramble.api.plugin.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.plugin.BluetoothEnableDisableReason;
abstract class BluetoothEvent extends Event {
private BluetoothEnableDisableReason selectedReason;
BluetoothEvent(BluetoothEnableDisableReason reason){
selectedReason = reason;
}
public BluetoothEnableDisableReason getReason(){
return selectedReason;
}
}

View File

@@ -0,0 +1,18 @@
package org.briarproject.bramble.api.plugin.event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.BluetoothEnableDisableReason;
import javax.annotation.concurrent.Immutable;
/**
* An event that asks the Bluetooth plugin to disable the Bluetooth adapter if
* we previously enabled it.
*/
@Immutable
@NotNullByDefault
public class DisableBluetoothEvent extends BluetoothEvent {
public DisableBluetoothEvent(BluetoothEnableDisableReason reason) {
super(reason);
}
}

View File

@@ -0,0 +1,18 @@
package org.briarproject.bramble.api.plugin.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.BluetoothEnableDisableReason;
import javax.annotation.concurrent.Immutable;
/**
* An event asks the Bluetooth plugin to enable the Bluetooth adapter.
*/
@Immutable
@NotNullByDefault
public class EnableBluetoothEvent extends BluetoothEvent {
public EnableBluetoothEvent(BluetoothEnableDisableReason reason){
super(reason);
}
}

View File

@@ -49,6 +49,13 @@ public interface TransportPropertyManager {
Map<ContactId, TransportProperties> getRemoteProperties(TransportId t)
throws DbException;
/**
* Returns the remote transport properties for the given contact and
* transport.
*/
TransportProperties getRemoteProperties(ContactId c, TransportId t)
throws DbException;
/**
* Merges the given properties with the existing local properties for the
* given transport.

View File

@@ -8,6 +8,7 @@ import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Collection;
import java.util.Random;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
@@ -27,6 +28,7 @@ public class StringUtils {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
private static final Random random = new Random();
public static boolean isNullOrEmpty(@Nullable String s) {
return s == null || s.length() == 0;
@@ -139,4 +141,12 @@ public class StringUtils {
}
return s.toString();
}
public static String getRandomString(int length) {
char[] c = new char[length];
for (int i = 0; i < length; i++)
c[i] = (char) ('a' + random.nextInt(26));
return new String(c);
}
}

View File

@@ -34,13 +34,6 @@ public class TestUtils {
return getRandomBytes(UniqueId.LENGTH);
}
public static String getRandomString(int length) {
char[] c = new char[length];
for (int i = 0; i < length; i++)
c[i] = (char) ('a' + random.nextInt(26));
return new String(c);
}
public static SecretKey getSecretKey() {
return new SecretKey(getRandomBytes(SecretKey.LENGTH));
}

View File

@@ -10,8 +10,8 @@ targetCompatibility = 1.6
apply plugin: 'witness'
dependencies {
compile project(':bramble-api')
compile 'com.madgag.spongycastle:core:1.56.0.0'
compile project(path: ':bramble-api', configuration: 'default')
compile 'com.madgag.spongycastle:core:1.58.0.0'
compile 'com.h2database:h2:1.4.192' // This is the last version that supports Java 1.6
compile 'org.bitlet:weupnp:0.1.4'
@@ -20,7 +20,7 @@ dependencies {
dependencyVerification {
verify = [
'com.madgag.spongycastle:core:5e791b0eaa9e0c4594231b44f616a52adddb7dccedeb0ad9ad74887e19499a23',
'com.madgag.spongycastle:core:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
'com.h2database:h2:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
'org.bitlet:weupnp:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
]

View File

@@ -283,6 +283,16 @@ class PluginManagerImpl implements PluginManager, Service {
}
}
@Override
public TransportProperties getRemoteProperties(ContactId c) {
try {
return transportPropertyManager.getRemoteProperties(c, id);
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
return new TransportProperties();
}
}
@Override
public void mergeSettings(Settings s) {
try {

View File

@@ -1,7 +1,6 @@
package org.briarproject.bramble.plugin.tcp;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
@@ -35,6 +34,7 @@ import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_LAN;
import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
import static org.briarproject.bramble.api.plugin.LanTcpConstants.PREF_LAN_IP_PORTS;
import static org.briarproject.bramble.api.plugin.LanTcpConstants.PROP_IP_PORTS;
import static org.briarproject.bramble.util.ByteUtils.MAX_16_BIT_UNSIGNED;
import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress;
@@ -45,7 +45,6 @@ class LanTcpPlugin extends TcpPlugin {
Logger.getLogger(LanTcpPlugin.class.getName());
private static final int MAX_ADDRESSES = 4;
private static final String PROP_IP_PORTS = "ipPorts";
private static final String SEPARATOR = ",";
LanTcpPlugin(Executor ioExecutor, Backoff backoff,
@@ -126,9 +125,8 @@ class LanTcpPlugin extends TcpPlugin {
}
@Override
protected List<InetSocketAddress> getRemoteSocketAddresses(ContactId c) {
TransportProperties p = callback.getRemoteProperties().get(c);
if (p == null) return Collections.emptyList();
protected List<InetSocketAddress> getRemoteSocketAddresses(
TransportProperties p) {
return parseSocketAddresses(p.get(PROP_IP_PORTS));
}

View File

@@ -9,6 +9,7 @@ import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.util.StringUtils;
import java.io.IOException;
@@ -24,6 +25,8 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
@@ -66,11 +69,11 @@ abstract class TcpPlugin implements DuplexPlugin {
protected abstract void setLocalSocketAddress(InetSocketAddress a);
/**
* Returns zero or more socket addresses for connecting to the given
* contact.
* Returns zero or more socket addresses for connecting to a contact with
* the given transport properties.
*/
protected abstract List<InetSocketAddress> getRemoteSocketAddresses(
ContactId c);
TransportProperties p);
/**
* Returns true if connections to the given address can be attempted.
@@ -207,16 +210,21 @@ abstract class TcpPlugin implements DuplexPlugin {
public void poll(Collection<ContactId> connected) {
if (!isRunning()) return;
backoff.increment();
// TODO: Pass properties to connectAndCallBack()
for (ContactId c : callback.getRemoteProperties().keySet())
if (!connected.contains(c)) connectAndCallBack(c);
Map<ContactId, TransportProperties> remote =
callback.getRemoteProperties();
for (Entry<ContactId, TransportProperties> e : remote.entrySet()) {
ContactId c = e.getKey();
if (!connected.contains(c)) connectAndCallBack(c, e.getValue());
}
}
private void connectAndCallBack(final ContactId c) {
private void connectAndCallBack(final ContactId c,
final TransportProperties p) {
ioExecutor.execute(new Runnable() {
@Override
public void run() {
DuplexTransportConnection d = createConnection(c);
if (!isRunning()) return;
DuplexTransportConnection d = createConnection(p);
if (d != null) {
backoff.reset();
callback.outgoingConnectionCreated(c, d);
@@ -228,7 +236,12 @@ abstract class TcpPlugin implements DuplexPlugin {
@Override
public DuplexTransportConnection createConnection(ContactId c) {
if (!isRunning()) return null;
for (InetSocketAddress remote : getRemoteSocketAddresses(c)) {
return createConnection(callback.getRemoteProperties(c));
}
@Nullable
private DuplexTransportConnection createConnection(TransportProperties p) {
for (InetSocketAddress remote : getRemoteSocketAddresses(p)) {
if (!isConnectable(remote)) {
if (LOG.isLoggable(INFO)) {
SocketAddress local = socket.getLocalSocketAddress();

View File

@@ -1,6 +1,5 @@
package org.briarproject.bramble.plugin.tcp;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
@@ -78,9 +77,8 @@ class WanTcpPlugin extends TcpPlugin {
}
@Override
protected List<InetSocketAddress> getRemoteSocketAddresses(ContactId c) {
TransportProperties p = callback.getRemoteProperties().get(c);
if (p == null) return Collections.emptyList();
protected List<InetSocketAddress> getRemoteSocketAddresses(
TransportProperties p) {
InetSocketAddress parsed = parseSocketAddress(p.get(PROP_IP_PORT));
if (parsed == null) return Collections.emptyList();
return Collections.singletonList(parsed);

View File

@@ -160,35 +160,52 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
@Override
public Map<ContactId, TransportProperties> getRemoteProperties(
TransportId t) throws DbException {
Map<ContactId, TransportProperties> remote =
new HashMap<ContactId, TransportProperties>();
Transaction txn = db.startTransaction(true);
try {
Map<ContactId, TransportProperties> remote =
new HashMap<ContactId, TransportProperties>();
Transaction txn = db.startTransaction(true);
try {
for (Contact c : db.getContacts(txn)) {
// Don't return properties for inactive contacts
if (!c.isActive()) continue;
Group g = getContactGroup(c);
// Find the latest remote update
LatestUpdate latest = findLatest(txn, g.getId(), t, false);
if (latest != null) {
// Retrieve and parse the latest remote properties
BdfList message = clientHelper.getMessageAsList(txn,
latest.messageId);
if (message == null) throw new DbException();
remote.put(c.getId(), parseProperties(message));
}
}
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return remote;
for (Contact c : db.getContacts(txn))
remote.put(c.getId(), getRemoteProperties(txn, c, t));
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return remote;
}
private TransportProperties getRemoteProperties(Transaction txn, Contact c,
TransportId t) throws DbException {
// Don't return properties for inactive contacts
if (!c.isActive()) return new TransportProperties();
Group g = getContactGroup(c);
try {
// Find the latest remote update
LatestUpdate latest = findLatest(txn, g.getId(), t, false);
if (latest == null) return new TransportProperties();
// Retrieve and parse the latest remote properties
BdfList message =
clientHelper.getMessageAsList(txn, latest.messageId);
if (message == null) throw new DbException();
return parseProperties(message);
} catch (FormatException e) {
throw new DbException(e);
}
}
@Override
public TransportProperties getRemoteProperties(ContactId c, TransportId t)
throws DbException {
TransportProperties p;
Transaction txn = db.startTransaction(true);
try {
p = getRemoteProperties(txn, db.getContact(txn, c), t);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return p;
}
@Override
public void mergeLocalProperties(TransportId t, TransportProperties p)
throws DbException {

View File

@@ -20,7 +20,7 @@ import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageFactory;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Test;
@@ -65,7 +65,7 @@ public class ClientHelperImplTest extends BrambleTestCase {
new Message(messageId, groupId, timestamp, rawMessage);
private final Metadata metadata = new Metadata();
private final BdfList list = BdfList.of("Sign this!", getRandomBytes(42));
private final String label = TestUtils.getRandomString(5);
private final String label = StringUtils.getRandomString(5);
public ClientHelperImplTest() {
clientHelper =

View File

@@ -4,6 +4,7 @@ import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.TestSecureRandomProvider;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.junit.Test;
import java.util.Arrays;
@@ -15,7 +16,7 @@ public class HashTest extends BrambleTestCase {
private final CryptoComponent crypto;
private final String label = TestUtils.getRandomString(42);
private final String label = StringUtils.getRandomString(42);
private final byte[] inputBytes = TestUtils.getRandomBytes(123);
private final byte[] inputBytes1 = TestUtils.getRandomBytes(234);
private final byte[] inputBytes2 = new byte[0];
@@ -40,7 +41,7 @@ public class HashTest extends BrambleTestCase {
@Test
public void testDifferentLabelsProduceDifferentHashes() {
String label2 = TestUtils.getRandomString(42);
String label2 = StringUtils.getRandomString(42);
byte[] hash1 = crypto.hash(label, inputBytes, inputBytes1, inputBytes2);
byte[] hash2 =
crypto.hash(label2, inputBytes, inputBytes1, inputBytes2);

View File

@@ -5,6 +5,7 @@ import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.TestSecureRandomProvider;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.junit.Test;
import java.util.Arrays;
@@ -18,7 +19,7 @@ public class SignatureTest extends BrambleTestCase {
private final CryptoComponent crypto;
private final byte[] publicKey, privateKey;
private final String label = TestUtils.getRandomString(42);
private final String label = StringUtils.getRandomString(42);
private final byte[] inputBytes = TestUtils.getRandomBytes(123);
public SignatureTest() {
@@ -64,7 +65,7 @@ public class SignatureTest extends BrambleTestCase {
public void testDifferentLabelsProduceDifferentSignatures()
throws Exception {
// Generate a second label
String label2 = TestUtils.getRandomString(42);
String label2 = StringUtils.getRandomString(42);
// Calculate the signature with different inputs
// the results should be different
byte[] sig1 = crypto.sign(label, inputBytes, privateKey);
@@ -100,7 +101,7 @@ public class SignatureTest extends BrambleTestCase {
@Test
public void testDifferentLabelFailsVerification() throws Exception {
// Generate a second label
String label2 = TestUtils.getRandomString(42);
String label2 = StringUtils.getRandomString(42);
// calculate the signature with different label, should fail to verify
byte[] sig = crypto.sign(label, inputBytes, privateKey);
assertFalse(crypto.verify(label2, inputBytes, publicKey, sig));

View File

@@ -4,7 +4,6 @@ import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.junit.Test;
@@ -159,7 +158,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
@Test
public void testReadString8() throws Exception {
String longest = TestUtils.getRandomString(Byte.MAX_VALUE);
String longest = StringUtils.getRandomString(Byte.MAX_VALUE);
String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
// "foo", the empty string, and 127 random letters
setContents("41" + "03" + "666F6F" + "41" + "00" +
@@ -181,7 +180,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
@Test
public void testSkipString8() throws Exception {
String longest = TestUtils.getRandomString(Byte.MAX_VALUE);
String longest = StringUtils.getRandomString(Byte.MAX_VALUE);
String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
// "foo", the empty string, and 127 random letters
setContents("41" + "03" + "666F6F" + "41" + "00" +
@@ -194,9 +193,9 @@ public class BdfReaderImplTest extends BrambleTestCase {
@Test
public void testReadString16() throws Exception {
String shortest = TestUtils.getRandomString(Byte.MAX_VALUE + 1);
String shortest = StringUtils.getRandomString(Byte.MAX_VALUE + 1);
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
String longest = TestUtils.getRandomString(Short.MAX_VALUE);
String longest = StringUtils.getRandomString(Short.MAX_VALUE);
String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
// 128 random letters and 2^15 -1 random letters
setContents("42" + "0080" + shortHex + "42" + "7FFF" + longHex);
@@ -207,7 +206,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
@Test(expected = FormatException.class)
public void testReadString16ChecksMaxLength() throws Exception {
String shortest = TestUtils.getRandomString(Byte.MAX_VALUE + 1);
String shortest = StringUtils.getRandomString(Byte.MAX_VALUE + 1);
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
// 128 random letters, twice
setContents("42" + "0080" + shortHex + "42" + "0080" + shortHex);
@@ -218,9 +217,9 @@ public class BdfReaderImplTest extends BrambleTestCase {
@Test
public void testSkipString16() throws Exception {
String shortest = TestUtils.getRandomString(Byte.MAX_VALUE + 1);
String shortest = StringUtils.getRandomString(Byte.MAX_VALUE + 1);
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
String longest = TestUtils.getRandomString(Short.MAX_VALUE);
String longest = StringUtils.getRandomString(Short.MAX_VALUE);
String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
// 128 random letters and 2^15 - 1 random letters
setContents("42" + "0080" + shortHex + "42" + "7FFF" + longHex);
@@ -231,7 +230,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
@Test
public void testReadString32() throws Exception {
String shortest = TestUtils.getRandomString(Short.MAX_VALUE + 1);
String shortest = StringUtils.getRandomString(Short.MAX_VALUE + 1);
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
// 2^15 random letters
setContents("44" + "00008000" + shortHex);
@@ -241,7 +240,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
@Test(expected = FormatException.class)
public void testReadString32ChecksMaxLength() throws Exception {
String shortest = TestUtils.getRandomString(Short.MAX_VALUE + 1);
String shortest = StringUtils.getRandomString(Short.MAX_VALUE + 1);
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
// 2^15 random letters, twice
setContents("44" + "00008000" + shortHex +
@@ -253,7 +252,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
@Test
public void testSkipString32() throws Exception {
String shortest = TestUtils.getRandomString(Short.MAX_VALUE + 1);
String shortest = StringUtils.getRandomString(Short.MAX_VALUE + 1);
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
// 2^15 random letters, twice
setContents("44" + "00008000" + shortHex +

View File

@@ -81,7 +81,7 @@ public class BdfWriterImplTest extends BrambleTestCase {
@Test
public void testWriteString8() throws IOException {
String longest = TestUtils.getRandomString(Byte.MAX_VALUE);
String longest = StringUtils.getRandomString(Byte.MAX_VALUE);
String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
w.writeString("foo bar baz bam ");
w.writeString(longest);
@@ -93,9 +93,9 @@ public class BdfWriterImplTest extends BrambleTestCase {
@Test
public void testWriteString16() throws IOException {
String shortest = TestUtils.getRandomString(Byte.MAX_VALUE + 1);
String shortest = StringUtils.getRandomString(Byte.MAX_VALUE + 1);
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
String longest = TestUtils.getRandomString(Short.MAX_VALUE);
String longest = StringUtils.getRandomString(Short.MAX_VALUE);
String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
w.writeString(shortest);
w.writeString(longest);
@@ -106,7 +106,7 @@ public class BdfWriterImplTest extends BrambleTestCase {
@Test
public void testWriteString32() throws IOException {
String shortest = TestUtils.getRandomString(Short.MAX_VALUE + 1);
String shortest = StringUtils.getRandomString(Short.MAX_VALUE + 1);
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
w.writeString(shortest);
// STRING_32 tag, length 2^15, UTF-8 bytes

View File

@@ -2,6 +2,7 @@ package org.briarproject.bramble.db;
import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -48,8 +49,8 @@ public class BasicH2Test extends BrambleTestCase {
createTable(connection);
// Generate an ID and two names
byte[] id = TestUtils.getRandomId();
String oldName = TestUtils.getRandomString(50);
String newName = TestUtils.getRandomString(50);
String oldName = StringUtils.getRandomString(50);
String newName = StringUtils.getRandomString(50);
// Insert the ID and old name into the table
insertRow(id, oldName);
// Check that the old name can be retrieved using the ID
@@ -78,8 +79,8 @@ public class BasicH2Test extends BrambleTestCase {
String[] newNames = new String[BATCH_SIZE];
for (int i = 0; i < BATCH_SIZE; i++) {
ids[i] = TestUtils.getRandomId();
oldNames[i] = TestUtils.getRandomString(50);
newNames[i] = TestUtils.getRandomString(50);
oldNames[i] = StringUtils.getRandomString(50);
newNames[i] = StringUtils.getRandomString(50);
}
// Insert the IDs and old names into the table as a batch
insertBatch(ids, oldNames);

View File

@@ -49,6 +49,7 @@ import org.briarproject.bramble.api.transport.OutgoingKeys;
import org.briarproject.bramble.api.transport.TransportKeys;
import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Test;
@@ -94,7 +95,7 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
private final Contact contact;
public DatabaseComponentImplTest() {
clientId = new ClientId(TestUtils.getRandomString(5));
clientId = new ClientId(StringUtils.getRandomString(5));
groupId = new GroupId(TestUtils.getRandomId());
byte[] descriptor = new byte[MAX_GROUP_DESCRIPTOR_LENGTH];
group = new Group(groupId, clientId, descriptor);

View File

@@ -24,6 +24,7 @@ import org.briarproject.bramble.system.SystemClock;
import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.TestDatabaseConfig;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -84,7 +85,7 @@ public class H2DatabaseTest extends BrambleTestCase {
public H2DatabaseTest() throws Exception {
groupId = new GroupId(TestUtils.getRandomId());
clientId = new ClientId(TestUtils.getRandomString(5));
clientId = new ClientId(StringUtils.getRandomString(5));
byte[] descriptor = new byte[MAX_GROUP_DESCRIPTOR_LENGTH];
group = new Group(groupId, clientId, descriptor);
AuthorId authorId = new AuthorId(TestUtils.getRandomId());

View File

@@ -11,6 +11,7 @@ import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.jmock.Expectations;
import org.junit.Test;
@@ -31,8 +32,9 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
private final Transaction txn = new Transaction(null, false);
private final LocalAuthor localAuthor =
new LocalAuthor(new AuthorId(TestUtils.getRandomId()),
TestUtils.getRandomString(8), TestUtils.getRandomBytes(42),
TestUtils.getRandomBytes(42), 0);
StringUtils.getRandomString(8),
TestUtils.getRandomBytes(42), TestUtils.getRandomBytes(42),
0);
private final Collection<LocalAuthor> localAuthors =
Collections.singletonList(localAuthor);
@@ -93,7 +95,7 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
assertEquals(UNKNOWN, identityManager.getAuthorStatus(authorId));
// add one unverified contact
Author author = new Author(authorId, TestUtils.getRandomString(8),
Author author = new Author(authorId, StringUtils.getRandomString(8),
TestUtils.getRandomBytes(42));
Contact contact =
new Contact(new ContactId(1), author, localAuthor.getId(),

View File

@@ -311,6 +311,11 @@ public class LanTcpPluginTest extends BrambleTestCase {
return remote;
}
@Override
public TransportProperties getRemoteProperties(ContactId c) {
return remote.get(c);
}
@Override
public void mergeSettings(Settings s) {
}

View File

@@ -14,6 +14,7 @@ import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.jmock.Mockery;
import org.junit.Test;
@@ -36,7 +37,7 @@ public class TransportPropertyValidatorTest extends BrambleTestCase {
bdfDictionary = new BdfDictionary();
GroupId groupId = new GroupId(TestUtils.getRandomId());
ClientId clientId = new ClientId(TestUtils.getRandomString(5));
ClientId clientId = new ClientId(StringUtils.getRandomString(5));
byte[] descriptor = TestUtils.getRandomBytes(12);
group = new Group(groupId, clientId, descriptor);
@@ -85,7 +86,7 @@ public class TransportPropertyValidatorTest extends BrambleTestCase {
public void testValidateLongTransportId() throws IOException {
String wrongTransportIdString =
TestUtils.getRandomString(MAX_TRANSPORT_ID_LENGTH + 1);
StringUtils.getRandomString(MAX_TRANSPORT_ID_LENGTH + 1);
BdfList body = BdfList.of(wrongTransportIdString, 4, bdfDictionary);
tpv.validateMessage(message, group, body);
}

View File

@@ -22,6 +22,7 @@ import org.briarproject.bramble.api.transport.StreamReaderFactory;
import org.briarproject.bramble.api.transport.StreamWriterFactory;
import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.junit.Test;
import java.io.ByteArrayInputStream;
@@ -78,7 +79,7 @@ public class SyncIntegrationTest extends BrambleTestCase {
headerKey = TestUtils.getSecretKey();
streamNumber = 123;
// Create a group
ClientId clientId = new ClientId(TestUtils.getRandomString(5));
ClientId clientId = new ClientId(StringUtils.getRandomString(5));
byte[] descriptor = new byte[MAX_GROUP_DESCRIPTOR_LENGTH];
Group group = groupFactory.createGroup(clientId, descriptor);
// Add two messages to the group

View File

@@ -23,6 +23,7 @@ import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.ImmediateExecutor;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.ByteUtils;
import org.briarproject.bramble.util.StringUtils;
import org.jmock.Expectations;
import org.junit.Before;
import org.junit.Test;
@@ -51,7 +52,7 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
private final Executor dbExecutor = new ImmediateExecutor();
private final Executor validationExecutor = new ImmediateExecutor();
private final ClientId clientId =
new ClientId(TestUtils.getRandomString(5));
new ClientId(StringUtils.getRandomString(5));
private final MessageId messageId = new MessageId(TestUtils.getRandomId());
private final MessageId messageId1 = new MessageId(TestUtils.getRandomId());
private final MessageId messageId2 = new MessageId(TestUtils.getRandomId());

View File

@@ -9,6 +9,7 @@ import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.util.StringUtils;
public abstract class ValidatorTestCase extends BrambleMockTestCase {
@@ -28,7 +29,7 @@ public abstract class ValidatorTestCase extends BrambleMockTestCase {
protected final Message message =
new Message(messageId, groupId, timestamp, raw);
protected final ClientId clientId =
new ClientId(TestUtils.getRandomString(123));
new ClientId(StringUtils.getRandomString(123));
protected final byte[] descriptor = TestUtils.getRandomBytes(123);
protected final Group group = new Group(groupId, clientId, descriptor);

View File

@@ -5,7 +5,7 @@ targetCompatibility = 1.7
apply plugin: 'witness'
dependencies {
compile project(':bramble-core')
compile project(path: ':bramble-core', configuration: 'default')
compile fileTree(dir: 'libs', include: '*.jar')
compile 'net.java.dev.jna:jna:4.4.0'
compile 'net.java.dev.jna:jna-platform:4.4.0'

View File

@@ -249,8 +249,7 @@ class BluetoothPlugin implements DuplexPlugin {
@Override
public DuplexTransportConnection createConnection(ContactId c) {
if (!running) return null;
TransportProperties p = callback.getRemoteProperties().get(c);
if (p == null) return null;
TransportProperties p = callback.getRemoteProperties(c);
String address = p.get(PROP_ADDRESS);
if (StringUtils.isNullOrEmpty(address)) return null;
String uuid = p.get(PROP_UUID);

View File

@@ -145,8 +145,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
String fromIso = callback.getLocalProperties().get("iso3166");
if (StringUtils.isNullOrEmpty(fromIso)) return null;
// Get the ISO 3166 code for the callee's country
TransportProperties properties = callback.getRemoteProperties().get(c);
if (properties == null) return null;
TransportProperties properties = callback.getRemoteProperties(c);
String toIso = properties.get("iso3166");
if (StringUtils.isNullOrEmpty(toIso)) return null;
// Get the callee's phone number

View File

@@ -9,8 +9,6 @@ import org.jmock.Mockery;
import org.junit.Test;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@@ -65,12 +63,10 @@ public class ModemPluginTest extends BrambleTestCase {
final Modem modem = context.mock(Modem.class);
final TransportProperties local = new TransportProperties();
local.put("iso3166", ISO_1336);
TransportProperties p = new TransportProperties();
p.put("iso3166", ISO_1336);
p.put("number", NUMBER);
ContactId contactId = new ContactId(234);
final Map<ContactId, TransportProperties> remote =
Collections.singletonMap(contactId, p);
final TransportProperties remote = new TransportProperties();
remote.put("iso3166", ISO_1336);
remote.put("number", NUMBER);
final ContactId contactId = new ContactId(234);
context.checking(new Expectations() {{
// start()
oneOf(serialPortList).getPortNames();
@@ -82,7 +78,7 @@ public class ModemPluginTest extends BrambleTestCase {
// createConnection()
oneOf(callback).getLocalProperties();
will(returnValue(local));
oneOf(callback).getRemoteProperties();
oneOf(callback).getRemoteProperties(contactId);
will(returnValue(remote));
oneOf(modem).dial(NUMBER);
will(returnValue(true));
@@ -106,12 +102,10 @@ public class ModemPluginTest extends BrambleTestCase {
final Modem modem = context.mock(Modem.class);
final TransportProperties local = new TransportProperties();
local.put("iso3166", ISO_1336);
TransportProperties p = new TransportProperties();
p.put("iso3166", ISO_1336);
p.put("number", NUMBER);
ContactId contactId = new ContactId(234);
final Map<ContactId, TransportProperties> remote =
Collections.singletonMap(contactId, p);
final TransportProperties remote = new TransportProperties();
remote.put("iso3166", ISO_1336);
remote.put("number", NUMBER);
final ContactId contactId = new ContactId(234);
context.checking(new Expectations() {{
// start()
oneOf(serialPortList).getPortNames();
@@ -123,7 +117,7 @@ public class ModemPluginTest extends BrambleTestCase {
// createConnection()
oneOf(callback).getLocalProperties();
will(returnValue(local));
oneOf(callback).getRemoteProperties();
oneOf(callback).getRemoteProperties(contactId);
will(returnValue(remote));
oneOf(modem).dial(NUMBER);
will(returnValue(false));
@@ -147,12 +141,10 @@ public class ModemPluginTest extends BrambleTestCase {
final Modem modem = context.mock(Modem.class);
final TransportProperties local = new TransportProperties();
local.put("iso3166", ISO_1336);
TransportProperties p = new TransportProperties();
p.put("iso3166", ISO_1336);
p.put("number", NUMBER);
ContactId contactId = new ContactId(234);
final Map<ContactId, TransportProperties> remote =
Collections.singletonMap(contactId, p);
final TransportProperties remote = new TransportProperties();
remote.put("iso3166", ISO_1336);
remote.put("number", NUMBER);
final ContactId contactId = new ContactId(234);
context.checking(new Expectations() {{
// start()
oneOf(serialPortList).getPortNames();
@@ -164,7 +156,7 @@ public class ModemPluginTest extends BrambleTestCase {
// createConnection()
oneOf(callback).getLocalProperties();
will(returnValue(local));
oneOf(callback).getRemoteProperties();
oneOf(callback).getRemoteProperties(contactId);
will(returnValue(remote));
oneOf(modem).dial(NUMBER);
will(throwException(new IOException()));

View File

@@ -1,6 +1,6 @@
[main]
host = https://www.transifex.com
lang_map = pt_BR: pt-rBR, fr_FR: fr, nb_NO: nb
lang_map = pt_BR: pt-rBR, fr_FR: fr, nb_NO: nb, zh-Hans: zh-rCN
[briar.stringsxml-5]
file_filter = src/main/res/values-<lang>/strings.xml

View File

@@ -3,8 +3,8 @@ apply plugin: 'witness'
dependencies {
def supportVersion = '23.2.1'
compile project(':briar-core')
compile project(':bramble-android')
compile project(path: ':briar-core', configuration: 'default')
compile project(path: ':bramble-android', configuration: 'default')
compile "com.android.support:support-v4:$supportVersion"
compile("com.android.support:appcompat-v7:$supportVersion") {
exclude module: 'support-v4'
@@ -73,13 +73,13 @@ def getGitHash = { ->
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
buildToolsVersion '25.0.0'
defaultConfig {
minSdkVersion 14
targetSdkVersion 22
versionCode 1610
versionName "0.16.10"
versionCode 1611
versionName "0.16.11"
applicationId "org.briarproject.briar.beta"
resValue "string", "app_package", "org.briarproject.briar.beta"
resValue "string", "app_name", "Briar Beta"
@@ -107,6 +107,10 @@ android {
targetCompatibility JavaVersion.VERSION_1_7
}
aaptOptions {
cruncherEnabled = false
}
lintOptions {
warning 'MissingTranslation'
warning 'ImpliedQuantity'

View File

@@ -32,6 +32,11 @@
</intent-filter>
</service>
<service
android:name="org.briarproject.briar.android.NotificationCleanupService"
android:exported="false">
</service>
<activity
android:name="org.briarproject.briar.android.reporting.DevReportActivity"
android:excludeFromRecents="true"

View File

@@ -26,7 +26,6 @@ import org.briarproject.briar.BriarCoreEagerSingletons;
import org.briarproject.briar.BriarCoreModule;
import org.briarproject.briar.android.reporting.BriarReportSender;
import org.briarproject.briar.api.android.AndroidNotificationManager;
import org.briarproject.briar.api.android.ReferenceManager;
import org.briarproject.briar.api.android.ScreenFilterMonitor;
import org.briarproject.briar.api.blog.BlogManager;
import org.briarproject.briar.api.blog.BlogPostFactory;
@@ -44,6 +43,7 @@ import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
import org.briarproject.briar.api.privategroup.PrivateGroupManager;
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationFactory;
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager;
import org.briarproject.briar.api.test.TestDataCreator;
import org.thoughtcrime.securesms.components.emoji.EmojiProvider;
import org.thoughtcrime.securesms.components.emoji.RecentEmojiPageModel;
@@ -73,8 +73,6 @@ public interface AndroidComponent
DatabaseConfig databaseConfig();
ReferenceManager referenceMangager();
@DatabaseExecutor
Executor databaseExecutor();
@@ -140,6 +138,8 @@ public interface AndroidComponent
Clock clock();
TestDataCreator testDataCreator();
@IoExecutor
Executor ioExecutor();
@@ -151,6 +151,8 @@ public interface AndroidComponent
void inject(RecentEmojiPageModel recentEmojiPageModel);
void inject(NotificationCleanupService notificationCleanupService);
// Eager singleton load
void inject(AppModule.EagerSingletons init);
}

View File

@@ -2,6 +2,7 @@ package org.briarproject.briar.android;
import android.app.Application;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
@@ -83,16 +84,6 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
private static final int BLOG_POST_NOTIFICATION_ID = 6;
private static final int INTRODUCTION_SUCCESS_NOTIFICATION_ID = 7;
// Content URIs to differentiate between pending intents
private static final String CONTACT_URI =
"content://org.briarproject.briar/contact";
private static final String GROUP_URI =
"content://org.briarproject.briar/group";
private static final String FORUM_URI =
"content://org.briarproject.briar/forum";
private static final String BLOG_URI =
"content://org.briarproject.briar/blog";
private static final long SOUND_DELAY = TimeUnit.SECONDS.toMillis(2);
private static final Logger LOG =
@@ -268,7 +259,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
if (count == null) contactCounts.put(c, 1);
else contactCounts.put(c, count + 1);
contactTotal++;
updateContactNotification();
updateContactNotification(true);
}
});
}
@@ -281,13 +272,13 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
Integer count = contactCounts.remove(c);
if (count == null) return; // Already cleared
contactTotal -= count;
updateContactNotification();
updateContactNotification(false);
}
});
}
@UiThread
private void updateContactNotification() {
private void updateContactNotification(boolean mayAlertAgain) {
if (contactTotal == 0) {
clearContactNotification();
} else if (settings.getBoolean(PREF_NOTIFY_PRIVATE, true)) {
@@ -303,7 +294,8 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
boolean showOnLockScreen =
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
b.setLockscreenVisibility(CATEGORY_MESSAGE, showOnLockScreen);
playSound(b);
if (mayAlertAgain) setAlertProperties(b);
setDeleteIntent(b, CONTACT_URI);
if (contactCounts.size() == 1) {
// Touching the notification shows the relevant conversation
Intent i = new Intent(appContext, ConversationActivity.class);
@@ -333,17 +325,15 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
}
@UiThread
private void playSound(BriarNotificationBuilder b) {
boolean sound = settings.getBoolean(PREF_NOTIFY_SOUND, true);
if (!sound) return;
private void setAlertProperties(BriarNotificationBuilder b) {
long currentTime = clock.currentTimeMillis();
if (currentTime - lastSound > SOUND_DELAY) {
boolean sound = settings.getBoolean(PREF_NOTIFY_SOUND, true);
String ringtoneUri = settings.get(PREF_NOTIFY_RINGTONE_URI);
if (!StringUtils.isNullOrEmpty(ringtoneUri))
if (sound && !StringUtils.isNullOrEmpty(ringtoneUri))
b.setSound(Uri.parse(ringtoneUri));
b.setDefaults(getDefaults());
lastSound = clock.currentTimeMillis();
lastSound = currentTime;
}
}
@@ -359,6 +349,23 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
return defaults;
}
private void setDeleteIntent(BriarNotificationBuilder b, String uri) {
Intent i = new Intent(appContext, NotificationCleanupService.class);
i.setData(Uri.parse(uri));
b.setDeleteIntent(PendingIntent.getService(appContext, nextRequestId++,
i, 0));
}
@Override
public void clearAllContactNotifications() {
androidExecutor.runOnUiThread(new Runnable() {
@Override
public void run() {
clearContactNotification();
}
});
}
@UiThread
private void showGroupMessageNotification(final GroupId g) {
androidExecutor.runOnUiThread(new Runnable() {
@@ -370,7 +377,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
if (count == null) groupCounts.put(g, 1);
else groupCounts.put(g, count + 1);
groupTotal++;
updateGroupMessageNotification();
updateGroupMessageNotification(true);
}
});
}
@@ -383,13 +390,13 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
Integer count = groupCounts.remove(g);
if (count == null) return; // Already cleared
groupTotal -= count;
updateGroupMessageNotification();
updateGroupMessageNotification(false);
}
});
}
@UiThread
private void updateGroupMessageNotification() {
private void updateGroupMessageNotification(boolean mayAlertAgain) {
if (groupTotal == 0) {
clearGroupMessageNotification();
} else if (settings.getBoolean(PREF_NOTIFY_GROUP, true)) {
@@ -405,7 +412,8 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
boolean showOnLockScreen =
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
b.setLockscreenVisibility(CATEGORY_SOCIAL, showOnLockScreen);
playSound(b);
if (mayAlertAgain) setAlertProperties(b);
setDeleteIntent(b, GROUP_URI);
if (groupCounts.size() == 1) {
// Touching the notification shows the relevant group
Intent i = new Intent(appContext, GroupActivity.class);
@@ -435,6 +443,16 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
}
}
@Override
public void clearAllGroupMessageNotifications() {
androidExecutor.runOnUiThread(new Runnable() {
@Override
public void run() {
clearGroupMessageNotification();
}
});
}
@UiThread
private void showForumPostNotification(final GroupId g) {
androidExecutor.runOnUiThread(new Runnable() {
@@ -446,7 +464,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
if (count == null) forumCounts.put(g, 1);
else forumCounts.put(g, count + 1);
forumTotal++;
updateForumPostNotification();
updateForumPostNotification(true);
}
});
}
@@ -459,13 +477,13 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
Integer count = forumCounts.remove(g);
if (count == null) return; // Already cleared
forumTotal -= count;
updateForumPostNotification();
updateForumPostNotification(false);
}
});
}
@UiThread
private void updateForumPostNotification() {
private void updateForumPostNotification(boolean mayAlertAgain) {
if (forumTotal == 0) {
clearForumPostNotification();
} else if (settings.getBoolean(PREF_NOTIFY_FORUM, true)) {
@@ -481,7 +499,8 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
boolean showOnLockScreen =
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
b.setLockscreenVisibility(CATEGORY_SOCIAL, showOnLockScreen);
playSound(b);
if (mayAlertAgain) setAlertProperties(b);
setDeleteIntent(b, FORUM_URI);
if (forumCounts.size() == 1) {
// Touching the notification shows the relevant forum
Intent i = new Intent(appContext, ForumActivity.class);
@@ -511,6 +530,16 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
}
}
@Override
public void clearAllForumPostNotifications() {
androidExecutor.runOnUiThread(new Runnable() {
@Override
public void run() {
clearForumPostNotification();
}
});
}
@UiThread
private void showBlogPostNotification(final GroupId g) {
androidExecutor.runOnUiThread(new Runnable() {
@@ -522,7 +551,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
if (count == null) blogCounts.put(g, 1);
else blogCounts.put(g, count + 1);
blogTotal++;
updateBlogPostNotification();
updateBlogPostNotification(true);
}
});
}
@@ -535,13 +564,13 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
Integer count = blogCounts.remove(g);
if (count == null) return; // Already cleared
blogTotal -= count;
updateBlogPostNotification();
updateBlogPostNotification(false);
}
});
}
@UiThread
private void updateBlogPostNotification() {
private void updateBlogPostNotification(boolean mayAlertAgain) {
if (blogTotal == 0) {
clearBlogPostNotification();
} else if (settings.getBoolean(PREF_NOTIFY_BLOG, true)) {
@@ -557,7 +586,8 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
boolean showOnLockScreen =
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
b.setLockscreenVisibility(CATEGORY_SOCIAL, showOnLockScreen);
playSound(b);
if (mayAlertAgain) setAlertProperties(b);
setDeleteIntent(b, BLOG_URI);
// Touching the notification shows the combined blog feed
Intent i = new Intent(appContext, NavDrawerActivity.class);
i.putExtra(INTENT_BLOGS, true);
@@ -607,7 +637,8 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
boolean showOnLockScreen =
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
b.setLockscreenVisibility(CATEGORY_MESSAGE, showOnLockScreen);
playSound(b);
setAlertProperties(b);
setDeleteIntent(b, INTRODUCTION_URI);
// Touching the notification shows the contact list
Intent i = new Intent(appContext, NavDrawerActivity.class);
i.putExtra(INTENT_CONTACTS, true);
@@ -623,6 +654,16 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
nm.notify(INTRODUCTION_SUCCESS_NOTIFICATION_ID, b.build());
}
@Override
public void clearAllIntroductionNotifications() {
androidExecutor.runOnUiThread(new Runnable() {
@Override
public void run() {
clearIntroductionSuccessNotification();
}
});
}
@Override
public void blockNotification(final GroupId g) {
androidExecutor.runOnUiThread(new Runnable() {

View File

@@ -6,8 +6,8 @@ package org.briarproject.briar.android;
*/
public interface BriarApplication {
// This build expires on 21 October 2017
long EXPIRY_DATE = 1508544000 * 1000L;
// This build expires on 31 December 2017
long EXPIRY_DATE = 1514761200 * 1000L;
AndroidComponent getApplicationComponent();

View File

@@ -0,0 +1,53 @@
package org.briarproject.briar.android;
import android.app.IntentService;
import android.content.Intent;
import android.support.annotation.Nullable;
import org.briarproject.briar.api.android.AndroidNotificationManager;
import javax.inject.Inject;
import static org.briarproject.briar.api.android.AndroidNotificationManager.BLOG_URI;
import static org.briarproject.briar.api.android.AndroidNotificationManager.CONTACT_URI;
import static org.briarproject.briar.api.android.AndroidNotificationManager.FORUM_URI;
import static org.briarproject.briar.api.android.AndroidNotificationManager.GROUP_URI;
import static org.briarproject.briar.api.android.AndroidNotificationManager.INTRODUCTION_URI;
public class NotificationCleanupService extends IntentService {
private static final String TAG =
NotificationCleanupService.class.getName();
@Inject
AndroidNotificationManager notificationManager;
public NotificationCleanupService() {
super(TAG);
}
@Override
public void onCreate() {
super.onCreate();
AndroidComponent applicationComponent =
((BriarApplication) getApplication()).getApplicationComponent();
applicationComponent.inject(this);
}
@Override
protected void onHandleIntent(@Nullable Intent i) {
if (i == null || i.getData() == null) return;
String uri = i.getData().toString();
if (uri.equals(CONTACT_URI)) {
notificationManager.clearAllContactNotifications();
} else if (uri.equals(GROUP_URI)) {
notificationManager.clearAllGroupMessageNotifications();
} else if (uri.equals(FORUM_URI)) {
notificationManager.clearAllForumPostNotifications();
} else if (uri.equals(BLOG_URI)) {
notificationManager.clearAllBlogPostNotifications();
} else if (uri.equals(INTRODUCTION_URI)) {
notificationManager.clearAllIntroductionNotifications();
}
}
}

View File

@@ -51,6 +51,7 @@ import org.briarproject.briar.android.privategroup.reveal.GroupRevealModule;
import org.briarproject.briar.android.privategroup.reveal.RevealContactsActivity;
import org.briarproject.briar.android.privategroup.reveal.RevealContactsFragment;
import org.briarproject.briar.android.settings.SettingsActivity;
import org.briarproject.briar.android.settings.SettingsFragment;
import org.briarproject.briar.android.sharing.BlogInvitationActivity;
import org.briarproject.briar.android.sharing.BlogSharingStatusActivity;
import org.briarproject.briar.android.sharing.ForumInvitationActivity;
@@ -179,4 +180,6 @@ public interface ActivityComponent {
void inject(IntroductionMessageFragment fragment);
void inject(SettingsFragment fragment);
}

View File

@@ -10,5 +10,6 @@ public interface RequestCodes {
int REQUEST_WRITE_BLOG_POST = 6;
int REQUEST_SHARE_BLOG = 7;
int REQUEST_RINGTONE = 8;
int REQUEST_PERMISSION_CAMERA = 9;
}

View File

@@ -179,6 +179,8 @@ public class ContactListFragment extends BaseFragment implements EventListener {
public void onStart() {
super.onStart();
eventBus.addListener(this);
notificationManager.clearAllContactNotifications();
notificationManager.clearAllIntroductionNotifications();
loadContacts();
list.startPeriodicUpdate();
}

View File

@@ -119,6 +119,7 @@ public class ForumListFragment extends BaseEventFragment implements
@Override
public void onStart() {
super.onStart();
notificationManager.clearAllForumPostNotifications();
loadForums();
loadAvailableForums();
list.startPeriodicUpdate();

View File

@@ -1,6 +1,12 @@
package org.briarproject.briar.android.keyagreement;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
import android.support.annotation.UiThread;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog.Builder;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.widget.Toast;
@@ -19,19 +25,25 @@ import org.briarproject.bramble.api.keyagreement.event.KeyAgreementFinishedEvent
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.R.string;
import org.briarproject.briar.R.style;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
import org.briarproject.briar.android.keyagreement.IntroFragment.IntroScreenSeenListener;
import org.briarproject.briar.android.util.UiUtils;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.inject.Inject;
import static android.Manifest.permission.CAMERA;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.widget.Toast.LENGTH_LONG;
import static java.util.logging.Level.WARNING;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PERMISSION_CAMERA;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
@@ -51,6 +63,8 @@ public class KeyAgreementActivity extends BriarActivity implements
@Inject
volatile IdentityManager identityManager;
private boolean continueClicked, gotCameraPermission;
@Override
public void injectActivity(ActivityComponent component) {
component.inject(this);
@@ -96,10 +110,27 @@ public class KeyAgreementActivity extends BriarActivity implements
}
}
@Override
protected void onPostResume() {
super.onPostResume();
// Workaround for
// https://code.google.com/p/android/issues/detail?id=190966
if (continueClicked && gotCameraPermission) {
showQrCodeFragment();
}
}
@Override
public void showNextScreen() {
// FIXME #824
// showNextFragment(ShowQrCodeFragment.newInstance());
// showNextFragment(ShowQrCodeFragment.newInstance());
continueClicked = true;
if (checkPermissions()) {
showQrCodeFragment();
}
}
private void showQrCodeFragment() {
BaseFragment f = ShowQrCodeFragment.newInstance();
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragmentContainer, f, f.getUniqueTag())
@@ -107,6 +138,73 @@ public class KeyAgreementActivity extends BriarActivity implements
.commit();
}
private boolean checkPermissions() {
if (ContextCompat.checkSelfPermission(this, CAMERA) !=
PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
CAMERA)) {
OnClickListener continueListener = new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
requestPermission();
}
};
Builder builder = new Builder(this, style.BriarDialogTheme);
builder.setTitle(string.permission_camera_title);
builder.setMessage(string.permission_camera_request_body);
builder.setNeutralButton(string.continue_button,
continueListener);
builder.show();
} else {
requestPermission();
}
return false;
} else {
return true;
}
}
private void requestPermission() {
ActivityCompat.requestPermissions(this, new String[] {CAMERA},
REQUEST_PERMISSION_CAMERA);
}
@Override
@UiThread
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
if (requestCode == REQUEST_PERMISSION_CAMERA) {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 &&
grantResults[0] == PERMISSION_GRANTED) {
gotCameraPermission = true;
} else {
if (!ActivityCompat.shouldShowRequestPermissionRationale(this,
CAMERA)) {
// The user has permanently denied the request
OnClickListener cancelListener = new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
supportFinishAfterTransition();
}
};
Builder builder = new Builder(this, style.BriarDialogTheme);
builder.setTitle(string.permission_camera_title);
builder.setMessage(string.permission_camera_denied_body);
builder.setPositiveButton(string.ok,
UiUtils.getGoToSettingsListener(this));
builder.setNegativeButton(string.cancel, cancelListener);
builder.show();
} else {
Toast.makeText(this, string.permission_camera_denied_toast,
LENGTH_LONG).show();
supportFinishAfterTransition();
}
}
}
}
@Override
public void eventOccurred(Event e) {
if (e instanceof KeyAgreementFinishedEvent) {
@@ -189,5 +287,4 @@ public class KeyAgreementActivity extends BriarActivity implements
}
});
}
}

View File

@@ -22,6 +22,7 @@ import android.widget.Toast;
import com.google.zxing.Result;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.keyagreement.KeyAgreementTask;
import org.briarproject.bramble.api.keyagreement.KeyAgreementTaskFactory;
import org.briarproject.bramble.api.keyagreement.Payload;
@@ -36,7 +37,9 @@ import org.briarproject.bramble.api.keyagreement.event.KeyAgreementWaitingEvent;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.plugin.BluetoothEnableDisableReason;
import org.briarproject.bramble.api.plugin.event.DisableBluetoothEvent;
import org.briarproject.bramble.api.plugin.event.EnableBluetoothEvent;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseEventFragment;
@@ -73,10 +76,10 @@ public class ShowQrCodeFragment extends BaseEventFragment
@Inject
PayloadParser payloadParser;
@Inject
AndroidExecutor androidExecutor;
@Inject
@IoExecutor
Executor ioExecutor;
@Inject
EventBus eventBus;
private CameraView cameraView;
private View statusView;
@@ -114,6 +117,7 @@ public class ShowQrCodeFragment extends BaseEventFragment
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_keyagreement_qr, container,
false);
}
@@ -143,13 +147,11 @@ public class ShowQrCodeFragment extends BaseEventFragment
@Override
public void onStart() {
super.onStart();
try {
cameraView.start();
} catch (CameraException e) {
logCameraExceptionAndFinish(e);
}
// Listen for changes to the Bluetooth state
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_STATE_CHANGED);
@@ -157,15 +159,12 @@ public class ShowQrCodeFragment extends BaseEventFragment
getActivity().registerReceiver(receiver, filter);
// Enable BT adapter if it is not already on.
final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
final BluetoothAdapter adapter =
BluetoothAdapter.getDefaultAdapter();
if (adapter != null && !adapter.isEnabled()) {
waitingForBluetooth = true;
androidExecutor.runOnBackgroundThread(new Runnable() {
@Override
public void run() {
adapter.enable();
}
});
eventBus.broadcast(new EnableBluetoothEvent(
BluetoothEnableDisableReason.ADD_CONTACT));
} else {
startListening();
}
@@ -174,6 +173,14 @@ public class ShowQrCodeFragment extends BaseEventFragment
@Override
public void onStop() {
super.onStop();
//Disable BT adapter if we enabled it
final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if(adapter != null && adapter.isEnabled()){
eventBus.broadcast(new DisableBluetoothEvent(
BluetoothEnableDisableReason.ADD_CONTACT));
}
stopListening();
if (receiver != null) getActivity().unregisterReceiver(receiver);
try {
@@ -385,7 +392,6 @@ public class ShowQrCodeFragment extends BaseEventFragment
public void onReceive(Context ctx, Intent intent) {
int state = intent.getIntExtra(EXTRA_STATE, 0);
if (state == STATE_ON && waitingForBluetooth) {
LOG.info("Bluetooth enabled");
waitingForBluetooth = false;
startListening();
}

View File

@@ -34,6 +34,7 @@ import org.briarproject.briar.android.forum.ForumListFragment;
import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
import org.briarproject.briar.android.fragment.SignOutFragment;
import org.briarproject.briar.android.navdrawer.NavDrawerController.ExpiryWarning;
import org.briarproject.briar.android.privategroup.list.GroupListFragment;
import org.briarproject.briar.android.settings.SettingsActivity;
@@ -48,6 +49,8 @@ import static android.support.v4.view.GravityCompat.START;
import static android.support.v4.widget.DrawerLayout.LOCK_MODE_LOCKED_CLOSED;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import static org.briarproject.briar.android.navdrawer.NavDrawerController.ExpiryWarning.NO;
import static org.briarproject.briar.android.navdrawer.NavDrawerController.ExpiryWarning.UPDATE;
import static org.briarproject.briar.android.util.UiUtils.getDaysUntilExpiry;
public class NavDrawerActivity extends BriarActivity implements
@@ -83,7 +86,8 @@ public class NavDrawerActivity extends BriarActivity implements
} else if (intent.getBooleanExtra(INTENT_FORUMS, false)) {
startFragment(ForumListFragment.newInstance(), R.id.nav_btn_forums);
} else if (intent.getBooleanExtra(INTENT_CONTACTS, false)) {
startFragment(ContactListFragment.newInstance(), R.id.nav_btn_contacts);
startFragment(ContactListFragment.newInstance(),
R.id.nav_btn_contacts);
} else if (intent.getBooleanExtra(INTENT_BLOGS, false)) {
startFragment(FeedFragment.newInstance(), R.id.nav_btn_blogs);
}
@@ -121,7 +125,8 @@ public class NavDrawerActivity extends BriarActivity implements
transportsView.setAdapter(transportsAdapter);
if (state == null) {
startFragment(ContactListFragment.newInstance(), R.id.nav_btn_contacts);
startFragment(ContactListFragment.newInstance(),
R.id.nav_btn_contacts);
}
if (getIntent() != null) {
onNewIntent(getIntent());
@@ -132,10 +137,10 @@ public class NavDrawerActivity extends BriarActivity implements
public void onStart() {
super.onStart();
updateTransports();
controller.showExpiryWarning(new UiResultHandler<Boolean>(this) {
controller.showExpiryWarning(new UiResultHandler<ExpiryWarning>(this) {
@Override
public void onResultUi(Boolean showWarning) {
if (showWarning) showExpiryWarning();
public void onResultUi(ExpiryWarning expiry) {
if (expiry != NO) showExpiryWarning(expiry);
}
});
}
@@ -178,7 +183,7 @@ public class NavDrawerActivity extends BriarActivity implements
clearBackStack();
loadFragment(item.getItemId());
//Don't display the Settings Item as checked
if (item.getItemId() == R.id.nav_btn_settings){
if (item.getItemId() == R.id.nav_btn_settings) {
return false;
}
return true;
@@ -204,7 +209,8 @@ public class NavDrawerActivity extends BriarActivity implements
* exiting. This models the typical Google navigation behaviour such
* as in Gmail/Inbox.
*/
startFragment(ContactListFragment.newInstance(), R.id.nav_btn_contacts);
startFragment(ContactListFragment.newInstance(),
R.id.nav_btn_contacts);
} else {
super.onBackPressed();
}
@@ -228,7 +234,7 @@ public class NavDrawerActivity extends BriarActivity implements
signOut(false);
}
private void startFragment(BaseFragment fragment, int itemId){
private void startFragment(BaseFragment fragment, int itemId) {
navigation.setCheckedItem(itemId);
startFragment(fragment);
}
@@ -265,7 +271,7 @@ public class NavDrawerActivity extends BriarActivity implements
}
@SuppressWarnings("ConstantConditions")
private void showExpiryWarning() {
private void showExpiryWarning(ExpiryWarning expiry) {
int daysUntilExpiry = getDaysUntilExpiry();
if (daysUntilExpiry < 0) signOut();
@@ -274,13 +280,26 @@ public class NavDrawerActivity extends BriarActivity implements
expiryWarning = (ViewGroup) findViewById(R.id.expiryWarning);
TextView expiryWarningText =
(TextView) expiryWarning.findViewById(R.id.expiryWarningText);
expiryWarningText.setText(getResources()
.getQuantityString(R.plurals.expiry_warning, daysUntilExpiry,
daysUntilExpiry));
// make close button functional
ImageView expiryWarningClose =
(ImageView) expiryWarning.findViewById(R.id.expiryWarningClose);
// show a different snackbar in green if this is an update
if (expiry == UPDATE) {
expiryWarning.setBackgroundColor(
ContextCompat.getColor(this, R.color.briar_green_light));
expiryWarningText.setText(
getString(R.string.expiry_update, daysUntilExpiry));
expiryWarningText.setTextColor(
ContextCompat.getColor(this, android.R.color.black));
expiryWarningClose.setColorFilter(
ContextCompat.getColor(this, android.R.color.black));
} else {
expiryWarningText.setText(getResources()
.getQuantityString(R.plurals.expiry_warning,
daysUntilExpiry, daysUntilExpiry));
}
expiryWarningClose.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

View File

@@ -8,9 +8,11 @@ import org.briarproject.briar.android.controller.handler.ResultHandler;
@NotNullByDefault
public interface NavDrawerController extends ActivityLifecycleController {
enum ExpiryWarning { SHOW, NO, UPDATE };
boolean isTransportRunning(TransportId transportId);
void showExpiryWarning(final ResultHandler<Boolean> handler);
void showExpiryWarning(final ResultHandler<ExpiryWarning> handler);
void expiryWarningDismissed();

View File

@@ -28,6 +28,9 @@ import javax.inject.Inject;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static org.briarproject.briar.android.BriarApplication.EXPIRY_DATE;
import static org.briarproject.briar.android.navdrawer.NavDrawerController.ExpiryWarning.NO;
import static org.briarproject.briar.android.navdrawer.NavDrawerController.ExpiryWarning.SHOW;
import static org.briarproject.briar.android.navdrawer.NavDrawerController.ExpiryWarning.UPDATE;
import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
@MethodsNotNullByDefault
@@ -38,6 +41,7 @@ public class NavDrawerControllerImpl extends DbControllerImpl
private static final Logger LOG =
Logger.getLogger(NavDrawerControllerImpl.class.getName());
private static final String EXPIRY_DATE_WARNING = "expiryDateWarning";
private static final String EXPIRY_SHOW_UPDATE = "expiryShowUpdate";
private final PluginManager pluginManager;
private final SettingsManager settingsManager;
@@ -103,7 +107,7 @@ public class NavDrawerControllerImpl extends DbControllerImpl
}
@Override
public void showExpiryWarning(final ResultHandler<Boolean> handler) {
public void showExpiryWarning(final ResultHandler<ExpiryWarning> handler) {
runOnDbThread(new Runnable() {
@Override
public void run() {
@@ -111,10 +115,12 @@ public class NavDrawerControllerImpl extends DbControllerImpl
Settings settings =
settingsManager.getSettings(SETTINGS_NAMESPACE);
int warningInt = settings.getInt(EXPIRY_DATE_WARNING, 0);
boolean showUpdate =
settings.getBoolean(EXPIRY_SHOW_UPDATE, true);
if (warningInt == 0) {
// we have not warned before
handler.onResult(true);
handler.onResult(SHOW);
} else {
long warningLong = warningInt * 1000L;
long now = System.currentTimeMillis();
@@ -123,15 +129,16 @@ public class NavDrawerControllerImpl extends DbControllerImpl
long daysBeforeExpiry =
(EXPIRY_DATE - now) / 1000 / 60 / 60 / 24;
if (daysSinceLastWarning >= 30) {
handler.onResult(true);
return;
if (showUpdate) {
handler.onResult(UPDATE);
} else if (daysSinceLastWarning >= 30) {
handler.onResult(SHOW);
} else if (daysBeforeExpiry <= 3 &&
daysSinceLastWarning > 0) {
handler.onResult(SHOW);
} else {
handler.onResult(NO);
}
if (daysBeforeExpiry <= 3 && daysSinceLastWarning > 0) {
handler.onResult(true);
return;
}
handler.onResult(false);
}
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
@@ -150,6 +157,7 @@ public class NavDrawerControllerImpl extends DbControllerImpl
Settings settings = new Settings();
int date = (int) (System.currentTimeMillis() / 1000L);
settings.putInt(EXPIRY_DATE_WARNING, date);
settings.putBoolean(EXPIRY_SHOW_UPDATE, false);
settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE);
} catch (DbException e) {
if (LOG.isLoggable(WARNING))

View File

@@ -79,6 +79,7 @@ class GroupListControllerImpl extends DbControllerImpl
throw new IllegalStateException(
"GroupListListener needs to be attached");
eventBus.addListener(this);
notificationManager.clearAllGroupMessageNotifications();
}
@Override

View File

@@ -33,6 +33,7 @@ import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE;
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
import static android.content.Context.ACTIVITY_SERVICE;
import static android.content.Context.CONNECTIVITY_SERVICE;
import static android.content.Context.WIFI_P2P_SERVICE;
import static android.content.Context.WIFI_SERVICE;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIFI;
@@ -162,6 +163,12 @@ public class BriarReportPrimer implements ReportPrimer {
else wifiStatus += "not connected";
customData.put("Wi-Fi status", wifiStatus);
// Is wifi direct supported?
String wifiDirectStatus = "Supported";
if (ctx.getSystemService(WIFI_P2P_SERVICE) == null)
wifiDirectStatus = "Not supported";
customData.put("Wi-Fi Direct", wifiDirectStatus);
if (wm != null) {
WifiInfo wifiInfo = wm.getConnectionInfo();
if (wifiInfo != null) {
@@ -189,6 +196,13 @@ public class BriarReportPrimer implements ReportPrimer {
// Is Bluetooth discoverable?
boolean btDiscoverable = bt != null &&
bt.getScanMode() == SCAN_MODE_CONNECTABLE_DISCOVERABLE;
// Is Bluetooth LE scanning and advertising supported?
boolean btLeApi = false, btLeScan = false, btLeAdvertise = false;
if (bt != null && Build.VERSION.SDK_INT >= 21) {
btLeApi = true;
btLeScan = bt.getBluetoothLeScanner() != null;
btLeAdvertise = bt.getBluetoothLeAdvertiser() != null;
}
String btStatus;
if (btAvailable) btStatus = "Available, ";
@@ -200,6 +214,14 @@ public class BriarReportPrimer implements ReportPrimer {
if (btDiscoverable) btStatus += "discoverable";
else btStatus += "not discoverable";
customData.put("Bluetooth status", btStatus);
if (btLeApi) {
String btLeStatus;
if (btLeScan) btLeStatus = "Scanning, ";
else btLeStatus = "No scanning, ";
if (btLeAdvertise) btLeStatus += "advertising";
else btLeStatus += "no advertising";
customData.put("Bluetooth LE status", btLeStatus);
}
if (bt != null)
customData.put("Bluetooth address",

View File

@@ -4,24 +4,12 @@ import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.view.MenuItem;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.settings.SettingsManager;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
import javax.inject.Inject;
public class SettingsActivity extends BriarActivity {
@Inject
protected AndroidExecutor androidExecutor;
@Inject
protected SettingsManager settingsManager;
@Inject
protected EventBus eventBus;
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
@@ -40,18 +28,6 @@ public class SettingsActivity extends BriarActivity {
component.inject(this);
}
public AndroidExecutor getAndroidExecutor() {
return androidExecutor;
}
public SettingsManager getSettingsManager() {
return settingsManager;
}
public EventBus getEventBus() {
return eventBus;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {

View File

@@ -1,6 +1,5 @@
package org.briarproject.briar.android.settings;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.media.Ringtone;
@@ -12,9 +11,6 @@ import android.support.v7.preference.CheckBoxPreference;
import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceFragmentCompat;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.Toast;
import org.acra.ACRA;
@@ -25,7 +21,10 @@ import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.BluetoothConstants;
import org.briarproject.bramble.api.plugin.BluetoothEnableDisableReason;
import org.briarproject.bramble.api.plugin.TorConstants;
import org.briarproject.bramble.api.plugin.event.DisableBluetoothEvent;
import org.briarproject.bramble.api.plugin.event.EnableBluetoothEvent;
import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.settings.SettingsManager;
import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
@@ -33,10 +32,12 @@ import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.R;
import org.briarproject.briar.android.util.UserFeedback;
import org.briarproject.briar.android.widget.PreferenceDividerDecoration;
import org.briarproject.briar.api.test.TestDataCreator;
import java.util.logging.Logger;
import javax.inject.Inject;
import static android.app.Activity.RESULT_OK;
import static android.media.RingtoneManager.ACTION_RINGTONE_PICKER;
import static android.media.RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI;
@@ -53,6 +54,7 @@ import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PREF_BT_ENABLE;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_ALWAYS;
import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_RINGTONE;
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_BLOG;
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_FORUM;
@@ -77,7 +79,6 @@ public class SettingsFragment extends PreferenceFragmentCompat
Logger.getLogger(SettingsFragment.class.getName());
private SettingsActivity listener;
private AndroidExecutor androidExecutor;
private ListPreference enableBluetooth;
private ListPreference torNetwork;
private CheckBoxPreference notifyPrivateMessages;
@@ -90,18 +91,24 @@ public class SettingsFragment extends PreferenceFragmentCompat
private Preference notifySound;
// Fields that are accessed from background threads must be volatile
private volatile SettingsManager settingsManager;
private volatile EventBus eventBus;
private volatile Settings settings;
volatile Settings settings;
@Inject
volatile SettingsManager settingsManager;
@Inject
volatile EventBus eventBus;
@Inject
AndroidExecutor androidExecutor;
@Inject
TestDataCreator testDataCreator;
@Override
public void onAttach(Context context) {
super.onAttach(context);
listener = (SettingsActivity) context;
androidExecutor = listener.getAndroidExecutor();
settingsManager = listener.getSettingsManager();
eventBus = listener.getEventBus();
// we need to inject here,
// because onActivityCreated() is called after onCreatePreferences()
listener.getActivityComponent().inject(this);
}
@Override
@@ -170,17 +177,24 @@ public class SettingsFragment extends PreferenceFragmentCompat
}
});
loadSettings();
}
Preference testData = findPreference("pref_key_test_data");
if (IS_DEBUG_BUILD) {
testData.setOnPreferenceClickListener(
new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(
Preference preference) {
LOG.info("Creating test data");
testDataCreator.createTestData();
getActivity().finish();
return true;
}
});
} else {
testData.setVisible(false);
}
@Override
public RecyclerView onCreateRecyclerView(LayoutInflater inflater,
ViewGroup parent, Bundle savedInstanceState) {
RecyclerView list = super.onCreateRecyclerView(inflater, parent,
savedInstanceState);
list.addItemDecoration(
new PreferenceDividerDecoration(getContext()).drawBottom(true));
return list;
loadSettings();
}
@Override
@@ -210,7 +224,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
if (LOG.isLoggable(INFO))
LOG.info("Loading settings took " + duration + " ms");
boolean btSetting =
btSettings.getBoolean(PREF_BT_ENABLE, false);
btSettings.getBoolean(PREF_BT_ENABLE, true);
int torSetting = torSettings.getInt(PREF_TOR_NETWORK,
PREF_TOR_NETWORK_ALWAYS);
displaySettings(btSetting, torSetting);
@@ -312,17 +326,11 @@ public class SettingsFragment extends PreferenceFragmentCompat
return true;
}
private void enableOrDisableBluetooth(final boolean enable) {
final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter != null) {
androidExecutor.runOnBackgroundThread(new Runnable() {
@Override
public void run() {
if (enable) adapter.enable();
else adapter.disable();
}
});
}
private void enableOrDisableBluetooth(boolean enable) {
if (enable) eventBus.broadcast(new EnableBluetoothEvent(
BluetoothEnableDisableReason.COMMUNICATION));
else eventBus.broadcast(new DisableBluetoothEvent(
BluetoothEnableDisableReason.COMMUNICATION));
}
private void storeTorSettings(final int torSetting) {
@@ -428,4 +436,5 @@ public class SettingsFragment extends PreferenceFragmentCompat
}
}
}
}

View File

@@ -6,7 +6,6 @@ import android.support.annotation.ColorRes;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.NotificationCompat;
import static android.support.v4.app.NotificationCompat.CATEGORY_MESSAGE;
import static android.support.v4.app.NotificationCompat.VISIBILITY_PRIVATE;
import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET;
@@ -15,6 +14,8 @@ public class BriarNotificationBuilder extends NotificationCompat.Builder {
public BriarNotificationBuilder(Context context) {
super(context);
// Auto-cancel does not fire the delete intent, see
// https://issuetracker.google.com/issues/36961721
setAutoCancel(true);
}
@@ -27,10 +28,8 @@ public class BriarNotificationBuilder extends NotificationCompat.Builder {
boolean show) {
if (Build.VERSION.SDK_INT >= 21) {
setCategory(category);
if (show)
setVisibility(VISIBILITY_PRIVATE);
else
setVisibility(VISIBILITY_SECRET);
if (show) setVisibility(VISIBILITY_PRIVATE);
else setVisibility(VISIBILITY_SECRET);
}
return this;
}

View File

@@ -1,6 +1,11 @@
package org.briarproject.briar.android.util;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.net.Uri;
import android.support.design.widget.TextInputLayout;
import android.support.v4.app.FragmentManager;
import android.support.v4.content.ContextCompat;
@@ -18,12 +23,14 @@ import android.view.View;
import android.widget.TextView;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.briar.BuildConfig;
import org.briarproject.briar.R;
import org.briarproject.briar.android.view.ArticleMovementMethod;
import org.briarproject.briar.android.widget.LinkDialogFragment;
import javax.annotation.Nullable;
import static android.content.Intent.*;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
import static android.text.format.DateUtils.FORMAT_ABBREV_RELATIVE;
@@ -31,6 +38,7 @@ import static android.text.format.DateUtils.FORMAT_ABBREV_TIME;
import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
import static org.briarproject.briar.BuildConfig.*;
import static org.briarproject.briar.android.BriarApplication.EXPIRY_DATE;
public class UiUtils {
@@ -126,5 +134,19 @@ public class UiUtils {
public static String getBulbTransitionName(ContactId c) {
return "bulb" + c.getInt();
}
public static OnClickListener getGoToSettingsListener(
final Context context) {
return new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent i = new Intent();
i.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
i.addCategory(CATEGORY_DEFAULT);
i.setData(Uri.parse("package:" + APPLICATION_ID));
i.addFlags(FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
};
}
}

View File

@@ -1,181 +0,0 @@
package org.briarproject.briar.android.widget;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.support.annotation.DimenRes;
import android.support.annotation.DrawableRes;
import android.support.v4.content.ContextCompat;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceGroupAdapter;
import android.support.v7.preference.PreferenceScreen;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.TintTypedArray;
import android.view.View;
import org.briarproject.briar.R;
/**
* Use this class to add dividers between {@link Preference} items.
* <p/>
* Source: https://github.com/consp1racy/android-support-preference
* <br/>
* License: Apache License v2.0
*/
public class PreferenceDividerDecoration extends RecyclerView.ItemDecoration {
private boolean mDrawTop = false;
private boolean mDrawBottom = false;
private boolean mDrawBetweenItems = true;
private boolean mDrawBetweenCategories = true;
private Drawable mDivider;
private int mDividerHeight;
public PreferenceDividerDecoration(Drawable divider, int dividerHeight) {
mDivider = divider;
mDividerHeight = dividerHeight;
}
public PreferenceDividerDecoration(Context context,
@DrawableRes int divider, @DimenRes int dividerHeight) {
mDivider = ContextCompat.getDrawable(context, divider);
mDividerHeight =
context.getResources().getDimensionPixelSize(dividerHeight);
}
public PreferenceDividerDecoration(Context context) {
TintTypedArray a = TintTypedArray.obtainStyledAttributes(context, null,
new int[] {R.attr.dividerHorizontal});
mDivider = a.getDrawable(0);
a.recycle();
mDividerHeight = mDivider.getIntrinsicHeight();
}
public boolean getDrawTop() {
return mDrawTop;
}
/**
* Controls whether to draw divider above the first item.
*/
public PreferenceDividerDecoration drawTop(boolean drawTop) {
mDrawTop = drawTop;
return this;
}
public boolean getDrawBottom() {
return mDrawBottom;
}
/**
* Controls whether to draw divider at the bottom of the last item.
*/
public PreferenceDividerDecoration drawBottom(boolean drawBottom) {
mDrawBottom = drawBottom;
return this;
}
public boolean getDrawBetweenItems() {
return mDrawBetweenItems;
}
/**
* Controls whether to draw divider at the bottom of each
* {@link Preference} and {@link PreferenceScreen} item.
*/
public PreferenceDividerDecoration drawBetweenItems(
boolean drawBetweenItems) {
mDrawBetweenItems = drawBetweenItems;
return this;
}
public boolean getDrawBetweenCategories() {
return mDrawBetweenCategories;
}
/**
* Controls whether to draw divider above each {@link PreferenceGroup}
* usually {@link PreferenceCategory}.
*/
public PreferenceDividerDecoration drawBetweenCategories(
boolean drawBetweenCategories) {
mDrawBetweenCategories = drawBetweenCategories;
return this;
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent,
RecyclerView.State state) {
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
final PreferenceGroupAdapter adapter =
(PreferenceGroupAdapter) parent.getAdapter();
final int adapterCount = adapter.getItemCount();
boolean wasLastPreferenceGroup = false;
for (int i = 0, childCount = parent.getChildCount(); i < childCount;
i++) {
final View child = parent.getChildAt(i);
final int adapterPosition = parent.getChildAdapterPosition(child);
Preference preference = adapter.getItem(adapterPosition);
boolean skipNextAboveDivider = false;
if (adapterPosition == 0) {
if (mDrawTop) {
drawAbove(c, left, right, child);
}
skipNextAboveDivider = true;
}
if (preference instanceof PreferenceGroup
&& !(preference instanceof PreferenceScreen)) {
if (mDrawBetweenCategories) {
if (!skipNextAboveDivider) {
drawAbove(c, left, right, child);
skipNextAboveDivider = true;
}
}
wasLastPreferenceGroup = true;
} else {
if (mDrawBetweenItems && !wasLastPreferenceGroup) {
if (!skipNextAboveDivider) {
drawAbove(c, left, right, child);
skipNextAboveDivider = true;
}
}
wasLastPreferenceGroup = false;
}
if (adapterPosition == adapterCount - 1) {
if (mDrawBottom) {
drawBottom(c, left, right, child);
}
}
}
}
private void drawAbove(Canvas c, int left, int right, View child) {
final RecyclerView.LayoutParams params =
(RecyclerView.LayoutParams) child.getLayoutParams();
final int top = child.getTop() - params.topMargin - mDividerHeight;
final int bottom = top + mDividerHeight;
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
private void drawBottom(Canvas c, int left, int right, View child) {
final RecyclerView.LayoutParams params =
(RecyclerView.LayoutParams) child.getLayoutParams();
final int top =
child.getBottom() + params.bottomMargin - mDividerHeight;
final int bottom = top + mDividerHeight;
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}

View File

@@ -9,6 +9,7 @@ import org.briarproject.bramble.api.sync.GroupId;
*/
public interface AndroidNotificationManager {
// Keys for notification preferences
String PREF_NOTIFY_PRIVATE = "notifyPrivateMessages";
String PREF_NOTIFY_GROUP = "notifyGroupMessages";
String PREF_NOTIFY_FORUM = "notifyForumPosts";
@@ -20,16 +21,31 @@ public interface AndroidNotificationManager {
String PREF_NOTIFY_VIBRATION = "notifyVibration";
String PREF_NOTIFY_LOCK_SCREEN = "notifyLockScreen";
// Content URIs for pending intents
String CONTACT_URI = "content://org.briarproject.briar/contact";
String GROUP_URI = "content://org.briarproject.briar/group";
String FORUM_URI = "content://org.briarproject.briar/forum";
String BLOG_URI = "content://org.briarproject.briar/blog";
String INTRODUCTION_URI = "content://org.briarproject.briar/introduction";
void clearContactNotification(ContactId c);
void clearAllContactNotifications();
void clearGroupMessageNotification(GroupId g);
void clearAllGroupMessageNotifications();
void clearForumPostNotification(GroupId g);
void clearAllForumPostNotifications();
void clearBlogPostNotification(GroupId g);
void clearAllBlogPostNotifications();
void clearAllIntroductionNotifications();
void blockContactNotification(ContactId c);
void unblockContactNotification(ContactId c);

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<View xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/divider">
</View>

View File

@@ -20,6 +20,8 @@
android:background="@color/menu_background"
app:elevation="0dp"
app:headerLayout="@layout/navigation_header"
app:itemIconTint="@color/briar_text_primary"
app:itemTextColor="@color/briar_text_primary"
app:menu="@menu/navigation_drawer"/>
<View

View File

@@ -0,0 +1,366 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<!--Setup-->
<string name="setup_title">Briar регистрация</string>
<string name="setup_explanation">Briar профилът се съхранява криптиран във вашето устройство, а не в облака. Ако деинсталирате Briar или забравите паролата си, няма как да възстановите профила и данните си.</string>
<string name="choose_nickname">Изберете име</string>
<string name="choose_password">Изберете парола</string>
<string name="confirm_password">Потвърдете парола</string>
<string name="name_too_long">Името е твърде дълго</string>
<string name="password_too_weak">Паролата е твърде слаба</string>
<string name="passwords_do_not_match">Паролите не съвпадат</string>
<string name="create_account_button">Създаване на профил</string>
<!--Login-->
<string name="enter_password">Въведете парола:</string>
<string name="try_again">Грешна парола, опитайте пак</string>
<string name="sign_in_button">Вход</string>
<string name="forgotten_password">Забравена парола</string>
<string name="dialog_title_lost_password">Забравена парола</string>
<string name="dialog_message_lost_password">Briar профилът се съхранява криптиран във вашето устройство, не в облака, така че не можем да зададем нова парола. Искате ли да изтриете профила си и да започнете отначало?\n\nВнимание: Вашият профил, контакти и съобщения ще бъдат изтрити завинаги.</string>
<string name="startup_failed_notification_title">Briar не можа да стартира</string>
<string name="startup_failed_notification_text">Може да се наложи да преинсталирате Briar.</string>
<string name="startup_failed_activity_title">Неуспешно стартиране</string>
<string name="startup_failed_db_error">Вашата база данни на Briar е повредена непоправимо. Вашият профил, данни и всички контакти са унищожени. За съжаление се налага да преинсталирате Briar и да създадете нов профил.</string>
<string name="startup_failed_service_error">Briar не успя да стартира задължителен плъгин. Обикновено преинсталирането на Briar решава този проблем. Моля, имайте предвид, че ще изгубите профила си и всички данни, асоциирани с него, тъй като Briar не съхранява данните ви в централни сървъри.</string>
<plurals name="expiry_warning">
<item quantity="one">Това е бета версия на Briar. Профилът ви ще изгуби валидност след %d ден и не може да бъде подновен.</item>
<item quantity="other">Това е бета версия на Briar. Профилът ви ще изгуби валидност след %d дни и не може да бъде подновен.</item>
</plurals>
<string name="expiry_date_reached">Софтуерът е невалиден.\nБлагодарим ви за тестването!</string>
<!--Navigation Drawer-->
<string name="nav_drawer_open_description">Отвори навигационно чекмедже</string>
<string name="nav_drawer_close_description">Затвори навигационно чекмедже</string>
<string name="contact_list_button">Контакти</string>
<string name="groups_button">Частни групи</string>
<string name="forums_button">Форуми</string>
<string name="blogs_button">Блогове</string>
<string name="settings_button">Настройки</string>
<string name="sign_out_button">Отписване</string>
<!--Transports-->
<string name="transport_tor">Интернет</string>
<string name="transport_bt">Bluetooth</string>
<string name="transport_lan">Wi-Fi</string>
<!--Notifications-->
<string name="ongoing_notification_title">Вписан сте в Briar</string>
<string name="ongoing_notification_text">Докоснете, за да отворите Briar.</string>
<plurals name="private_message_notification_text">
<item quantity="one">Ново лично съобщение.</item>
<item quantity="other">%d нови лични съобщения.</item>
</plurals>
<plurals name="group_message_notification_text">
<item quantity="one">Ново групово съобщение.</item>
<item quantity="other">%d нови групови съобщения.</item>
</plurals>
<plurals name="forum_post_notification_text">
<item quantity="one">Нов форумен пост.</item>
<item quantity="other">%d нови форумни публикации.</item>
</plurals>
<plurals name="blog_post_notification_text">
<item quantity="one">Нов блог пост.</item>
<item quantity="other">%d нови блог публикации.</item>
</plurals>
<!--Misc-->
<string name="now">сега</string>
<string name="show">Покажи</string>
<string name="hide">Скрий</string>
<string name="ok">ОК</string>
<string name="cancel">Отказ</string>
<string name="got_it">Разбрах</string>
<string name="delete">Изтрий</string>
<string name="accept">Приеми</string>
<string name="decline">Откажи</string>
<string name="options">Опции</string>
<string name="online">Онлайн</string>
<string name="offline">Офлайн</string>
<string name="send">Изпрати</string>
<string name="allow">Позволи</string>
<string name="open">Отвори</string>
<string name="no_data">Няма данни</string>
<string name="ellipsis">...</string>
<string name="text_too_long">Въведеният текст е твърде дълъг</string>
<string name="show_onboarding">Показване на помощен диалог</string>
<!--Contacts and Private Conversations-->
<string name="no_contacts">Няма добавени контакти.\n\nНатиснете плюса и следвайте инструкциите, за да добавите приятели.\n\nВнимание: Трябва да се срещнете лично с човека, когото искате да добавите в Контакти. По този начин никой не може да се представи за вас или да чете съобщенията ви в бъдеще.</string>
<string name="date_no_private_messages">Няма съобщения.</string>
<string name="no_private_messages">Тук се показват съобщенията ви.\n\nНяма съобщения.</string>
<string name="message_hint">Напиши съобщение</string>
<string name="delete_contact">Изтрий контакт</string>
<string name="dialog_title_delete_contact">Потвърди изтриването на контакт</string>
<string name="dialog_message_delete_contact">Сигурни ли сте, че искате да изтриете този контакт и всички съобщения, обменени с този контакт?</string>
<string name="contact_deleted_toast">Контактът е изтрит</string>
<!--Adding Contacts-->
<string name="add_contact_title">Добавяне на контакт</string>
<string name="your_nickname">Изберете профил:</string>
<string name="face_to_face">Трябва да се срещнете лично с човека, когото искате да добавите в Контакти.\n\nПо този начин никой не може да се представи за вас или да чете съобщенията ви в бъдеще.</string>
<string name="continue_button">Напред</string>
<string name="your_invitation_code">Кодът ви за покана е</string>
<string name="enter_invitation_code">Моля, въведете кодът за покана на контакта ви:</string>
<string name="searching_format">Търсене на контакт с код за покана %06d\u2026</string>
<string name="connection_failed">Неуспешна връзка</string>
<string name="could_not_find_contact">Briar не можа да открие вашият контакт </string>
<string name="try_again_button">Опитай пак</string>
<string name="connected_to_contact">Свързан с контакт</string>
<string name="calculating_confirmation_code">Изчисляване на код за потвърждение\u2026</string>
<string name="your_confirmation_code">Кодът ви за потвърждение е</string>
<string name="enter_confirmation_code">Моля, въведете кодът за потвърждение на контакта ви</string>
<string name="waiting_for_contact">Изчакване на контакта\u2026</string>
<string name="waiting_for_contact_to_scan">Изчакване контактът да сканира и да се свърже\u2026</string>
<string name="exchanging_contact_details">Обмен на данни за контакт\u2026</string>
<string name="codes_do_not_match">Кодовете не съвпадат</string>
<string name="interfering">Това може да значи, че някой се опитва да попречи на свързването.</string>
<string name="contact_added_toast">Добавен конктакт: %s</string>
<string name="contact_already_exists">Контактът %s вече съществува</string>
<string name="contact_exchange_failed">Неуспех при обмен на контакти</string>
<string name="qr_code_invalid">QR кодът е невалиден</string>
<string name="connecting_to_device">Свързване с устройство\u2026</string>
<string name="authenticating_with_device">Удостоверяване с устройство\u2026</string>
<string name="connection_aborted_local">Връзката е прекъсната от нас! Това може да значи, че някой се опитва да попречи на свързването</string>
<string name="connection_aborted_remote">Връзката е прекъсната от контакта ви! Това може да значи, че някой се опитва да попречи на свързването</string>
<!--Introductions-->
<string name="introduction_onboarding_title">Представете контактите си</string>
<string name="introduction_onboarding_text">Можете да представите контактите си един на друг, за да не им се налага да се срещат лично, когато се свързват чрез Briar.</string>
<string name="introduction_activity_title">Избери контакт</string>
<string name="introduction_message_title">Представи контакти</string>
<string name="introduction_message_hint">Добавете съобщение (незадължително)</string>
<string name="introduction_button">Представи</string>
<string name="introduction_sent">Представянето ви е изпратено.</string>
<string name="introduction_error">Възникна грешка при представянето.</string>
<string name="introduction_response_error">Грешка при отговор на представянето</string>
<string name="introduction_request_sent">Помолихте да представите %1$s на %2$s.</string>
<string name="introduction_request_received">%1$s помоли да ви представи %2$s. Искате ли да добавите %2$s към контактите си?</string>
<string name="introduction_request_exists_received">%1$s помоли да ви представи на %2$s, но %2$s вече е в списъка ви с контакти. Тъй като %1$s може би не знае, все пак можете да отговорите:</string>
<string name="introduction_request_answered_received">%1$s помоли да ви представи на %2$s.</string>
<string name="introduction_response_accepted_sent">Приехте представянето на %1$s.</string>
<string name="introduction_response_declined_sent">Отказахте представянето на %1$s.</string>
<string name="introduction_response_accepted_received">%1$s прие представянето на %2$s.</string>
<string name="introduction_response_declined_received">%1$s отказа представянето на %2$s.</string>
<string name="introduction_response_declined_received_by_introducee">%1$s казва, че %2$s отказва представянето.</string>
<plurals name="introduction_notification_text">
<item quantity="one">Добавен нов контакт.</item>
<item quantity="other">%d добавени нови контакти.</item>
</plurals>
<!--Private Groups-->
<string name="groups_list_empty">Не сте включен в група.\n\nНатиснете плюса, за да създадете своя група, или помолете контактите си да ви добавят в техните групи.</string>
<string name="groups_created_by">Създаден от %s</string>
<plurals name="messages">
<item quantity="one">%d съобщение</item>
<item quantity="other">%d съобщения</item>
</plurals>
<string name="groups_group_is_empty">Групата е празна</string>
<string name="groups_group_is_dissolved">Групата се е разпаднала</string>
<string name="groups_remove">Премахни</string>
<string name="groups_create_group_title">Създаване на група</string>
<string name="groups_create_group_button">Създай група</string>
<string name="groups_create_group_invitation_button">Изпрати покана</string>
<string name="groups_create_group_hint">Изберете име за групата</string>
<string name="groups_invitation_sent">Поканата в група е изпратена</string>
<string name="groups_message_sent">Съобщението е изпратено</string>
<string name="groups_member_list">Списък с участници</string>
<string name="groups_invite_members">Поканете участници</string>
<string name="groups_member_created_you">Вие създадохте групата</string>
<string name="groups_member_created">%s създаде групата</string>
<string name="groups_member_joined_you">Включихте се в групата</string>
<string name="groups_member_joined">%s се включи в групата</string>
<string name="groups_leave">Напусни групата</string>
<string name="groups_leave_dialog_title">Потвърждение на напускането</string>
<string name="groups_leave_dialog_message">Сигурни ли сте, че искате да напуснете тази група?</string>
<string name="groups_dissolve">Затвори групата</string>
<string name="groups_dissolve_dialog_title">Потвърди затварянето на групата</string>
<string name="groups_dissolve_dialog_message">Сигурни ли сте, че искате да затворите групата?\n\nВсички други участници няма да могат да продължат разговора и може да не получат най-новите съобщения. </string>
<string name="groups_dissolve_button">Затвори</string>
<string name="groups_dissolved_dialog_title">Групата е затворена</string>
<string name="groups_dissolved_dialog_message">Групата е затворена от създателя.\n\nНе можете да пишете нови съобщения в груповия чат и може да не получите най-новите съобщения. </string>
<!--Private Group Invitations-->
<string name="groups_invitations_title">Покани в група</string>
<string name="groups_invitations_invitation_sent">Поканихте %1$s в групата \"%2$s\"</string>
<string name="groups_invitations_invitation_received">%1$s ви покани в групата \"%2$s\".</string>
<string name="groups_invitations_joined">Включихте се в групата</string>
<string name="groups_invitations_declined">Отказана покана в група</string>
<plurals name="groups_invitations_open">
<item quantity="one">%d отворена покана в група</item>
<item quantity="other">%d отворени покани в група</item>
</plurals>
<string name="groups_invitations_response_accepted_sent">Приехте поканата в група на %s.</string>
<string name="groups_invitations_response_declined_sent">Отказахте поканата в група на %s.</string>
<string name="groups_invitations_response_accepted_received">%s прие поканата в група.</string>
<string name="groups_invitations_response_declined_received">%s отказа поканата в група. </string>
<string name="sharing_status_groups">Само създателят може да покани нови участници в групата. По-долу са изброени сегашните участници в групата.</string>
<!--Private Groups Revealing Contacts-->
<string name="groups_reveal_contacts">Разкрий контакти</string>
<string name="groups_reveal_dialog_message">Може да изберете да разкриете контактите на всички сегашни и бъдещи участници в тази група.\n\nРазкриването на контактите прави връзката с групата по-бърза и сигурна, тъй като можете да общувате с разкрити контакти, дори когато създателят на групата е офлайн.</string>
<string name="groups_reveal_visible">Връзка с контакта се вижда от групата</string>
<string name="groups_reveal_visible_revealed_by_us">Връзка с контакта се вижда от групата (разкрита от вас)</string>
<string name="groups_reveal_visible_revealed_by_contact">Връзка с контакта се вижда от групата (разкрита от %s)</string>
<string name="groups_reveal_invisible">Връзка с контакта не се вижда от групата</string>
<!--Forums-->
<string name="no_forums">Няма добавени форуми.\n\nНатиснете плюса, за да създадете нов форум.\n\nМожете също да помолите контактите си да споделят форуми с вас.</string>
<string name="create_forum_title">Създаване на форум</string>
<string name="choose_forum_hint">Изберете име за форума</string>
<string name="create_forum_button">Създай форум</string>
<string name="forum_created_toast">Форумът е създаден</string>
<string name="no_forum_posts">Форумът е празен.\n\nВъведете текст, за да съставите първата публикация.\n\nСподелете този форум с други ваши контакти!</string>
<string name="no_posts">Няма публикации</string>
<plurals name="posts">
<item quantity="one">%d публикация</item>
<item quantity="other">%d публикации</item>
</plurals>
<string name="forum_new_entry_posted">Публикувано</string>
<string name="forum_new_message_hint">Нова публикация</string>
<string name="forum_message_reply_hint">Нов отговор</string>
<string name="btn_reply">Отговори</string>
<string name="forum_leave">Напусни форума</string>
<string name="dialog_title_leave_forum">Потвърдете напускането на форума</string>
<string name="dialog_message_leave_forum">Сигурни ли сте, че искате да напуснете този форум? Контактите, с които сте споделили този форум, ще престанат да получават ъпдейти от него.</string>
<string name="dialog_button_leave">Напусни</string>
<string name="forum_left_toast">Напуснахте форума</string>
<!--Forum Sharing-->
<string name="forum_share_button">Сподели форум</string>
<string name="contacts_selected">Избрани контакти</string>
<string name="activity_share_toolbar_header">Избиране на контакти</string>
<string name="no_contacts_selector">Няма добавени контакти.\n\nМоля, върнете се тук, когато добавите първия си контакт.</string>
<string name="forum_shared_snackbar">Форумът е споделен с избраните контакти</string>
<string name="forum_share_message">Добавете съобщение (незадължително)</string>
<string name="forum_share_error">Възникна грешка при споделянето на този форум.</string>
<string name="forum_invitation_received">%1$s сподели форума \"%2$s\" с вас.</string>
<string name="forum_invitation_sent">Споделихте форума \"%1$s\" с %2$s.</string>
<string name="forum_invitations_title">Покани във форум</string>
<string name="forum_invitation_exists">Вече приехте поканата за този форум. Приемането на още покани ще подпомогне развитието на форума. </string>
<string name="forum_joined_toast">Включихте се във форума</string>
<string name="forum_declined_toast">Поканата във форум е отказана</string>
<string name="shared_by_format">Споделен от %s</string>
<string name="forum_invitation_already_sharing">Вече е споделен</string>
<string name="forum_invitation_response_accepted_sent">Приехте поканата за форум на %s.</string>
<string name="forum_invitation_response_declined_sent">Отказахте поканата във форум от %s.</string>
<string name="forum_invitation_response_accepted_received">%s прие поканата във форум.</string>
<string name="forum_invitation_response_declined_received">%s отказа поканата във форум.</string>
<string name="sharing_status">Статус на споделянето</string>
<string name="sharing_status_forum">Всеки участник във форума може да го сподели с контактите си. Споделяте този форум със следните контакти. Възможно е да има и други, които не можете да видите.</string>
<string name="shared_with">Споделен с %1$d (%2$d онлайн)</string>
<plurals name="forums_shared">
<item quantity="one">%d форум, споделен от контакти</item>
<item quantity="other">%d форума, споделени от контакти</item>
</plurals>
<string name="nobody">Никого</string>
<!--Blogs-->
<string name="blogs_other_blog_empty_state">Блогът е празен.\n\nИли авторът още не е публикувал нищо, или е нужно да е онлайн човекът, който е споделил този блог с вас, за да се синхронизират публикациите.</string>
<string name="read_more">прочети още</string>
<string name="blogs_write_blog_post">Нова блог публикация</string>
<string name="blogs_write_blog_post_body_hint">Въведете новата публикация тук</string>
<string name="blogs_publish_blog_post">Публикуване</string>
<string name="blogs_blog_post_created">Блог публикацията е създадена</string>
<string name="blogs_blog_post_received">Нова блог публикация</string>
<string name="blogs_feed_empty_state">Това е глобалната блог емисия.\n\nНикой още не е публикувал нищо.\n\nБъдете първия и натиснете писалката, за да напишете първата блог публикация.</string>
<string name="blogs_remove_blog">Премахване на блог</string>
<string name="blogs_remove_blog_dialog_message">Сигурни ли сте, че искате да премахнете този блог и всички публикации?\nБлогът няма да бъдат премахнат от устройствата на други хора.</string>
<string name="blogs_remove_blog_ok">Премахни блог</string>
<string name="blogs_blog_removed">Блогът е премахнат</string>
<string name="blogs_reblog_comment_hint">Добавете съобщение (незадължително)</string>
<string name="blogs_reblog_button">Реблог</string>
<!--Blog Sharing-->
<string name="blogs_sharing_share">Споделяне на блог</string>
<string name="blogs_sharing_error">Възникна грешка при споделянето на този блог.</string>
<string name="blogs_sharing_button">Сподели блог</string>
<string name="blogs_sharing_snackbar">Блогът е споделен с избраните контакти</string>
<string name="blogs_sharing_response_accepted_sent">Приехте поканата в блог от %s.</string>
<string name="blogs_sharing_response_declined_sent">Отказахте поканата в блог от %s.</string>
<string name="blogs_sharing_response_accepted_received">%s прие поканата в блог.</string>
<string name="blogs_sharing_response_declined_received">%s отказа поканата в блог.</string>
<string name="blogs_sharing_invitation_received">%1$s сподели блога \"%2$s\" с вас.</string>
<string name="blogs_sharing_invitation_sent">Споделихте блога \"%1$s\" с %2$s.</string>
<string name="blogs_sharing_invitations_title">Блог покани</string>
<string name="blogs_sharing_joined_toast">Абонирахте се за блога</string>
<string name="blogs_sharing_declined_toast">Поканата в блог е отказана</string>
<string name="sharing_status_blog">Всеки абонат на блога може да го сподели с контактите си. Споделяте този блог със следните контакти. Възможно е да има и други, които не можете да видите.</string>
<!--RSS Feeds-->
<string name="blogs_rss_feeds_import">Внасяне на RSS емисия</string>
<string name="blogs_rss_feeds_import_button">Внасяне</string>
<string name="blogs_rss_feeds_import_hint">Въведете URL адреса на RSS емисията</string>
<string name="blogs_rss_feeds_import_error">Възникна грешка при внасянето на емисия.</string>
<string name="blogs_rss_feeds_manage">Управление на RSS емисии</string>
<string name="blogs_rss_feeds_manage_imported">Внесена:</string>
<string name="blogs_rss_feeds_manage_author">Автор:</string>
<string name="blogs_rss_feeds_manage_updated">Последно актуализиране:</string>
<string name="blogs_rss_remove_feed">Премахване на емисия</string>
<string name="blogs_rss_remove_feed_dialog_message">Сигурни ли сте, че искате да премахнете тази емисия и всички нейни публикации?\nВсички споделени от вас публикации няма да бъдат премахнати от устройствата на други хора.</string>
<string name="blogs_rss_remove_feed_ok">Емисията е премахната</string>
<string name="blogs_rss_feeds_manage_delete_error">Емисията не можа да бъде изтрита!</string>
<string name="blogs_rss_feeds_manage_empty_state">Нямате добавени RSS емисии.\n\nНатиснете плюса в горния десен ъгъл на екрана, за да добавите нова емисия.</string>
<string name="blogs_rss_feeds_manage_error">Възникна проблем при зареждането на емисиите ви. Моля, опитайте пак по-късно.</string>
<!--Settings Network-->
<string name="network_settings_title">Мрежа</string>
<string name="bluetooth_setting">Свързване чрез Bluetooth</string>
<string name="bluetooth_setting_enabled">Когато контактите са наблизо</string>
<string name="bluetooth_setting_disabled">Само при добавяне на контакти</string>
<string name="tor_network_setting">Свързване чрез Tor</string>
<string name="tor_network_setting_never">Никога</string>
<string name="tor_network_setting_wifi">Само при активна Wi-Fi връзка</string>
<string name="tor_network_setting_always">През Wi-Fi или мобилни данни</string>
<!--Settings Security and Panic-->
<string name="security_settings_title">Сигурност</string>
<string name="change_password">Промяна на паролата</string>
<string name="current_password">Въведете сегашната си парола:</string>
<string name="choose_new_password">Изберете нова парола:</string>
<string name="confirm_new_password">Потвърдете нова парола:</string>
<string name="password_changed">Паролата е променена.</string>
<string name="panic_setting">Настройка на паник бутон</string>
<string name="panic_setting_title">Паник бутон</string>
<string name="panic_setting_hint">Конфигурация на приложение за паник бутон</string>
<string name="panic_app_setting_title">Приложение за паник бутон</string>
<string name="unknown_app">непознато приложение</string>
<string name="panic_app_setting_summary">Няма зададено приложение</string>
<string name="panic_app_setting_none">Няма</string>
<string name="dialog_title_connect_panic_app">Потвърждение на паник приложение</string>
<string name="dialog_message_connect_panic_app">Сигурни ли сте, че искате да позволите на %1$s да задейства унищожителни действия на паник бутон?</string>
<string name="lock_setting_title">Отписване</string>
<string name="lock_setting_summary">Отписване от Briar, ако паник бутонът е натиснат</string>
<string name="purge_setting_title">Изтриване на профил</string>
<string name="purge_setting_summary">Изтриване на Briar профила, ако паник бутонът е натиснат. Внимание: Изтрива завинаги вашия профил, контакти и съобщения</string>
<string name="uninstall_setting_title">Деинсталиране на Briar</string>
<string name="uninstall_setting_summary">Изисква ръчно потвърждение в паник случай</string>
<!--Settings Notifications-->
<string name="notification_settings_title">Известия</string>
<string name="notify_private_messages_setting_title">Лични съобщения</string>
<string name="notify_private_messages_setting_summary">Показвай известия за лични съобщения</string>
<string name="notify_group_messages_setting_title">Групови съобщения</string>
<string name="notify_group_messages_setting_summary">Показвай известия за групови съобщения</string>
<string name="notify_forum_posts_setting_title">Форумни публикации</string>
<string name="notify_forum_posts_setting_summary">Показвай известия за форумни публикации</string>
<string name="notify_blog_posts_setting_title">Блог публикации</string>
<string name="notify_blog_posts_setting_summary">Показвай известия за блог публикации</string>
<string name="notify_vibration_setting">Вибрация</string>
<string name="notify_lock_screen_setting_title">Заключен екран</string>
<string name="notify_lock_screen_setting_summary">Показвай известия за на заключен екран</string>
<string name="notify_sound_setting">Звук</string>
<string name="notify_sound_setting_default">Мелодия по подразбиране</string>
<string name="notify_sound_setting_disabled">Никакви</string>
<string name="choose_ringtone_title">Изберете рингтон</string>
<!--Settings Feedback-->
<string name="feedback_settings_title">Отзиви</string>
<string name="send_feedback">Изпращане на отзиви</string>
<!--Link Warning-->
<string name="link_warning_title">Предупреждение за линк</string>
<string name="link_warning_intro">Линкът ще се отвори във външно приложение.</string>
<string name="link_warning_text">Линкът може да се използва, за да ви идентифицира. Помислете дали имате доверие на човека, който ви изпраща линка, и обмислете дали да не го отворите с Orfox.</string>
<string name="link_warning_open_link">Отвори линк</string>
<!--Crash Reporter-->
<string name="crash_report_title">Доклад на срив</string>
<string name="briar_crashed">Извинете, Briar се срина.</string>
<string name="not_your_fault">Не е по ваша вина.</string>
<string name="please_send_report">Моля, помогнете да изградим по-добър Briar, като ни изпратите доклад.</string>
<string name="report_is_encrypted">Гарантираме, че докладът е криптиран и изпратен безопасно.</string>
<string name="feedback_title">Отзиви</string>
<string name="describe_crash">Опишете станалото (незадължително)</string>
<string name="enter_feedback">Въведете отзив</string>
<string name="optional_contact_email">Имейл адресът ви (незадължително)</string>
<string name="include_debug_report_crash">Добави анонимни данни за срива</string>
<string name="include_debug_report_feedback">Добави анонимни данни за това устройствo</string>
<string name="could_not_load_report_data">Данните за доклада не можаха да заредят.</string>
<string name="send_report">Изпращане на доклад</string>
<string name="close">Затваряне</string>
<string name="dev_report_saved">Докладът е запазен. Ще бъде изпратен при следващото влизане в Briar.</string>
<!--Sign Out-->
<string name="progress_title_logout">Отписване от Briar...</string>
<!--Screen Filters & Tapjacking-->
<string name="screen_filter_title">Открит е овърлей на екрана</string>
<string name="screen_filter_body">Друго приложение чертае върху Briar. За да защити вашата сигурност, Briar няма да реагира на докосване, докато друго приложение чертае отгоре.\n\nОпитайте да изключите следните приложения, когато използвате Briar:\n\n%1$s</string>
</resources>

View File

@@ -0,0 +1,222 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<!--Setup-->
<string name="setup_title">Configuració de Briar</string>
<string name="setup_explanation">El teu compte de Briar està encriptat al teu dispositiu, no al núvol. Si desinstal·les Briar o oblides la contrasenya, no hi ha manera de recuperar el teu compte i les teves dades.</string>
<string name="choose_nickname">Trieu el sobrenom</string>
<string name="choose_password">Trieu la contrasenya</string>
<string name="confirm_password">Confirmeu la contrasenya</string>
<string name="name_too_long">El nom és massa llarg</string>
<string name="password_too_weak">La contrasenya és dèbil</string>
<string name="passwords_do_not_match">Les contrasenyes no coincideixen</string>
<string name="create_account_button">Crear compte</string>
<!--Login-->
<string name="enter_password">Introdueix la teva contrasenya:</string>
<string name="try_again">La contrasenya és incorrecta, torna-ho a provar</string>
<string name="sign_in_button">Inicia la sessió</string>
<string name="forgotten_password">He oblidat la contrasenya</string>
<string name="dialog_title_lost_password">Contrasenya perduda</string>
<string name="dialog_message_lost_password">El vostre compte de Briar s\'emmagatzema xifrat al vostre dispositiu, no al núvol; per tant no podem restaurar-ne la contrasenya. Voleu esborrar el compte i tornar a començar?\n\nAlerta: les vostres identitats, contactes i missatges es perdran per sempre.</string>
<string name="startup_failed_notification_title">Briar no s\'ha pogut iniciar</string>
<string name="startup_failed_notification_text">Potser us caldrà reinstal·lar Briar.</string>
<string name="startup_failed_activity_title">Error iniciant Briar</string>
<string name="startup_failed_db_error">Per algun motiu, la vostra base de dades de Briar s\'ha corromput i no té solució. El vostre compte, les vostres dades i totes les connexions s\'han perdut. Malauradament, haureu de reinstal·lar i configurar un compte nou.</string>
<string name="startup_failed_service_error">Briar no ha pogut engegar un plugin necessari. La sol.lució sol ser reinstal.lar Briar. De tota manera, tingueu en compte que si ho feu perdreu el vostre compte i totes les dades associades, doncs Briar no usa servidors centrals per desar les vostres dades.</string>
<plurals name="expiry_warning">
<item quantity="one">Això és una versió beta de Briar. El teu compte expirarà en %d dia i no pot ser renovat.</item>
<item quantity="other">Això és una versió beta de Briar. El teu compte expirarà en %d dies i no pot ser renovat.</item>
</plurals>
<string name="expiry_date_reached">Aquest programa ha caducat.\nGràcies per haver-lo provat!</string>
<!--Navigation Drawer-->
<string name="nav_drawer_open_description">Obre el calaix de navegació</string>
<string name="nav_drawer_close_description">Tanca el calaix de navegació</string>
<string name="contact_list_button">Contactes</string>
<string name="groups_button">Grups privats</string>
<string name="forums_button">Fòrums</string>
<string name="blogs_button">Blogs</string>
<string name="settings_button">Configuració</string>
<string name="sign_out_button">Tanca la sessió </string>
<!--Transports-->
<string name="transport_tor">Internet</string>
<string name="transport_bt">Bluetooth</string>
<string name="transport_lan">Wi-Fi</string>
<!--Notifications-->
<string name="ongoing_notification_title">Sessió iniciada</string>
<string name="ongoing_notification_text">Toca per a obrir Briar.</string>
<plurals name="private_message_notification_text">
<item quantity="one">Missatge privat nou.</item>
<item quantity="other">1%d missatges privats nous.</item>
</plurals>
<plurals name="group_message_notification_text">
<item quantity="one">Missatge de grup nou.</item>
<item quantity="other">1%d missatges de grup nous</item>
</plurals>
<!--Misc-->
<string name="now">Ara</string>
<string name="show">Mostrar</string>
<string name="hide">Ocultar</string>
<string name="ok">D\'acord</string>
<string name="cancel">Cancel·la</string>
<string name="got_it">D\'acord</string>
<string name="delete">Suprimeix</string>
<string name="accept">Accepta</string>
<string name="decline">Rebutja</string>
<string name="options">Opcions</string>
<string name="online">En línia</string>
<string name="offline">Fora de línia</string>
<string name="send">Envia</string>
<string name="allow">Permet</string>
<string name="open">Obre</string>
<string name="no_data">Sense dades</string>
<string name="ellipsis">...</string>
<string name="text_too_long">El text introduït és massa llarg</string>
<string name="show_onboarding">Mostra el diàleg d\'ajuda.</string>
<!--Contacts and Private Conversations-->
<string name="no_contacts">Sembla que sou nouvingut i no teniu contactes encara.\n\nToqueu la icona + en la part superior i seguiu les instruccions per a afegir amics a la llista.\n\nRecordeu: afegiu només contactes cara a cara per a evitar que algú es faça passar per vós o pugui llegir els vostres missatges en el futur. </string>
<string name="date_no_private_messages">Sense missatges.</string>
<string name="message_hint">Escriu el missatge.</string>
<string name="delete_contact">Suprimeix contacte</string>
<string name="dialog_title_delete_contact">Confirma la supressió del contacte</string>
<string name="dialog_message_delete_contact">Estàs segur que vols esborrar aquest contacte i tots els missatges que hi has intercanviat?</string>
<string name="contact_deleted_toast">Contacte suprimit</string>
<!--Adding Contacts-->
<string name="add_contact_title">Afegir contacte</string>
<string name="your_nickname">Escull la identitat que vols utilitzar:</string>
<string name="face_to_face">T\'has de trobar amb la persona que vols afegir com a contacte.\n\nAixò evitarà que algú suplanti la teva identitat o llegeixi els teus missatges.</string>
<string name="continue_button">Continua</string>
<string name="your_invitation_code">El teu codi d\'invitació és</string>
<string name="enter_invitation_code">Si us plau, entra el codi d\'invitació del teu contacte:</string>
<string name="searching_format">Cercant el contacte amb codi d\'invitació %06d\u2026</string>
<string name="connection_failed">La connexió ha fallat</string>
<string name="could_not_find_contact">Briar no ha pogut trobar el teu contacte aprop</string>
<string name="try_again_button">Torna-ho a provar</string>
<string name="connected_to_contact">Connectat amb el contacte</string>
<string name="calculating_confirmation_code">Calculant el codi de confirmació\u2026</string>
<string name="your_confirmation_code">El teu codi de confirmació és</string>
<string name="enter_confirmation_code">Si us plau entra el codi de confirmació del teu contacte:</string>
<string name="waiting_for_contact">Esperant el contacte\u2026</string>
<string name="waiting_for_contact_to_scan">Esperant que el teu contacte escanegi i connecti\u2026</string>
<string name="exchanging_contact_details">Intercanviant els detalls del contacte\u2026</string>
<string name="codes_do_not_match">Els codis no coincideixen</string>
<string name="interfering">Això pot significar que algú està intentant interferir la teva connexió</string>
<string name="contact_added_toast">Contacte afegit: %s</string>
<string name="contact_already_exists">El contacte %s ja existeix</string>
<string name="contact_exchange_failed">L\'intercanvi de contactes ha fallat</string>
<string name="qr_code_invalid">El codi QR és invàlid</string>
<string name="connecting_to_device">Connectant al dispositiu\u2026</string>
<string name="authenticating_with_device">Autenticant-se amb el dispositiu\u2026</string>
<string name="connection_aborted_local">Hem avortat la connexió! Això podria significar que algú està provant d\'interferir la vostra connexió</string>
<string name="connection_aborted_remote">El teu contacte ha avortat la connexió! Això podria significar que algú està provant d\'interferir la vostra connexió</string>
<!--Introductions-->
<string name="introduction_onboarding_title">Introdueix els teus contactes</string>
<string name="introduction_onboarding_text">Pots presentar els teus contactes entre si, de manera que no necessiten trobar-se en persona per a donar-se d\'alta com a contactes a Briar.</string>
<string name="introduction_activity_title">Seleccionar contacte</string>
<string name="introduction_message_title">Introduir contacte</string>
<string name="introduction_message_hint">Afegir un missatge (opcional)</string>
<string name="introduction_button">Presentar contactes entre si</string>
<string name="introduction_sent">S\'ha enviat la teva presentació.</string>
<string name="introduction_error">Hi ha hagut un error al fer la presentació de contactes.</string>
<string name="introduction_response_error">Error en respondre a la presentació</string>
<string name="introduction_response_accepted_sent">Has acceptat la presentació amb el contacte %1$s.</string>
<!--Private Groups-->
<string name="groups_list_empty">No pertanyeu a cap grup.\n\nToqueu la icona + en la part superior per a crear un grup o demaneu als vostres contactes que us conviden a un grup.</string>
<string name="groups_created_by">Creat per 1%s</string>
<plurals name="messages">
<item quantity="one">1%d missatge</item>
<item quantity="other">1%d missatges</item>
</plurals>
<string name="groups_group_is_empty">Aquest grup està buit.</string>
<string name="groups_group_is_dissolved">Aquest grup s\'ha dissolt.</string>
<string name="groups_remove">Suprimeix</string>
<string name="groups_create_group_title">Crea un Grup Privat</string>
<string name="groups_create_group_button">Crea un Grup</string>
<string name="groups_create_group_invitation_button">Envia una invitació</string>
<string name="groups_create_group_hint">Tria un nom per al teu grup privat</string>
<string name="groups_invitation_sent">S\'ha enviat la invitació del grup</string>
<string name="groups_message_sent">Missatge enviat</string>
<string name="groups_member_list">Llistat de membres</string>
<string name="groups_invite_members">Convida membres</string>
<string name="groups_member_created_you">Has creat el grup</string>
<string name="groups_member_created">%s ha creat el grup</string>
<string name="groups_member_joined_you">T\'has unit al grup</string>
<string name="groups_member_joined">%s s\'ha unit al grup</string>
<string name="groups_leave">Deixar el Grup</string>
<string name="groups_leave_dialog_title">Confirma que deixes el Grup</string>
<string name="groups_leave_dialog_message">Estàs segur que vols deixar aquest grup?</string>
<string name="groups_dissolve">Dissoldre el grup</string>
<string name="groups_dissolve_dialog_title">Confirma la dissolució del grup</string>
<string name="groups_dissolve_dialog_message">Esteu segur que voleu dissoldre aquest grup?\n\nCap altre membre podrà continuar la conversa i podrien no rebre els darrers missatges.</string>
<string name="groups_dissolve_button">Dissoldre</string>
<string name="groups_dissolved_dialog_title">S\'ha dissolt el Grup</string>
<string name="groups_dissolved_dialog_message">El creador del grup l\'ha dissolt.\n\nJa no hi podeu escriure missatges i podríeu no rebre tots els missatges que s\'hi havien escrit.</string>
<!--Private Group Invitations-->
<string name="groups_invitations_title">Invitacions al grup</string>
<string name="groups_invitations_invitation_sent">Heu convidat a 1%1$s al grup \"%2$s \".</string>
<string name="groups_invitations_invitation_received">1%1$s us ha convidat a unir-vos al grup \" 2%2$s \".</string>
<string name="sharing_status_groups">Només el creador del grup pot convidar a nous membres. Tot seguit hi ha la llista dels membres del grup.</string>
<!--Private Groups Revealing Contacts-->
<!--Forums-->
<string name="no_forums">No teniu cap fòrum encara.\n\nPer què no en creeu un de nou tocant el + que hi ha a la part superior dreta?\n\nTambé podeu demanar els vostres contactes que us conviden a fòrums.</string>
<string name="create_forum_title">Crea un fòrum</string>
<string name="choose_forum_hint">Trieu un nom per al fòrum</string>
<string name="create_forum_button">Crea el fòrum</string>
<string name="forum_created_toast">S\'ha creat el fòrum</string>
<string name="no_posts">No hi ha publicacions</string>
<plurals name="posts">
<item quantity="one">%d publicacio</item>
<item quantity="other">%d publicacions</item>
</plurals>
<string name="forum_new_entry_posted">Entrada publicada al fòrum</string>
<string name="forum_new_message_hint">Entrada nova</string>
<string name="forum_message_reply_hint">Resposta nova</string>
<string name="btn_reply">Respon</string>
<string name="forum_leave">Abandona el fòrum</string>
<string name="dialog_title_leave_forum">Confirmeu la sortida del Forum</string>
<string name="dialog_message_leave_forum">Esteu segur que voleu sotir del fòrum? Els contactes amb qui heu compartit aquest fòrum podrien deixar de rebre\'n actualitzacions</string>
<!--Forum Sharing-->
<string name="activity_share_toolbar_header">Tria contactes</string>
<string name="forum_share_message">Afegiu un missatge (opcional)</string>
<!--Blogs-->
<string name="read_more">llegir més</string>
<!--Blog Sharing-->
<!--RSS Feeds-->
<string name="blogs_rss_feeds_import_button">Importa</string>
<string name="blogs_rss_feeds_manage_imported">Importat:</string>
<string name="blogs_rss_feeds_manage_author">Autor:</string>
<!--Settings Network-->
<string name="bluetooth_setting">Connecta via bluetooth</string>
<string name="tor_network_setting">Connecta via Tor</string>
<string name="tor_network_setting_never">Mai</string>
<string name="tor_network_setting_wifi">Només amb WiFi</string>
<!--Settings Security and Panic-->
<string name="security_settings_title">Seguretat</string>
<string name="change_password">Canvia la contrasenya</string>
<string name="current_password">Introduïu la contrasenya actual:</string>
<string name="choose_new_password">Escriviu la contrasenya nova:</string>
<string name="confirm_new_password">Confirmeu la contrasenya nova:</string>
<string name="password_changed">Heu canviat la contrasenya.</string>
<string name="panic_setting">Configuració del botó del pànic</string>
<string name="panic_setting_title">Botó de pànic</string>
<string name="panic_setting_hint">Configureu com reaccionarà Briar quan feu servir una aplicació del pànic</string>
<string name="lock_setting_title">Tanca la sessió</string>
<string name="purge_setting_title">Esborra el compte</string>
<string name="uninstall_setting_title">Desinstal·la Briar</string>
<!--Settings Notifications-->
<string name="notification_settings_title">Notificacions</string>
<string name="notify_private_messages_setting_title">Missatges privats</string>
<string name="notify_vibration_setting">Vibra</string>
<string name="notify_lock_screen_setting_title">Bloca la pantalla</string>
<string name="notify_sound_setting">So</string>
<!--Settings Feedback-->
<!--Link Warning-->
<string name="link_warning_intro">L\'enllaç s\'obrirà amb una aplicació externa.</string>
<string name="link_warning_text">Açò podria usar-se per a identificar-vos. Penseu si confieu prou en la persona que us ha enviat l\'enllaç i si convindria obrir-lo amb Orfox.</string>
<string name="link_warning_open_link">Obri l\'enllaç</string>
<!--Crash Reporter-->
<string name="optional_contact_email">La vostra adreça de correu (opcional)</string>
<string name="include_debug_report_feedback">Inclou dades anònimes sobre el dispositiu</string>
<string name="send_report">Envia l\'informe</string>
<string name="close">Tanca</string>
<!--Sign Out-->
<!--Screen Filters & Tapjacking-->
</resources>

View File

@@ -174,7 +174,7 @@
<string name="groups_invitations_title">Invitaciones de grupo</string>
<string name="groups_invitations_invitation_sent">Has invitado a %1$s a ingresar en el grupo «%2$s».</string>
<string name="groups_invitations_invitation_received">%1$s te ha invitado a unirte al grupo «%2$s».</string>
<string name="groups_invitations_joined">Te uniste al grupo</string>
<string name="groups_invitations_joined">Te has unido al grupo</string>
<string name="groups_invitations_declined">Invitación de grupo declinada</string>
<plurals name="groups_invitations_open">
<item quantity="one">%d invitación de grupo sin responder</item>

View File

@@ -0,0 +1,367 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<!--Setup-->
<string name="setup_title">Briar ezarpena</string>
<string name="setup_explanation">Zure Briar kontua zure gailuan zifratuta gordetzen da, ez hodeian. Briar desinstalatzen baduzu edo pasahitza ahazten baduzu, ez dago zure kontua eta datuak berreskuratzeko modurik.</string>
<string name="choose_nickname">Hautatu zure ezizena</string>
<string name="choose_password">Hautatu zure pasahitza</string>
<string name="confirm_password">Berretsi zure pasahitza</string>
<string name="name_too_long">Izena luzeegia da</string>
<string name="password_too_weak">Pasahitza ahulegia da</string>
<string name="passwords_do_not_match">Pasahitzak ez datoz bat</string>
<string name="create_account_button">Sortu kontua</string>
<!--Login-->
<string name="enter_password">Sartu zure pasahitza:</string>
<string name="try_again">Pasahitz okerra, saiatu berriro</string>
<string name="sign_in_button">Hasi saioa</string>
<string name="forgotten_password">Nire pasahitza ahaztu dut</string>
<string name="dialog_title_lost_password">Pasahitz galdua</string>
<string name="dialog_message_lost_password">Zure Briar kontua zure gailuan zifratuta gordetzen da, ez hodeian, beraz ezin dugu zure pasahitza berrezarri. Zure kontua ezabatu eta berriro hasi nahi duzu?\n\nKontuz: Zure identitateak, kontaktuak eta mezuak betirako galduko dira.</string>
<string name="startup_failed_notification_title">Ezin izan da Briar abiatu</string>
<string name="startup_failed_notification_text">Agian Briar berrinstalatu behar duzu.</string>
<string name="startup_failed_activity_title">Briar abio-hutsegitea</string>
<string name="startup_failed_db_error">Arrazoiren bategatik, zure Briar datubasea hondatuta dago eta ezin da konpondu. Zure kontua, datuak eta kontaktuekin konexioak galdu dira. Zoritxarrez Briar berrinstalatu behar duzu kontu berria sortzeko.</string>
<string name="startup_failed_service_error">Briar aplikazioak ezin izan du ezinbesteko plugin bat abiatu. Briar berrinstalatzeak arazoa konpondu ohi du. Hala ere, jakin zure kontua eta datuak galduko dituzula Briar aplikazioak ez baititu zerbitzari zentralak erabiltzen zure datuak gordetzeko.</string>
<plurals name="expiry_warning">
<item quantity="one">Hau Briar aplikazioaren beta bertsio bat da. Zure kontua egun %d barru iraungitu da eta ezin da berritu.</item>
<item quantity="other">Hau Briar aplikazioaren beta bertsio bat da. Zure kontua %d egun barru iraungitu da eta ezin da berritu.</item>
</plurals>
<string name="expiry_date_reached">Programa hau iraungitu da.\nEskerrik asko probatzeagatik!</string>
<!--Navigation Drawer-->
<string name="nav_drawer_open_description">Ireki nabigazio tiradera</string>
<string name="nav_drawer_close_description">Itxi nabigazio tiradera</string>
<string name="contact_list_button">Kontaktuak</string>
<string name="groups_button">Talde pribatuak</string>
<string name="forums_button">Foroak</string>
<string name="blogs_button">Blogak</string>
<string name="settings_button">Ezarpenak</string>
<string name="sign_out_button">Amaitu saioa</string>
<!--Transports-->
<string name="transport_tor">Internet</string>
<string name="transport_bt">Bluetooth</string>
<string name="transport_lan">Wi-Fi</string>
<!--Notifications-->
<string name="ongoing_notification_title">Briar saioa hasita</string>
<string name="ongoing_notification_text">Ukitu Briar irekitzeko</string>
<plurals name="private_message_notification_text">
<item quantity="one">Mezu pribatu berri bat.</item>
<item quantity="other">%d mezu pribatu berri.</item>
</plurals>
<plurals name="group_message_notification_text">
<item quantity="one">Talde mezu berri bat.</item>
<item quantity="other">%d talde mezu berri.</item>
</plurals>
<plurals name="forum_post_notification_text">
<item quantity="one">Foro sarrera berri bat.</item>
<item quantity="other">%d foro sarrera berri.</item>
</plurals>
<plurals name="blog_post_notification_text">
<item quantity="one">Blog sarrera berri bat.</item>
<item quantity="other">%d blog sarrera berri.</item>
</plurals>
<!--Misc-->
<string name="now">orain</string>
<string name="show">Erakutsi</string>
<string name="hide">Ezkutatu</string>
<string name="ok">Ados</string>
<string name="cancel">Utzi</string>
<string name="got_it">Ulertu dut</string>
<string name="delete">Ezabatu</string>
<string name="accept">Onartu</string>
<string name="decline">Ukatu</string>
<string name="options">Aukerak</string>
<string name="online">Konektatuta</string>
<string name="offline">Deskonektatuta</string>
<string name="send">Bidali</string>
<string name="allow">Baimendu</string>
<string name="open">Ireki</string>
<string name="no_data">Daturik ez</string>
<string name="ellipsis"></string>
<string name="text_too_long">Sartutako testua luzeegia da</string>
<string name="show_onboarding">Erakutsi laguntza elkarrizketa-koadroa</string>
<!--Contacts and Private Conversations-->
<string name="no_contacts">Badirudi heldu berria zarela eta ez duzula kontakturik hemen oraindik.\n\nSakatu goiko + ikonoa eta jarraitu argibideak lagunak zure zerrendara gehitzeko.\nGogoratu: Kontaktu berriak aurrez aurre besterik ezin dira gehitu beste inork zure itxurak ez egiteko edo zure mezuak ez irakurtzeko.</string>
<string name="date_no_private_messages">Mezurik ez.</string>
<string name="no_private_messages">Hau elkarrizketa ikuspegia da.\n\nBadirudi ez dagoela elkarrizketarik.\n\nSakatu beheko sarrera eremua elkarrizketa hasteko.</string>
<string name="message_hint">Idatzi mezua</string>
<string name="delete_contact">Ezabatu kontaktua</string>
<string name="dialog_title_delete_contact">Berretsi kontaktua ezabatzea</string>
<string name="dialog_message_delete_contact">Ziur kontaktu hau eta berarekin trukatutako mezu guztiak mezu guztiak kendu nahi dituzula?</string>
<string name="contact_deleted_toast">Kontaktua ezabatuta</string>
<!--Adding Contacts-->
<string name="add_contact_title">Gehitu kontaktua</string>
<string name="your_nickname">Hautatu erabili nahi duzun identitatea:</string>
<string name="face_to_face">Aurrez aurre aurkitu behar zara pertsonarekin kontaktua gehitzeko.\n\nHonek inork zure itxurak egitea edo zure mezuak irakurtzea eragotziko du.</string>
<string name="continue_button">Jarraitu</string>
<string name="your_invitation_code">Zure gonbidapen kodea hau da</string>
<string name="enter_invitation_code">Sartu zure gonbidapen kodea:</string>
<string name="searching_format">%06d gonbidapen kodea duen erabiltzailea bilatzen\u2026</string>
<string name="connection_failed">Konexioak huts egin du</string>
<string name="could_not_find_contact">Briar aplikazioak ezin izan du zure kontaktua inguruan aurkitu</string>
<string name="try_again_button">Saiatu berriro</string>
<string name="connected_to_contact">Kontaktura konektatuta</string>
<string name="calculating_confirmation_code">Berreste kode kalkulatzen\u2026</string>
<string name="your_confirmation_code">Zure berreste kodea hau da:</string>
<string name="enter_confirmation_code">Sartu zure kontaktuaren berreste kodea:</string>
<string name="waiting_for_contact">Kontaktuaren zain\u2026</string>
<string name="waiting_for_contact_to_scan">Kontaktuak eskaneatu dezan eta konektatu dadin zain\u2026</string>
<string name="exchanging_contact_details">Kontaktu-xehetasunak trukatzen\u2016</string>
<string name="codes_do_not_match">Kodeak ez datoz bat</string>
<string name="interfering">Norbait zure konexioan interferentziak sortzen saiatzen ari dela esan nahi lezake</string>
<string name="contact_added_toast">Kontaktua gehituta: %s</string>
<string name="contact_already_exists">%s kontaktua badago aurretik</string>
<string name="contact_exchange_failed">Kontaktuen trukeak huts egin du</string>
<string name="qr_code_invalid">QR kodea baliogabea da</string>
<string name="connecting_to_device">Gailura konektatzen\u2026</string>
<string name="authenticating_with_device">Gailuarekin autentifikatzen\u2026</string>
<string name="connection_aborted_local">Guk eten dugu konexioa! Norbait zure konexioan interferentziak sortzen saiatzen ari dela esan nahi lezake</string>
<string name="connection_aborted_remote">Zure kontaktuak eten du konexioa! Norbait zure konexioan interferentziak sortzen saiatzen ari dela esan nahi lezake</string>
<!--Introductions-->
<string name="introduction_onboarding_title">Aurkeztu zure kontaktuak</string>
<string name="introduction_onboarding_text">Zure kontaktuak bata besteari aurkeztu ditzakezu, horrela ez dute aurrez aurre elkartzeko beharra Briar erabiltzeko.</string>
<string name="introduction_activity_title">Hautatu kontaktua</string>
<string name="introduction_message_title">Aurkeztu kontaktuak</string>
<string name="introduction_message_hint">Gehitu mezu bat (aukerazkoa)</string>
<string name="introduction_button">Egin aurkezpena</string>
<string name="introduction_sent">Zure aurkezpena bidali da</string>
<string name="introduction_error">Errorea gertatu da aurkezpena egitean.</string>
<string name="introduction_response_error">Errorea aurkezpenari erantzutean</string>
<string name="introduction_request_sent">%1$s erabiltzailea %2$s erabiltzaileari aurkeztea eskatu duzu</string>
<string name="introduction_request_received">%1$s erabiltzaileak %2$s zuri aurkeztea eskatu dizu. %2$s Kontaktuen zerrendara gehitu nahi duzu?</string>
<string name="introduction_request_exists_received">%1$s erabiltzaileak %2$s zuri aurkeztea eskatu dizu, baina %2$s badago zure kontaktuen zerrendan. Agian %1$s erabiltzaileak ez daki, erantzun dezakezu:</string>
<string name="introduction_request_answered_received">%1$s erabiltzaileak %2$s zuri aurkeztea eskatu du.</string>
<string name="introduction_response_accepted_sent">%1$s erabiltzailearen aurkezpena onartu duzu.</string>
<string name="introduction_response_declined_sent">%1$s erabiltzailearen aurkezpena ukatu duzu.</string>
<string name="introduction_response_accepted_received">%1$s erabiltzaileak %2$s erabiltzailearen aurkezpena onartu du.</string>
<string name="introduction_response_declined_received">%1$s erabiltzaileak %2$s erabiltzailearen aurkezpena ukatu du.</string>
<string name="introduction_response_declined_received_by_introducee">%1$s erabiltzaileak dio %2$s erabiltzaileak aurkezpena ukatu duela.</string>
<plurals name="introduction_notification_text">
<item quantity="one">Kontaktu berria gehituta.</item>
<item quantity="other">%d kontaktu berri gehituta.</item>
</plurals>
<!--Private Groups-->
<string name="groups_list_empty">Ez zaude inolako taldetan parte hartzen.\n\nSakatu goiko + ikonoa zuk zeuk talde bat sartzeko edo eskatu kontaktuei bere talderen batetara zu gonbidatzea.</string>
<string name="groups_created_by">%s erabiltzaileak sortuta</string>
<plurals name="messages">
<item quantity="one">mezu %d</item>
<item quantity="other">%d mezu</item>
</plurals>
<string name="groups_group_is_empty">Talde hau hutsik dago</string>
<string name="groups_group_is_dissolved">Talde hau disolbatu da</string>
<string name="groups_remove">Kendu</string>
<string name="groups_create_group_title">Sortu talde pribatua</string>
<string name="groups_create_group_button">Sortu taldea</string>
<string name="groups_create_group_invitation_button">Bidali gonbidapena</string>
<string name="groups_create_group_hint">Aukeratu zure talde pribatuaren izena</string>
<string name="groups_invitation_sent">Talde gonbidapena bidali da</string>
<string name="groups_message_sent">Mezua bidalita</string>
<string name="groups_member_list">Kideen zerrenda</string>
<string name="groups_invite_members">Gonbidatu kideak</string>
<string name="groups_member_created_you">Zuk taldea sortu duzu</string>
<string name="groups_member_created"> %s erabiltzaileak taldea sortu du</string>
<string name="groups_member_joined_you">Zu taldera elkartu zara</string>
<string name="groups_member_joined">%s taldera elkartu da</string>
<string name="groups_leave">Utzi taldea</string>
<string name="groups_leave_dialog_title">Berretsi taldea uztea</string>
<string name="groups_leave_dialog_message">Ziur talde hau utzi nahi duzula?</string>
<string name="groups_dissolve">Disolbatu taldea</string>
<string name="groups_dissolve_dialog_title">Berretsi taldea disolbatzea</string>
<string name="groups_dissolve_dialog_message">Ziur talde hau disolbatu nahi duzula?\n\nBeste kideek ezin izango dute elkarrizketarekin jarraitu eta ez dituzu azken mezuak jasoko.</string>
<string name="groups_dissolve_button">Disolbatu</string>
<string name="groups_dissolved_dialog_title">Taldea disolbatu da</string>
<string name="groups_dissolved_dialog_message">Talde honen sortzaileak taldea disolbatu du.\n\nEzin dituzu jada mezuak bidali talde honetara eta agian ez dituzu jasoko idatzi diren mezu guztiak.</string>
<!--Private Group Invitations-->
<string name="groups_invitations_title">Talde gonbidapenak</string>
<string name="groups_invitations_invitation_sent">%1$s erabiltzailea \"%2$s\" taldera gonbidatu duzu.</string>
<string name="groups_invitations_invitation_received">%1$s erabiltzailea \"%2$s\" taldera gonbidatu zaitu.</string>
<string name="groups_invitations_joined">Taldera elkartuta</string>
<string name="groups_invitations_declined">Talde gonbidapena ukatuta</string>
<plurals name="groups_invitations_open">
<item quantity="one">talde ireki gonbidapen %d</item>
<item quantity="other">%d talde ireki gonbidapen</item>
</plurals>
<string name="groups_invitations_response_accepted_sent">%s erabiltzailearen talde gonbidapena onartu duzu.</string>
<string name="groups_invitations_response_declined_sent">%s erabiltzailearen talde gonbidapena ukatu duzu. </string>
<string name="groups_invitations_response_accepted_received">%s erabiltzaileak talde gonbidapena onartu du.</string>
<string name="groups_invitations_response_declined_received">%s erabiltzaileak talde gonbidapena ukatu du.</string>
<string name="sharing_status_groups">Sortzaileak besterik ezin ditu kide berriak gehitu taldera. Behean oraingo kide guztiak daude.</string>
<!--Private Groups Revealing Contacts-->
<string name="groups_reveal_contacts">Argitara eman kontaktuak</string>
<string name="groups_reveal_dialog_message">Taldeko oraingo eta etorkizuneko kide guztiei kontaktuak argitara eman ala ez aukeratu dezakezu.\n\nKontaktuak partekatzean zure taldera konexioa azkarragoa eta egonkorragoa izango da, argitara emandako kontaktuekin komunikatu zaitezkeelako sortzailea deskonektatuta badago ere.</string>
<string name="groups_reveal_visible">Kontaktuen erlazioa taldean ikusgai dago</string>
<string name="groups_reveal_visible_revealed_by_us">Kontaktuen erlazioa taldean ikusgai dago (Zuk argitara emana)</string>
<string name="groups_reveal_visible_revealed_by_contact">Kontaktuen erlazioa taldean ikusgai dago (%s erabiltzaileak argitara emana)</string>
<string name="groups_reveal_invisible">Kontaktuen erlazioa ez dago taldean ikusgai</string>
<!--Forums-->
<string name="no_forums">Ez duzu fororik oraindik.\n\nSortu batu zuk zeuk goiko + ikonoa sakatuz.\n\nKontaktuei eskatu ahal diezu ere foroak zurekin partekatu ditzatela.</string>
<string name="create_forum_title">Sortu foroa</string>
<string name="choose_forum_hint">Hautatu zure foroaren izena</string>
<string name="create_forum_button">Sortu foroa</string>
<string name="forum_created_toast">Foroa sortuta</string>
<string name="no_forum_posts">Foro hau hutsik dago.\n\nErabili goiko arkatzaren ikonoa lehen mezua idazteko.\n\nBakarrik sentitzen zara hemen? Partekatu foro hau zure kontaktuekin!</string>
<string name="no_posts">Sarrerarik ez</string>
<plurals name="posts">
<item quantity="one">Bidalketa %d</item>
<item quantity="other">%d sarrera</item>
</plurals>
<string name="forum_new_entry_posted">Foroko sarrera bidali da</string>
<string name="forum_new_message_hint">Sarrera berria</string>
<string name="forum_message_reply_hint">Erantzun berria</string>
<string name="btn_reply">Erantzun</string>
<string name="forum_leave">Utzi foroa</string>
<string name="dialog_title_leave_forum">Berretsi foroa uztea</string>
<string name="dialog_message_leave_forum">Ziur foro hau utzi nahi duzula? Zure kontaktuekin foro hau partekatu baduzu, agian ez dituzte eguneraketa gehiago jasoko.</string>
<string name="dialog_button_leave">Utzi</string>
<string name="forum_left_toast">Foroa utzita</string>
<!--Forum Sharing-->
<string name="forum_share_button">Partekatu foroa</string>
<string name="contacts_selected">Kontaktuak hautatuta</string>
<string name="activity_share_toolbar_header">Hautatu kontaktuak</string>
<string name="no_contacts_selector">Badirudi hemen berria zarela eta ez duzula kontakturik oraindik.\n\nItzuli hona gutxienez kontaktu bat gehitu eta gero.</string>
<string name="forum_shared_snackbar">Foroa partekatuta hautatutako kontaktuekin</string>
<string name="forum_share_message">Gehitu mezua (aukerazkoa)</string>
<string name="forum_share_error">Errore bat egon da foro hau partekatzean.</string>
<string name="forum_invitation_received">%1$s erabiltzaileak \"%2$s\" foroa partekatu du zurekin.</string>
<string name="forum_invitation_sent">\"%1$s\" foroa partekatu duzu %2$s erabiltzailearekin.</string>
<string name="forum_invitations_title">Forora gonbidapenak</string>
<string name="forum_invitation_exists">Onartu duzu jada foro honetarako gonbidapen bat. Gonbidapen gehiago onartzeak foroarekin komunikazioa hobetu eta indartuko du.</string>
<string name="forum_joined_toast">Forora elkartuta</string>
<string name="forum_declined_toast">Foro gonbidapena ukatuta</string>
<string name="shared_by_format">%s erabiltzaileak partekatuta</string>
<string name="forum_invitation_already_sharing">Dagoeneko partekatzen</string>
<string name="forum_invitation_response_accepted_sent"> %s erabiltzailearen foro gonbidapena onartu duzu.</string>
<string name="forum_invitation_response_declined_sent">%s erabiltzailearen foro gonbidapena ukatu duzu.</string>
<string name="forum_invitation_response_accepted_received">%s erabiltzaileak foro gonbidapena onartu du.</string>
<string name="forum_invitation_response_declined_received"> %s erabiltzaileak foro gonbidapena ukatu du.</string>
<string name="sharing_status">Partekatze egoera</string>
<string name="sharing_status_forum">Foroko edozein kidek partekatu dezake bere kontaktuekin. Honako erabiltzaileekin partekatzen duzu zuk. Ikusten ez dituzun kide gehiago egon daitezke.</string>
<string name="shared_with">%1$d erabiltzaileekin partekatuta (%2$d konektatuta)</string>
<plurals name="forums_shared">
<item quantity="one">Kontaktuek partekatutako foro %d</item>
<item quantity="other">Kontaktuek partekatutako %d foro</item>
</plurals>
<string name="nobody">Inor ez</string>
<!--Blogs-->
<string name="blogs_other_blog_empty_state">Blog hau orain hutsik dago.\n\nEgileak ez du ezer idatzi edo blog hau zurekin partekatu duen kontaktua deskonektatuta dago, eta ezin da orain sinkronizatu.</string>
<string name="read_more">irakurri gehiago</string>
<string name="blogs_write_blog_post">Idatzi blog sarrera</string>
<string name="blogs_write_blog_post_body_hint">Idatzi zure blog sarrera hemen</string>
<string name="blogs_publish_blog_post">Argitaratu</string>
<string name="blogs_blog_post_created">Blog sarrera sortuta</string>
<string name="blogs_blog_post_received">Blog sarrera berria jasota</string>
<string name="blogs_blog_post_scroll_to">Korritu hona</string>
<string name="blogs_feed_empty_state">Hau blogen jario orokorra da.\n\nBadirudi inork ez duela blog sarrerarik idatzi oraindik.\n\nIzan lehena eta sakatu arkatzaren ikonoa blog sarrera bat idazteko.</string>
<string name="blogs_remove_blog">Kendu bloga</string>
<string name="blogs_remove_blog_dialog_message">Ziur blog hau eta sarrera guztiak kendu nahi dituzula?\nJakin honek ez duela bloga kenduko besteen gailuetatik.</string>
<string name="blogs_remove_blog_ok">Kendu bloga</string>
<string name="blogs_blog_removed">Bloga kenduta</string>
<string name="blogs_reblog_comment_hint">Gehitu iruzkina (aukerazkoa)</string>
<string name="blogs_reblog_button">Birblogeatu</string>
<!--Blog Sharing-->
<string name="blogs_sharing_share">Partekatu bloga</string>
<string name="blogs_sharing_error">Errore bat egon da blog hau partekatzean.</string>
<string name="blogs_sharing_button">Partekatu bloga</string>
<string name="blogs_sharing_snackbar">Bloga hautatutako kontaktuekin partekatuta</string>
<string name="blogs_sharing_response_accepted_sent">%s erabiltzailearen blog gonbidapena onartu duzu.</string>
<string name="blogs_sharing_response_declined_sent">%s erabiltzailearen blog gonbidapena ukatu duzu.</string>
<string name="blogs_sharing_response_accepted_received">%s erabiltzaileak blog gonbidapena onartu du.</string>
<string name="blogs_sharing_response_declined_received">%s erabiltzaileak blog gonbidapena ukatu du.</string>
<string name="blogs_sharing_invitation_received">%1$s erabiltzaileak \"%2$s\" bloga partekatu du zurekin.</string>
<string name="blogs_sharing_invitation_sent">\"%1$s\" bloga partekatu duzu %2$s erabiltzailearekin.</string>
<string name="blogs_sharing_invitations_title">Blog gonbidapenak</string>
<string name="blogs_sharing_joined_toast">Blogera harpidetuta</string>
<string name="blogs_sharing_declined_toast">Blog gonbidapena ukatuta</string>
<string name="sharing_status_blog">Blog batetara harpidetutako edonork berau partekatu dezake bere kontaktuekin. Honako kontaktuekin partekatzen duzu zuk. Ikusten ez dituzun harpidedun gehiago egon daitezke.</string>
<!--RSS Feeds-->
<string name="blogs_rss_feeds_import">Inportatu RSS jarioa</string>
<string name="blogs_rss_feeds_import_button">Inportatu</string>
<string name="blogs_rss_feeds_import_hint">Sartu RSS jarioaren URLa</string>
<string name="blogs_rss_feeds_import_error">Sentitzen dugu! Zure jarioa inportatzean errore bat gertatu da.</string>
<string name="blogs_rss_feeds_manage">Kudeatu RSS jarioak</string>
<string name="blogs_rss_feeds_manage_imported">Inportatuta:</string>
<string name="blogs_rss_feeds_manage_author">Egilea:</string>
<string name="blogs_rss_feeds_manage_updated">Azken eguneraketa:</string>
<string name="blogs_rss_remove_feed">Kendu jarioa:</string>
<string name="blogs_rss_remove_feed_dialog_message">Ziur jario hau eta bere sarrera guztiak kendu nahi dituzula?\nPartekatu dituzun sarrerak ez dira besteen gailuetatik kenduko.</string>
<string name="blogs_rss_remove_feed_ok">Kendu jarioa</string>
<string name="blogs_rss_feeds_manage_delete_error">Ezin izan da jarioa ezabatu!</string>
<string name="blogs_rss_feeds_manage_empty_state">Ez duzu RSS jariorik inportatu.\n\nSakatu goiko eskumako + ikonoa lehena gehitzeko.</string>
<string name="blogs_rss_feeds_manage_error">Arazo bat egon da zure jarioak kargatzean. Saiatu berriro geroago.</string>
<!--Settings Network-->
<string name="network_settings_title">Sareak</string>
<string name="bluetooth_setting">Bluetooth bidez konektatuta</string>
<string name="bluetooth_setting_enabled">Kontaktuak hurbil daudeneak</string>
<string name="bluetooth_setting_disabled">Kontaktuak gehitzean besterik ez</string>
<string name="tor_network_setting">Konektatu Tor bidez</string>
<string name="tor_network_setting_never">Inoiz ez</string>
<string name="tor_network_setting_wifi">Wi-Fi erabiltzean besterik ez</string>
<string name="tor_network_setting_always">Wi-Fi edo datu mugikorrak erabiltzean</string>
<!--Settings Security and Panic-->
<string name="security_settings_title">Segurtasuna</string>
<string name="change_password">Aldatu pasahitza</string>
<string name="current_password">Sartu oraingo pasahitza:</string>
<string name="choose_new_password">Hautatu pasahitz berria:</string>
<string name="confirm_new_password">Berretsi pasahitz berria:</string>
<string name="password_changed">Pasahitza aldatu da.</string>
<string name="panic_setting">Larrialdi botoiaren ezarpena</string>
<string name="panic_setting_title">Larrialdi botoia</string>
<string name="panic_setting_hint">Konfiguratu Briar aplikazioak nola jokatuko duen larrialdi botoiaren aplikazioa erabiltzean</string>
<string name="panic_app_setting_title">Larrialdi botoiaren aplikazioa</string>
<string name="unknown_app">aplikazio ezezagun bat</string>
<string name="panic_app_setting_summary">Ez da aplikaziorik ezarri</string>
<string name="panic_app_setting_none">Bat ere ez</string>
<string name="dialog_title_connect_panic_app">Berretsi larrialdi-aplikazioa</string>
<string name="dialog_message_connect_panic_app">Ziur %1$s baimendu nahi duzula larrialdi botoiaren ekintza suntsitzaileak burutzea?</string>
<string name="lock_setting_title">Amaitu saioa</string>
<string name="lock_setting_summary">Amaitu saioa larrialdi botoia zapaltzen bada</string>
<string name="purge_setting_title">Ezabatu kontua</string>
<string name="purge_setting_summary">Ezabatu kontua Briar larrialdi botoia zapaltzen bada. Kontuz: Honek behin betiko ezabatuko ditu zure identitateak, kontaktuak eta mezuak</string>
<string name="uninstall_setting_title">Desinstalatu Briar</string>
<string name="uninstall_setting_summary">Honek eskuzko berrespena behar du larrialdi egoeran</string>
<!--Settings Notifications-->
<string name="notification_settings_title">Jakinarazpenak</string>
<string name="notify_private_messages_setting_title">Mezu pribatuak</string>
<string name="notify_private_messages_setting_summary">Erakutsi mezu pribatuen alertak</string>
<string name="notify_group_messages_setting_title">Talde mezuak</string>
<string name="notify_group_messages_setting_summary">Erakutsi taldeetako mezuen alertak</string>
<string name="notify_forum_posts_setting_title">Foroko sarrerak</string>
<string name="notify_forum_posts_setting_summary">Erakutsi foroko sarreren alertak</string>
<string name="notify_blog_posts_setting_title">Blog sarrerak</string>
<string name="notify_blog_posts_setting_summary">Erakutsi blog sarreren alertak</string>
<string name="notify_vibration_setting">Bibratu</string>
<string name="notify_lock_screen_setting_title">Blokeatu pantaila</string>
<string name="notify_lock_screen_setting_summary">Erakutsi jakinarazpenak blokeo-pantailan</string>
<string name="notify_sound_setting">Soinua</string>
<string name="notify_sound_setting_default">Lehenetsitako dei-doinua</string>
<string name="notify_sound_setting_disabled">Bat ere ez</string>
<string name="choose_ringtone_title">Hautatu dei-doinua</string>
<!--Settings Feedback-->
<string name="feedback_settings_title">Iruzkinak</string>
<string name="send_feedback">Bidali iruzkinak</string>
<!--Link Warning-->
<string name="link_warning_title">Estekari buruzko abisua</string>
<string name="link_warning_intro">Honako esteka hau kanpo aplikazio batekin irekitzear zaude.</string>
<string name="link_warning_text">Hau zu identifikatzeko erabili daiteke. Pentsatu esteka hau bidali dizun pertsonarengan konfiantza duzun eta baloratu Orfox bidez irekitzea.</string>
<string name="link_warning_open_link">Ireki esteka</string>
<!--Crash Reporter-->
<string name="crash_report_title">Briar kraskatze errorea</string>
<string name="briar_crashed">Briar kraskatu da.</string>
<string name="not_your_fault">Ez da zure errua.</string>
<string name="please_send_report">Lagundu Briar hobetzen kraskatze txostena guri bidaliz.</string>
<string name="report_is_encrypted">Txostena zifratuta dagoela eta modu seguruan bidaliko dela agintzen dizugu.</string>
<string name="feedback_title">Iruzkinak</string>
<string name="describe_crash">Deskribatu zer gertatu den (aukerazkoa)</string>
<string name="enter_feedback">Idatzi zure iruzkinak</string>
<string name="optional_contact_email">Zure e-mail helbidea (aukerazkoa)</string>
<string name="include_debug_report_crash">Gehitu kraskatzeari buruzko informazio anonimoa</string>
<string name="include_debug_report_feedback">Gehitu gailu honi buruzko informazio anonimoa</string>
<string name="could_not_load_report_data">Ezin izan dira kargatu txostenaren datuak.</string>
<string name="send_report">Bidali txostena</string>
<string name="close">Itxi</string>
<string name="dev_report_saved">Txostena gordeta. Briar saioa hasten duzunean bidaliko da.</string>
<!--Sign Out-->
<string name="progress_title_logout">Briar saioa amaitzen...</string>
<!--Screen Filters & Tapjacking-->
<string name="screen_filter_title">Pantaila gainjartzea antzeman da</string>
<string name="screen_filter_body">Briar aplikazioaren gainean marrazten ari den beste aplikazio bat dago. Zure segurtasuna babesteko Briar aplikazioak ez dio ukimenari erantzungo beste aplikazio bat gainean marrazten dagoen bitartean.\n\nSaiatu honako aplikazioak ixten Briar erabiltzean:\n\n%1$s</string>
</resources>

View File

@@ -0,0 +1,367 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<!--Setup-->
<string name="setup_title">Briarin asetus</string>
<string name="setup_explanation">Sinun Briar tili on tallennettu salattuna sinun laitteelle, ei pilvipalvelimelle. Jos poistat Briarin asennuksen tai unohdat salasanasi, ei ole mitään keinoa jolla tilisi tai dataasi voisi palauttaa.</string>
<string name="choose_nickname">Valitse nimimerkki</string>
<string name="choose_password">Valitse salasana</string>
<string name="confirm_password">Vahvista salasana</string>
<string name="name_too_long">Nimi on liian pitkä</string>
<string name="password_too_weak">Salasana on liian heikko</string>
<string name="passwords_do_not_match">Salasanat eivät täsmää</string>
<string name="create_account_button">Luo tili</string>
<!--Login-->
<string name="enter_password">Syötä salasana:</string>
<string name="try_again">Väärä salasana, yritä uudelleen</string>
<string name="sign_in_button">Kirjaudu sisään</string>
<string name="forgotten_password">Olen unohtanut salasanan</string>
<string name="dialog_title_lost_password">Unohtunut salasana</string>
<string name="dialog_message_lost_password">Sinun Briar tili on tallennettu salattuna sinun laitteelle, ei pilvipalvelimelle, joten emme voi palauttaa salasanaasi. Haluatko poistaa tilisi ja aloittaa alusta?\n\nVaroitus: Tulet menettämään tunnuksesi, yhteystietosi ja viestisi lopullisesti.</string>
<string name="startup_failed_notification_title">Briarin käynnistys epäonnistui</string>
<string name="startup_failed_notification_text">Sinun täytyy ehkä uudelleenasentaa Briar.</string>
<string name="startup_failed_activity_title">Briarin käynnistys epäonnistui</string>
<string name="startup_failed_db_error">Jostain syystä sinun Briar tietokanta on korruptoitunut korjauskelvottomaksi. Tilisi, tietosi ja kaikki yhteystietosi on menetetty. Valitettavasti, sinun täytyy asentaa Briar uudelleen ja luoda uusi tili.</string>
<string name="startup_failed_service_error">Briar ei kyennyt käynnistämään vaadittua liitännäistä. Briarin uudelleenasennus yleensä korjaa ongelman. Huomaa kuitenkin, että tulet menettämään tilisi ja kaikki siihen liittyvä data koska Briar ei käytä palvelimia sinun tietojesi säilyttämiseen.</string>
<plurals name="expiry_warning">
<item quantity="one">Tämä on Briarin beeta versio. Sinun tilisi tulee vanhentumaan %d päivän päästä eikä sitä voi uusia.</item>
<item quantity="other">Tämä on Briarin beeta versio. Sinun tilisi tulee vanhentumaan %d päivän päästä eikä sitä voi uusia.</item>
</plurals>
<string name="expiry_date_reached">Tämä sovellus on vanhentunut.\nKiitos testaamisesta!</string>
<!--Navigation Drawer-->
<string name="nav_drawer_open_description">Avaa navigointilaatikko</string>
<string name="nav_drawer_close_description">Sulje navigointilaatikko</string>
<string name="contact_list_button">Yhteystiedot</string>
<string name="groups_button">Yksityiset ryhmät</string>
<string name="forums_button">Foorumit</string>
<string name="blogs_button">Blogit</string>
<string name="settings_button">Asetukset</string>
<string name="sign_out_button">Kirjaudu ulos</string>
<!--Transports-->
<string name="transport_tor">Internet</string>
<string name="transport_bt">Bluetooth</string>
<string name="transport_lan">Wi-Fi</string>
<!--Notifications-->
<string name="ongoing_notification_title">Kirjautunut Briariin</string>
<string name="ongoing_notification_text">Napauta avataksesi Briar.</string>
<plurals name="private_message_notification_text">
<item quantity="one">Uusi yksityisviesti.</item>
<item quantity="other">%d uutta yksityisviestiä.</item>
</plurals>
<plurals name="group_message_notification_text">
<item quantity="one">Uusi ryhmäviesti.</item>
<item quantity="other">%d uutta ryhmäviestiä.</item>
</plurals>
<plurals name="forum_post_notification_text">
<item quantity="one">Uusi foorumiviesti.</item>
<item quantity="other">%d uutta foorumiviestiä.</item>
</plurals>
<plurals name="blog_post_notification_text">
<item quantity="one">Uusi blogikirjoitus.</item>
<item quantity="other">%d uutta blogikirjoitusta.</item>
</plurals>
<!--Misc-->
<string name="now">nyt</string>
<string name="show">Näytä</string>
<string name="hide">Piilota</string>
<string name="ok">OK</string>
<string name="cancel">Peruuta</string>
<string name="got_it">Selvä</string>
<string name="delete">Poista</string>
<string name="accept">Hyväksy</string>
<string name="decline">Kieltäydy</string>
<string name="options">Valitsimet</string>
<string name="online">Verkossa</string>
<string name="offline">Poissa verkosta</string>
<string name="send">Lähetä</string>
<string name="allow">Salli</string>
<string name="open">Avaa</string>
<string name="no_data">Ei dataa</string>
<string name="ellipsis"></string>
<string name="text_too_long">Kirjoitettu teksti on liian pitkä</string>
<string name="show_onboarding">Näytä apudialogi</string>
<!--Contacts and Private Conversations-->
<string name="no_contacts">Näyttää siltä, että olet uusi täällä, eikä sinulla vielä ole yhteyshenkilöitä.\n\nNapauta yllä olevaa + -kuvaketta ja seuraa ohjeita lisätäksesi kavereita luetteloon.\n\nMuista: Voit ainoastaan lisätä uusia yhteyshenkilöitä tapaamalla heidät kasvokkain. Tämä estää sen, että joku voisi esittää olevansa sinä tai lukea viestejäsi tulevaisuudessa.</string>
<string name="date_no_private_messages">Ei viestejä.</string>
<string name="no_private_messages">Tämä on keskustelunäkymä.\n\nKeskustelu näyttää puuttuvan.\n\nNapauta syöttökenttää sivun pohjalla aloittaaksesi keskustelun.</string>
<string name="message_hint">Kirjoita viesti</string>
<string name="delete_contact">Poista yhteystieto</string>
<string name="dialog_title_delete_contact">Vahvista yhteystiedon poistaminen</string>
<string name="dialog_message_delete_contact">Oletko varma, että haluat poistaa tämän yhteyshenkilön ja kaikki hänen kanssa vaihdetut viestit?</string>
<string name="contact_deleted_toast">Yhteystieto poistettu</string>
<!--Adding Contacts-->
<string name="add_contact_title">Lisää yhteystieto</string>
<string name="your_nickname">Valitse tunnus jota haluat käyttää:</string>
<string name="face_to_face">Sinun täytyy tavata käyttäjä, jonka haluat lisätä yhteystietoihisi.\n\nTämä estää sen, että joku voisi esittää olevansa sinä tai lukea viestejäsi tulevaisuudessa</string>
<string name="continue_button">Jatka</string>
<string name="your_invitation_code">Sinun kutsukoodi on</string>
<string name="enter_invitation_code">Syötä yhteyshenkilösi kutsukoodi:</string>
<string name="searching_format">Etsitään yhteyshenkilöä jolla on kutsukoodi %06d\u2026</string>
<string name="connection_failed">Yhteys epäonnistui</string>
<string name="could_not_find_contact">Briar ei löytänyt yhteyshenkilöä lähistöltä</string>
<string name="try_again_button">Yritä uudelleen</string>
<string name="connected_to_contact">Yhdistetty yhteyshenkilöön</string>
<string name="calculating_confirmation_code">Luodaan varmennuskoodi\u2026</string>
<string name="your_confirmation_code">Sinun varmennuskoodi on</string>
<string name="enter_confirmation_code">Syötä yhteyshenkilösi varmennuskoodi:</string>
<string name="waiting_for_contact">Odotetaan yhteyshenkilöä\u2026</string>
<string name="waiting_for_contact_to_scan">Odotetaan, että käyttäjä skannaa ja saa yhteyden\u2026</string>
<string name="exchanging_contact_details">Yhteystietoja vaihdetaan\u2026</string>
<string name="codes_do_not_match">Koodit eivät täsmää</string>
<string name="interfering">Tämä voi tarkoittaa, että joku yrittää häiritä sinun ja toisen käyttäjän välistä yhteyttä</string>
<string name="contact_added_toast">Yhteystieto lisätty: %s</string>
<string name="contact_already_exists">Yhteystieto %s on jo olemassa</string>
<string name="contact_exchange_failed">Yhteystietojen vaihto epäonnistui</string>
<string name="qr_code_invalid">QR koodi on virheellinen</string>
<string name="connecting_to_device">Yhdistetään laitteeseen\u2026</string>
<string name="authenticating_with_device">Tunnistaudutaan laitteen kanssa\u2026</string>
<string name="connection_aborted_local">Katkaisimme sinun ja toisen käyttäjän välisen yhteyden! Tämä voi tarkoittaa, että joku muu yrittää häiritä sinun ja toisen käyttäjän välistä yhteyttä</string>
<string name="connection_aborted_remote">Toinen käyttäjä katkaisi yhteyden! Tämä voi tarkoittaa, että joku muu yrittää häiritä sinun ja toisen käyttäjän välistä yhteyttä</string>
<!--Introductions-->
<string name="introduction_onboarding_title">Esittele yhteyshenkilösi</string>
<string name="introduction_onboarding_text">Voit esitellä muita käyttäjiä toisilleen, niin että heidän ei tarvitse tavata kasvokkain ollakseen yhteydessä Briarin kautta.</string>
<string name="introduction_activity_title">Valitse yhteystieto</string>
<string name="introduction_message_title">Esittele yhteyshenkilö</string>
<string name="introduction_message_hint">Lisää viesti (valinnainen)</string>
<string name="introduction_button">Tee esittely</string>
<string name="introduction_sent">Esittelysi on lähetetty.</string>
<string name="introduction_error">Esittelyssä tapahtui virhe.</string>
<string name="introduction_response_error">Esittelyyn vastaamisessa tapahtui virhe</string>
<string name="introduction_request_sent">Olet pyytänyt, että %1$s ja %2$s esitellään toisilleen.</string>
<string name="introduction_request_received">%1$s on pyytänyt, että sinut esitellään käyttäjälle %2$s. Haluatko lisätä käyttäjän %2$s yhteystietoihisi?</string>
<string name="introduction_request_exists_received">%1$s on pyytänyt, että sinut esitellään käyttäjälle %2$s, mutta %2$s on jo yhteystiedoissasi. %1$s ei välttämättä tiedä tätä, joten voit silti vastata:</string>
<string name="introduction_request_answered_received">%1$s on pyytänyt, että sinut esitellään käyttäjälle %2$s.</string>
<string name="introduction_response_accepted_sent">Olet hyväksynyt esittelyn käyttäjälle %1$s.</string>
<string name="introduction_response_declined_sent">Olet kieltäytynyt esittelystä käyttäjälle %1$s.</string>
<string name="introduction_response_accepted_received">%1$s hyväksyi esittelyn käyttäjälle %2$s.</string>
<string name="introduction_response_declined_received">%1$s kieltäytyi esittelystä käyttäjälle %2$s.</string>
<string name="introduction_response_declined_received_by_introducee">%1$s sanoo, että %2$s on kieltäytynyt esittelystä.</string>
<plurals name="introduction_notification_text">
<item quantity="one">Uusi yhteystieto lisätty.</item>
<item quantity="other">%d uutta yhteystietoa lisätty.</item>
</plurals>
<!--Private Groups-->
<string name="groups_list_empty">Et ole jäsen missään ryhmissä.\n\nNapauta yllä olevaa + -kuvaketta luodaksesi ryhmän itse tai pyydä yhteyshenkilöltä kutsua päästäksesi yhteen heidän ryhmistä.</string>
<string name="groups_created_by">Luonut %s</string>
<plurals name="messages">
<item quantity="one">%d viesti</item>
<item quantity="other">%d viestiä</item>
</plurals>
<string name="groups_group_is_empty">Tämä ryhmä on tyhjä</string>
<string name="groups_group_is_dissolved">Tämä ryhmä on hajautettu</string>
<string name="groups_remove">Poista</string>
<string name="groups_create_group_title">Luo yksityinen ryhmä</string>
<string name="groups_create_group_button">Luo ryhmä</string>
<string name="groups_create_group_invitation_button">Lähetä kutsu</string>
<string name="groups_create_group_hint">Valitse nimi yksityiselle ryhmällesi</string>
<string name="groups_invitation_sent">Ryhmäkutsu on lähetetty</string>
<string name="groups_message_sent">Viesti lähetetty</string>
<string name="groups_member_list">Jäsenluettelo</string>
<string name="groups_invite_members">Kutsu jäseniä</string>
<string name="groups_member_created_you">Sinä loit ryhmän</string>
<string name="groups_member_created">%s loi ryhmän</string>
<string name="groups_member_joined_you">Olet liittynyt ryhmään</string>
<string name="groups_member_joined">%s liittyi ryhmään</string>
<string name="groups_leave">Lähde ryhmästä</string>
<string name="groups_leave_dialog_title">Vahvista ryhmästä lähtö</string>
<string name="groups_leave_dialog_message">Oletko varma, että haluat lähteä tästä ryhmästä?</string>
<string name="groups_dissolve">Hajauta ryhmä</string>
<string name="groups_dissolve_dialog_title">Vahvista ryhmän hajauttaminen</string>
<string name="groups_dissolve_dialog_message">Oletko varma, että haluat hajauttaa tämän ryhmän?\n\nRyhmän muut jäsenet eivät sen jälkeen voi enää jatkaa ryhmäkeskustelua eivätkä välttämättä tule saamaan viimeisimpiä viestejä.</string>
<string name="groups_dissolve_button">Hajauta</string>
<string name="groups_dissolved_dialog_title">Ryhmä on nyt hajautettu</string>
<string name="groups_dissolved_dialog_message">Tämän ryhmän aloittaja on hajauttanut sen.\n\nEt voi enää kirjoitta uusia viestejä ryhmälle, etkä välttämättä tule saamaan kaikkia tähän mennessä kirjoitettuja viestejä.</string>
<!--Private Group Invitations-->
<string name="groups_invitations_title">Ryhmäkutsut</string>
<string name="groups_invitations_invitation_sent">Olet kutsunut käyttäjän %1$s mukaan ryhmään \"%2$s\".</string>
<string name="groups_invitations_invitation_received">%1$s on kutsunut sinut mukaan ryhmään \"%2$s\".</string>
<string name="groups_invitations_joined">Liittyi ryhmään</string>
<string name="groups_invitations_declined">Kutsu liittyä ryhmään on hylätty</string>
<plurals name="groups_invitations_open">
<item quantity="one">%d avoin ryhmäkutsu</item>
<item quantity="other">%d avointa ryhmäkutsua</item>
</plurals>
<string name="groups_invitations_response_accepted_sent">Olet hyväksynyt käyttäjän %s lähettämän ryhmäkutsun.</string>
<string name="groups_invitations_response_declined_sent">Olet kieltäytynyt käyttäjän %s lähettämästä ryhmäkutsusta.</string>
<string name="groups_invitations_response_accepted_received">%s hyväksyi ryhmäkutsun.</string>
<string name="groups_invitations_response_declined_received">%s kieltäytyi ryhmäkutsusta.</string>
<string name="sharing_status_groups">Vain ryhmäkeskustelun aloittaja voi pyytää uusia jäseniä mukaan ryhmään. Alla ovat kaikki ryhmän nykyiset jäsenet.</string>
<!--Private Groups Revealing Contacts-->
<string name="groups_reveal_contacts">Näytä yhteystiedot</string>
<string name="groups_reveal_dialog_message">Voit valita haluatko paljastaa yhteytesi muihin käyttäjiin tämän ryhmän nykyisille ja tuleville jäsenille.\n\nKäyttäjä yhteyksien paljastaminen tekee yhteydestä nopeamman ja luotettavamman, koska voit pitää yhteyttä muihin käyttäjiin myös silloin kun ryhmän aloittaja on poissa verkosta.</string>
<string name="groups_reveal_visible">Yhteys käyttäjään on näkyvissä ryhmän jäsenille</string>
<string name="groups_reveal_visible_revealed_by_us">Yhteys käyttäjään on näkyvissä ryhmän jäsenille (sinun paljastamana)</string>
<string name="groups_reveal_visible_revealed_by_contact">Yhteys käyttäjään on näkyvissä ryhmän jäsenille (käyttäjän %s paljastamana)</string>
<string name="groups_reveal_invisible">Yhteys käyttäjään ei ole näkyvissä ryhmän jäsenille</string>
<!--Forums-->
<string name="no_forums">Sinulla ei vielä ole yhtäkään foorumia.\n\nMiksi et aloita uutta napauttamalla yllä olevaa + -kuvaketta?\n\nVoit myös pyytää muita käyttäjiä jakamaan foorumeita kanssasi.</string>
<string name="create_forum_title">Luo foorumi</string>
<string name="choose_forum_hint">Valitse nimi foorumillesi</string>
<string name="create_forum_button">Luo foorumi</string>
<string name="forum_created_toast">Foorumi luotu</string>
<string name="no_forum_posts">Tämä foorumi on tyhjä.\n\nKäytä yllä olevaa kynää kirjoittaaksesi ensimmäisen viestin.\n\nTuntuuko yksinäiseltä? Kerro tästä foorumista muille!</string>
<string name="no_posts">Ei viestejä</string>
<plurals name="posts">
<item quantity="one">%d viesti</item>
<item quantity="other">%d viestiä</item>
</plurals>
<string name="forum_new_entry_posted">Foorumikirjoitus julkaistu</string>
<string name="forum_new_message_hint">Uusi viesti</string>
<string name="forum_message_reply_hint">Uusi vastaus</string>
<string name="btn_reply">Vastaa</string>
<string name="forum_leave">Lähde foorumista</string>
<string name="dialog_title_leave_forum">Vahvista foorumista lähteminen</string>
<string name="dialog_message_leave_forum">Oletko varma, että haluat lähteä tästä foorumista? Käyttäjät, jotka olet kutsunut tähän foorumiin, eivät välttämättä tule enää saamaan päivityksiä tästä foorumista.</string>
<string name="dialog_button_leave">Lähde</string>
<string name="forum_left_toast">Lähti foorumista</string>
<!--Forum Sharing-->
<string name="forum_share_button">Jaa foorumi</string>
<string name="contacts_selected">Yhteystiedot valittu</string>
<string name="activity_share_toolbar_header">Valitse yhteystiedot</string>
<string name="no_contacts_selector">Näyttää siltä, että olet uusi täällä, eikä sinulla vielä ole yhteyshenkilöitä.\n\nTule takaisin sen jälkeen kun olet lisännyt ensimmäisen yhteyshenkilösi.</string>
<string name="forum_shared_snackbar">Foorumi jaettu valittujen käyttäjien kanssa</string>
<string name="forum_share_message">Lisää viesti (valinnainen)</string>
<string name="forum_share_error">Tämän foorumin jakamisessa tapahtui virhe.</string>
<string name="forum_invitation_received">%1$s on jakanut \"%2$s\" -nimisen foorumin kanssasi.</string>
<string name="forum_invitation_sent">Olet jakanut \"%1$s\" -nimisen foorumin käyttäjälle %2$s.</string>
<string name="forum_invitations_title">Kutsut liittyä foorumeihin</string>
<string name="forum_invitation_exists">Olet jo hyväksynyt kutsun liittyä tähän foorumiin. Useamman kutsun hyväksyminen kasvattaa ja vahvistaa foorumin kommunikaatiota.</string>
<string name="forum_joined_toast">Liittyi foorumiin</string>
<string name="forum_declined_toast">Kutsu liittyä foorumiin on hylätty</string>
<string name="shared_by_format">Jakanut %s</string>
<string name="forum_invitation_already_sharing">On jo jakamassa</string>
<string name="forum_invitation_response_accepted_sent">Olet hyväksynyt käyttäjän %s lähettämän foorumikutsun.</string>
<string name="forum_invitation_response_declined_sent">Olet kieltäytynyt käyttäjän %s lähettämästä foorumikutsusta.</string>
<string name="forum_invitation_response_accepted_received">%s hyväksyi foorumikutsun.</string>
<string name="forum_invitation_response_declined_received">%s kieltäytyi foorumikutsusta.</string>
<string name="sharing_status">Jaetaan tilaa</string>
<string name="sharing_status_forum">Kuka tahansa foorumin jäsen voi jakaa sen tuntemilleen käyttäjille. Olet jakamassa tämän foorumin seuraaville käyttäjille. Voi myös olla muita jäseniä, joita sinä et näe.</string>
<string name="shared_with">Jaettu %1$d kanssa (%2$d verkossa)</string>
<plurals name="forums_shared">
<item quantity="one">%d foorumi jaettu</item>
<item quantity="other">%d foorumia jaettu</item>
</plurals>
<string name="nobody">Ei kukaan</string>
<!--Blogs-->
<string name="blogs_other_blog_empty_state">Blogi on tällä hetkellä tyhjä.\n\nJoko blogin julkaisija ei ole kirjoittanut mitään vielä, tai tämän blogin sinulle jakaneen henkilön on liityttävä takaisin verkkoon, jotta blogikirjoitukset voitaisiin synkronisoida.</string>
<string name="read_more">lue lisää</string>
<string name="blogs_write_blog_post">Julkaise blogikirjoitus</string>
<string name="blogs_write_blog_post_body_hint">Kirjoita blogikirjoitus tähän</string>
<string name="blogs_publish_blog_post">Julkaise</string>
<string name="blogs_blog_post_created">Blogikirjoitus julkaistu</string>
<string name="blogs_blog_post_received">Uusi blogikirjoitus vastaanotettu</string>
<string name="blogs_blog_post_scroll_to">Vieritä kohtaan</string>
<string name="blogs_feed_empty_state">Tämä on universaali blogi syöte.\n\nNäyttää vielä siltä, ettei kukaan ole vielä julkaissut mitään.\n\nOle ensimmäinen ja napauta kynää kirjoittaaksesi uuden blogikirjoituksen.</string>
<string name="blogs_remove_blog">Poista blogi</string>
<string name="blogs_remove_blog_dialog_message">Oletko varma, että haluat poistaa tämän blogin ja kaikki siihen kuuluvat kirjoitukset?\nOta huomioon, että tämä ei tule poistamaan kirjoituksia muiden käyttäjien laitteilta.</string>
<string name="blogs_remove_blog_ok">Poista blogi</string>
<string name="blogs_blog_removed">Blogi poistettu</string>
<string name="blogs_reblog_comment_hint">Lisää kommentti (valinnainen)</string>
<string name="blogs_reblog_button">Jaa blogikirjoitus</string>
<!--Blog Sharing-->
<string name="blogs_sharing_share">Jaa blogi</string>
<string name="blogs_sharing_error">Tämän blogin jakamisessa tapahtui virhe.</string>
<string name="blogs_sharing_button">Jaa blogi</string>
<string name="blogs_sharing_snackbar">Blogi jaettu valittujen käyttäjien kanssa</string>
<string name="blogs_sharing_response_accepted_sent">Olet hyväksynyt käyttäjän %s lähettämän blogikutsun.</string>
<string name="blogs_sharing_response_declined_sent">Olet kieltäytynyt käyttäjän %s lähettämästä blogikutsusta.</string>
<string name="blogs_sharing_response_accepted_received">%s hyväksyi blogikutsun.</string>
<string name="blogs_sharing_response_declined_received">%s kieltäytyi blogikutsusta.</string>
<string name="blogs_sharing_invitation_received">%1$s on jakanut \"%2$s\" -nimisen blogin kanssasi.</string>
<string name="blogs_sharing_invitation_sent">Olet jakanut \"%1$s\" -nimisen blogin käyttäjälle %2$s.</string>
<string name="blogs_sharing_invitations_title">Blogi kutsut</string>
<string name="blogs_sharing_joined_toast">Blogi tilattu</string>
<string name="blogs_sharing_declined_toast">Kutsu blogiin on hylätty</string>
<string name="sharing_status_blog">Kuka tahansa joka tilaa blogin voi jakaa sen tuntemilleen käyttäjille. Olet jakamassa tämän blogin seuraaville käyttäjille. Voi myös olla muita blogin tilaajia, joita sinä et näe.</string>
<!--RSS Feeds-->
<string name="blogs_rss_feeds_import">Tuo RSS syöte</string>
<string name="blogs_rss_feeds_import_button">Tuo</string>
<string name="blogs_rss_feeds_import_hint">Syötä RSS syötteen URL osoite</string>
<string name="blogs_rss_feeds_import_error">Pahoittelemme! Syötteen noutamisessa tapahtui virhe.</string>
<string name="blogs_rss_feeds_manage">Muokkaa RSS syötteitä</string>
<string name="blogs_rss_feeds_manage_imported">Tuotu:</string>
<string name="blogs_rss_feeds_manage_author">Tekijä:</string>
<string name="blogs_rss_feeds_manage_updated">Viimeksi päivitetty:</string>
<string name="blogs_rss_remove_feed">Poista syöte</string>
<string name="blogs_rss_remove_feed_dialog_message">Oletko varma, että haluat poistaa tämän syötteen kaikki sen julkaisut?\nJakamasi julkaisut eivät tule poistumaan muiden henkilöiden laitteilta.</string>
<string name="blogs_rss_remove_feed_ok">Poista syöte</string>
<string name="blogs_rss_feeds_manage_delete_error">Syötteen poistaminen epäonnistui!</string>
<string name="blogs_rss_feeds_manage_empty_state">Et ole tilannut yhtäkään RSS syötettä.\n\nMiksi et napauta yllä olevaa plussaa ja lisää ensimmäistä?</string>
<string name="blogs_rss_feeds_manage_error">Syötteiden lataamisessa tapahtui virhe. Yritä myöhemmin uudelleen.</string>
<!--Settings Network-->
<string name="network_settings_title">Verkot</string>
<string name="bluetooth_setting">Yhdistä Bluetoothin kautta</string>
<string name="bluetooth_setting_enabled">Silloin kun yhteyshenkilöt ovat lähellä</string>
<string name="bluetooth_setting_disabled">Vain kun yhteyshenkilöitä lisätään</string>
<string name="tor_network_setting">Yhdistä Tor-verkon kautta</string>
<string name="tor_network_setting_never">Ei koskaan</string>
<string name="tor_network_setting_wifi">Vain kun on Wi-Fi yhteys</string>
<string name="tor_network_setting_always">Kun on Wi-Fi tai mobiilidatayhteys</string>
<!--Settings Security and Panic-->
<string name="security_settings_title">Turvallisuus</string>
<string name="change_password">Vaihda salasana</string>
<string name="current_password">Syötä nykyinen salasana:</string>
<string name="choose_new_password">Valitse uusi salasana:</string>
<string name="confirm_new_password">Vahvista uusi salasana:</string>
<string name="password_changed">Salasana on vaihdettu.</string>
<string name="panic_setting">Paniikkinapin asetus</string>
<string name="panic_setting_title">Paniikkinappi</string>
<string name="panic_setting_hint">Säädä miten Briar tulee käyttäytymään kun käytät paniikkinappisovellusta</string>
<string name="panic_app_setting_title">Paniikkinappisovellus</string>
<string name="unknown_app">tuntematon sovellus</string>
<string name="panic_app_setting_summary">Sovellusta ei ole valittu</string>
<string name="panic_app_setting_none">Ei mitään</string>
<string name="dialog_title_connect_panic_app">Vahvista paniikkisovellus</string>
<string name="dialog_message_connect_panic_app">Oletko varma, että haluat myöntää ohjelmalle %1$s luvan laukaista tuhoa aiheuttavia paniikkinapin toimintoja?</string>
<string name="lock_setting_title">Kirjaudu ulos</string>
<string name="lock_setting_summary">Kirjaudu ulos Briarista jos paniikkinappia on painettu</string>
<string name="purge_setting_title">Poista tili</string>
<string name="purge_setting_summary">Poista Briar tilisi jos paniikkinappia on painettu. Varoitus: Tämä tulee pysyvästi poistamaan sinun tunnukset, yhteystiedot ja viestit</string>
<string name="uninstall_setting_title">Poista Briarin asennus</string>
<string name="uninstall_setting_summary">Tämä tulee vaatimaan manuaalisen varmennuksen paniikkitilanteessa</string>
<!--Settings Notifications-->
<string name="notification_settings_title">Ilmoitukset</string>
<string name="notify_private_messages_setting_title">Yksityisviestit</string>
<string name="notify_private_messages_setting_summary">Näytä ilmoitukset yksityisviesteistä</string>
<string name="notify_group_messages_setting_title">Ryhmäviestit</string>
<string name="notify_group_messages_setting_summary">Näytä ilmoitukset ryhmäviesteistä</string>
<string name="notify_forum_posts_setting_title">Foorumikirjoitukset</string>
<string name="notify_forum_posts_setting_summary">Näytä ilmoitukset foorumikirjoituksista</string>
<string name="notify_blog_posts_setting_title">Blogikirjoitukset</string>
<string name="notify_blog_posts_setting_summary">Näytä ilmoitukset blogikirjoituksista</string>
<string name="notify_vibration_setting">Värinä</string>
<string name="notify_lock_screen_setting_title">Lukitusnäyttö</string>
<string name="notify_lock_screen_setting_summary">Näytä ilmoitukset lukitusnäytöllä</string>
<string name="notify_sound_setting">Ääni</string>
<string name="notify_sound_setting_default">Oletussoittoääni</string>
<string name="notify_sound_setting_disabled">Ei mikään</string>
<string name="choose_ringtone_title">Valitse soittoääni</string>
<!--Settings Feedback-->
<string name="feedback_settings_title">Palaute</string>
<string name="send_feedback">Lähetä palautetta</string>
<!--Link Warning-->
<string name="link_warning_title">Linkkivaroitus</string>
<string name="link_warning_intro">Olet aikomassa avata seuraavan linkin toisessa sovelluksessa.</string>
<string name="link_warning_text">Tätä voidaan käyttää sinun tunnistamiseen. Mieti luotatko käyttäjään, joka lähetti sinulle kyseisen linkin, ja harkitse sen avaamista Orfoxilla.</string>
<string name="link_warning_open_link">Avaa linkki</string>
<!--Crash Reporter-->
<string name="crash_report_title">Briar kaatumisilmoitus</string>
<string name="briar_crashed">Pahoittelemme, Briar on kaatunut.</string>
<string name="not_your_fault">Tämä ei ole sinun syysi.</string>
<string name="please_send_report">Auta meitä rakentamaan parempi Briar lähettämällä meille kaatumisilmoitus.</string>
<string name="report_is_encrypted">Lupaamme, että ilmoitus on salattu ja lähetetty turvallisesti.</string>
<string name="feedback_title">Palaute</string>
<string name="describe_crash">Kuvaile mitä tapahtui (valinnainen)</string>
<string name="enter_feedback">Kirjoita palaute</string>
<string name="optional_contact_email">Sähköpostiosoite (valinnainen)</string>
<string name="include_debug_report_crash">Liitä anonyymiä dataa kaatumisesta</string>
<string name="include_debug_report_feedback">Liitä anonyymiä dataa tästä laitteesta</string>
<string name="could_not_load_report_data">Ilmoituksen tietojen lataaminen epäonnistui.</string>
<string name="send_report">Lähetä ilmoitus</string>
<string name="close">Sulje</string>
<string name="dev_report_saved">Ilmoitus tallennettu. Sen lähetys tapahtuu seuraavan kerran kun kirjaudut sisään Briariin.</string>
<!--Sign Out-->
<string name="progress_title_logout">Kirjaudutaan ulos Briarista...</string>
<!--Screen Filters & Tapjacking-->
<string name="screen_filter_title">Näyttökerros havaittu</string>
<string name="screen_filter_body">Toinen sovellus on piirtämässä Briarin päälle. Suojellakseen sinun turvallisuutta, Briar ei tule vastaamaan kosketuksiin silloin kun toinen sovellus on piirtämässä Briarin päälle.\n\nYritä sulkea seuraavat sovellukset silloin kun käytät Briaria:\n\n%1$s</string>
</resources>

View File

@@ -16,7 +16,7 @@
<string name="sign_in_button">Connexion</string>
<string name="forgotten_password">J\'ai oublié mon mot de passe</string>
<string name="dialog_title_lost_password">Mot de passe oublié</string>
<string name="dialog_message_lost_password">Votre compte Briar est enregistré chiffré sur votre appareil et non sur le nuage et nous ne pouvons donc pas réinitialiser votre mot de passe. Voulez-vous supprimer votre compte et recommencer?\n\nAttention : vos identités, contacts et messages seront perdus irrémédiablement.</string>
<string name="dialog_message_lost_password">Votre compte Briar est enregistré chiffré sur votre appareil, pas dans le nuage, et nous ne pouvons donc pas réinitialiser votre mot de passe. Voulez-vous supprimer votre compte et recommencer?\n\nAttention : vos identités, contacts et messages seront perdus irrémédiablement.</string>
<string name="startup_failed_notification_title">Impossible de démarrer Briar</string>
<string name="startup_failed_notification_text">Il vous faudra peut-être réinstaller Briar.</string>
<string name="startup_failed_activity_title">Échec de démarrage de Briar</string>
@@ -249,7 +249,7 @@
<string name="blogs_publish_blog_post">Publier</string>
<string name="blogs_blog_post_created">L\'article de blogue a été créé</string>
<string name="blogs_blog_post_received">Un nouvel article de blogue a été reçu</string>
<string name="blogs_blog_post_scroll_to">Faire défiler jusqu\'à</string>
<string name="blogs_blog_post_scroll_to">Atteindre</string>
<string name="blogs_feed_empty_state">Ceci est le flux global des blogues.\n\nIl semble que personne n\'ait encore rien écrit.\n\nSoyez le premier et touchez l\'icône de crayon pour rédiger un nouvel article de blogue.</string>
<string name="blogs_remove_blog">Supprimer le blogue</string>
<string name="blogs_remove_blog_dialog_message">Voulez-vous vraiment supprimer ce blogue et tous ses messages?\nNotez que cela ne le supprimera pas des appareils d\'autrui.</string>
@@ -321,7 +321,7 @@
<!--Settings Notifications-->
<string name="notification_settings_title">Notifications</string>
<string name="notify_private_messages_setting_title">Messages privés</string>
<string name="notify_private_messages_setting_summary">Afficher des alertes pour les messages privés</string>
<string name="notify_private_messages_setting_summary">Afficher des notifications pour les messages privés</string>
<string name="notify_group_messages_setting_title">Messages de groupe</string>
<string name="notify_group_messages_setting_summary">Afficher des alertes pour les messages de groupe</string>
<string name="notify_forum_posts_setting_title">Articles de forum</string>

View File

@@ -0,0 +1,128 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<!--Setup-->
<string name="setup_title">Configuración de Briar</string>
<string name="setup_explanation">Briar almacena a súa configuración encriptada no dispositivo, non na nube. Se desinstala Briar ou esquece a súa clave, non hai forma de recuperar a súa conta e datos.</string>
<string name="choose_nickname">Escolle o teu alcume</string>
<string name="choose_password">Escolle a túa clave</string>
<string name="confirm_password">Confirma a túa clave</string>
<string name="name_too_long">O nome é demasiado longo</string>
<string name="password_too_weak">A clave é demasiado débil</string>
<string name="passwords_do_not_match">As claves non coinciden</string>
<string name="create_account_button">Crea a conta</string>
<!--Login-->
<string name="enter_password">Introduce a túa clave:</string>
<string name="try_again">Clave incorrecta, tenteo de novo</string>
<string name="sign_in_button">Iniciar sesión</string>
<string name="forgotten_password">Esquecín a miña clave</string>
<string name="dialog_title_lost_password">Clave perdida</string>
<string name="dialog_message_lost_password">Briar almacena a súa configuración encriptada no dispositivo, non na nube, así que non podemos restabelecer a súa clave. Querrías borrar a túa conta e empezar de novo?\n\nPrecaución: As túas identidades, contactos e mensaxes serán eliminadas de forma permanente.</string>
<string name="startup_failed_notification_title">Briar non puido iniciarse</string>
<string name="startup_failed_notification_text">Pode que precises instalar Briar de novo</string>
<string name="startup_failed_activity_title">Fallo de Inicio de Briar</string>
<string name="startup_failed_db_error">A súa base de datos de Briar está corrompida ate o punto que é irreparábel. Perdeuse a súa conta, os seus datos e todos os contactos conectados. Por desgraza debes instalar de novo Briar e configurar unha nova conta.</string>
<string name="startup_failed_service_error"> Briar non puido iniciar un complemento necesario. Xeralmente reinstalar Briar resolve este problema. Teña en conta que entón perderá a súa conta e todos os datos asociados a esta pois Briar non está a utilizar servidores centrais para almacenar os seus datos.</string>
<string name="expiry_date_reached">Este software caducou.\nGrazas por probalo!</string>
<!--Navigation Drawer-->
<string name="nav_drawer_open_description">Abra a gaveta de navegación</string>
<string name="nav_drawer_close_description">Peche a gaveta de navegación</string>
<string name="contact_list_button">Contactos</string>
<string name="groups_button">Grupos Privados</string>
<string name="forums_button">Foros</string>
<string name="blogs_button">Blogues</string>
<string name="settings_button">Axustes</string>
<string name="sign_out_button">Finalizar sesión</string>
<!--Transports-->
<string name="transport_tor">Internet</string>
<string name="transport_bt">Bluetooth</string>
<string name="transport_lan">Wi-Fi</string>
<!--Notifications-->
<string name="ongoing_notification_title">Conectado a Briar</string>
<string name="ongoing_notification_text">Toque para abrir Briar</string>
<!--Misc-->
<string name="now">agora</string>
<string name="show">Amosar</string>
<string name="hide">Agochar</string>
<string name="ok">OK</string>
<string name="cancel">Cancelar</string>
<string name="got_it">Comprendido</string>
<string name="delete">Eliminar</string>
<string name="accept">Aceptar</string>
<string name="decline">Rexeitar</string>
<string name="options">Opcións</string>
<string name="online">Conectado</string>
<string name="offline">Desconectado</string>
<string name="send">Enviar</string>
<string name="allow">Permitir</string>
<string name="open">Abrir</string>
<string name="no_data">Sen datos</string>
<string name="ellipsis">...</string>
<string name="text_too_long">O texto inserido e demasiado longo</string>
<string name="show_onboarding">Amosar xanela de axuda</string>
<!--Contacts and Private Conversations-->
<string name="date_no_private_messages">Sen mensaxes</string>
<string name="message_hint">Esciba unha mensaxe</string>
<string name="delete_contact">Eliminar contacto</string>
<string name="dialog_title_delete_contact">Confirme a eliminación do contacto</string>
<string name="contact_deleted_toast">Contacto eliminado</string>
<!--Adding Contacts-->
<string name="add_contact_title">Engada un contacto</string>
<string name="your_nickname">Escolla a identidade que quere usar:</string>
<string name="continue_button">Continuar</string>
<string name="your_invitation_code">O seu código de convite é</string>
<string name="enter_invitation_code">Por favor, insira o código de convite do seu contacto</string>
<string name="connection_failed">Fallou a conexión</string>
<string name="try_again_button">Tenteo de novo</string>
<string name="connected_to_contact">Conectado ao contacto</string>
<string name="your_confirmation_code">O seu código de confirmación é</string>
<string name="codes_do_not_match">Os códigos non coinciden</string>
<string name="qr_code_invalid">O código QR non é válido</string>
<!--Introductions-->
<string name="introduction_activity_title">Escoller contacto</string>
<string name="introduction_message_title">Introducir Contactos</string>
<string name="introduction_message_hint">Engadir unha mensaxe (opcional)</string>
<!--Private Groups-->
<string name="groups_group_is_empty">Este grupo está valeiro</string>
<string name="groups_group_is_dissolved">Este grupo foi disolto</string>
<string name="groups_remove">Eliminar</string>
<string name="groups_create_group_title">Crear Grupo Privado</string>
<string name="groups_create_group_button">Crear Grupo</string>
<string name="groups_create_group_invitation_button">Enviar Convite</string>
<string name="groups_create_group_hint">Escolla un nome para o seu grupo privado</string>
<string name="groups_message_sent">Mensaxe enviada</string>
<string name="groups_member_list">Lista de Membros</string>
<string name="groups_invite_members">Convidar a Membros</string>
<string name="groups_member_created_you">Vostede creou o grupo</string>
<string name="groups_member_joined_you">Vostede ingresou no grupo</string>
<string name="groups_leave">Deixar Grupo</string>
<string name="groups_leave_dialog_title">Confirme que deixa o Grupo</string>
<string name="groups_leave_dialog_message">Está certo de que quere deixar este grupo?</string>
<!--Private Group Invitations-->
<!--Private Groups Revealing Contacts-->
<!--Forums-->
<string name="create_forum_title">Crear Foro</string>
<string name="choose_forum_hint">Escolla un nome para o seu foro</string>
<string name="create_forum_button">Crear Foro</string>
<string name="forum_created_toast">Foro creado</string>
<string name="no_posts">Non hai mensaxes</string>
<string name="forum_new_message_hint">Nova Entrada</string>
<string name="forum_message_reply_hint">Nova Resposta</string>
<string name="btn_reply">Respostar</string>
<!--Forum Sharing-->
<string name="forum_share_button">Compartir Foro</string>
<string name="activity_share_toolbar_header">Escolla Contactos</string>
<string name="forum_share_message">Engadir unha mensaxe (opcional)</string>
<!--Blogs-->
<string name="read_more">ler mais</string>
<string name="blogs_publish_blog_post">Publicar</string>
<!--Blog Sharing-->
<!--RSS Feeds-->
<!--Settings Network-->
<!--Settings Security and Panic-->
<!--Settings Notifications-->
<!--Settings Feedback-->
<!--Link Warning-->
<!--Crash Reporter-->
<!--Sign Out-->
<!--Screen Filters & Tapjacking-->
</resources>

View File

@@ -0,0 +1,367 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<!--Setup-->
<string name="setup_title">ब्रियर सेटअप</string>
<string name="setup_explanation">आपका ब्रियर खाता आपके डिवाइस पर एन्क्रिप्ट किया गया है, न कि क्लाउड में। यदि आप बिअर की स्थापना रद्द करते हैं या अपना पासवर्ड भूल जाते हैं, तो आपके खाता और आपके डेटा को पुनर्प्राप्त करने का कोई तरीका नहीं है।</string>
<string name="choose_nickname">आपका मुंहबोला नाम चुनें</string>
<string name="choose_password">अपना पासवर्ड चुनें</string>
<string name="confirm_password">अपने पासवर्ड की पुष्टि करें</string>
<string name="name_too_long">नाम बहुत लंबा है</string>
<string name="password_too_weak">पासवर्ड बहुत कमजोर है</string>
<string name="passwords_do_not_match">पासवर्ड मेल नहीं खाते</string>
<string name="create_account_button">खाता बनाएं</string>
<!--Login-->
<string name="enter_password">अपना पासवर्ड डालें:</string>
<string name="try_again">गलत पासवर्ड, फिर से प्रयास करें</string>
<string name="sign_in_button">साइन इन करें</string>
<string name="forgotten_password">मुझे अपना पासवर्ड याद नहीं है</string>
<string name="dialog_title_lost_password">पासवर्ड खो गया</string>
<string name="dialog_message_lost_password">आपका ब्रियर खाता आपके डिवाइस पर एन्क्रिप्ट किया गया है, बादल में नहीं, इसलिए हम आपका पासवर्ड रीसेट नहीं कर सकते। क्या आप अपना खाता हटाना चाहते हैं और फिर से शुरू करना चाहते हैं? \ N \ n सावधानी: आपकी पहचान, संपर्क और संदेश स्थायी रूप से खो जाएंगे</string>
<string name="startup_failed_notification_title">बियर शुरू नहीं हो सका</string>
<string name="startup_failed_notification_text">आपको ब्रियर को पुनर्स्थापित करने की आवश्यकता हो सकती है</string>
<string name="startup_failed_activity_title">ब्रियर स्टार्टअप विफलता</string>
<string name="startup_failed_db_error">किसी कारण से, आपके ब्रियर डेटाबेस की मरम्मत से परे भ्रष्ट है। आपका खाता, आपका डेटा और आपके सभी संपर्क कनेक्शन खो जाते हैं। दुर्भाग्य से, आपको ब्रियर को पुनर्स्थापित करना होगा और एक नया खाता सेट अप करना होगा।</string>
<string name="startup_failed_service_error">ब्रियर एक आवश्यक प्लगइन प्रारंभ करने में असमर्थ था बरिअर को पुनः स्थापित करना आमतौर पर इस समस्या को हल करता है हालांकि, कृपया ध्यान दें कि बियर आपके डेटा को स्टोर करने के लिए केंद्रीय सर्वर का उपयोग नहीं कर रहा है, इसके बाद आप अपने खाता और उसके साथ जुड़े सभी डेटा खो देंगे।</string>
<plurals name="expiry_warning">
<item quantity="one">यह बियर का बीटा संस्करण है आपका खाता%d दिनों में समाप्त हो जाएगा और नवीनीकरण नहीं किया जा सकता है।</item>
<item quantity="other">यह बियर का बीटा संस्करण है आपका खाता%d दिनों में समाप्त हो जाएगा और नवीनीकरण नहीं किया जा सकता है।</item>
</plurals>
<string name="expiry_date_reached">यह सॉफ्टवेयर समाप्त हो गया है। \n परीक्षण के लिए धन्यवाद!</string>
<!--Navigation Drawer-->
<string name="nav_drawer_open_description">नेविगेशन ड्रॉवर खोलें</string>
<string name="nav_drawer_close_description">नेविगेशन ड्रॉवर को बंद करें</string>
<string name="contact_list_button">संपर्क</string>
<string name="groups_button">निजी समूह</string>
<string name="forums_button">मंच</string>
<string name="blogs_button">ब्लॉग</string>
<string name="settings_button">सेटिंग्स</string>
<string name="sign_out_button">साइन आउट</string>
<!--Transports-->
<string name="transport_tor">इंटरनेट</string>
<string name="transport_bt">ब्लूटूथ</string>
<string name="transport_lan">वाई - फाई</string>
<!--Notifications-->
<string name="ongoing_notification_title">ब्रायर में हस्ताक्षर किए</string>
<string name="ongoing_notification_text">ब्रियर को खोलने के लिए स्पर्श करें</string>
<plurals name="private_message_notification_text">
<item quantity="one">नया निजी संदेश</item>
<item quantity="other">%dनया निजी संदेश</item>
</plurals>
<plurals name="group_message_notification_text">
<item quantity="one">नया समूह संदेश</item>
<item quantity="other">%dनया समूह संदेश</item>
</plurals>
<plurals name="forum_post_notification_text">
<item quantity="one">नया मंच पोस्ट</item>
<item quantity="other">%dनया मंच पोस्ट</item>
</plurals>
<plurals name="blog_post_notification_text">
<item quantity="one">नए ब्लॉग पोस्ट</item>
<item quantity="other">%dनए ब्लॉग पोस्ट</item>
</plurals>
<!--Misc-->
<string name="now">अभी व</string>
<string name="show">दिखाना</string>
<string name="hide">छिपाना</string>
<string name="ok">ठीक</string>
<string name="cancel">रद्द करना</string>
<string name="got_it">समझ गया</string>
<string name="delete">हटाना</string>
<string name="accept">स्वीकारें</string>
<string name="decline">पतन</string>
<string name="options">विकल्प</string>
<string name="online">ऑनलाइन</string>
<string name="offline">ऑफलाइन</string>
<string name="send">भेजना</string>
<string name="allow">अनुमति दें</string>
<string name="open">खोलें </string>
<string name="no_data">नो डाटा </string>
<string name="ellipsis"></string>
<string name="text_too_long">प्रवेश किया हुआ पाठ बहुत लंबा है</string>
<string name="show_onboarding">सहायता संवाद दिखाएं</string>
<!--Contacts and Private Conversations-->
<string name="no_contacts">ऐसा लगता है कि आप यहां नए हैं और अभी तक कोई संपर्क नहीं है। \ N \ n शीर्ष पर + आइकन टैप करें और कुछ मित्रों को अपनी सूची में जोड़ने के लिए निर्देशों का पालन करें। \ N \ n कृपया याद रखें: आप केवल नए संपर्कों को आमने-सामने जोड़ सकते हैं किसी भी व्यक्ति को भविष्य में आपके प्रतिरूपण या पढ़ने से रोकने के लिए -फाइल</string>
<string name="date_no_private_messages">कोई संदेश नहीं।</string>
<string name="no_private_messages">यह वार्तालाप दृश्य है। \ N \ n वार्तालाप की कमी महसूस होती है। \ N \ n वार्तालाप शुरू करने के लिए बस नीचे इनपुट फ़ील्ड को टैप करें।</string>
<string name="message_hint">संदेश लिखें</string>
<string name="delete_contact">संपर्क मिटा दें</string>
<string name="dialog_title_delete_contact">संपर्क हटाने की पुष्टि करें</string>
<string name="dialog_message_delete_contact">क्या आप निश्चित हैं कि आप इस संपर्क और सभी संदेशों को इस संपर्क से निकाला जाना चाहते हैं?</string>
<string name="contact_deleted_toast">संपर्क हटा दिया गया</string>
<!--Adding Contacts-->
<string name="add_contact_title">संपर्क जोड़ना</string>
<string name="your_nickname">वह पहचान चुनें जिसे आप उपयोग करना चाहते हैं:</string>
<string name="face_to_face">आपको उस व्यक्ति के साथ मिलना चाहिए जिसे आप संपर्क के रूप में जोड़ना चाहते हैं। \ N \ n यह किसी को भविष्य में आपके प्रतिरूपण या पढ़ने के बाद से किसी को भी रोकेगा।</string>
<string name="continue_button">जारी रहना</string>
<string name="your_invitation_code">आपका निमंत्रण कोड है</string>
<string name="enter_invitation_code">कृपया अपने संपर्क के निमंत्रण कोड को दर्ज करें:</string>
<string name="searching_format">निमंत्रण कोड%06d\ u2026 के साथ संपर्क के लिए खोज रहे हैं</string>
<string name="connection_failed">कनेक्शन विफल</string>
<string name="could_not_find_contact">ब्रियर आपके संपर्क के पास नहीं मिल सका</string>
<string name="try_again_button">पुनः प्रयास करें</string>
<string name="connected_to_contact">संपर्क से कनेक्ट किया गया</string>
<string name="calculating_confirmation_code">पुष्टि कोड की गणना \ u2026</string>
<string name="your_confirmation_code">आपका पुष्टिकरण कोड है</string>
<string name="enter_confirmation_code">कृपया अपने संपर्क का पुष्टिकरण कोड दर्ज करें:</string>
<string name="waiting_for_contact">संपर्क की प्रतीक्षा कर रहा है \ u2026</string>
<string name="waiting_for_contact_to_scan">स्कैन करने और कनेक्ट करने के लिए संपर्क की प्रतीक्षा कर रहा है \ u2026</string>
<string name="exchanging_contact_details">संपर्क विवरणों का आदान-प्रदान करें \ u2026</string>
<string name="codes_do_not_match">कोड मेल नहीं खाते हैं</string>
<string name="interfering">इसका मतलब यह हो सकता है कि कोई आपके कनेक्शन में हस्तक्षेप करने का प्रयास कर रहा है</string>
<string name="contact_added_toast">संपर्क जोड़ा गया:%s</string>
<string name="contact_already_exists">संपर्क%s पहले से मौजूद है</string>
<string name="contact_exchange_failed">संपर्क विनिमय विफल</string>
<string name="qr_code_invalid">QR कोड अमान्य है</string>
<string name="connecting_to_device">उपकरण \ u2026 से कनेक्ट हो रहा है</string>
<string name="authenticating_with_device">डिवाइस के साथ प्रमाणीकरण \ u2026</string>
<string name="connection_aborted_local">कनेक्शन हमारे द्वारा निरस्त कर दिया! इसका मतलब यह हो सकता है कि कोई आपके कनेक्शन में हस्तक्षेप करने का प्रयास कर रहा है</string>
<string name="connection_aborted_remote">आपके संपर्क से कनेक्शन निरस्त! इसका मतलब यह हो सकता है कि कोई आपके कनेक्शन में हस्तक्षेप करने का प्रयास कर रहा है</string>
<!--Introductions-->
<string name="introduction_onboarding_title">अपने संपर्कों का परिचय दें</string>
<string name="introduction_onboarding_text">आप अपने संपर्कों को एक दूसरे से जोड़ सकते हैं, इसलिए उन्हें ब्रियर से जुड़ने के लिए व्यक्तिगत रूप से मिलने की जरूरत नहीं है।</string>
<string name="introduction_activity_title">संपर्क का चयन करें</string>
<string name="introduction_message_title">संपर्कों का परिचय</string>
<string name="introduction_message_hint">एक संदेश जोड़ें (वैकल्पिक)</string>
<string name="introduction_button">परिचय करें</string>
<string name="introduction_sent">आपका परिचय भेजा गया है।</string>
<string name="introduction_error">परिचय बनाने में एक त्रुटि हुई।</string>
<string name="introduction_response_error">परिचय का जवाब देने में त्रुटि</string>
<string name="introduction_request_sent">आपने%2$s से%1$s का परिचय देने के लिए कहा है</string>
<string name="introduction_request_received">%1$sने आपको%2$s में पेश करने को कहा है क्या आप अपनी संपर्क सूची में%2$s जोड़ना चाहते हैं?</string>
<string name="introduction_request_exists_received">%1$sने आपको%2$s में लाने के लिए कहा है, लेकिन%2$s आपकी संपर्क सूची में पहले से मौजूद है। चूंकि%1$s शायद यह नहीं जान पाए, आप फिर भी जवाब दे सकते हैं:</string>
<string name="introduction_request_answered_received">%1$sने आपको%2$s में पेश करने को कहा है</string>
<string name="introduction_response_accepted_sent">आपने%1$s की शुरूआत स्वीकार कर ली है</string>
<string name="introduction_response_declined_sent">आपने%1$s की शुरुआत करने से मना कर दिया</string>
<string name="introduction_response_accepted_received">%1$s%2$s की शुरूआत स्वीकार कर ली</string>
<string name="introduction_response_declined_received">%1$s%2$sकी शुरूआत में गिरावट आई</string>
<string name="introduction_response_declined_received_by_introducee">%1$sकहते हैं कि%2$sने परिचय को अस्वीकार कर दिया</string>
<plurals name="introduction_notification_text">
<item quantity="one">नया संपर्क जोड़ा।</item>
<item quantity="other">%dनया संपर्क जोड़ा।</item>
</plurals>
<!--Private Groups-->
<string name="groups_list_empty">आप किसी भी समूह में भाग नहीं ले रहे हैं। \ N \ n शीर्ष पर + आइकन टैप करें, खुद को समूह बनाएं या अपने संपर्कों से अपने समूह में से किसी एक को आमंत्रित करें।</string>
<string name="groups_created_by">के द्वारा बनाई गई%s</string>
<plurals name="messages">
<item quantity="one">संदेशों%d</item>
<item quantity="other">संदेशों %d</item>
</plurals>
<string name="groups_group_is_empty">यह समूह खाली है</string>
<string name="groups_group_is_dissolved">यह समूह भंग कर दिया गया है</string>
<string name="groups_remove">हटाना</string>
<string name="groups_create_group_title">निजी समूह बनाएं</string>
<string name="groups_create_group_button">समूह बनाएँ</string>
<string name="groups_create_group_invitation_button">निमंत्रण भेजना</string>
<string name="groups_create_group_hint">अपने निजी समूह के लिए एक नाम चुनें</string>
<string name="groups_invitation_sent">समूह आमंत्रण भेजा गया है</string>
<string name="groups_message_sent">मैसेज बेजा गया</string>
<string name="groups_member_list">सदस्य सूची</string>
<string name="groups_invite_members">सदस्यों को आमंत्रित करो</string>
<string name="groups_member_created_you">आपने समूह बनाया है</string>
<string name="groups_member_created">%sसमूह बनाया</string>
<string name="groups_member_joined_you">आप समूह में शामिल हो गए</string>
<string name="groups_member_joined">%sसमूह में शामिल हो गए</string>
<string name="groups_leave">समूह छोड़ दें</string>
<string name="groups_leave_dialog_title">समूह छोड़ने की पुष्टि करें</string>
<string name="groups_leave_dialog_message">क्या आप वाकई इस समूह को छोड़ना चाहते हैं?</string>
<string name="groups_dissolve">समूह भंग करें</string>
<string name="groups_dissolve_dialog_title">डिसोल्विंग ग्रुप की पुष्टि करें</string>
<string name="groups_dissolve_dialog_message">क्या आप निश्चित हैं कि आप इस समूह को भंग करना चाहते हैं? \ N \ n अन्य सभी सदस्य अपनी बातचीत जारी नहीं रख पाएंगे और शायद नवीनतम संदेश प्राप्त न हो जाएंगे।</string>
<string name="groups_dissolve_button">भंग</string>
<string name="groups_dissolved_dialog_title">समूह भंग कर दिया गया है</string>
<string name="groups_dissolved_dialog_message">इस समूह के निर्माता ने उसे भंग कर दिया है। \ N \ n आप अब समूह को संदेश नहीं लिख सकते हैं और जो सभी पोस्ट लिखी गई हैं उन्हें प्राप्त नहीं हो सकता है।</string>
<!--Private Group Invitations-->
<string name="groups_invitations_title">समूह आमंत्रण</string>
<string name="groups_invitations_invitation_sent">आपने समूह \"%2$s\" में शामिल होने के लिए %1$sको आमंत्रित किया है</string>
<string name="groups_invitations_invitation_received">%1$sने आपको \"%2$s\" समूह में शामिल होने के लिए आमंत्रित किया है</string>
<string name="groups_invitations_joined">समूह में शामिल</string>
<string name="groups_invitations_declined">समूह आमंत्रण अस्वीकृत हुआ</string>
<plurals name="groups_invitations_open">
<item quantity="one">%dखुला समूह आमंत्रण</item>
<item quantity="other">%dखुला समूह आमंत्रण</item>
</plurals>
<string name="groups_invitations_response_accepted_sent">आपने%s से समूह निमंत्रण स्वीकार कर लिया है</string>
<string name="groups_invitations_response_declined_sent">आपने%s से समूह निमंत्रण को मना कर दिया</string>
<string name="groups_invitations_response_accepted_received">%sसमूह निमंत्रण से मना कर दिया</string>
<string name="groups_invitations_response_declined_received">%sसमूह निमंत्रण से मना कर दिया</string>
<string name="sharing_status_groups">केवल निर्माता समूह में नए सदस्यों को आमंत्रित कर सकता है। नीचे समूह के सभी मौजूदा सदस्य हैं</string>
<!--Private Groups Revealing Contacts-->
<string name="groups_reveal_contacts">संपर्क प्रकट करें</string>
<string name="groups_reveal_dialog_message">आप यह समूह चुन सकते हैं कि इस समूह के सभी वर्तमान और भविष्य के सदस्यों के संपर्कों को प्रकट करना है। \ N \ n संपर्कों का स्वागत करते हुए समूह से आपका कनेक्शन तेज़ और अधिक विश्वसनीय बना देता है, क्योंकि आप समूह के निर्माता ऑफ़लाइन होने पर भी पता चला संपर्कों के साथ संवाद कर सकते हैं।</string>
<string name="groups_reveal_visible">संपर्क संबंध समूह को दिखाई देता है</string>
<string name="groups_reveal_visible_revealed_by_us">संपर्क संबंध समूह को दिखाई देता है (आपके द्वारा पता चला है)</string>
<string name="groups_reveal_visible_revealed_by_contact">संपर्क संबंध समूह को दिखाई देता है (%s द्वारा पता चला है)</string>
<string name="groups_reveal_invisible">संपर्क संबंध समूह को दिखाई नहीं दे रहा है</string>
<!--Forums-->
<string name="no_forums">आपके पास अभी तक कोई मंच नहीं है। \ N \ n शीर्ष पर + आइकन टैप करके आप अपने आप को एक नया क्यों नहीं बनाते? \ N \ n आप अपने संपर्कों को अपने साथ फ़ोरम साझा करने के लिए भी कह सकते हैं</string>
<string name="create_forum_title">फोरम बनाएँ</string>
<string name="choose_forum_hint">अपने मंच का नाम चुनें</string>
<string name="create_forum_button">फोरम बनाएँ</string>
<string name="forum_created_toast">फोरम बनाया</string>
<string name="no_forum_posts">यह फ़ोरम रिक्त है। \ N \ n पहली पोस्ट लिखने के लिए शीर्ष पर पेन आइकन का उपयोग करें। \ N \ n यहां अकेले आना? इस फोरम को अपने अधिक संपर्कों के साथ साझा करें!</string>
<string name="no_posts">कोई पोस्ट नहीं</string>
<plurals name="posts">
<item quantity="one">%dपदों</item>
<item quantity="other">%dपदों</item>
</plurals>
<string name="forum_new_entry_posted">फ़ोरम प्रविष्टि पोस्ट की गई</string>
<string name="forum_new_message_hint">नविन प्रवेश</string>
<string name="forum_message_reply_hint">नया उत्तर</string>
<string name="btn_reply">जवाब दें</string>
<string name="forum_leave">फोरम छोड़ें</string>
<string name="dialog_title_leave_forum">फोरम छोड़ने की पुष्टि करें</string>
<string name="dialog_message_leave_forum">क्या आप वाकई इस मंच को छोड़ना चाहते हैं? जिन संपर्कों ने आप इस मंच को साझा किया है, वे इस फ़ोरम के अपडेट प्राप्त करने से कट हो सकते हैं।</string>
<string name="dialog_button_leave">छोड़ना</string>
<string name="forum_left_toast">वाम फोरम</string>
<!--Forum Sharing-->
<string name="forum_share_button">शेयर फ़ोरम</string>
<string name="contacts_selected">संपर्क चयनित</string>
<string name="activity_share_toolbar_header">संपर्क चुनें</string>
<string name="no_contacts_selector">ऐसा लगता है कि आप यहां नए हैं और अभी तक कोई संपर्क नहीं है। \ N \ n कृपया अपना पहला संपर्क जोड़ने के बाद यहां वापस आएँ।</string>
<string name="forum_shared_snackbar">चयनित संपर्कों के साथ फ़ोरम साझा किया गया</string>
<string name="forum_share_message">एक संदेश जोड़ें (वैकल्पिक)</string>
<string name="forum_share_error">इस फ़ोरम को साझा करने में कोई त्रुटि थी।</string>
<string name="forum_invitation_received">%1$sने आपके साथ \"%2$s\" मंच साझा किया है</string>
<string name="forum_invitation_sent">आपने%2$s के साथ \"%1$s\" मंच साझा किया है</string>
<string name="forum_invitations_title">फोरम निमंत्रण</string>
<string name="forum_invitation_exists">आपने पहले से ही इस मंच के लिए एक आमंत्रण स्वीकार कर लिया है। अधिक निमंत्रण स्वीकार करना मंच में संचार बढ़ेगा और मजबूत करेगा।</string>
<string name="forum_joined_toast">फ़ोरम में शामिल</string>
<string name="forum_declined_toast">फोरम आमंत्रण अस्वीकृत</string>
<string name="shared_by_format">%s द्वारा साझा किया गया</string>
<string name="forum_invitation_already_sharing">पहले से ही साझा करना</string>
<string name="forum_invitation_response_accepted_sent">आपने%s से मंच निमंत्रण स्वीकार कर लिया है</string>
<string name="forum_invitation_response_declined_sent">आपने%s से मंच निमंत्रण को अस्वीकार कर दिया है</string>
<string name="forum_invitation_response_accepted_received">%sमंच निमंत्रण स्वीकार कर लिया</string>
<string name="forum_invitation_response_declined_received">%sमंच निमंत्रण मना कर दिया</string>
<string name="sharing_status">शेयरिंग स्थिति</string>
<string name="sharing_status_forum">फ़ोरम के किसी भी सदस्य को अपने संपर्कों के साथ साझा कर सकते हैं आप इस फ़ोरम को निम्नलिखित संपर्कों के साथ साझा कर रहे हैं ऐसे अन्य सदस्य भी हो सकते हैं जिन्हें आप नहीं देख सकते हैं</string>
<string name="shared_with">%1$d (%2$d ऑनलाइन) के साथ साझा किया गया</string>
<plurals name="forums_shared">
<item quantity="one">%dसंपर्कों द्वारा साझा मंच</item>
<item quantity="other">%dसंपर्कों द्वारा साझा मंच</item>
</plurals>
<string name="nobody">कोई भी नहीं</string>
<!--Blogs-->
<string name="blogs_other_blog_empty_state">यह ब्लॉग वर्तमान में खाली है। \ N \ n या तो लेखक ने अभी तक कुछ भी लिखा नहीं है, या जिस व्यक्ति ने आपके साथ इस ब्लॉग को साझा किया है, वह ऑनलाइन आना होगा, ताकि पोस्ट सिंक्रनाइज़ हो सकें।</string>
<string name="read_more">अधिक पढ़ें</string>
<string name="blogs_write_blog_post">ब्लॉग पोस्ट लिखें</string>
<string name="blogs_write_blog_post_body_hint">अपना ब्लॉग पोस्ट यहाँ लिखें</string>
<string name="blogs_publish_blog_post">प्रकाशित करना</string>
<string name="blogs_blog_post_created">ब्लॉग पोस्ट बनाया</string>
<string name="blogs_blog_post_received">नया ब्लॉग पोस्ट प्राप्त हुआ</string>
<string name="blogs_blog_post_scroll_to">स्क्रॉल टू</string>
<string name="blogs_feed_empty_state">यह वैश्विक ब्लॉग फीड है। \ N \ n ऐसा लगता है कि कोई भी ब्लॉग को कुछ भी नहीं, फिर भी। \ N \ n एक नया ब्लॉग पोस्ट लिखने के लिए पहले और कलम आइकन टैप करें।</string>
<string name="blogs_remove_blog">ब्लॉग निकालें</string>
<string name="blogs_remove_blog_dialog_message">क्या आप वाकई इस ब्लॉग और सभी पोस्ट को हटाना चाहते हैं? \ नोट यह ब्लॉग को अन्य लोगों के उपकरणों से नहीं हटाएगा</string>
<string name="blogs_remove_blog_ok">ब्लॉग निकालें</string>
<string name="blogs_blog_removed">ब्लॉग निकाला गया</string>
<string name="blogs_reblog_comment_hint">एक टिप्पणी जोड़ें (वैकल्पिक)</string>
<string name="blogs_reblog_button">पुनः ब्लॉग</string>
<!--Blog Sharing-->
<string name="blogs_sharing_share">ब्लॉग शेयर करें</string>
<string name="blogs_sharing_error">इस ब्लॉग को साझा करने में एक त्रुटि थी</string>
<string name="blogs_sharing_button">ब्लॉग शेयरकरें</string>
<string name="blogs_sharing_snackbar">चयनित संपर्कों के साथ साझा ब्लॉग</string>
<string name="blogs_sharing_response_accepted_sent">आपने%s से ब्लॉग निमंत्रण स्वीकार कर लिया है</string>
<string name="blogs_sharing_response_declined_sent">आपने ब्लॉग आमंत्रण से इनकार कर दिया%s</string>
<string name="blogs_sharing_response_accepted_received">%sब्लॉग निमंत्रण स्वीकार कर लिया</string>
<string name="blogs_sharing_response_declined_received">%sब्लॉग आमंत्रण को अस्वीकार कर दिया</string>
<string name="blogs_sharing_invitation_received">%1$sने आपके साथ \"%2$s\" ब्लॉग को साझा किया है</string>
<string name="blogs_sharing_invitation_sent">आपने %1$s को%2$s के साथ साझा किया है</string>
<string name="blogs_sharing_invitations_title">ब्लॉग आमंत्रण</string>
<string name="blogs_sharing_joined_toast">ब्लॉग के लिए सदस्यता लिया</string>
<string name="blogs_sharing_declined_toast">ब्लॉग आमंत्रण अस्वीकृत</string>
<string name="sharing_status_blog">जो कोई भी ब्लॉग के लिए सदस्यता लेता है, उसे अपने संपर्कों के साथ साझा कर सकता है आप इस ब्लॉग को निम्नलिखित संपर्कों के साथ साझा कर रहे हैं। ऐसे अन्य सदस्य भी हो सकते हैं जिन्हें आप नहीं देख सकते हैं।</string>
<!--RSS Feeds-->
<string name="blogs_rss_feeds_import">आरएसएस फ़ीड आयात करें</string>
<string name="blogs_rss_feeds_import_button">आयात</string>
<string name="blogs_rss_feeds_import_hint">आरएसएस फ़ीड का यूआरएल दर्ज करें</string>
<string name="blogs_rss_feeds_import_error">हमें खेद है! आपकी फ़ीड आयात करने में एक त्रुटि हुई</string>
<string name="blogs_rss_feeds_manage">आरएसएस फ़ीड प्रबंधित करें</string>
<string name="blogs_rss_feeds_manage_imported">आयातित:</string>
<string name="blogs_rss_feeds_manage_author">लेखक:</string>
<string name="blogs_rss_feeds_manage_updated">आखरी अपडेट:</string>
<string name="blogs_rss_remove_feed">फ़ीड निकालें</string>
<string name="blogs_rss_remove_feed_dialog_message">क्या आप वाकई इस फ़ीड और सभी पदों को निकालना चाहते हैं? \ N आपके द्वारा साझा की गईं अन्य पोस्ट अन्य लोगों के डिवाइस से नहीं हटाई जाएंगी</string>
<string name="blogs_rss_remove_feed_ok">फ़ीड निकालें</string>
<string name="blogs_rss_feeds_manage_delete_error">फीड हटाया नहीं जा सका!</string>
<string name="blogs_rss_feeds_manage_empty_state">आपने किसी भी आरएसएस फ़ीड का आयात नहीं किया है। \ N \ n आप पहली बार जोड़ने के लिए शीर्ष दाएं स्क्रीन कोने में प्लस क्यों नहीं क्लिक करते हैं?</string>
<string name="blogs_rss_feeds_manage_error">आपकी फ़ीड लोड करने में एक समस्या थी बाद में पुन: प्रयास करें।</string>
<!--Settings Network-->
<string name="network_settings_title">नेटवर्क</string>
<string name="bluetooth_setting">ब्लूटूथ के माध्यम से कनेक्ट करें</string>
<string name="bluetooth_setting_enabled">जब भी संपर्क आस-पास हो</string>
<string name="bluetooth_setting_disabled">केवल जब संपर्क जोड़ते हैं</string>
<string name="tor_network_setting">टो के माध्यम से कनेक्ट करें</string>
<string name="tor_network_setting_never">कभी नहीँ</string>
<string name="tor_network_setting_wifi">केवल वाईफ़ाई का उपयोग करते समय</string>
<string name="tor_network_setting_always">वाई-फ़ाई या मोबाइल डेटा का उपयोग करते समय</string>
<!--Settings Security and Panic-->
<string name="security_settings_title">सुरक्षा</string>
<string name="change_password">पासवर्ड बदलें</string>
<string name="current_password">अपना वर्तमान पासवर्ड दर्ज करें:</string>
<string name="choose_new_password">अपना नया पासवर्ड चुनें:</string>
<string name="confirm_new_password">अपने नए पासवर्ड की पुष्टि करें:</string>
<string name="password_changed">पासवर्ड बदला जा चुका है।</string>
<string name="panic_setting">आतंक बटन सेटअप</string>
<string name="panic_setting_title">घबराहट होना</string>
<string name="panic_setting_hint">कॉन्फ़िगर करें कि जब आप एक आतंक बटन ऐप का उपयोग करते हैं तो Briar कैसे प्रतिक्रिया करेगा</string>
<string name="panic_app_setting_title">आतंक बटन ऐप</string>
<string name="unknown_app">एक अज्ञात ऐप</string>
<string name="panic_app_setting_summary">कोई ऐप सेट नहीं किया गया है</string>
<string name="panic_app_setting_none">कुछ भी नहीं</string>
<string name="dialog_title_connect_panic_app">आतंक ऐप की पुष्टि करें</string>
<string name="dialog_message_connect_panic_app">क्या आप निश्चित हैं कि आप%1$s को विनाशकारी आतंक बटन क्रियाओं को ट्रिगर करने की अनुमति देना चाहते हैं?</string>
<string name="lock_setting_title">साइन आउट</string>
<string name="lock_setting_summary">यदि कोई आतंक बटन दबाया जाता है तो बियर से साइन आउट करें</string>
<string name="purge_setting_title">खाता हटा दो</string>
<string name="purge_setting_summary">यदि आपका आतंक बटन दबाया गया हो तो अपने ब्रियर खाते को हटा दें। सावधानी: यह आपकी पहचान, संपर्क और संदेश को स्थायी रूप से हटा देगा</string>
<string name="uninstall_setting_title">बरिअर की स्थापना रद्द करें</string>
<string name="uninstall_setting_summary">इसके लिए एक आतंक घटना में मैन्युअल पुष्टिकरण की आवश्यकता है</string>
<!--Settings Notifications-->
<string name="notification_settings_title">सूचनाएं</string>
<string name="notify_private_messages_setting_title">निजी संदेश</string>
<string name="notify_private_messages_setting_summary">निजी संदेशों के लिए अलर्ट दिखाएं</string>
<string name="notify_group_messages_setting_title">समूह संदेश</string>
<string name="notify_group_messages_setting_summary">समूह संदेशों के लिए अलर्ट्स दिखाएं</string>
<string name="notify_forum_posts_setting_title">फ़ोरम पोस्ट</string>
<string name="notify_forum_posts_setting_summary">फ़ोरम पोस्ट के लिए अलर्ट्स दिखाएं</string>
<string name="notify_blog_posts_setting_title">वेबदैनिकी डाक</string>
<string name="notify_blog_posts_setting_summary">ब्लॉग पोस्ट के लिए अलर्ट्स दिखाएं</string>
<string name="notify_vibration_setting">कांपना</string>
<string name="notify_lock_screen_setting_title">लॉक स्क्रीन</string>
<string name="notify_lock_screen_setting_summary">लॉक स्क्रीन पर सूचनाएं दिखाएं</string>
<string name="notify_sound_setting">ध्वनि</string>
<string name="notify_sound_setting_default">बकाया घंटी</string>
<string name="notify_sound_setting_disabled">कोई नहीं</string>
<string name="choose_ringtone_title">रिंगटोन चुनें</string>
<!--Settings Feedback-->
<string name="feedback_settings_title">प्रतिक्रिया</string>
<string name="send_feedback">प्रतिक्रिया भेजें</string>
<!--Link Warning-->
<string name="link_warning_title">लिंक चेतावनी</string>
<string name="link_warning_intro">आप बाहरी एप्लिकेशन के साथ निम्न लिंक खोलने वाले हैं</string>
<string name="link_warning_text">इसका इस्तेमाल आपको पहचानने के लिए किया जा सकता है इस बारे में सोचें कि क्या आपको उस व्यक्ति पर भरोसा है जिसने आपको यह लिंक भेजा है और इसे ऑर्फ़ॉक्स के साथ खोलने पर विचार किया है।</string>
<string name="link_warning_open_link">खुली लिंक</string>
<!--Crash Reporter-->
<string name="crash_report_title">ब्रियर क्रैश रिपोर्ट</string>
<string name="briar_crashed">क्षमा करें, बियर दुर्घटनाग्रस्त हो गया है।</string>
<string name="not_your_fault">यह आपकी गलती नहीं है</string>
<string name="please_send_report">कृपया हमें क्रैश रिपोर्ट भेजकर बेहतर बियर बनाने में हमारी सहायता करें</string>
<string name="report_is_encrypted">हम वादा करते हैं कि रिपोर्ट एन्क्रिप्ट की गई है और सुरक्षित रूप से भेजा गया है।</string>
<string name="feedback_title">प्रतिक्रिया</string>
<string name="describe_crash">वर्णन करें कि क्या हुआ (वैकल्पिक)</string>
<string name="enter_feedback">अपना फ़ीडबैक दर्ज करें</string>
<string name="optional_contact_email">आपका ईमेल पता (वैकल्पिक)</string>
<string name="include_debug_report_crash">दुर्घटना के बारे में अनाम डेटा शामिल करें</string>
<string name="include_debug_report_feedback">इस डिवाइस के बारे में अनाम डेटा शामिल करें</string>
<string name="could_not_load_report_data">रिपोर्ट डेटा लोड नहीं किया जा सका</string>
<string name="send_report">रिपोर्ट भेजो</string>
<string name="close">बंद करे</string>
<string name="dev_report_saved">रिपोर्ट सहेजी गई अगली बार जब आप ब्रियर में प्रवेश करेंगे तो उसे भेजा जाएगा।</string>
<!--Sign Out-->
<string name="progress_title_logout">ब्रियर से साइन आउट हो रहा है ...</string>
<!--Screen Filters & Tapjacking-->
<string name="screen_filter_title">स्क्रीन ओवरले का पता लगाया</string>
<string name="screen_filter_body">एक और ऐप ब्रियर के शीर्ष पर है। आपकी सुरक्षा की सुरक्षा के लिए, ब्रियर किसी अन्य ऐप को शीर्ष पर खींचने पर स्पर्श का जवाब नहीं देगा। \ N \ n बरिआर का उपयोग करते समय निम्नलिखित ऐप्स बंद कर दें: \ n \ n%1$s</string>
</resources>

View File

@@ -2,7 +2,7 @@
<resources>
<!--Setup-->
<string name="setup_title">Configuracion de Briar</string>
<string name="setup_explanation">Vòstre compte Briar es salvat e chifrat sus vòstre aparelh, non pas sus en un servidor alunhat \"cloud\". Se desinstalletz Briar o oblidetz vòstre senhal, vòstre compte e vòstras donadas seràn irrecuperables.</string>
<string name="setup_explanation">Vòstre compte Briar es salvat e chifrat sus vòstre aparelh, non pas sus un servidor alonhat \"cloud\". Se desinstalletz Briar o oblidetz vòstre senhal, vòstre compte e vòstras donadas serà pas possible de los recuperar.</string>
<string name="choose_nickname">Causir un escais-nom</string>
<string name="choose_password">Causir un senhal</string>
<string name="confirm_password">Confirmar lo senhal</string>
@@ -16,13 +16,13 @@
<string name="sign_in_button">Se connectar</string>
<string name="forgotten_password">Senhal oblidat</string>
<string name="dialog_title_lost_password">Senhal oblidat</string>
<string name="dialog_message_lost_password">Vòstre compte Briar es salvat e chifrat sus vòstre aparelh, non pas sus en un servidor alunhat \"cloud\". De fècte podèm pas reïnicializar vòstre senhal.
<string name="dialog_message_lost_password">Vòstre compte Briar es salvat e chifrat sus vòstre aparelh, non pas sus un servidor alonhat \"cloud\". De efècte podèm pas reïnicializar vòstre senhal.
Volètz suprimir vòstre compte e ne crear un nòu?\n
\nMèfi:vòstra identitat, vòstres contactes e messatges seràn perduts per totjorn.</string>
<string name="startup_failed_notification_title">Briar a pas pogut aviar</string>
<string name="startup_failed_notification_text">Benlèu que vos cal tornar installar Briar.</string>
<string name="startup_failed_activity_title">Fracàs de laviada de Briar.</string>
<string name="startup_failed_db_error">Per una rason desconeguda vòstra basa de donadas Briar es pas utilizabla e irrecuperabla. Vòstres comptes, donadas e contactes son perduts. Per malastre vos cal tornar installar Briar e configurar un compte nòu.</string>
<string name="startup_failed_db_error">Per una rason desconeguda vòstra basa de donadas Briar es pas utilizabla nimai recuperabla. Vòstres comptes, donadas e contactes son perduts. Per malastre vos cal tornar installar Briar e configurar un compte nòu.</string>
<string name="startup_failed_service_error">Briar a pas pogut aviar un modul necessari. Tornar installar Briar pòt resolver aquò. Que aquò siá dich:perdretz vòstre compte e totas las donadas ligadas a aqueste. Briar utiliza pas de servidor centralizat per salvar sas donadas.</string>
<plurals name="expiry_warning">
<item quantity="one">Aquò es una version Beta de Briar. Vòstre compte sacabarà dins %d jorn e poirà pas èsser renovat.</item>

View File

@@ -22,6 +22,10 @@
<string name="startup_failed_activity_title">Inicialização do Briar falhou</string>
<string name="startup_failed_db_error">Por alguma razão, seus dados do Briar estão corrompidos e não podem ser reparados. Sua conta, seus dados e todas suas conexões com contatos estão perdidas. Infelizmente você terá que resintalar o Briar e criar uma nova conta.</string>
<string name="startup_failed_service_error">O Briar não pode iniciar devido a um plugin. Reinstalar o Briar geralmente resolve esse problema. Porém, note que ao fazer isso você perderá sua conta e todos os dados associados a ela, já que o Briar não usa um servidor central para armazenar seus dados.</string>
<plurals name="expiry_warning">
<item quantity="one">Esta é uma versão beta do Briar. Sua conta irá expirar em %d dias e não poderá ser renovada.</item>
<item quantity="other">Esta é uma versão beta do Briar. Sua conta irá expirar em %d dias e não poderá ser renovada.</item>
</plurals>
<string name="expiry_date_reached">Este software expirou.\nObrigado por testar!</string>
<!--Navigation Drawer-->
<string name="nav_drawer_open_description">Abrir aba de navegação</string>

View File

@@ -20,14 +20,13 @@
<string name="startup_failed_notification_title">Не удалось запустить Briar</string>
<string name="startup_failed_notification_text">Возможно, потребуется переустановить Briar.</string>
<string name="startup_failed_activity_title">Сбой при запуске Briar</string>
<string name="startup_failed_db_error">По какой-то причине, ваша база данных Briar повреждена без возможности восстановления. Ваша учетная запись, ваши данные и все ваши связи с контактами потеряны.
К сожалению, необходимо переустановить Briar и настроить новую учетную запись.</string>
<string name="startup_failed_db_error">По какой-то причине, ваша база данных Briar повреждена без возможности восстановления. Ваша учетная запись, ваши данные и все ваши связи с контактами потеряны. К сожалению, необходимо переустановить Briar и настроить новую учетную запись.</string>
<string name="startup_failed_service_error">Briar не смог запустить требуемый подключаемый модуль. Переустановка Briar обычно решает эту проблему. Однако обратите внимание, что после этого вы потеряете свою учетную запись и все связанные с ней данные, поскольку Briar не использует центральных серверов для хранения данных.</string>
<plurals name="expiry_warning">
<item quantity="one">Это бета-версия Briar. Срок действия вашей учетной записи истекает через %d день и не может быть продлен.</item>
<item quantity="few">Это бета-версия Briar. Срок действия вашей учетной записи истекает через %d дней и не может быть продлен.</item>
<item quantity="many">Это бета-версия Briar. Срок действия вашей учетной записи истекает через %d дней и не может быть продлен.</item>
<item quantity="other">Это бета-версия Briar. Срок действия вашей учетной записи истекает через %d дней и не может быть продлен.</item>
<item quantity="other">Это бета-версия Briar. Срок действия вашей учетной записи истечет через %d дней и не может быть продлен.</item>
</plurals>
<string name="expiry_date_reached">Срок действия этого программного обеспечения истек.\nСпасибо за тестирование!</string>
<!--Navigation Drawer-->
@@ -91,7 +90,7 @@
<string name="text_too_long">Введенный текст слишком длинный</string>
<string name="show_onboarding">Показать справку</string>
<!--Contacts and Private Conversations-->
<string name="no_contacts">Видимо, вы здесь новенький и пока что не имеете контактов.\n\nКоснитесь значка + вверху и следуйте инструкциям, чтобы добавить друзей в список.\n\nПомните: вы можете добавлять новые контакты только лично, чтобы никто не выдал себя за вас и не мог читать ваши сообщения.</string>
<string name="no_contacts">Кажется, вы здесь новенький и у вас нет контактов.\n\nКоснитесь значка + вверху и следуйте инструкциям, чтобы добавить друзей в список.\n\nПомните: вы можете добавлять новые контакты только лично, чтобы никто не выдал себя за вас и не мог читать ваши сообщения.</string>
<string name="date_no_private_messages">Нет сообщений.</string>
<string name="no_private_messages">Это представление беседы.\n\nКажется, у нас нет беседы.\n\nПросто коснитесь поля ввода внизу, чтобы начать беседу.</string>
<string name="message_hint">Печатает сообщение</string>
@@ -102,7 +101,7 @@
<!--Adding Contacts-->
<string name="add_contact_title">Добавить контакт</string>
<string name="your_nickname">Выберите идентификатор, который хотите использовать:</string>
<string name="face_to_face">Необходимо встретиться с человеком, который требуется добавить в качестве контакта.\n\nЭто не позволит кому-либо выдать себя за вас или читать ваши сообщения.</string>
<string name="face_to_face">Вы должны встретиться с человеком, которого хотите добавить в контакты.\n\nЭто не позволит кому-либо выдать себя за вас или читать ваши сообщения.</string>
<string name="continue_button">Продолжить</string>
<string name="your_invitation_code">Ваш код приглашения</string>
<string name="enter_invitation_code">Введите код приглашения вашего контакта:</string>
@@ -153,7 +152,7 @@
<item quantity="other">%d новых контактов добавлено.</item>
</plurals>
<!--Private Groups-->
<string name="groups_list_empty">Вы не состоите в каких-либо группах.\n\nКоснитесь значка + вверху, чтобы создать группу самостоятельно или попросить ваши контакты пригласить их в одну из своих групп.</string>
<string name="groups_list_empty">Вы не состоите в каких-либо группах.\n\nКоснитесь значка + вверху, чтобы создать группу самостоятельно или попросить ваши контакты пригласить вас в одну из своих групп.</string>
<string name="groups_created_by">Создано %s</string>
<plurals name="messages">
<item quantity="one">%d сообщение</item>
@@ -201,21 +200,21 @@
<string name="groups_invitations_response_declined_sent">Вы отклонили приглашение в группу от %s.</string>
<string name="groups_invitations_response_accepted_received">%s принял приглашение в группу.</string>
<string name="groups_invitations_response_declined_received">%s отклонил приглашение в группу.</string>
<string name="sharing_status_groups">Только создатель может пригласить новых членов в группу. Ниже перечислены все текущие члены группы.</string>
<string name="sharing_status_groups">Только создатель может пригласить новых пользователей в группу. Ниже перечислены все текущие пользователи группы.</string>
<!--Private Groups Revealing Contacts-->
<string name="groups_reveal_contacts">Показать контакты</string>
<string name="groups_reveal_dialog_message">Вы можете выбрать, раскрывать ли контакты всем текущим и будущим членам этой группы.\n\nПри раскрытии контактов связь с группой становится более быстрой и надежной, поскольку вы можете общаться с раскрытыми контактами, даже если создатель группы находится в автономном режиме.</string>
<string name="groups_reveal_dialog_message">Вы можете выбрать, раскрывать ли контакты текущим и будущим участникам этой группы.\n\nПри раскрытии контактов связь с группой становится более быстрой и надежной, поскольку вы можете общаться с раскрытыми контактами, даже если создатель группы находится в автономном режиме.</string>
<string name="groups_reveal_visible">Связь между контактами видна группе</string>
<string name="groups_reveal_visible_revealed_by_us">Связь между контактами видна группе (раскрывается вами)</string>
<string name="groups_reveal_visible_revealed_by_contact">Связь между контактами видна группе (раскрывается %s)</string>
<string name="groups_reveal_invisible">Связь между контактами не видна группе</string>
<!--Forums-->
<string name="no_forums">У вас еще нет форумов.\n\nПочему бы вам не создать новый, коснувшись значка + вверху?\n\nВы также можете попросить свои контакты поделиться с вами форумами.</string>
<string name="no_forums">У вас еще нет форумов.\n\nПочему бы вам не создать новый, коснувшись значка + вверху?\n\nМожно также попросить контакты поделиться с вами форумами.</string>
<string name="create_forum_title">Создать форум</string>
<string name="choose_forum_hint">Выберите имя для вашего форума</string>
<string name="create_forum_button">Создать форум</string>
<string name="forum_created_toast">Форум создан</string>
<string name="no_forum_posts">Этот форум пуст.\n\nИспользуйте значок пера вверху, чтобы создать первый пост.\n\nЧувствуете одиночество? Поделитесь этим форумом с вашими контактами!</string>
<string name="no_forum_posts">Этот форум пуст.\n\nСоздайте свою первую запись.\n\nЧувствуете одиночество? Поделитесь этим форумом с вашими контактами!</string>
<string name="no_posts">Нет постов</string>
<plurals name="posts">
<item quantity="one">%d пост</item>
@@ -229,14 +228,14 @@
<string name="btn_reply">Ответ</string>
<string name="forum_leave">Покинуть форум</string>
<string name="dialog_title_leave_forum">Подтвердить</string>
<string name="dialog_message_leave_forum">Вы уверены, что хотите покинуть этот форум? Контакты, с которыми вы поделились этим форумом, могут быть перестать получать обновления этого форума.</string>
<string name="dialog_message_leave_forum">Вы уверены, что хотите покинуть этот форум? Контакты, с которыми вы поделились этим форумом, могут перестать получать обновления этого форума.</string>
<string name="dialog_button_leave">Покинуть</string>
<string name="forum_left_toast">Покинул форум</string>
<!--Forum Sharing-->
<string name="forum_share_button">Поделиться форумом</string>
<string name="contacts_selected">Выбранные контакты</string>
<string name="activity_share_toolbar_header">Выбор контактов</string>
<string name="no_contacts_selector">Кажется, вы здесь новенький и не имеете контактов.\n\nПожалуйста, вернитесь сюда после того, как добавите свой первый контакт.</string>
<string name="no_contacts_selector">Кажется, вы здесь новенький и у вас нет контактов.\n\nПожалуйста, вернитесь сюда после того, как добавите свой первый контакт.</string>
<string name="forum_shared_snackbar">Поделиться форумом совместно с выбранными контактами</string>
<string name="forum_share_message">Добавить сообщение (необязательно)</string>
<string name="forum_share_error">Произошла ошибка при при попытке поделиться этим форумом.</string>
@@ -253,7 +252,7 @@
<string name="forum_invitation_response_accepted_received">%sпринял приглашение на форум.</string>
<string name="forum_invitation_response_declined_received">%s отклонил приглашение на форум.</string>
<string name="sharing_status">Статус общего доступа</string>
<string name="sharing_status_forum">Любой член форума может поделиться своими контактами. Вы делитесь этим форумом со следующими контактами. Могут быть и другие члены, которых вы не видите.</string>
<string name="sharing_status_forum">Любой участник форума может поделиться своими контактами. Вы делитесь этим форумом со следующими контактами. Могут быть и другие участники, которых вы не видите.</string>
<string name="shared_with">Совместно с %1$d (%2$d в сети)</string>
<plurals name="forums_shared">
<item quantity="one">%d форум, общий с контактами</item>
@@ -261,7 +260,7 @@
<item quantity="many">%d форумов, общих с контактами</item>
<item quantity="other">%d форумов, общих с контактами</item>
</plurals>
<string name="nobody">Никто</string>
<string name="nobody">Никого</string>
<!--Blogs-->
<string name="blogs_other_blog_empty_state">Этот блог пуст.\n\nЛибо автор еще ничего не написал, либо человек, который поделился с вами этим блогом, должен выйти в Интернет, чтобы сообщения могли быть синхронизированы.</string>
<string name="read_more">подробнее</string>
@@ -292,7 +291,7 @@
<string name="blogs_sharing_invitations_title">Приглашения в блог</string>
<string name="blogs_sharing_joined_toast">Подписался на блог</string>
<string name="blogs_sharing_declined_toast">Приглашение в блог отклонено</string>
<string name="sharing_status_blog">Любой, кто подписывается на блог, может поделиться им со своими контактами. Вы делитесь этим блогом со следующими контактами. Могут также быть и другие подписчики, которых вы не видите.</string>
<string name="sharing_status_blog">Любой, кто подписывается на блог, может поделиться им со своими контактами. Вы делитесь этим блогом со следующими контактами. Могут быть и другие подписчики, которых вы не видите.</string>
<!--RSS Feeds-->
<string name="blogs_rss_feeds_import">Импорт RSS-канала</string>
<string name="blogs_rss_feeds_import_button">Импорт</string>
@@ -324,21 +323,21 @@
<string name="choose_new_password">Выберите новый пароль:</string>
<string name="confirm_new_password">Подтвердите новый пароль:</string>
<string name="password_changed">Пароль был изменен.</string>
<string name="panic_setting">Настройка кнопки паники</string>
<string name="panic_setting_title">Кнопка паники</string>
<string name="panic_setting_hint">Настройте поведение Briar, когда вы используете приложение Кнопка паники</string>
<string name="panic_app_setting_title">Приложение Кнопка паники</string>
<string name="panic_setting">Настройка тревожной кнопки</string>
<string name="panic_setting_title">Тревожная кнопка</string>
<string name="panic_setting_hint">Настройте поведение Briar, когда вы используете тревожную кнопку</string>
<string name="panic_app_setting_title">Выбор тревожной кнопки</string>
<string name="unknown_app">неизвестное приложение</string>
<string name="panic_app_setting_summary">Приложение не установлено</string>
<string name="panic_app_setting_none">Никто</string>
<string name="dialog_title_connect_panic_app">Подтвердить приложение Паника</string>
<string name="dialog_message_connect_panic_app">Вы уверены, что хотите разрешить %1$s запускать действия разрушительной Кнопкой паники?</string>
<string name="panic_app_setting_none">Нет</string>
<string name="dialog_title_connect_panic_app">Подтвердить тревожную кнопку</string>
<string name="dialog_message_connect_panic_app">Вы уверены, что хотите разрешить %1$s запускать действия тревожной кнопки?</string>
<string name="lock_setting_title">Выйти</string>
<string name="lock_setting_summary">Выйти из Briar, если нажата Кнопка паники</string>
<string name="lock_setting_summary">Выйти из Briar, если нажата тревожная кнопка</string>
<string name="purge_setting_title">Удалить аккаунт</string>
<string name="purge_setting_summary">Удалите свою учетную запись Briar, если нажата Кнопка паники. Предупреждение: это необратимо удалит ваши идентификаторы, контакты и сообщения</string>
<string name="purge_setting_summary">Удалить вашу учетную запись Briar при нажатии тревожной кнопки. Внимание: это необратимо удалит ваши идентификаторы, контакты и сообщения</string>
<string name="uninstall_setting_title">Удалить Briar</string>
<string name="uninstall_setting_summary">Это требует подтверждения вручную в случае возникновения паники</string>
<string name="uninstall_setting_summary">Это потребует вашего подтверждения</string>
<!--Settings Notifications-->
<string name="notification_settings_title">Уведомления</string>
<string name="notify_private_messages_setting_title">Приватные сообщения</string>
@@ -373,7 +372,7 @@
<string name="feedback_title">Обратная связь</string>
<string name="describe_crash">Опишите, что произошло (необязательно)</string>
<string name="enter_feedback">Введите свой отзыв</string>
<string name="optional_contact_email">Ваш адрес электронной почты (необязательно)</string>
<string name="optional_contact_email">Ваш email адрес (необязательно)</string>
<string name="include_debug_report_crash">Включить анонимные данные о сбое</string>
<string name="include_debug_report_feedback">Включить анонимные данные об этом устройстве</string>
<string name="could_not_load_report_data">Не удалось загрузить данные отчета.</string>

View File

@@ -0,0 +1,357 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<!--Setup-->
<string name="setup_title">安装 Briar</string>
<string name="setup_explanation">您的 Briar 账号只会被加密储存在您的设备上,不会被上传。如果您卸载了 Briar 或忘记了密码,将无法恢复您的账号和数据。</string>
<string name="choose_nickname">设置昵称</string>
<string name="choose_password">设置密码</string>
<string name="confirm_password">确认密码</string>
<string name="name_too_long">昵称过长</string>
<string name="password_too_weak">密码强度过弱</string>
<string name="passwords_do_not_match">两次键入密码不一致</string>
<string name="create_account_button">创建账号</string>
<!--Login-->
<string name="enter_password">请输入密码:</string>
<string name="try_again">密码不正确,请重试</string>
<string name="sign_in_button">登录</string>
<string name="forgotten_password">我忘记了密码</string>
<string name="dialog_title_lost_password">忘记密码</string>
<string name="dialog_message_lost_password">您的 Briar 账号被加密储存在您的设备上,而非云端,因此我们无法重置您的密码。您是否希望删除帐号,重新开始?\n\n注意您的身份、联系人和消息将会永久遗失。</string>
<string name="startup_failed_notification_title">Briar 无法启动</string>
<string name="startup_failed_notification_text">你可能需要重新安装 Briar</string>
<string name="startup_failed_activity_title">Briar 启动失败</string>
<string name="startup_failed_db_error">由于某些原因,您的 Briar 数据库损坏并无法修复。您的账号、数据和一切联系人关系均已遗失。我们遗憾地告诉您,您需要重新安装 Briar 并建立新帐号。</string>
<string name="startup_failed_service_error">Briar 无法开启一个必要插件。通常情况下,重新安装 Briar 可以解决这个问题。但是由于 Briar 并不采用中央服务器来储存您的数据,您将丢失您的账号和与您的账号相关的一切数据。</string>
<plurals name="expiry_warning">
<item quantity="other">这是 Briar 的一个测试版本。您的账号将在 %d 天后失效,并且无法恢复。</item>
</plurals>
<string name="expiry_date_reached">本软件已过期。\n感谢您的测试</string>
<!--Navigation Drawer-->
<string name="nav_drawer_open_description">打开抽屉式导航栏</string>
<string name="nav_drawer_close_description">关闭抽屉式导航栏</string>
<string name="contact_list_button">联系人</string>
<string name="groups_button">私有群聊</string>
<string name="forums_button">论坛</string>
<string name="blogs_button">博客</string>
<string name="settings_button">设置</string>
<string name="sign_out_button">登出</string>
<!--Transports-->
<string name="transport_tor">网络</string>
<string name="transport_bt">蓝牙</string>
<string name="transport_lan">无线局域网</string>
<!--Notifications-->
<string name="ongoing_notification_title">登录 Briar</string>
<string name="ongoing_notification_text">轻触以打开 Briar</string>
<plurals name="private_message_notification_text">
<item quantity="other">%d 条新私信。</item>
</plurals>
<plurals name="group_message_notification_text">
<item quantity="other">%d 条新群消息。</item>
</plurals>
<plurals name="forum_post_notification_text">
<item quantity="other">%d 条新论坛帖子。</item>
</plurals>
<plurals name="blog_post_notification_text">
<item quantity="other">%d 条新博文。</item>
</plurals>
<!--Misc-->
<string name="now">现在</string>
<string name="show">显示</string>
<string name="hide">隐藏</string>
<string name="ok"></string>
<string name="cancel">取消</string>
<string name="got_it">知道了</string>
<string name="delete">删除</string>
<string name="accept">接受</string>
<string name="decline">拒绝</string>
<string name="options">选项</string>
<string name="online">在线</string>
<string name="offline">离线</string>
<string name="send">发送</string>
<string name="allow">允许</string>
<string name="open">打开</string>
<string name="no_data">没有数据</string>
<string name="ellipsis"></string>
<string name="text_too_long">输入的文本过长</string>
<string name="show_onboarding">显示帮助对话</string>
<!--Contacts and Private Conversations-->
<string name="no_contacts">似乎你是新来的,目前还没有联系人。\n\n点击上方的 + 按钮并根据提示添加联系人。\n\n请牢记您只能通过面对面的方式添加新联系人以防止未来他人冒充您的身份并查看您的信息。</string>
<string name="date_no_private_messages">没有消息。</string>
<string name="no_private_messages">这是对话视图。\n\n这里似乎缺少对话。\n\n点击下方的输入框来开始对话。</string>
<string name="message_hint">键入信息</string>
<string name="delete_contact">删除联系人</string>
<string name="dialog_title_delete_contact">确认删除联系人</string>
<string name="dialog_message_delete_contact">确认要删除该联系人和与之交流的所有消息吗?</string>
<string name="contact_deleted_toast">联系人已删除</string>
<!--Adding Contacts-->
<string name="add_contact_title">添加联系人</string>
<string name="your_nickname">选取您想使用的身份:</string>
<string name="face_to_face">您必须与您想要添加的联系人见面。\n\n这样可以防止未来他人冒充您的身份并查看您的信息。</string>
<string name="continue_button">继续</string>
<string name="your_invitation_code">您的邀请码是</string>
<string name="enter_invitation_code">请输入您的联系人的邀请码:</string>
<string name="searching_format">正在查找该邀请码对应的联系人 %06d\u2026</string>
<string name="connection_failed">连接失败</string>
<string name="could_not_find_contact">Briar 无法找到您身边的联系人</string>
<string name="try_again_button">重试</string>
<string name="connected_to_contact">连接至联系人</string>
<string name="calculating_confirmation_code">正在计算确认码\u2026</string>
<string name="your_confirmation_code">您的确认码是</string>
<string name="enter_confirmation_code">请输入您的联系人的确认码:</string>
<string name="waiting_for_contact">等待联系人\u2026</string>
<string name="waiting_for_contact_to_scan">等待联系人扫描并连接\u2026</string>
<string name="exchanging_contact_details">交换联系人细节\u2026</string>
<string name="codes_do_not_match">密码不匹配</string>
<string name="interfering">这可能意味着有人正在尝试干预你们的连接</string>
<string name="contact_added_toast">联系人已添加: %s</string>
<string name="contact_already_exists">联系人 %s 已存在</string>
<string name="contact_exchange_failed">联系人交换失败</string>
<string name="qr_code_invalid">二维码无效</string>
<string name="connecting_to_device">正在连接至设备\u2026</string>
<string name="authenticating_with_device">正在验证设备\u2026</string>
<string name="connection_aborted_local">连接已被我们中止!这可能意味着有人正在尝试干预你们的连接</string>
<string name="connection_aborted_remote">连接已被您的联系人中止!这可能意味着有人正在尝试干预你们的连接</string>
<!--Introductions-->
<string name="introduction_onboarding_title">介绍您的联系人</string>
<string name="introduction_onboarding_text">您可以互相介绍联系人,这样他们可以直接在 Briar 上建立联系而不必亲自见面。</string>
<string name="introduction_activity_title">选择联系人</string>
<string name="introduction_message_title">介绍联系人</string>
<string name="introduction_message_hint">添加一句话 (选填)</string>
<string name="introduction_button">完成介绍</string>
<string name="introduction_sent">您的介绍已送出。</string>
<string name="introduction_error">介绍时发生错误。</string>
<string name="introduction_response_error">响应介绍时出错</string>
<string name="introduction_request_sent">您已将 %1$s 介绍给 %2$s。</string>
<string name="introduction_request_received">%1$s 想要将您介绍给 %2$s。您希望将 %2$s 添加至您的联系人列表吗?</string>
<string name="introduction_request_exists_received">%1$s 想要将您介绍给 %2$s但是 %2$s 已经在您的联系人列表。%1$s 可能并不知情,但您仍可以做出回复:</string>
<string name="introduction_request_answered_received">%1$s 想要将您介绍给 %2$s。</string>
<string name="introduction_response_accepted_sent">您已接受与 %1$s 建立联系</string>
<string name="introduction_response_declined_sent">您已谢绝与 %1$s 建立联系</string>
<string name="introduction_response_accepted_received">%1$s 接受与 %2$s 建立联系</string>
<string name="introduction_response_declined_received">%1$s 谢绝与 %2$s 建立联系</string>
<string name="introduction_response_declined_received_by_introducee">%1$s 表示 %2$s 谢绝了介绍。</string>
<plurals name="introduction_notification_text">
<item quantity="other">已添加 %d 位新联系人。</item>
</plurals>
<!--Private Groups-->
<string name="groups_list_empty">您尚未参与任何群聊\n\n轻触上方的 + 按钮创建群聊或通过联系人邀请进入群聊。</string>
<string name="groups_created_by">由 %s 创建</string>
<plurals name="messages">
<item quantity="other">%d 条消息。</item>
</plurals>
<string name="groups_group_is_empty">该群聊是空的</string>
<string name="groups_group_is_dissolved">该群聊已被解散</string>
<string name="groups_remove">删除</string>
<string name="groups_create_group_title">创建私有群聊</string>
<string name="groups_create_group_button">创建群聊</string>
<string name="groups_create_group_invitation_button">发送邀请</string>
<string name="groups_create_group_hint">为私有群聊命名</string>
<string name="groups_invitation_sent">群聊邀请已发送</string>
<string name="groups_message_sent">消息已发送</string>
<string name="groups_member_list">成员列表</string>
<string name="groups_invite_members">邀请成员</string>
<string name="groups_member_created_you">您创建了群聊</string>
<string name="groups_member_created">%s 创建了群聊</string>
<string name="groups_member_joined_you">您加入了群聊</string>
<string name="groups_member_joined">%s 加入了群聊</string>
<string name="groups_leave">退出群聊</string>
<string name="groups_leave_dialog_title">确认退出群聊</string>
<string name="groups_leave_dialog_message">确认要退出该群聊吗?</string>
<string name="groups_dissolve">解散群聊</string>
<string name="groups_dissolve_dialog_title">确认解散群聊</string>
<string name="groups_dissolve_dialog_message">确认要解散该群聊吗?\n\n所有其他成员将无法继续会话并可能无法接收最新的消息。</string>
<string name="groups_dissolve_button">解散</string>
<string name="groups_dissolved_dialog_title">群聊已解散</string>
<string name="groups_dissolved_dialog_message">群聊创建者已解散该群聊。\n\n您将无法在群聊中发送消息并可能无法接收所有已编辑好的消息。</string>
<!--Private Group Invitations-->
<string name="groups_invitations_title">群聊邀请</string>
<string name="groups_invitations_invitation_sent">您已邀请 %1$s 加入群聊 “%2$s”。</string>
<string name="groups_invitations_invitation_received">%1$s 已邀请您加入群聊 “%2$s”。</string>
<string name="groups_invitations_joined">群聊已加入</string>
<string name="groups_invitations_declined">群聊邀请已谢绝</string>
<plurals name="groups_invitations_open">
<item quantity="other">%d 打开了群聊邀请</item>
</plurals>
<string name="groups_invitations_response_accepted_sent">您接受了来自 %s的群聊邀请</string>
<string name="groups_invitations_response_declined_sent">您谢绝了来自 %s的群聊邀请</string>
<string name="groups_invitations_response_accepted_received">%s 接受了群聊邀请。</string>
<string name="groups_invitations_response_declined_received">%s 谢绝了群聊邀请。</string>
<string name="sharing_status_groups">只有创建者可以邀请新成员加入群聊。下面是目前的群成员。</string>
<!--Private Groups Revealing Contacts-->
<string name="groups_reveal_contacts">显示联系人</string>
<string name="groups_reveal_dialog_message">您可以决定是否对当前和将来的群成员显示联系人列表\n\n这将使你们之间的联系更快捷和稳定因为你们可与已显示的联系人交流即使群创建者离线。</string>
<string name="groups_reveal_visible">联系人关系对群聊可见</string>
<string name="groups_reveal_visible_revealed_by_us">联系人关系对群聊可见 (由您设定)</string>
<string name="groups_reveal_visible_revealed_by_contact">联系人关系对群聊可见 (由 %s 设定)</string>
<string name="groups_reveal_invisible">联系人关系对群聊不可见</string>
<!--Forums-->
<string name="no_forums">您目前还没有加入论坛\n\n轻触上方的 + 按钮以创建新论坛。\n\n您还可以通过联系人分享论坛给您。</string>
<string name="create_forum_title">创建论坛</string>
<string name="choose_forum_hint">为论坛命名</string>
<string name="create_forum_button">创建论坛</string>
<string name="forum_created_toast">论坛已创建</string>
<string name="no_forum_posts">该论坛是空的\n\n使用上方的钢笔按钮创建第一篇博文\n\n感觉很孤单将此论坛分享给您的联系人吧</string>
<string name="no_posts">无帖子</string>
<plurals name="posts">
<item quantity="other">%d 条帖子</item>
</plurals>
<string name="forum_new_entry_posted">论坛条目已发布</string>
<string name="forum_new_message_hint">新条目</string>
<string name="forum_message_reply_hint">新回复</string>
<string name="btn_reply">回复</string>
<string name="forum_leave">退出论坛</string>
<string name="dialog_title_leave_forum">确认退出论坛</string>
<string name="dialog_message_leave_forum">确认要离开此论坛吗?那些经过你的分享而进入该论坛的联系人将不会收到此论坛的更新。</string>
<string name="dialog_button_leave">退出</string>
<string name="forum_left_toast">已退出论坛</string>
<!--Forum Sharing-->
<string name="forum_share_button">分享论坛</string>
<string name="contacts_selected">已选择联系人</string>
<string name="activity_share_toolbar_header">选择联系人</string>
<string name="no_contacts_selector">似乎你是新来的,目前还没有联系人。\n\n请添加联系人后再来。</string>
<string name="forum_shared_snackbar">论坛已分享给选中的联系人</string>
<string name="forum_share_message">添加一句话 (选填)</string>
<string name="forum_share_error">分享此论坛时发生错误。</string>
<string name="forum_invitation_received">%1$s 已将论坛 “%2$s” 分享给你。</string>
<string name="forum_invitation_sent">您已将论坛 “%1$s” 分享给 %2$s。</string>
<string name="forum_invitations_title">论坛邀请</string>
<string name="forum_invitation_exists">您已接收了加入此论坛的一个邀请。接受更多邀请会促进和增强论坛的交流。</string>
<string name="forum_joined_toast">已加入论坛</string>
<string name="forum_declined_toast">论坛邀请已谢绝</string>
<string name="shared_by_format">由 %s 分享</string>
<string name="forum_invitation_already_sharing">已在分享</string>
<string name="forum_invitation_response_accepted_sent">您接受了来自 %s的论坛邀请</string>
<string name="forum_invitation_response_declined_sent">您谢绝了来自 %s的论坛邀请</string>
<string name="forum_invitation_response_accepted_received">%s 接受了论坛邀请。</string>
<string name="forum_invitation_response_declined_received">%s 谢绝了论坛邀请。</string>
<string name="sharing_status">分享状态</string>
<string name="sharing_status_forum">论坛的任何成员都可以将论坛分享给他们的联系人。您正在分享此论坛给下列联系人。论坛中可能有您所不可见的其他成员。</string>
<string name="shared_with">被 %1$d 人分享 (%2$d 人在线)</string>
<plurals name="forums_shared">
<item quantity="other">%d 个论坛被联系人分享</item>
</plurals>
<string name="nobody">没有人</string>
<!--Blogs-->
<string name="blogs_other_blog_empty_state">这个博客目前是空的。\n\n这有可能是因为作者尚未发布任何内容或者是分享该博客给您的人需要上线以使博文同步。</string>
<string name="read_more">阅读更多</string>
<string name="blogs_write_blog_post">写博文</string>
<string name="blogs_write_blog_post_body_hint">在此输入博文</string>
<string name="blogs_publish_blog_post">发布</string>
<string name="blogs_blog_post_created">博文已创建</string>
<string name="blogs_blog_post_received">收到新博文</string>
<string name="blogs_blog_post_scroll_to">滑动至</string>
<string name="blogs_feed_empty_state">这里是环球博客订阅\n\n目前似乎还没有人发表博文。\n\n轻触钢笔按钮以书写一个新博文成为第一个发表博文的人。</string>
<string name="blogs_remove_blog">删除博客</string>
<string name="blogs_remove_blog_dialog_message">确认要删除此订阅及其所有博文吗?\n请注意该博客将不会从他人的设备中删除。</string>
<string name="blogs_remove_blog_ok">删除博客</string>
<string name="blogs_blog_removed">博客已删除</string>
<string name="blogs_reblog_comment_hint">添加评论 (选填)</string>
<string name="blogs_reblog_button">转载</string>
<!--Blog Sharing-->
<string name="blogs_sharing_share">分享博客</string>
<string name="blogs_sharing_error">分享此博客时发生错误。</string>
<string name="blogs_sharing_button">分享博客</string>
<string name="blogs_sharing_snackbar">博客已分享给选中的联系人</string>
<string name="blogs_sharing_response_accepted_sent">您接受了来自 %s的博客邀请</string>
<string name="blogs_sharing_response_declined_sent">您谢绝了来自 %s的博客邀请</string>
<string name="blogs_sharing_response_accepted_received">%s 接受了博客邀请。</string>
<string name="blogs_sharing_response_declined_received">%s 谢绝了博客邀请。</string>
<string name="blogs_sharing_invitation_received">%1$s 向您分享博客 “%2$s”。</string>
<string name="blogs_sharing_invitation_sent">您已将博客 “%1$s” 分享给 %2$s。</string>
<string name="blogs_sharing_invitations_title">博客邀请</string>
<string name="blogs_sharing_joined_toast">订阅到博客</string>
<string name="blogs_sharing_declined_toast">博客邀请已谢绝</string>
<string name="sharing_status_blog">任何订阅博客的人都可以将它分享给他的联系人。您正在将该博客分享给下列联系人。可能有其他您所不可见的订阅者存在。</string>
<!--RSS Feeds-->
<string name="blogs_rss_feeds_import">导入 RSS 订阅</string>
<string name="blogs_rss_feeds_import_button">导入</string>
<string name="blogs_rss_feeds_import_hint">输入 RSS 订阅链接</string>
<string name="blogs_rss_feeds_import_error">抱歉!导入订阅时出错。</string>
<string name="blogs_rss_feeds_manage">管理 RSS 订阅。</string>
<string name="blogs_rss_feeds_manage_imported">已导入:</string>
<string name="blogs_rss_feeds_manage_author">作者:</string>
<string name="blogs_rss_feeds_manage_updated">最后更新于:</string>
<string name="blogs_rss_remove_feed">删除订阅</string>
<string name="blogs_rss_remove_feed_dialog_message">确认要删除此订阅及其所有博文吗?\n任何您分享过的博文不会从他人的设备中删除。</string>
<string name="blogs_rss_remove_feed_ok">删除订阅</string>
<string name="blogs_rss_feeds_manage_delete_error">该订阅无法被删除!</string>
<string name="blogs_rss_feeds_manage_empty_state">您尚未导入任何 RSS 订阅。\n\n轻触屏幕右上角的加号以添加第一个订阅。</string>
<string name="blogs_rss_feeds_manage_error">加载订阅时出错。请稍候再试。</string>
<!--Settings Network-->
<string name="network_settings_title">网络</string>
<string name="bluetooth_setting">通过蓝牙连接</string>
<string name="bluetooth_setting_enabled">联系人在附近时</string>
<string name="bluetooth_setting_disabled">仅在添加联系人时</string>
<string name="tor_network_setting">通过 Tor 连接</string>
<string name="tor_network_setting_never">从不</string>
<string name="tor_network_setting_wifi">仅在使用无线局域网时</string>
<string name="tor_network_setting_always">使用无线局域网或数据流量时</string>
<!--Settings Security and Panic-->
<string name="security_settings_title">安全</string>
<string name="change_password">更改密码</string>
<string name="current_password">输入当前密码:</string>
<string name="choose_new_password">键入新密码:</string>
<string name="confirm_new_password">确认新密码:</string>
<string name="password_changed">密码已更改。</string>
<string name="panic_setting">创建应急开关</string>
<string name="panic_setting_title">应急开关</string>
<string name="panic_setting_hint">设置触发应急开关时 Briar 的响应</string>
<string name="panic_app_setting_title">应急开关应用程序</string>
<string name="unknown_app">未知应用</string>
<string name="panic_app_setting_summary">未设置应用</string>
<string name="panic_app_setting_none"></string>
<string name="dialog_title_connect_panic_app">确认应急应用</string>
<string name="dialog_message_connect_panic_app">是否允许 %1$s 触发破坏性应急开关反应?</string>
<string name="lock_setting_title">登出</string>
<string name="lock_setting_summary">触发应急开关时登出 Briar</string>
<string name="purge_setting_title">删除账号</string>
<string name="purge_setting_summary">触发应急开关时删除您的账号。注意:您的身份、联系人和消息将会永久遗失。</string>
<string name="uninstall_setting_title">卸载 Briar</string>
<string name="uninstall_setting_summary">这需要在紧急事件中进行人工确认</string>
<!--Settings Notifications-->
<string name="notification_settings_title">消息提醒</string>
<string name="notify_private_messages_setting_title">私信</string>
<string name="notify_private_messages_setting_summary">显示私信通知</string>
<string name="notify_group_messages_setting_title">群消息</string>
<string name="notify_group_messages_setting_summary">显示群聊消息通知</string>
<string name="notify_forum_posts_setting_title">论坛帖子</string>
<string name="notify_forum_posts_setting_summary">显示论坛帖子通知</string>
<string name="notify_blog_posts_setting_title">博文</string>
<string name="notify_blog_posts_setting_summary">显示博文通知</string>
<string name="notify_vibration_setting">震动</string>
<string name="notify_lock_screen_setting_title">锁定屏幕</string>
<string name="notify_lock_screen_setting_summary">在锁定屏幕上显示通知</string>
<string name="notify_sound_setting">声音</string>
<string name="notify_sound_setting_default">默认铃声</string>
<string name="notify_sound_setting_disabled"></string>
<string name="choose_ringtone_title">选择铃声</string>
<!--Settings Feedback-->
<string name="feedback_settings_title">反馈</string>
<string name="send_feedback">提交反馈</string>
<!--Link Warning-->
<string name="link_warning_title">链接警告</string>
<string name="link_warning_intro">您将要在另一个应用中打开以下链接</string>
<string name="link_warning_text">这可能被用来辨认您。请考虑您是否信任发送链接的人,并考虑使用 Orfox 打开链接。</string>
<string name="link_warning_open_link">打开链接</string>
<!--Crash Reporter-->
<string name="crash_report_title">Briar 崩溃报告</string>
<string name="briar_crashed">抱歉, Briar 已崩溃。</string>
<string name="not_your_fault">这并非您的错误所致。</string>
<string name="please_send_report">发送崩溃报告,以帮助我们优化 Briar 。</string>
<string name="report_is_encrypted">我们保证报告将会加密并被安全地发送。</string>
<string name="feedback_title">反馈</string>
<string name="describe_crash">描述发生了什么 (选填)</string>
<string name="enter_feedback">输入您的反馈</string>
<string name="optional_contact_email">您的邮箱地址 (选填)</string>
<string name="include_debug_report_crash">包含本次崩溃的匿名数据</string>
<string name="include_debug_report_feedback">包含本设备的匿名数据</string>
<string name="could_not_load_report_data">无法加载报告数据。</string>
<string name="send_report">发送报告</string>
<string name="close">关闭</string>
<string name="dev_report_saved">报告已保存,将于下次登录时发送。</string>
<!--Sign Out-->
<string name="progress_title_logout">登出 Briar…</string>
<!--Screen Filters & Tapjacking-->
<string name="screen_filter_title">检测到屏幕覆盖</string>
<string name="screen_filter_body">另一个应用覆盖在 Briar 上。为了保护您的安全,在有其他应用覆盖的情况下, Briar 将不会对触控做出反应。\n\n使用 Briar 时请尝试关闭以下程序:\n\n%1$s</string>
</resources>

View File

@@ -22,12 +22,13 @@
<string name="startup_failed_notification_title">Briar could not start</string>
<string name="startup_failed_notification_text">You may need to reinstall Briar.</string>
<string name="startup_failed_activity_title">Briar Startup Failure</string>
<string name="startup_failed_db_error">For some reason, your Briar database is corrupted beyond repair. Your account, your data and all your contact connections are lost. Unfortunately, you need to reinstall Briar und set up a new account.</string>
<string name="startup_failed_db_error">For some reason, your Briar database is corrupted beyond repair. Your account, your data and all your contacts are lost. Unfortunately, you need to reinstall Briar and set up a new account.</string>
<string name="startup_failed_service_error">Briar was unable to start a required plugin. Reinstalling Briar usually solves this problem. However, please note that you will then lose your account and all data associated with it since Briar is not using central servers to store your data on.</string>
<plurals name="expiry_warning">
<item quantity="one">This is a beta version of Briar. Your account will expire in %d day and cannot be renewed.</item>
<item quantity="other">This is a beta version of Briar. Your account will expire in %d days and cannot be renewed.</item>
</plurals>
<string name="expiry_update">The beta expiry date has been extended. Your account will now expire in %d days.</string>
<string name="expiry_date_reached">This software has expired.\nThank you for testing!</string>
<!-- Navigation Drawer -->
@@ -111,7 +112,7 @@
<string name="camera_error">Camera error</string>
<string name="connecting_to_device">Connecting to device\u2026</string>
<string name="authenticating_with_device">Authenticating with device\u2026</string>
<string name="connection_aborted_local">Connection aborted by us! This could mean that someone is trying to interfere with your connection</string>
<string name="connection_aborted_local">Connection aborted! This could mean that someone is trying to interfere with your connection</string>
<string name="connection_aborted_remote">Connection aborted by your contact! This could mean that someone is trying to interfere with your connection</string>
<!-- Introductions -->
@@ -381,4 +382,10 @@
<string name="screen_filter_title">Screen overlay detected</string>
<string name="screen_filter_body">Another app is drawing on top of Briar. To protect your security, Briar will not respond to touches when another app is drawing on top.\n\nTry turning off the following apps when using Briar:\n\n%1$s</string>
<!-- Permission Requests and Doze Mode -->
<string name="permission_camera_title">Camera permission</string>
<string name="permission_camera_request_body">To scan the QR code, Briar needs access to the camera.</string>
<string name="permission_camera_denied_body">You have denied access to the camera, but adding contacts requires using the camera.\n\nPlease consider granting access.</string>
<string name="permission_camera_denied_toast">Camera permission was not granted</string>
</resources>

View File

@@ -25,6 +25,8 @@
</PreferenceCategory>
<PreferenceCategory android:layout="@layout/divider_preference"/>
<PreferenceCategory
android:title="@string/security_settings_title">
@@ -39,6 +41,8 @@
</PreferenceCategory>
<PreferenceCategory android:layout="@layout/divider_preference"/>
<PreferenceCategory
android:title="@string/panic_setting_title">
@@ -54,6 +58,8 @@
</PreferenceCategory>
<PreferenceCategory android:layout="@layout/divider_preference"/>
<PreferenceCategory
android:title="@string/notification_settings_title">
@@ -61,36 +67,36 @@
android:defaultValue="true"
android:key="pref_key_notify_private_messages"
android:persistent="false"
android:title="@string/notify_private_messages_setting_title"
android:summary="@string/notify_private_messages_setting_summary"/>
android:summary="@string/notify_private_messages_setting_summary"
android:title="@string/notify_private_messages_setting_title"/>
<CheckBoxPreference
android:defaultValue="true"
android:key="pref_key_notify_group_messages"
android:persistent="false"
android:title="@string/notify_group_messages_setting_title"
android:summary="@string/notify_group_messages_setting_summary"/>
android:summary="@string/notify_group_messages_setting_summary"
android:title="@string/notify_group_messages_setting_title"/>
<CheckBoxPreference
android:defaultValue="true"
android:key="pref_key_notify_forum_posts"
android:persistent="false"
android:title="@string/notify_forum_posts_setting_title"
android:summary="@string/notify_forum_posts_setting_summary"/>
android:summary="@string/notify_forum_posts_setting_summary"
android:title="@string/notify_forum_posts_setting_title"/>
<CheckBoxPreference
android:defaultValue="true"
android:key="pref_key_notify_blog_posts"
android:persistent="false"
android:title="@string/notify_blog_posts_setting_title"
android:summary="@string/notify_blog_posts_setting_summary"/>
android:summary="@string/notify_blog_posts_setting_summary"
android:title="@string/notify_blog_posts_setting_title"/>
<CheckBoxPreference
android:defaultValue="false"
android:key="pref_key_notify_lock_screen"
android:persistent="false"
android:title="@string/notify_lock_screen_setting_title"
android:summary="@string/notify_lock_screen_setting_summary"
android:title="@string/notify_lock_screen_setting_title"
android:visibility="gone"/>
<CheckBoxPreference
@@ -105,6 +111,8 @@
</PreferenceCategory>
<PreferenceCategory android:layout="@layout/divider_preference"/>
<PreferenceCategory
android:title="@string/feedback_settings_title">
@@ -114,4 +122,8 @@
</PreferenceCategory>
<Preference
android:key="pref_key_test_data"
android:title="Create Test Data"/>
</PreferenceScreen>

View File

@@ -5,5 +5,5 @@ targetCompatibility = 1.6
apply plugin: 'witness'
dependencies {
compile project(':bramble-api')
compile project(path: ':bramble-api', configuration: 'default')
}

View File

@@ -0,0 +1,11 @@
package org.briarproject.briar.api.test;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface TestDataCreator {
/* Creates fake test data on the DatabaseExecutor */
void createTestData();
}

View File

@@ -10,13 +10,13 @@ targetCompatibility = 1.6
apply plugin: 'witness'
dependencies {
compile project(':briar-api')
compile project(path: ':briar-api', configuration: 'default')
compile 'com.rometools:rome:1.7.3'
compile 'org.jdom:jdom2:2.0.6'
compile 'com.squareup.okhttp3:okhttp:3.8.0'
compile 'org.jsoup:jsoup:1.10.3'
testCompile project(':bramble-core')
testCompile project(path: ':bramble-core', configuration: 'default')
testCompile project(path: ':bramble-core', configuration: 'testOutput')
testCompile project(path: ':bramble-api', configuration: 'testOutput')
testCompile 'net.jodah:concurrentunit:0.4.2'

View File

@@ -26,4 +26,5 @@ public interface BriarCoreEagerSingletons {
void inject(PrivateGroupModule.EagerSingletons init);
void inject(SharingModule.EagerSingletons init);
}

View File

@@ -10,6 +10,7 @@ import org.briarproject.briar.messaging.MessagingModule;
import org.briarproject.briar.privategroup.PrivateGroupModule;
import org.briarproject.briar.privategroup.invitation.GroupInvitationModule;
import org.briarproject.briar.sharing.SharingModule;
import org.briarproject.briar.test.TestModule;
import dagger.Module;
@@ -23,7 +24,8 @@ import dagger.Module;
IntroductionModule.class,
MessagingModule.class,
PrivateGroupModule.class,
SharingModule.class
SharingModule.class,
TestModule.class
})
public class BriarCoreModule {

View File

@@ -0,0 +1,68 @@
package org.briarproject.briar.test;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH;
public interface TestData {
String AUTHOR_NAMES[] = {
"Thales",
"Pythagoras",
"Plato",
"Aristotle",
"Euclid",
"Archimedes",
"Hipparchus",
"Ptolemy",
"Sun Tzu",
"Ibrahim ibn Sinan",
"Muhammad Al-Karaji",
"Yang Hui",
"René Descartes",
"Pierre de Fermat",
"Blaise Pascal",
"Jacob Bernoulli",
"Christian Goldbach",
"Leonhard Euler",
"Joseph Louis Lagrange",
"Pierre-Simon Laplace",
"Joseph Fourier",
"Carl Friedrich Gauss",
"Charles Babbage",
"George Boole",
"John Venn",
"Gottlob Frege",
"Henri Poincaré",
"David Hilbert",
"Bertrand Russell",
"John von Neumann",
"Kurt Gödel",
"Alan Turing",
"Benoît Mandelbrot",
"John Nash",
getRandomString(MAX_AUTHOR_NAME_LENGTH),
getRandomString(MAX_AUTHOR_NAME_LENGTH),
getRandomString(MAX_AUTHOR_NAME_LENGTH),
getRandomString(MAX_AUTHOR_NAME_LENGTH),
getRandomString(MAX_AUTHOR_NAME_LENGTH),
getRandomString(MAX_AUTHOR_NAME_LENGTH),
getRandomString(MAX_AUTHOR_NAME_LENGTH),
};
String GROUP_NAMES[] = {
"Private Messengers",
"The Darknet",
"Bletchley Park",
"Acropolis",
"General Discussion",
"The Undiscovered Country",
"The Place to Be",
"Forum Romanum",
getRandomString(MAX_FORUM_NAME_LENGTH),
getRandomString(MAX_FORUM_NAME_LENGTH),
getRandomString(MAX_FORUM_NAME_LENGTH),
getRandomString(MAX_FORUM_NAME_LENGTH),
};
}

View File

@@ -0,0 +1,409 @@
package org.briarproject.briar.test;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.plugin.BluetoothConstants;
import org.briarproject.bramble.api.plugin.LanTcpConstants;
import org.briarproject.bramble.api.plugin.TorConstants;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.briar.api.blog.Blog;
import org.briarproject.briar.api.blog.BlogManager;
import org.briarproject.briar.api.blog.BlogPost;
import org.briarproject.briar.api.blog.BlogPostFactory;
import org.briarproject.briar.api.client.MessageTracker;
import org.briarproject.briar.api.forum.Forum;
import org.briarproject.briar.api.forum.ForumManager;
import org.briarproject.briar.api.forum.ForumPost;
import org.briarproject.briar.api.messaging.MessagingManager;
import org.briarproject.briar.api.messaging.PrivateMessage;
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
import org.briarproject.briar.api.test.TestDataCreator;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import javax.inject.Inject;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.briarproject.briar.test.TestData.AUTHOR_NAMES;
import static org.briarproject.briar.test.TestData.GROUP_NAMES;
public class TestDataCreatorImpl implements TestDataCreator {
private final static int NUM_CONTACTS = 20;
private final static int NUM_PRIVATE_MSGS = 15;
private final static int NUM_BLOG_POSTS = 30;
private final static int NUM_FORUMS = 3;
private final static int NUM_FORUM_POSTS = 30;
private final Logger LOG =
Logger.getLogger(TestDataCreatorImpl.class.getName());
private final AuthorFactory authorFactory;
private final Clock clock;
private final PrivateMessageFactory privateMessageFactory;
private final ClientHelper clientHelper;
private final MessageTracker messageTracker;
private final BlogPostFactory blogPostFactory;
private final CryptoComponent cryptoComponent;
private final DatabaseComponent db;
private final IdentityManager identityManager;
private final ContactManager contactManager;
private final TransportPropertyManager transportPropertyManager;
private final MessagingManager messagingManager;
private final BlogManager blogManager;
private final ForumManager forumManager;
@IoExecutor
private final Executor ioExecutor;
private final Random random = new Random();
private final Map<Contact, LocalAuthor> localAuthors =
new HashMap<Contact, LocalAuthor>();
@Inject
TestDataCreatorImpl(AuthorFactory authorFactory, Clock clock,
PrivateMessageFactory privateMessageFactory,
ClientHelper clientHelper, MessageTracker messageTracker,
BlogPostFactory blogPostFactory, CryptoComponent cryptoComponent,
DatabaseComponent db, IdentityManager identityManager,
ContactManager contactManager,
TransportPropertyManager transportPropertyManager,
MessagingManager messagingManager, BlogManager blogManager,
ForumManager forumManager, @IoExecutor Executor ioExecutor) {
this.authorFactory = authorFactory;
this.clock = clock;
this.privateMessageFactory = privateMessageFactory;
this.clientHelper = clientHelper;
this.messageTracker = messageTracker;
this.blogPostFactory = blogPostFactory;
this.cryptoComponent = cryptoComponent;
this.db = db;
this.identityManager = identityManager;
this.contactManager = contactManager;
this.transportPropertyManager = transportPropertyManager;
this.messagingManager = messagingManager;
this.blogManager = blogManager;
this.forumManager = forumManager;
this.ioExecutor = ioExecutor;
}
public void createTestData() {
ioExecutor.execute(new Runnable() {
@Override
public void run() {
try {
createTestDataOnDbExecutor();
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) {
LOG.log(WARNING, "Creating test data failed", e);
}
}
}
});
}
@IoExecutor
private void createTestDataOnDbExecutor() throws DbException {
List<Contact> contacts = createContacts();
createPrivateMessages(contacts);
createBlogPosts(contacts);
List<Forum> forums = createForums(contacts);
for (Forum forum : forums) {
createRandomForumPosts(forum, contacts);
}
}
private List<Contact> createContacts() throws DbException {
List<Contact> contacts = new ArrayList<Contact>(NUM_CONTACTS);
LocalAuthor localAuthor = identityManager.getLocalAuthor();
for (int i = 0; i < NUM_CONTACTS; i++) {
Contact contact = addRandomContact(localAuthor);
contacts.add(contact);
}
return contacts;
}
private Contact addRandomContact(LocalAuthor localAuthor)
throws DbException {
// prepare to add contact
LocalAuthor author = getRandomAuthor();
SecretKey secretKey = getSecretKey();
long timestamp = clock.currentTimeMillis();
boolean verified = random.nextBoolean();
// prepare transport properties
Map<TransportId, TransportProperties> props =
getRandomTransportProperties();
Contact contact;
Transaction txn = db.startTransaction(false);
try {
ContactId contactId = contactManager
.addContact(txn, author, localAuthor.getId(), secretKey,
timestamp, true, verified, true);
transportPropertyManager.addRemoteProperties(txn, contactId, props);
contact = db.getContact(txn, contactId);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
if (LOG.isLoggable(INFO)) {
LOG.info("Added contact " + author.getName());
LOG.info("with transport properties: " + props.toString());
}
localAuthors.put(contact, author);
return contact;
}
private LocalAuthor getRandomAuthor() {
int i = random.nextInt(AUTHOR_NAMES.length);
String authorName = AUTHOR_NAMES[i];
KeyPair keyPair = cryptoComponent.generateSignatureKeyPair();
byte[] publicKey = keyPair.getPublic().getEncoded();
byte[] privateKey = keyPair.getPrivate().getEncoded();
return authorFactory
.createLocalAuthor(authorName, publicKey, privateKey);
}
private SecretKey getSecretKey() {
byte[] b = new byte[SecretKey.LENGTH];
random.nextBytes(b);
return new SecretKey(b);
}
private Map<TransportId, TransportProperties> getRandomTransportProperties() {
Map<TransportId, TransportProperties> props =
new HashMap<TransportId, TransportProperties>();
// Bluetooth
TransportProperties bt = new TransportProperties();
String btAddress = getRandomBluetoothAddress();
bt.put(BluetoothConstants.PROP_ADDRESS, btAddress);
props.put(BluetoothConstants.ID, bt);
// LAN
TransportProperties lan = new TransportProperties();
String lanAddress = getRandomLanAddress();
lan.put(LanTcpConstants.PROP_IP_PORTS, lanAddress);
props.put(LanTcpConstants.ID, lan);
// Tor
TransportProperties tor = new TransportProperties();
String torAddress = getRandomTorAddress();
tor.put(TorConstants.PROP_ONION, torAddress);
props.put(TorConstants.ID, tor);
return props;
}
private String getRandomBluetoothAddress() {
byte[] mac = new byte[6];
random.nextBytes(mac);
StringBuilder sb = new StringBuilder(18);
for (byte b : mac) {
if (sb.length() > 0) sb.append(":");
sb.append(String.format("%02x", b));
}
return sb.toString();
}
private String getRandomLanAddress() {
StringBuilder sb = new StringBuilder();
// address
for (int i = 0; i < 4; i++) {
if (sb.length() > 0) sb.append(".");
sb.append(random.nextInt(256));
}
// port
sb.append(":");
sb.append(1024 + random.nextInt(50000));
return sb.toString();
}
private String getRandomTorAddress() {
StringBuilder sb = new StringBuilder();
// address
for (int i = 0; i < 16; i++) {
if (random.nextBoolean())
sb.append(2 + random.nextInt(5));
else
sb.append((char) (random.nextInt(26) + 'a'));
}
return sb.toString();
}
private void createPrivateMessages(List<Contact> contacts)
throws DbException {
for (Contact contact : contacts) {
Group group = messagingManager.getContactGroup(contact);
for (int i = 0; i < NUM_PRIVATE_MSGS; i++) {
try {
createPrivateMessage(group.getId(), i);
} catch (FormatException e) {
throw new RuntimeException(e);
}
}
}
if (LOG.isLoggable(INFO)) {
LOG.info("Created " + NUM_PRIVATE_MSGS +
" private messages per contact.");
}
}
private void createPrivateMessage(GroupId groupId, int num)
throws DbException, FormatException {
long timestamp = clock.currentTimeMillis() - num * 60 * 1000;
String body = getRandomText();
PrivateMessage m = privateMessageFactory
.createPrivateMessage(groupId, timestamp, body);
boolean local = random.nextBoolean();
BdfDictionary meta = new BdfDictionary();
meta.put("timestamp", timestamp);
meta.put("local", local);
meta.put("read", local); // all local messages are read
Transaction txn = db.startTransaction(false);
try {
clientHelper.addLocalMessage(txn, m.getMessage(), meta, true);
if (local) messageTracker.trackOutgoingMessage(txn, m.getMessage());
else messageTracker.trackIncomingMessage(txn, m.getMessage());
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
}
private void createBlogPosts(List<Contact> contacts)
throws DbException {
for (int i = 0; i < NUM_BLOG_POSTS; i++) {
Contact contact = contacts.get(random.nextInt(contacts.size()));
LocalAuthor author = localAuthors.get(contact);
addBlogPost(author, i);
}
if (LOG.isLoggable(INFO)) {
LOG.info("Created " + NUM_BLOG_POSTS + " blog posts.");
}
}
private void addBlogPost(LocalAuthor author, int num) throws DbException {
Blog blog = blogManager.getPersonalBlog(author);
long timestamp = clock.currentTimeMillis() - num * 60 * 1000;
String body = getRandomText();
try {
BlogPost blogPost = blogPostFactory
.createBlogPost(blog.getId(), timestamp, null, author,
body);
blogManager.addLocalPost(blogPost);
} catch (FormatException e) {
throw new RuntimeException(e);
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
}
}
private List<Forum> createForums(List<Contact> contacts)
throws DbException {
List<Forum> forums = new ArrayList<Forum>(NUM_FORUMS);
for (int i = 0; i < NUM_FORUMS; i++) {
// create forum
String name = GROUP_NAMES[random.nextInt(GROUP_NAMES.length)];
Forum forum = forumManager.addForum(name);
// share with all contacts
Transaction txn = db.startTransaction(false);
try {
for (Contact c : contacts) {
db.setGroupVisibility(txn, c.getId(), forum.getId(),
SHARED);
}
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
forums.add(forum);
}
if (LOG.isLoggable(INFO)) {
LOG.info("Created " + NUM_FORUMS + " forums with " +
NUM_FORUM_POSTS + " posts each.");
}
return forums;
}
private void createRandomForumPosts(Forum forum, List<Contact> contacts)
throws DbException {
List<ForumPost> posts = new ArrayList<ForumPost>();
for (int i = 0; i < NUM_FORUM_POSTS; i++) {
Contact contact = contacts.get(random.nextInt(contacts.size()));
LocalAuthor author = localAuthors.get(contact);
long timestamp = clock.currentTimeMillis() - i * 60 * 1000;
String body = getRandomText();
MessageId parent = null;
if (random.nextBoolean() && posts.size() > 0) {
ForumPost parentPost =
posts.get(random.nextInt(posts.size()));
parent = parentPost.getMessage().getId();
}
ForumPost post = forumManager
.createLocalPost(forum.getId(), body, timestamp, parent,
author);
posts.add(post);
forumManager.addLocalPost(post);
if (random.nextBoolean()) {
forumManager
.setReadFlag(forum.getId(), post.getMessage().getId(),
false);
}
}
}
private String getRandomText() {
int minLength = 3 + random.nextInt(500);
int maxWordLength = 15;
StringBuilder sb = new StringBuilder();
while (sb.length() < minLength) {
if (sb.length() > 0) sb.append(' ');
sb.append(getRandomString(random.nextInt(maxWordLength) + 1));
}
if (random.nextBoolean()) {
sb.append(" \uD83D\uDC96 \uD83E\uDD84 \uD83C\uDF08");
}
return sb.toString();
}
}

View File

@@ -0,0 +1,19 @@
package org.briarproject.briar.test;
import org.briarproject.briar.api.test.TestDataCreator;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class TestModule {
@Provides
@Singleton
TestDataCreator getTestDataCreator(TestDataCreatorImpl testDataCreator) {
return testDataCreator;
}
}

View File

@@ -39,7 +39,7 @@ import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_K
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_LENGTH;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.test.TestUtils.getRandomString;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_ID;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_NAME;

View File

@@ -25,7 +25,7 @@ import static junit.framework.Assert.assertNotNull;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomString;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.briarproject.briar.api.blog.MessageType.COMMENT;
import static org.briarproject.briar.api.blog.MessageType.POST;
import static org.briarproject.briar.api.blog.MessageType.WRAPPED_COMMENT;

View File

@@ -18,6 +18,7 @@ import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.system.SystemClock;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.api.blog.Blog;
import org.briarproject.briar.api.blog.BlogFactory;
import org.briarproject.briar.test.BriarTestCase;
@@ -64,7 +65,7 @@ public class BlogPostValidatorTest extends BriarTestCase {
private final BlogFactory blogFactory = context.mock(BlogFactory.class);
private final ClientHelper clientHelper = context.mock(ClientHelper.class);
private final Author author;
private final String body = TestUtils.getRandomString(42);
private final String body = StringUtils.getRandomString(42);
public BlogPostValidatorTest() {
GroupId groupId = new GroupId(TestUtils.getRandomId());

View File

@@ -19,6 +19,7 @@ import org.briarproject.bramble.api.sync.ValidationManager.MessageValidator;
import org.briarproject.bramble.test.CaptureArgumentAction;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.ByteUtils;
import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.api.client.MessageQueueManager.IncomingQueueMessageHook;
import org.briarproject.briar.api.client.MessageQueueManager.QueueMessageValidator;
import org.briarproject.briar.api.client.QueueMessage;
@@ -45,7 +46,7 @@ public class MessageQueueManagerImplTest extends BriarTestCase {
private final GroupId groupId = new GroupId(TestUtils.getRandomId());
private final ClientId clientId =
new ClientId(TestUtils.getRandomString(5));
new ClientId(StringUtils.getRandomString(5));
private final byte[] descriptor = new byte[0];
private final Group group = new Group(groupId, clientId, descriptor);
private final long timestamp = System.currentTimeMillis();

View File

@@ -11,6 +11,7 @@ import org.briarproject.bramble.api.sync.InvalidMessageException;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.test.ValidatorTestCase;
import org.briarproject.bramble.util.StringUtils;
import org.jmock.Expectations;
import org.junit.Test;
@@ -30,12 +31,12 @@ public class ForumPostValidatorTest extends ValidatorTestCase {
private final MessageId parentId = new MessageId(TestUtils.getRandomId());
private final String authorName =
TestUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH);
StringUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH);
private final byte[] authorPublicKey =
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
private final BdfList authorList = BdfList.of(authorName, authorPublicKey);
private final String content =
TestUtils.getRandomString(MAX_FORUM_POST_BODY_LENGTH);
StringUtils.getRandomString(MAX_FORUM_POST_BODY_LENGTH);
private final byte[] signature =
TestUtils.getRandomBytes(MAX_SIGNATURE_LENGTH);
private final AuthorId authorId = new AuthorId(TestUtils.getRandomId());
@@ -165,7 +166,7 @@ public class ForumPostValidatorTest extends ValidatorTestCase {
@Test
public void testAcceptsMinLengthAuthorName() throws Exception {
final String shortAuthorName = TestUtils.getRandomString(1);
final String shortAuthorName = StringUtils.getRandomString(1);
BdfList shortNameAuthorList =
BdfList.of(shortAuthorName, authorPublicKey);
final Author shortNameAuthor =
@@ -190,7 +191,7 @@ public class ForumPostValidatorTest extends ValidatorTestCase {
@Test(expected = FormatException.class)
public void testRejectsTooLongAuthorName() throws Exception {
String invalidAuthorName =
TestUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH + 1);
StringUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH + 1);
BdfList invalidAuthorList =
BdfList.of(invalidAuthorName, authorPublicKey);
ForumPostValidator v = new ForumPostValidator(authorFactory,
@@ -278,7 +279,7 @@ public class ForumPostValidatorTest extends ValidatorTestCase {
@Test(expected = FormatException.class)
public void testRejectsTooLongContent() throws Exception {
String invalidContent =
TestUtils.getRandomString(MAX_FORUM_POST_BODY_LENGTH + 1);
StringUtils.getRandomString(MAX_FORUM_POST_BODY_LENGTH + 1);
context.checking(new Expectations() {{
oneOf(authorFactory).createAuthor(authorName, authorPublicKey);

View File

@@ -27,6 +27,7 @@ import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.test.TestDatabaseModule;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.api.client.SessionId;
import org.briarproject.briar.api.introduction.IntroductionManager;
import org.briarproject.briar.api.introduction.IntroductionMessage;
@@ -479,7 +480,7 @@ public class IntroductionIntegrationTest
new BdfEntry(TYPE, TYPE_REQUEST),
new BdfEntry(SESSION_ID, sessionId),
new BdfEntry(GROUP_ID, group.getId()),
new BdfEntry(NAME, TestUtils.getRandomString(42)),
new BdfEntry(NAME, StringUtils.getRandomString(42)),
new BdfEntry(PUBLIC_KEY,
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH))
);

View File

@@ -20,6 +20,7 @@ import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.MessageStatus;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.api.client.MessageTracker;
import org.briarproject.briar.api.client.SessionId;
import org.briarproject.briar.test.BriarTestCase;
@@ -81,7 +82,7 @@ public class IntroductionManagerImplTest extends BriarTestCase {
introducee2 =
new Contact(contactId2, author2, localAuthorId2, true, true);
ClientId clientId = new ClientId(TestUtils.getRandomString(5));
ClientId clientId = new ClientId(StringUtils.getRandomString(5));
introductionGroup1 = new Group(new GroupId(TestUtils.getRandomId()),
clientId, new byte[0]);
introductionGroup2 = new Group(new GroupId(TestUtils.getRandomId()),

View File

@@ -15,6 +15,7 @@ import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.system.SystemClock;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.api.client.SessionId;
import org.briarproject.briar.test.BriarTestCase;
import org.jmock.Mockery;
@@ -59,7 +60,7 @@ public class IntroductionValidatorTest extends BriarTestCase {
public IntroductionValidatorTest() {
GroupId groupId = new GroupId(TestUtils.getRandomId());
ClientId clientId = new ClientId(TestUtils.getRandomString(5));
ClientId clientId = new ClientId(StringUtils.getRandomString(5));
byte[] descriptor = TestUtils.getRandomBytes(12);
group = new Group(groupId, clientId, descriptor);
@@ -83,11 +84,11 @@ public class IntroductionValidatorTest extends BriarTestCase {
@Test
public void testValidateProperIntroductionRequest() throws IOException {
final byte[] sessionId = TestUtils.getRandomId();
final String name = TestUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH);
final String name = StringUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH);
final byte[] publicKey =
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
final String text =
TestUtils.getRandomString(MAX_INTRODUCTION_MESSAGE_LENGTH);
StringUtils.getRandomString(MAX_INTRODUCTION_MESSAGE_LENGTH);
BdfList body = BdfList.of(TYPE_REQUEST, sessionId,
name, publicKey, text);
@@ -144,9 +145,9 @@ public class IntroductionValidatorTest extends BriarTestCase {
private BdfDictionary getValidIntroductionRequest() throws FormatException {
byte[] sessionId = TestUtils.getRandomId();
String name = TestUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH);
String name = StringUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH);
byte[] publicKey = TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
String text = TestUtils.getRandomString(MAX_MESSAGE_BODY_LENGTH);
String text = StringUtils.getRandomString(MAX_MESSAGE_BODY_LENGTH);
BdfDictionary msg = new BdfDictionary();
msg.put(TYPE, TYPE_REQUEST);
@@ -168,11 +169,11 @@ public class IntroductionValidatorTest extends BriarTestCase {
byte[] sessionId = TestUtils.getRandomId();
long time = clock.currentTimeMillis();
byte[] publicKey = TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
String transportId = TestUtils
String transportId = StringUtils
.getRandomString(TransportId.MAX_TRANSPORT_ID_LENGTH);
BdfDictionary tProps = BdfDictionary.of(
new BdfEntry(TestUtils.getRandomString(MAX_PROPERTY_LENGTH),
TestUtils.getRandomString(MAX_PROPERTY_LENGTH))
new BdfEntry(StringUtils.getRandomString(MAX_PROPERTY_LENGTH),
StringUtils.getRandomString(MAX_PROPERTY_LENGTH))
);
BdfDictionary tp = BdfDictionary.of(
new BdfEntry(transportId, tProps)
@@ -230,7 +231,7 @@ public class IntroductionValidatorTest extends BriarTestCase {
throws IOException {
BdfDictionary msg = getValidIntroductionResponse(true);
BdfDictionary tp = msg.getDictionary(TRANSPORT);
tp.put(TestUtils
tp.put(StringUtils
.getRandomString(TransportId.MAX_TRANSPORT_ID_LENGTH), "X");
msg.put(TRANSPORT, tp);
@@ -260,11 +261,11 @@ public class IntroductionValidatorTest extends BriarTestCase {
byte[] sessionId = TestUtils.getRandomId();
long time = clock.currentTimeMillis();
byte[] publicKey = TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
String transportId = TestUtils
String transportId = StringUtils
.getRandomString(TransportId.MAX_TRANSPORT_ID_LENGTH);
BdfDictionary tProps = BdfDictionary.of(
new BdfEntry(TestUtils.getRandomString(MAX_PROPERTY_LENGTH),
TestUtils.getRandomString(MAX_PROPERTY_LENGTH))
new BdfEntry(StringUtils.getRandomString(MAX_PROPERTY_LENGTH),
StringUtils.getRandomString(MAX_PROPERTY_LENGTH))
);
BdfDictionary tp = BdfDictionary.of(
new BdfEntry(transportId, tProps)
@@ -310,7 +311,7 @@ public class IntroductionValidatorTest extends BriarTestCase {
BdfDictionary msg = BdfDictionary.of(
new BdfEntry(TYPE, TYPE_ACK),
new BdfEntry(SESSION_ID, TestUtils.getRandomId()),
new BdfEntry("garbage", TestUtils.getRandomString(255))
new BdfEntry("garbage", StringUtils.getRandomString(255))
);
BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID),
msg.getString("garbage"));
@@ -357,7 +358,7 @@ public class IntroductionValidatorTest extends BriarTestCase {
BdfDictionary msg = BdfDictionary.of(
new BdfEntry(TYPE, TYPE_ABORT),
new BdfEntry(SESSION_ID, TestUtils.getRandomId()),
new BdfEntry("garbage", TestUtils.getRandomString(255))
new BdfEntry("garbage", StringUtils.getRandomString(255))
);
BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID),
msg.getString("garbage"));

View File

@@ -15,6 +15,7 @@ import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.api.client.MessageQueueManager;
import org.briarproject.briar.api.client.SessionId;
import org.briarproject.briar.test.BriarTestCase;
@@ -60,7 +61,7 @@ public class MessageSenderTest extends BriarTestCase {
final Transaction txn = new Transaction(null, false);
final Group privateGroup =
new Group(new GroupId(TestUtils.getRandomId()),
new ClientId(TestUtils.getRandomString(5)),
new ClientId(StringUtils.getRandomString(5)),
new byte[0]);
final SessionId sessionId = new SessionId(TestUtils.getRandomId());
byte[] mac = TestUtils.getRandomBytes(42);

View File

@@ -65,7 +65,7 @@ public class MessageSizeIntegrationTest extends BriarTestCase {
@Test
public void testForumPostFitsIntoPacket() throws Exception {
// Create a maximum-length author
String authorName = TestUtils.getRandomString(
String authorName = StringUtils.getRandomString(
MAX_AUTHOR_NAME_LENGTH);
byte[] authorPublic = new byte[MAX_PUBLIC_KEY_LENGTH];
PrivateKey privateKey = crypto.generateSignatureKeyPair().getPrivate();
@@ -76,7 +76,7 @@ public class MessageSizeIntegrationTest extends BriarTestCase {
GroupId groupId = new GroupId(getRandomId());
long timestamp = Long.MAX_VALUE;
MessageId parent = new MessageId(getRandomId());
String body = TestUtils.getRandomString(MAX_FORUM_POST_BODY_LENGTH);
String body = StringUtils.getRandomString(MAX_FORUM_POST_BODY_LENGTH);
ForumPost post = forumPostFactory.createPost(groupId,
timestamp, parent, author, body);
// Check the size of the serialised message

View File

@@ -4,8 +4,8 @@ import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.client.BdfMessageContext;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.test.ValidatorTestCase;
import org.briarproject.bramble.util.StringUtils;
import org.junit.Test;
import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
@@ -48,7 +48,7 @@ public class PrivateMessageValidatorTest extends ValidatorTestCase {
PrivateMessageValidator v = new PrivateMessageValidator(clientHelper,
metadataEncoder, clock);
String invalidContent =
TestUtils.getRandomString(MAX_PRIVATE_MESSAGE_BODY_LENGTH + 1);
StringUtils.getRandomString(MAX_PRIVATE_MESSAGE_BODY_LENGTH + 1);
v.validateMessage(message, group, BdfList.of(invalidContent));
}
@@ -57,7 +57,7 @@ public class PrivateMessageValidatorTest extends ValidatorTestCase {
PrivateMessageValidator v = new PrivateMessageValidator(clientHelper,
metadataEncoder, clock);
String content =
TestUtils.getRandomString(MAX_PRIVATE_MESSAGE_BODY_LENGTH);
StringUtils.getRandomString(MAX_PRIVATE_MESSAGE_BODY_LENGTH);
BdfMessageContext messageContext =
v.validateMessage(message, group, BdfList.of(content));
assertExpectedContext(messageContext);

Some files were not shown because too many files have changed in this diff Show More