Fragment/Tile: Make success/error messages translatable
Signed-off-by: Samuel Holland <samuel@sholland.org>
This commit is contained in:
parent
6361628e16
commit
710ffc7bb3
@ -16,7 +16,6 @@ import com.wireguard.android.model.Tunnel;
|
|||||||
import com.wireguard.android.model.Tunnel.State;
|
import com.wireguard.android.model.Tunnel.State;
|
||||||
import com.wireguard.android.model.TunnelManager;
|
import com.wireguard.android.model.TunnelManager;
|
||||||
import com.wireguard.android.util.ExceptionLoggers;
|
import com.wireguard.android.util.ExceptionLoggers;
|
||||||
import com.wireguard.android.util.RootShell;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@ -63,16 +62,13 @@ public class QuickTileService extends TileService {
|
|||||||
tunnelManager.removeOnPropertyChangedCallback(onTunnelChangedCallback);
|
tunnelManager.removeOnPropertyChangedCallback(onTunnelChangedCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
private void onToggleFinished(final State state, final Throwable throwable) {
|
||||||
private Void onToggleFinished(final State state, final Throwable throwable) {
|
|
||||||
if (throwable == null)
|
if (throwable == null)
|
||||||
return null;
|
return;
|
||||||
Log.e(TAG, "Cannot toggle tunnel", throwable);
|
final String error = ExceptionLoggers.unwrap(throwable).getMessage();
|
||||||
final String message = throwable instanceof RootShell.NoRootException ?
|
final String message = getString(R.string.toggle_error, error);
|
||||||
getApplicationContext().getString(R.string.error_rootshell) :
|
Log.e(TAG, message, throwable);
|
||||||
getApplicationContext().getString(R.string.error_toggle) + ": " + throwable.getMessage();
|
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
|
||||||
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTile() {
|
private void updateTile() {
|
||||||
|
@ -55,7 +55,7 @@ public final class WgQuickBackend implements Backend {
|
|||||||
try {
|
try {
|
||||||
if (rootShell.run(output, "wg show interfaces") != 0 || output.isEmpty())
|
if (rootShell.run(output, "wg show interfaces") != 0 || output.isEmpty())
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
} catch (Exception e) {
|
} catch (final Exception ignored) {
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
// wg puts all interface names on the same line. Split them into separate elements.
|
// wg puts all interface names on the same line. Split them into separate elements.
|
||||||
|
@ -19,7 +19,6 @@ import com.wireguard.android.databinding.TunnelListItemBinding;
|
|||||||
import com.wireguard.android.model.Tunnel;
|
import com.wireguard.android.model.Tunnel;
|
||||||
import com.wireguard.android.model.Tunnel.State;
|
import com.wireguard.android.model.Tunnel.State;
|
||||||
import com.wireguard.android.util.ExceptionLoggers;
|
import com.wireguard.android.util.ExceptionLoggers;
|
||||||
import com.wireguard.android.util.RootShell;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method shared by TunnelListFragment and TunnelDetailFragment.
|
* Helper method shared by TunnelListFragment and TunnelDetailFragment.
|
||||||
@ -48,7 +47,6 @@ public final class TunnelController {
|
|||||||
tunnel.setState(State.of(checked)).whenComplete((state, throwable) -> {
|
tunnel.setState(State.of(checked)).whenComplete((state, throwable) -> {
|
||||||
if (throwable == null)
|
if (throwable == null)
|
||||||
return;
|
return;
|
||||||
Log.e(TAG, "Cannot set state of tunnel " + tunnel.getName(), throwable);
|
|
||||||
final Context context = view.getContext();
|
final Context context = view.getContext();
|
||||||
if (throwable instanceof ErrnoException
|
if (throwable instanceof ErrnoException
|
||||||
&& ((ErrnoException) throwable).errno == OsConstants.ENODEV) {
|
&& ((ErrnoException) throwable).errno == OsConstants.ENODEV) {
|
||||||
@ -61,13 +59,13 @@ public final class TunnelController {
|
|||||||
// Make links work.
|
// Make links work.
|
||||||
((TextView) dialog.findViewById(android.R.id.message))
|
((TextView) dialog.findViewById(android.R.id.message))
|
||||||
.setMovementMethod(LinkMovementMethod.getInstance());
|
.setMovementMethod(LinkMovementMethod.getInstance());
|
||||||
} else if (throwable instanceof RootShell.NoRootException) {
|
Log.e(TAG, "WireGuard not supported");
|
||||||
Snackbar.make(view, R.string.error_rootshell, Snackbar.LENGTH_LONG).show();
|
|
||||||
} else {
|
} else {
|
||||||
final String message =
|
final String error = ExceptionLoggers.unwrap(throwable).getMessage();
|
||||||
context.getString(checked ? R.string.error_up : R.string.error_down) + ": "
|
final int messageResId = checked ? R.string.error_up : R.string.error_down;
|
||||||
+ ExceptionLoggers.unwrap(throwable).getMessage();
|
final String message = context.getString(messageResId, error);
|
||||||
Snackbar.make(view, message, Snackbar.LENGTH_LONG).show();
|
Snackbar.make(view, message, Snackbar.LENGTH_LONG).show();
|
||||||
|
Log.e(TAG, message, throwable);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -60,17 +60,19 @@ public class TunnelEditorFragment extends BaseFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onConfigSaved(final Config config, final Throwable throwable) {
|
private void onConfigSaved(final Config config, final Throwable throwable) {
|
||||||
if (throwable != null) {
|
final String message;
|
||||||
Log.e(TAG, "Cannot save configuration", throwable);
|
if (throwable == null) {
|
||||||
final String message = "Cannot save configuration: "
|
message = getString(R.string.config_save_success, localTunnel.getName());
|
||||||
+ ExceptionLoggers.unwrap(throwable).getMessage();
|
Log.d(TAG, message);
|
||||||
|
onFinished();
|
||||||
|
} else {
|
||||||
|
final String error = ExceptionLoggers.unwrap(throwable).getMessage();
|
||||||
|
message = getString(R.string.config_save_error, localTunnel.getName(), error);
|
||||||
|
Log.e(TAG, message, throwable);
|
||||||
if (binding != null) {
|
if (binding != null) {
|
||||||
final CoordinatorLayout container = binding.mainContainer;
|
final CoordinatorLayout container = binding.mainContainer;
|
||||||
Snackbar.make(container, message, Snackbar.LENGTH_LONG).show();
|
Snackbar.make(container, message, Snackbar.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Log.d(TAG, "Successfully saved configuration for " + localTunnel.getName());
|
|
||||||
onFinished();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,38 +193,40 @@ public class TunnelEditorFragment extends BaseFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onTunnelCreated(final Tunnel tunnel, final Throwable throwable) {
|
private void onTunnelCreated(final Tunnel tunnel, final Throwable throwable) {
|
||||||
if (throwable != null) {
|
final String message;
|
||||||
Log.e(TAG, "Cannot create tunnel", throwable);
|
if (throwable == null) {
|
||||||
final String message = "Cannot create tunnel: "
|
message = getString(R.string.tunnel_create_success, tunnel.getName());
|
||||||
+ ExceptionLoggers.unwrap(throwable).getMessage();
|
Log.d(TAG, message);
|
||||||
|
onFinished();
|
||||||
|
} else {
|
||||||
|
final String error = ExceptionLoggers.unwrap(throwable).getMessage();
|
||||||
|
message = getString(R.string.tunnel_create_error, error);
|
||||||
|
Log.e(TAG, message, throwable);
|
||||||
if (binding != null) {
|
if (binding != null) {
|
||||||
final CoordinatorLayout container = binding.mainContainer;
|
final CoordinatorLayout container = binding.mainContainer;
|
||||||
Snackbar.make(container, message, Snackbar.LENGTH_LONG).show();
|
Snackbar.make(container, message, Snackbar.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Log.d(TAG, "Successfully created tunnel " + tunnel.getName());
|
|
||||||
localTunnel = tunnel;
|
|
||||||
onFinished();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void onTunnelRenamed(final Tunnel tunnel, final Throwable throwable) {
|
private void onTunnelRenamed(final Tunnel tunnel, final Throwable throwable) {
|
||||||
if (throwable != null) {
|
final String message;
|
||||||
Log.e(TAG, "Cannot rename tunnel", throwable);
|
if (throwable == null) {
|
||||||
final String message = "Cannot rename tunnel: "
|
message = getString(R.string.tunnel_rename_success, localTunnel.getName(),
|
||||||
+ ExceptionLoggers.unwrap(throwable).getMessage();
|
tunnel.getName());
|
||||||
|
Log.d(TAG, message);
|
||||||
|
localTunnel = tunnel;
|
||||||
|
// Now save the rest of configuration changes.
|
||||||
|
Log.d(TAG, "Attempting to save config of renamed tunnel " + tunnel.getName());
|
||||||
|
tunnel.setConfig(localConfig).whenComplete(this::onConfigSaved);
|
||||||
|
} else {
|
||||||
|
final String error = ExceptionLoggers.unwrap(throwable).getMessage();
|
||||||
|
message = getString(R.string.tunnel_rename_error, error);
|
||||||
|
Log.e(TAG, message, throwable);
|
||||||
if (binding != null) {
|
if (binding != null) {
|
||||||
final CoordinatorLayout container = binding.mainContainer;
|
final CoordinatorLayout container = binding.mainContainer;
|
||||||
Snackbar.make(container, message, Snackbar.LENGTH_LONG).show();
|
Snackbar.make(container, message, Snackbar.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Log.d(TAG, "Successfully renamed tunnel to " + tunnel.getName());
|
|
||||||
localTunnel = tunnel;
|
|
||||||
// Now save the rest of configuration changes.
|
|
||||||
Log.d(TAG, "Attempting to save config of " + tunnel.getName());
|
|
||||||
tunnel.setConfig(localConfig)
|
|
||||||
.whenComplete(this::onConfigSaved);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,13 +148,12 @@ public class TunnelListFragment extends BaseFragment {
|
|||||||
|
|
||||||
private void onTunnelDeletionFinished(final Integer count, final Throwable throwable) {
|
private void onTunnelDeletionFinished(final Integer count, final Throwable throwable) {
|
||||||
final String message;
|
final String message;
|
||||||
final String plural = count == 1 ? "" : "s";
|
|
||||||
if (throwable == null) {
|
if (throwable == null) {
|
||||||
message = "Successfully deleted " + count + " tunnel" + plural;
|
message = getResources().getQuantityString(R.plurals.delete_success, count, count);
|
||||||
} else {
|
} else {
|
||||||
message = "Unable to delete tunnel" + plural + ": "
|
final String error = ExceptionLoggers.unwrap(throwable).getMessage();
|
||||||
+ ExceptionLoggers.unwrap(throwable).getMessage();
|
message = getResources().getQuantityString(R.plurals.delete_error, count, count, error);
|
||||||
Log.e(TAG, "Cannot delete tunnel" + plural, throwable);
|
Log.e(TAG, message, throwable);
|
||||||
}
|
}
|
||||||
if (binding != null) {
|
if (binding != null) {
|
||||||
final CoordinatorLayout container = binding.mainContainer;
|
final CoordinatorLayout container = binding.mainContainer;
|
||||||
@ -165,11 +164,11 @@ public class TunnelListFragment extends BaseFragment {
|
|||||||
private void onTunnelImportFinished(final Tunnel tunnel, final Throwable throwable) {
|
private void onTunnelImportFinished(final Tunnel tunnel, final Throwable throwable) {
|
||||||
final String message;
|
final String message;
|
||||||
if (throwable == null) {
|
if (throwable == null) {
|
||||||
message = "Successfully imported tunnel '" + tunnel.getName() + '\'';
|
message = getString(R.string.import_success, tunnel.getName());
|
||||||
} else {
|
} else {
|
||||||
message = "Cannot import tunnel: "
|
final String error = ExceptionLoggers.unwrap(throwable).getMessage();
|
||||||
+ ExceptionLoggers.unwrap(throwable).getMessage();
|
message = getString(R.string.import_error, error);
|
||||||
Log.e(TAG, "Cannot import tunnel", throwable);
|
Log.e(TAG, message, throwable);
|
||||||
}
|
}
|
||||||
if (binding != null) {
|
if (binding != null) {
|
||||||
final CoordinatorLayout container = binding.mainContainer;
|
final CoordinatorLayout container = binding.mainContainer;
|
||||||
@ -245,7 +244,7 @@ public class TunnelListFragment extends BaseFragment {
|
|||||||
|
|
||||||
private void updateTitle(final ActionMode mode) {
|
private void updateTitle(final ActionMode mode) {
|
||||||
final int count = (int) getCheckedPositions().count();
|
final int count = (int) getCheckedPositions().count();
|
||||||
mode.setTitle(resources.getQuantityString(R.plurals.list_delete_title, count, count));
|
mode.setTitle(resources.getQuantityString(R.plurals.delete_title, count, count));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,12 +7,14 @@ import android.util.Log;
|
|||||||
|
|
||||||
import com.wireguard.android.Application.ApplicationContext;
|
import com.wireguard.android.Application.ApplicationContext;
|
||||||
import com.wireguard.android.Application.ApplicationScope;
|
import com.wireguard.android.Application.ApplicationScope;
|
||||||
|
import com.wireguard.android.R;
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -34,6 +36,7 @@ public class RootShell {
|
|||||||
{"libwg-quick.so", "wg-quick"}
|
{"libwg-quick.so", "wg-quick"}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private final String exceptionMessage;
|
||||||
private final String preamble;
|
private final String preamble;
|
||||||
|
|
||||||
private BufferedWriter stdin;
|
private BufferedWriter stdin;
|
||||||
@ -59,6 +62,7 @@ public class RootShell {
|
|||||||
builder.append(String.format("export PATH=\"%s:$PATH\" TMPDIR=\"%s\";", binDir, tmpDir));
|
builder.append(String.format("export PATH=\"%s:$PATH\" TMPDIR=\"%s\";", binDir, tmpDir));
|
||||||
builder.append("id;\n");
|
builder.append("id;\n");
|
||||||
|
|
||||||
|
exceptionMessage = context.getString(R.string.error_root);
|
||||||
preamble = builder.toString();
|
preamble = builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +76,7 @@ public class RootShell {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensureRoot() throws Exception {
|
private void ensureRoot() throws ErrnoException, IOException, NoRootException {
|
||||||
try {
|
try {
|
||||||
if (process != null) {
|
if (process != null) {
|
||||||
process.exitValue();
|
process.exitValue();
|
||||||
@ -83,7 +87,7 @@ public class RootShell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isExecutable("su"))
|
if (!isExecutable("su"))
|
||||||
throw new NoRootException();
|
throw new NoRootException(exceptionMessage);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final ProcessBuilder builder = new ProcessBuilder();
|
final ProcessBuilder builder = new ProcessBuilder();
|
||||||
@ -104,7 +108,7 @@ public class RootShell {
|
|||||||
String line;
|
String line;
|
||||||
while ((line = stderr.readLine()) != null) {
|
while ((line = stderr.readLine()) != null) {
|
||||||
if (line.contains("Permission denied"))
|
if (line.contains("Permission denied"))
|
||||||
throw new NoRootException();
|
throw new NoRootException(exceptionMessage);
|
||||||
}
|
}
|
||||||
throw new ErrnoException("Unknown error when obtaining root access", errno);
|
throw new ErrnoException("Unknown error when obtaining root access", errno);
|
||||||
} catch (IllegalThreadStateException e) {
|
} catch (IllegalThreadStateException e) {
|
||||||
@ -112,7 +116,7 @@ public class RootShell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (id == null || !id.contains("uid=0"))
|
if (id == null || !id.contains("uid=0"))
|
||||||
throw new NoRootException();
|
throw new NoRootException(exceptionMessage);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Session failed with exception", e);
|
Log.w(TAG, "Session failed with exception", e);
|
||||||
process.destroy();
|
process.destroy();
|
||||||
@ -121,7 +125,7 @@ public class RootShell {
|
|||||||
if (match.find()) {
|
if (match.find()) {
|
||||||
final int errno = Integer.valueOf(match.group(1));
|
final int errno = Integer.valueOf(match.group(1));
|
||||||
if (errno == OsConstants.EACCES)
|
if (errno == OsConstants.EACCES)
|
||||||
throw new NoRootException();
|
throw new NoRootException(exceptionMessage);
|
||||||
else
|
else
|
||||||
throw new ErrnoException("Unknown error when obtaining root access", errno);
|
throw new ErrnoException("Unknown error when obtaining root access", errno);
|
||||||
}
|
}
|
||||||
@ -137,7 +141,8 @@ public class RootShell {
|
|||||||
* @param command Command to run as root.
|
* @param command Command to run as root.
|
||||||
* @return The exit value of the last command run, or -1 if there was an internal error.
|
* @return The exit value of the last command run, or -1 if there was an internal error.
|
||||||
*/
|
*/
|
||||||
public int run(final List<String> output, final String command) throws Exception {
|
public int run(final List<String> output, final String command)
|
||||||
|
throws ErrnoException, IOException, NoRootException {
|
||||||
ensureRoot();
|
ensureRoot();
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
@ -205,6 +210,9 @@ public class RootShell {
|
|||||||
return errnoStdout;
|
return errnoStdout;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NoRootException extends Exception {
|
public static class NoRootException extends Exception {
|
||||||
|
public NoRootException(final String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
package com.wireguard.android.util;
|
package com.wireguard.android.util;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.system.ErrnoException;
|
||||||
import android.system.OsConstants;
|
import android.system.OsConstants;
|
||||||
|
|
||||||
import com.wireguard.android.Application.ApplicationContext;
|
import com.wireguard.android.Application.ApplicationContext;
|
||||||
import com.wireguard.android.Application.ApplicationScope;
|
import com.wireguard.android.Application.ApplicationScope;
|
||||||
|
import com.wireguard.android.util.RootShell.NoRootException;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -67,7 +70,11 @@ public final class ToolsInstaller {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return rootShell.run(null, script.toString());
|
return rootShell.run(null, script.toString());
|
||||||
} catch (Exception e) {
|
} catch (final ErrnoException e) {
|
||||||
|
return e.errno;
|
||||||
|
} catch (final IOException ignored) {
|
||||||
|
return OsConstants.EXIT_FAILURE;
|
||||||
|
} catch (final NoRootException ignored) {
|
||||||
return OsConstants.EACCES;
|
return OsConstants.EACCES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,23 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
<plurals name="list_delete_title">
|
<plurals name="delete_error">
|
||||||
<item quantity="one">%d configuration selected</item>
|
<item quantity="one">Unable to delete %d tunnel: %s</item>
|
||||||
<item quantity="other">%d configurations selected</item>
|
<item quantity="other">Unable to delete %d tunnels: %s</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="delete_success">
|
||||||
|
<item quantity="one">Successfully deleted %d tunnel</item>
|
||||||
|
<item quantity="other">Successfully deleted %d tunnels</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="delete_title">
|
||||||
|
<item quantity="one">%d tunnel selected</item>
|
||||||
|
<item quantity="other">%d tunnels selected</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="add_peer">Add peer</string>
|
<string name="add_peer">Add peer</string>
|
||||||
<string name="addresses">Addresses</string>
|
<string name="addresses">Addresses</string>
|
||||||
<string name="allowed_ips">Allowed IPs</string>
|
<string name="allowed_ips">Allowed IPs</string>
|
||||||
<string name="app_name">WireGuard</string>
|
<string name="app_name">WireGuard</string>
|
||||||
|
<string name="config_save_error">Unable to configuration for “%s”: %s</string>
|
||||||
|
<string name="config_save_success">Successfully saved configuration for “%s”</string>
|
||||||
<string name="create_activity_title">Create WireGuard Tunnel</string>
|
<string name="create_activity_title">Create WireGuard Tunnel</string>
|
||||||
<string name="create_empty">Create from scratch</string>
|
<string name="create_empty">Create from scratch</string>
|
||||||
<string name="create_from_file">Create from file</string>
|
<string name="create_from_file">Create from file</string>
|
||||||
@ -15,20 +25,21 @@
|
|||||||
<string name="dns_servers">DNS servers</string>
|
<string name="dns_servers">DNS servers</string>
|
||||||
<string name="edit">Edit</string>
|
<string name="edit">Edit</string>
|
||||||
<string name="endpoint">Endpoint</string>
|
<string name="endpoint">Endpoint</string>
|
||||||
<string name="error_down">Error bringing down WireGuard tunnel</string>
|
<string name="error_down">Error bringing down tunnel: %s</string>
|
||||||
<string name="error_up">Error bringing up WireGuard tunnel</string>
|
<string name="error_root">Please obtain root access and try again</string>
|
||||||
<string name="error_toggle">Error toggling WireGuard tunnel</string>
|
<string name="error_up">Error bringing up tunnel: %s</string>
|
||||||
<string name="error_rootshell">Please obtain root access and try again</string>
|
|
||||||
<string name="generate">Generate</string>
|
<string name="generate">Generate</string>
|
||||||
<string name="hint_automatic">(auto)</string>
|
<string name="hint_automatic">(auto)</string>
|
||||||
<string name="hint_generated">(generated)</string>
|
<string name="hint_generated">(generated)</string>
|
||||||
<string name="hint_optional">(optional)</string>
|
<string name="hint_optional">(optional)</string>
|
||||||
<string name="hint_random">(random)</string>
|
<string name="hint_random">(random)</string>
|
||||||
|
<string name="import_error">Unable to import tunnel: %s</string>
|
||||||
|
<string name="import_success">Successfully imported “%s”</string>
|
||||||
<string name="interface_title">Interface</string>
|
<string name="interface_title">Interface</string>
|
||||||
<string name="listen_port">Listen port</string>
|
<string name="listen_port">Listen port</string>
|
||||||
<string name="mtu">MTU</string>
|
<string name="mtu">MTU</string>
|
||||||
<string name="name">Name</string>
|
<string name="name">Name</string>
|
||||||
<string name="not_supported_message"><![CDATA[
|
<string name="not_supported_message" tools:ignore="TypographyQuotes"><![CDATA[
|
||||||
<p>Your Android device does not <em>currently</em> have the WireGuard kernel module. Please
|
<p>Your Android device does not <em>currently</em> have the WireGuard kernel module. Please
|
||||||
talk to the manufacturer of your Android device or the author of your device’s ROM
|
talk to the manufacturer of your Android device or the author of your device’s ROM
|
||||||
about including the WireGuard kernel module.</p>
|
about including the WireGuard kernel module.</p>
|
||||||
@ -55,10 +66,15 @@
|
|||||||
<string name="restore_on_boot_title">Restore on boot</string>
|
<string name="restore_on_boot_title">Restore on boot</string>
|
||||||
<string name="save">Save</string>
|
<string name="save">Save</string>
|
||||||
<string name="settings">Settings</string>
|
<string name="settings">Settings</string>
|
||||||
|
<string name="toggle_error">Error toggling WireGuard tunnel: %s</string>
|
||||||
<string name="tools_installer_already">wg and wg-quick are already installed</string>
|
<string name="tools_installer_already">wg and wg-quick are already installed</string>
|
||||||
<string name="tools_installer_failure">Command line tools could not be installed (no root?)</string>
|
<string name="tools_installer_failure">Unable to install command-line tools (no root?)</string>
|
||||||
<string name="tools_installer_initial">Install optional tools for scripting into the system partition</string>
|
<string name="tools_installer_initial">Install optional tools for scripting into the system partition</string>
|
||||||
<string name="tools_installer_success">wg and wg-quick installed into the system partition</string>
|
<string name="tools_installer_success">wg and wg-quick installed into the system partition</string>
|
||||||
<string name="tools_installer_title">Install command line tools</string>
|
<string name="tools_installer_title">Install command line tools</string>
|
||||||
<string name="tools_installer_working">Installing wg and wg-quick into the system partition</string>
|
<string name="tools_installer_working">Installing wg and wg-quick into the system partition</string>
|
||||||
|
<string name="tunnel_create_error">Unable to create tunnel: %s</string>
|
||||||
|
<string name="tunnel_create_success">Successfully created tunnel “%s”</string>
|
||||||
|
<string name="tunnel_rename_error">Unable to rename tunnel: %s</string>
|
||||||
|
<string name="tunnel_rename_success">Successfully renamed tunnel “%s” to “%s”</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user