[controller] reacomodo de cadenas y traducción.

This commit is contained in:
Luis Guzmán 2026-04-04 14:34:54 -06:00
parent 9cebf0893f
commit 1ce0bdc680
14 changed files with 505 additions and 331 deletions

View File

@ -9,8 +9,8 @@ android {
applicationId "org.iiab.controller" applicationId "org.iiab.controller"
minSdkVersion 24 minSdkVersion 24
targetSdkVersion 34 targetSdkVersion 34
versionCode 27 versionCode 28
versionName "v0.1.31beta" versionName "v0.1.32beta"
setProperty("archivesBaseName", "$applicationId-$versionName") setProperty("archivesBaseName", "$applicationId-$versionName")
ndk { ndk {
abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64" abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"

View File

@ -11,9 +11,9 @@
"type": "SINGLE", "type": "SINGLE",
"filters": [], "filters": [],
"attributes": [], "attributes": [],
"versionCode": 27, "versionCode": 28,
"versionName": "v0.1.31beta", "versionName": "v0.1.32beta",
"outputFile": "org.iiab.controller-v0.1.31beta-release.apk" "outputFile": "org.iiab.controller-v0.1.32beta-release.apk"
} }
], ],
"elementType": "File", "elementType": "File",
@ -22,14 +22,14 @@
"minApi": 28, "minApi": 28,
"maxApi": 30, "maxApi": 30,
"baselineProfiles": [ "baselineProfiles": [
"baselineProfiles/1/org.iiab.controller-v0.1.31beta-release.dm" "baselineProfiles/1/org.iiab.controller-v0.1.32beta-release.dm"
] ]
}, },
{ {
"minApi": 31, "minApi": 31,
"maxApi": 2147483647, "maxApi": 2147483647,
"baselineProfiles": [ "baselineProfiles": [
"baselineProfiles/0/org.iiab.controller-v0.1.31beta-release.dm" "baselineProfiles/0/org.iiab.controller-v0.1.32beta-release.dm"
] ]
} }
], ],

View File

@ -92,4 +92,5 @@
tools:ignore="QueryAllPackagesPermission" /> tools:ignore="QueryAllPackagesPermission" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" <uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"
android:minSdkVersion="34" /> android:minSdkVersion="34" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
</manifest> </manifest>

View File

@ -86,11 +86,11 @@ public class IIABWatchdog {
context.startService(intent); context.startService(intent);
} catch (SecurityException e) { } catch (SecurityException e) {
// This catches specific permission errors on newer Android versions // This catches specific permission errors on newer Android versions
Log.e(TAG, "Permission Denied: Ensure manifest has RUN_COMMAND and app is not restricted.", e); Log.e(TAG, context.getString(R.string.permission_denied_log), e);
writeToBlackBox(context, context.getString(R.string.critical_os_blocked)); writeToBlackBox(context, context.getString(R.string.critical_os_blocked));
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "Unexpected error sending intent to Termux", e); Log.e(TAG, context.getString(R.string.unexpected_error_termux), e);
writeToBlackBox(context, "Pulse Error: " + e.getMessage()); writeToBlackBox(context, context.getString(R.string.pulse_error_log, e.getMessage()));
} }
} }
@ -143,7 +143,7 @@ public class IIABWatchdog {
writer.append(datePrefix).append(" - ").append(message).append("\n"); writer.append(datePrefix).append(" - ").append(message).append("\n");
broadcastLog(context, message); broadcastLog(context, message);
} catch (IOException e) { } catch (IOException e) {
Log.e(TAG, "Failed to write to BlackBox", e); Log.e(TAG, context.getString(R.string.failed_write_blackbox), e);
} }
} }
@ -199,7 +199,7 @@ public class IIABWatchdog {
pw.println(l); pw.println(l);
} }
} catch (IOException e) { } catch (IOException e) {
Log.e(TAG, "Maintenance write failed", e); Log.e(TAG, context.getString(R.string.maintenance_write_failed), e);
} }
} }

View File

@ -74,11 +74,11 @@ public class LogManager {
long size = logFile.exists() ? logFile.length() : 0; long size = logFile.exists() ? logFile.length() : 0;
if (size < 1024) { if (size < 1024) {
return size + " B"; return context.getString(R.string.log_size_bytes, size);
} else if (size < 1024 * 1024) { } else if (size < 1024 * 1024) {
return String.format(Locale.getDefault(), "%.1f KB", size / 1024.0); return String.format(Locale.getDefault(), context.getString(R.string.log_size_kb), size / 1024.0);
} else { } else {
return String.format(Locale.getDefault(), "%.2f MB", size / (1024.0 * 1024.0)); return String.format(Locale.getDefault(), context.getString(R.string.log_size_mb), size / (1024.0 * 1024.0));
} }
} }
} }

View File

@ -220,9 +220,9 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
result -> { result -> {
for (Map.Entry<String, Boolean> entry : result.entrySet()) { for (Map.Entry<String, Boolean> entry : result.entrySet()) {
if (entry.getKey().equals(TERMUX_PERMISSION)) { if (entry.getKey().equals(TERMUX_PERMISSION)) {
addToLog(entry.getValue() ? "Termux permission granted" : "Termux permission denied"); addToLog(getString(entry.getValue() ? R.string.termux_perm_granted : R.string.termux_perm_denied));
} else if (entry.getKey().equals(Manifest.permission.POST_NOTIFICATIONS)) { } else if (entry.getKey().equals(Manifest.permission.POST_NOTIFICATIONS)) {
addToLog(entry.getValue() ? "Notification permission granted" : "Notification permission denied"); addToLog(getString(entry.getValue() ? R.string.notif_perm_granted : R.string.notif_perm_denied));
} }
} }
prepareVpn(); prepareVpn();
@ -298,7 +298,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
if (targetServerState != null) return; if (targetServerState != null) return;
// Freeze the transition text and define the TARGET state // Freeze the transition text and define the TARGET state
serverTransitionText = !isServerAlive ? "Booting..." : "Shutting down..."; serverTransitionText = !isServerAlive ? getString(R.string.server_booting) : getString(R.string.server_shutting_down);
targetServerState = !isServerAlive; targetServerState = !isServerAlive;
// Lock the UI and start infinite animation // Lock the UI and start infinite animation
@ -311,7 +311,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
targetServerState = null; // Abort transition targetServerState = null; // Abort transition
btnServerControl.stopProgress(); btnServerControl.stopProgress();
updateUIColorsAndVisibility(); updateUIColorsAndVisibility();
addToLog("Warning: Server state transition timed out."); addToLog(getString(R.string.server_timeout_warning));
} }
}; };
timeoutHandler.postDelayed(timeoutRunnable, getResources().getInteger(R.integer.server_cool_off_duration_ms)); timeoutHandler.postDelayed(timeoutRunnable, getResources().getInteger(R.integer.server_cool_off_duration_ms));
@ -560,7 +560,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
String version = pInfo.versionName; String version = pInfo.versionName;
versionFooter.setText(version); versionFooter.setText(version);
} catch (PackageManager.NameNotFoundException e) { } catch (PackageManager.NameNotFoundException e) {
versionFooter.setText("v0.1.x"); versionFooter.setText(R.string.default_version);
} }
} }
@ -629,7 +629,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
private void toggleVisibility(View view, TextView label, String text) { private void toggleVisibility(View view, TextView label, String text) {
boolean isGone = view.getVisibility() == View.GONE; boolean isGone = view.getVisibility() == View.GONE;
view.setVisibility(isGone ? View.VISIBLE : View.GONE); view.setVisibility(isGone ? View.VISIBLE : View.GONE);
label.setText((isGone ? "" : "") + text); label.setText(String.format(getString(isGone ? R.string.label_separator_down : R.string.label_separator_up), text));
} }
@Override @Override
@ -931,7 +931,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
// STATE: NORMAL (Unlocked) // STATE: NORMAL (Unlocked)
btnServerControl.setAlpha(1.0f); btnServerControl.setAlpha(1.0f);
if (isServerAlive) { if (isServerAlive) {
btnServerControl.setText("🛑 Stop Server"); btnServerControl.setText(R.string.stop_server);
if (isWatchdogOn) { if (isWatchdogOn) {
deckContainer.setBackgroundColor(Color.parseColor("#44FF9800")); deckContainer.setBackgroundColor(Color.parseColor("#44FF9800"));
btnServerControl.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_watchdog_on)); btnServerControl.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_watchdog_on));
@ -943,7 +943,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
} }
} else { } else {
deckContainer.setBackgroundColor(Color.TRANSPARENT); deckContainer.setBackgroundColor(Color.TRANSPARENT);
btnServerControl.setText("🚀 Launch Server"); btnServerControl.setText(R.string.launch_server);
btnServerControl.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_success)); btnServerControl.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_success));
watchdogControl.setBackgroundTintList(ContextCompat.getColorStateList(this, isWatchdogOn ? R.color.btn_watchdog_on : R.color.btn_watchdog_off)); watchdogControl.setBackgroundTintList(ContextCompat.getColorStateList(this, isWatchdogOn ? R.color.btn_watchdog_on : R.color.btn_watchdog_off));
} }
@ -1040,9 +1040,9 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
} else { } else {
startService(intent); startService(intent);
} }
addToLog("Sent to Termux: " + actionFlag); addToLog(getString(R.string.sent_to_termux, actionFlag));
} catch (Exception e) { } catch (Exception e) {
addToLog("CRITICAL: Failed Termux Intent: " + e.getMessage()); addToLog(getString(R.string.failed_termux_intent, e.getMessage()));
} }
} }

View File

@ -95,11 +95,11 @@ public class PortalActivity extends AppCompatActivity {
rawUrl = "http://localhost:8085/home"; rawUrl = "http://localhost:8085/home";
} }
// 1. Damos alcance global seguro a la URL para todos los lambdas de aquí en adelante // We are giving the URL secure global reach for all lambdas from now on
final String finalTargetUrl = rawUrl; final String finalTargetUrl = rawUrl;
btnHome.setOnClickListener(v -> { btnHome.setOnClickListener(v -> {
webView.loadUrl(finalTargetUrl); // Usamos la variable final webView.loadUrl(finalTargetUrl);
resetTimer.run(); resetTimer.run();
}); });
@ -108,9 +108,9 @@ public class PortalActivity extends AppCompatActivity {
if (isPageLoading) { if (isPageLoading) {
webView.stopLoading(); webView.stopLoading();
} else { } else {
// 1. Disable cache temporarily // Disable cache temporarily
webView.getSettings().setCacheMode(android.webkit.WebSettings.LOAD_NO_CACHE); webView.getSettings().setCacheMode(android.webkit.WebSettings.LOAD_NO_CACHE);
// 2. Force download from scratch // Force download from scratch
webView.reload(); webView.reload();
} }
resetTimer.run(); resetTimer.run();
@ -123,12 +123,12 @@ public class PortalActivity extends AppCompatActivity {
String url = request.getUrl().toString(); String url = request.getUrl().toString();
String host = request.getUrl().getHost(); String host = request.getUrl().getHost();
// 1. Internal server link (Box) // Internal server link (Box)
if (host != null && (host.equals("box") || host.equals("127.0.0.1") || host.equals("localhost"))) { if (host != null && (host.equals("box") || host.equals("127.0.0.1") || host.equals("localhost"))) {
return false; // Remains in our app and travels through the proxy return false; // Remains in our app and travels through the proxy
} }
// 2. External link (Real Internet) // External link (Real Internet)
try { try {
// Tell Android to find the correct app to open this (Chrome, YouTube, etc.) // Tell Android to find the correct app to open this (Chrome, YouTube, etc.)
Intent intent = new Intent(Intent.ACTION_VIEW, request.getUrl()); Intent intent = new Intent(Intent.ACTION_VIEW, request.getUrl());
@ -184,11 +184,11 @@ public class PortalActivity extends AppCompatActivity {
webView.getSettings().setJavaScriptEnabled(true); webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDomStorageEnabled(true); webView.getSettings().setDomStorageEnabled(true);
// 2. Port and Mirror logic // Port and Mirror logic
int tempPort = prefs.getSocksPort(); int tempPort = prefs.getSocksPort();
if (tempPort <= 0) tempPort = 1080; if (tempPort <= 0) tempPort = 1080;
// 3. Restauramos la variable segura para el puerto // We restored the secure variable for the port
final int finalProxyPort = tempPort; final int finalProxyPort = tempPort;
// 4. Proxy block (ONLY IF VPN IS ACTIVE) // 4. Proxy block (ONLY IF VPN IS ACTIVE)
@ -216,7 +216,7 @@ public class PortalActivity extends AppCompatActivity {
} }
} }
// 4. Cleanup (Important to not leave the proxy active) // Cleanup (Important to not leave the proxy active)
@Override @Override
protected void onDestroy() { protected void onDestroy() {
super.onDestroy(); super.onDestroy();

View File

@ -154,7 +154,7 @@ public class SetupActivity extends AppCompatActivity {
intent.setData(Uri.parse("package:com.termux")); intent.setData(Uri.parse("package:com.termux"));
startActivity(intent); startActivity(intent);
} catch (Exception e) { } catch (Exception e) {
Snackbar.make(v, "Termux is not installed or device not supported.", Snackbar.LENGTH_LONG).show(); Snackbar.make(v, R.string.termux_not_installed_error, Snackbar.LENGTH_LONG).show();
} }
}); });
@ -165,7 +165,7 @@ public class SetupActivity extends AppCompatActivity {
intent.setData(Uri.parse("package:com.termux")); intent.setData(Uri.parse("package:com.termux"));
startActivity(intent); startActivity(intent);
} catch (Exception e) { } catch (Exception e) {
Snackbar.make(v, "Termux is not installed.", Snackbar.LENGTH_LONG).show(); Snackbar.make(v, R.string.termux_not_installed, Snackbar.LENGTH_LONG).show();
} }
}); });
} }
@ -189,8 +189,8 @@ public class SetupActivity extends AppCompatActivity {
switchView.startAnimation(shake); switchView.startAnimation(shake);
// Show Snackbar with action to go to Settings // Show Snackbar with action to go to Settings
Snackbar.make(findViewById(android.R.id.content), "To revoke permissions, you must do it from system settings.", Snackbar.LENGTH_LONG) Snackbar.make(findViewById(android.R.id.content), R.string.revoke_permission_warning, Snackbar.LENGTH_LONG)
.setAction("SETTINGS", v -> openAppSettings()).show(); .setAction(R.string.settings_label, v -> openAppSettings()).show();
} }
private void openAppSettings() { private void openAppSettings() {
@ -242,4 +242,4 @@ public class SetupActivity extends AppCompatActivity {
} }
return true; return true;
} }
} }

View File

@ -76,7 +76,7 @@ public class TProxyService extends VpnService {
private void syncWatchdogLocks() { private void syncWatchdogLocks() {
Preferences prefs = new Preferences(this); Preferences prefs = new Preferences(this);
boolean watchdogEnabled = prefs.getWatchdogEnable(); boolean watchdogEnabled = prefs.getWatchdogEnable();
Log.d(TAG, "Syncing Watchdog state. Enabled: " + watchdogEnabled); Log.d(TAG, getString(R.string.syncing_watchdog, watchdogEnabled));
if (watchdogEnabled) { if (watchdogEnabled) {
acquireLocks(); acquireLocks();
@ -94,7 +94,7 @@ public class TProxyService extends VpnService {
IIABWatchdog.logSessionStart(this); IIABWatchdog.logSessionStart(this);
watchdogThread = new Thread(() -> { watchdogThread = new Thread(() -> {
Log.i(TAG, "Watchdog Thread: Started loop"); Log.i(TAG, getString(R.string.watchdog_thread_started));
while (isWatchdogRunning) { while (isWatchdogRunning) {
try { try {
// Perform only the heartbeat stimulus (Intent-based) // Perform only the heartbeat stimulus (Intent-based)
@ -106,13 +106,13 @@ public class TProxyService extends VpnService {
// Sleep for 30 seconds // Sleep for 30 seconds
Thread.sleep(30000); Thread.sleep(30000);
} catch (InterruptedException e) { } catch (InterruptedException e) {
Log.i(TAG, "Watchdog Thread: Interrupted, stopping..."); Log.i(TAG, getString(R.string.watchdog_thread_interrupted));
break; break;
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "Watchdog Thread: Error in loop", e); Log.e(TAG, getString(R.string.watchdog_thread_error), e);
} }
} }
Log.i(TAG, "Watchdog Thread: Loop ended"); Log.i(TAG, getString(R.string.watchdog_thread_ended));
}); });
watchdogThread.setName("IIAB-Watchdog-Thread"); watchdogThread.setName("IIAB-Watchdog-Thread");
watchdogThread.start(); watchdogThread.start();
@ -133,16 +133,16 @@ public class TProxyService extends VpnService {
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "IIAB:TProxyWakeLock"); wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "IIAB:TProxyWakeLock");
wakeLock.acquire(); wakeLock.acquire();
Log.i(TAG, "CPU WakeLock acquired under VPN shield"); Log.i(TAG, getString(R.string.cpu_wakelock_acquired));
} }
if (wifiLock == null) { if (wifiLock == null) {
WifiManager wm = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE); WifiManager wm = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "IIAB:TProxyWifiLock"); wifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "IIAB:TProxyWifiLock");
wifiLock.acquire(); wifiLock.acquire();
Log.i(TAG, "Wi-Fi Lock acquired under VPN shield"); Log.i(TAG, getString(R.string.wifi_lock_acquired));
} }
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "Error acquiring locks", e); Log.e(TAG, getString(R.string.error_acquiring_locks), e);
} }
} }
@ -150,12 +150,12 @@ public class TProxyService extends VpnService {
if (wakeLock != null && wakeLock.isHeld()) { if (wakeLock != null && wakeLock.isHeld()) {
wakeLock.release(); wakeLock.release();
wakeLock = null; wakeLock = null;
Log.i(TAG, "CPU WakeLock released"); Log.i(TAG, getString(R.string.cpu_wakelock_released));
} }
if (wifiLock != null && wifiLock.isHeld()) { if (wifiLock != null && wifiLock.isHeld()) {
wifiLock.release(); wifiLock.release();
wifiLock = null; wifiLock = null;
Log.i(TAG, "Wi-Fi Lock released"); Log.i(TAG, getString(R.string.wifi_lock_released));
} }
} }
@ -228,7 +228,7 @@ public class TProxyService extends VpnService {
builder.addDisallowedApplication(selfName); builder.addDisallowedApplication(selfName);
if (prefs.getMaintenanceMode()) { // Verify if the maintenance mode is enabled if (prefs.getMaintenanceMode()) { // Verify if the maintenance mode is enabled
builder.addDisallowedApplication("com.termux"); builder.addDisallowedApplication("com.termux");
Log.i(TAG, "Maintenance mode enabled: Termux has direct Internet access"); Log.i(TAG, getString(R.string.maintenance_mode_enabled));
} }
} catch (NameNotFoundException e) { } catch (NameNotFoundException e) {
} }
@ -283,7 +283,7 @@ public class TProxyService extends VpnService {
TProxyStartService(tproxy_file.getAbsolutePath(), tunFd.getFd()); TProxyStartService(tproxy_file.getAbsolutePath(), tunFd.getFd());
prefs.setEnable(true); prefs.setEnable(true);
String channelName = "socks5"; String channelName = getString(R.string.tproxy_channel_name);
initNotificationChannel(channelName); initNotificationChannel(channelName);
createNotification(channelName); createNotification(channelName);

View File

@ -34,7 +34,7 @@ public class VpnRecoveryReceiver extends BroadcastReceiver {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel( NotificationChannel channel = new NotificationChannel(
CHANNEL_ID, "VPN Recovery", CHANNEL_ID, context.getString(R.string.recovery_channel_name),
NotificationManager.IMPORTANCE_HIGH NotificationManager.IMPORTANCE_HIGH
); );
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
@ -52,8 +52,8 @@ public class VpnRecoveryReceiver extends BroadcastReceiver {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID) NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(android.R.drawable.ic_dialog_alert) .setSmallIcon(android.R.drawable.ic_dialog_alert)
.setContentTitle("Safe Pocket Web Interrupted") .setContentTitle(context.getString(R.string.recovery_notif_title))
.setContentText("Tap to restore secure environment immediately.") .setContentText(context.getString(R.string.recovery_notif_text))
.setPriority(NotificationCompat.PRIORITY_HIGH) .setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_ALARM) .setCategory(NotificationCompat.CATEGORY_ALARM)
.setAutoCancel(true) .setAutoCancel(true)

View File

@ -63,12 +63,12 @@ public class WatchdogService extends Service {
@Override @Override
public void onDestroy() { public void onDestroy() {
// 1. Avisamos inmediatamente a la UI que nos estamos apagando // We immediately notify the UI that we are shutting down.
Intent stopIntent = new Intent(ACTION_STATE_STOPPED); Intent stopIntent = new Intent(ACTION_STATE_STOPPED);
stopIntent.setPackage(getPackageName()); stopIntent.setPackage(getPackageName());
sendBroadcast(stopIntent); sendBroadcast(stopIntent);
// 2. Limpiamos la basura // We clean up the trash
cancelHeartbeat(); cancelHeartbeat();
IIABWatchdog.logSessionStop(this); IIABWatchdog.logSessionStop(this);
stopForeground(true); stopForeground(true);
@ -85,6 +85,7 @@ public class WatchdogService extends Service {
return PendingIntent.getService(this, 0, intent, flags); return PendingIntent.getService(this, 0, intent, flags);
} }
@android.annotation.SuppressLint("ScheduleExactAlarm")
private void scheduleHeartbeat() { private void scheduleHeartbeat() {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = getHeartbeatPendingIntent(); PendingIntent pendingIntent = getHeartbeatPendingIntent();
@ -92,12 +93,12 @@ public class WatchdogService extends Service {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// This wakes up the device even in Doze Mode // This wakes up the device even in Doze Mode
alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + HEARTBEAT_INTERVAL_MS, SystemClock.elapsedRealtime() + HEARTBEAT_INTERVAL_MS,
pendingIntent); pendingIntent);
} else { } else {
alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + HEARTBEAT_INTERVAL_MS, SystemClock.elapsedRealtime() + HEARTBEAT_INTERVAL_MS,
pendingIntent); pendingIntent);
} }
} }
@ -117,10 +118,10 @@ public class WatchdogService extends Service {
private void createNotificationChannel() { private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel( NotificationChannel channel = new NotificationChannel(
CHANNEL_ID, "IIAB Watchdog Service", CHANNEL_ID, getString(R.string.watchdog_channel_name),
NotificationManager.IMPORTANCE_HIGH NotificationManager.IMPORTANCE_HIGH
); );
channel.setDescription("Ensures services remain active when screen is off."); channel.setDescription(getString(R.string.watchdog_channel_desc));
NotificationManager manager = getSystemService(NotificationManager.class); NotificationManager manager = getSystemService(NotificationManager.class);
if (manager != null) { if (manager != null) {
manager.createNotificationChannel(channel); manager.createNotificationChannel(channel);
@ -134,8 +135,8 @@ public class WatchdogService extends Service {
PendingIntent.FLAG_IMMUTABLE); PendingIntent.FLAG_IMMUTABLE);
return new NotificationCompat.Builder(this, CHANNEL_ID) return new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("IIAB Watchdog Active") .setContentTitle(getString(R.string.watchdog_notif_title))
.setContentText("Protecting Termux environment...") .setContentText(getString(R.string.watchdog_notif_text))
.setSmallIcon(android.R.drawable.ic_lock_idle_lock) .setSmallIcon(android.R.drawable.ic_lock_idle_lock)
.setContentIntent(pendingIntent) .setContentIntent(pendingIntent)
.setPriority(NotificationCompat.PRIORITY_HIGH) .setPriority(NotificationCompat.PRIORITY_HIGH)

View File

@ -1,96 +1,155 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="setup_title">Initial Setup</string> <!-- General App -->
<string name="setup_welcome">Welcome to the %1$s setup wizard.\n\nIn order to work properly, we need the following permissions:</string> <string name="app_name">IIAB-oA Controller</string>
<string name="setup_perm_notifications">Push Notifications</string> <string name="default_version">v0.1.x</string>
<string name="setup_perm_termux">Termux Execution</string> <string name="save">Guardar</string>
<string name="setup_perm_vpn">Safe Pocket Web (VPN)</string> <string name="cancel">Cancelar</string>
<string name="setup_perm_battery">Disable Battery Optimization</string> <string name="saved_toast">Guardado</string>
<string name="setup_continue">Continue</string> <string name="settings_saved">Ajustes Guardados</string>
<string name="app_name">IIAB-oA Controller</string> <string name="fix_action">CORREGIR</string>
<string name="socks_addr">Dirección Socks:</string> <string name="configuration_label">Configuración</string>
<string name="socks_udp_addr">Dirección UDP Socks:</string> <string name="advanced_settings_label">Ajustes del Túnel</string>
<string name="socks_port">Puerto Socks:</string> <string name="connection_log_label">Log de Conexión</string>
<string name="socks_user">Usuario Socks:</string> <string name="settings_label">AJUSTES</string>
<string name="socks_pass">Contraseña Socks:</string>
<string name="dns_ipv4">DNS IPv4:</string>
<string name="dns_ipv6">DNS IPv6:</string>
<string name="udp_in_tcp">Relé UDP sobre TCP</string>
<string name="remote_dns">DNS Remoto</string>
<string name="ipv4">IPv4</string>
<string name="ipv6">IPv6</string>
<string name="global">Global</string>
<string name="apps">Aplicaciones</string>
<string name="save">Guardar</string>
<string name="control_enable">Activar Safe Pocket Web</string>
<string name="control_disable">Desactivar Safe Pocket Web</string>
<string name="vpn_description">Habilite URLs amigables. Bloquee las amenazas.</string>
<string name="watchdog_enable">Activar\nWatchdog Maestro</string>
<string name="watchdog_disable">Desactivar\nWatchdog Maestro</string>
<string name="log_reset_confirm_title">¿Reiniciar historial de log?</string>
<string name="log_reset_confirm_msg">Esto borrará permanentemente todos los logs de conexión guardados. Esta acción no se puede deshacer.</string>
<string name="log_warning_rapid_growth">El archivo de log está creciendo demasiado rápido, verifique si algo está fallando</string>
<!-- New strings for translatability --> <!-- SetupActivity -->
<string name="browse_content">🚀 Explorar Contenido</string> <string name="setup_title">Configuración Inicial</string>
<string name="watchdog_description">Protege Termux del modo Doze y mantiene el Wi-Fi activo.</string> <string name="setup_welcome">Bienvenido al asistente de configuración de %1$s.\n\nPara funcionar correctamente, necesitamos los siguientes permisos:</string>
<string name="reset_log">Reiniciar Log</string> <string name="setup_perm_notifications">Notificaciones Push</string>
<string name="copy_all">Copiar Todo</string> <string name="setup_perm_termux">Ejecución de Termux</string>
<string name="system_ready">Sistema listo...\n</string> <string name="setup_perm_vpn">Safe Pocket Web (VPN)</string>
<string name="configuration_label">Configuración</string> <string name="setup_perm_battery">Desactivar Optimización de Batería</string>
<string name="advanced_settings_label">Ajustes del Túnel</string> <string name="setup_continue">Continuar</string>
<string name="connection_log_label">Log de Conexión</string> <string name="revoke_permission_warning">Para revocar permisos, debe hacerlo desde los ajustes del sistema.</string>
<string name="app_started">Aplicación Iniciada</string> <string name="termux_not_installed_error">Termux no está instalado o el dispositivo no es compatible.</string>
<string name="no_blackbox_found">--- No se encontró el archivo BlackBox ---</string> <string name="termux_not_installed">Termux no está instalado.</string>
<string name="loading_history">--- Cargando Historial ---</string>
<string name="error_reading_history">Error al leer el historial: %s</string>
<string name="end_of_history">--- Fin del Historial ---</string>
<string name="recovery_pulse_received">Pulso de recuperación recibido del sistema. Forzando VPN...</string>
<string name="battery_opt_title">Optimización de Batería</string>
<string name="battery_opt_msg">Para que el Watchdog funcione de manera confiable, desactive las optimizaciones de batería para esta aplicación.</string>
<string name="go_to_settings">Ir a Ajustes</string>
<string name="cancel">Cancelar</string>
<string name="saved_toast">Guardado</string>
<string name="settings_saved">Ajustes Guardados</string>
<string name="log_reset_log">Log reiniciado</string>
<string name="log_reset_user">Log reiniciado por el usuario</string>
<string name="log_copied_toast">Log copiado al portapapeles</string>
<string name="watchdog_stopped">Watchdog Detenido</string>
<string name="watchdog_started">Watchdog Iniciado</string>
<string name="vpn_stopping">Deteniendo VPN...</string>
<string name="vpn_starting">Iniciando VPN...</string>
<string name="log_cleared_toast">Log borrado</string>
<string name="failed_reset_log">Error al reiniciar log: %s</string>
<string name="unlock_watchdog_title">Desbloquear Watchdog Maestro</string>
<string name="unlock_watchdog_subtitle">Se requiere autenticación para detener la protección de Termux</string>
<string name="auth_success_disconnect">Autenticación exitosa. Desconectando...</string>
<string name="auth_required_title">Autenticación requerida</string>
<string name="auth_required_subtitle">Autentíquese para desactivar el entorno seguro</string>
<string name="security_required_title">Seguridad Requerida</string>
<string name="security_required_msg">Debe configurar un PIN, Patrón o Huella digital en su dispositivo antes de activar el entorno seguro.</string>
<string name="user_initiated_conn">Conexión iniciada por el usuario</string>
<string name="vpn_permission_granted">Permiso de VPN concedido. Conectando...</string>
<!-- IIABWatchdog strings --> <!-- VPN / Socks -->
<string name="pulse_stimulating">Pulso: Estimulando Termux...</string> <string name="control_enable">Activar Safe Pocket Web</string>
<string name="critical_os_blocked">CRÍTICO: El SO bloqueó el estímulo a Termux (SecurityException).</string> <string name="control_disable">Desactivar Safe Pocket Web</string>
<string name="ping_ok">PING 8085: OK</string> <string name="vpn_description">Habilite URLs amigables. Bloquee las amenazas.</string>
<string name="ping_fail">PING 8085: ERROR (%s)</string> <string name="socks_addr">Dirección Socks:</string>
<string name="session_started">SESIÓN DE LATIDO INICIADA</string> <string name="socks_udp_addr">Dirección UDP Socks:</string>
<string name="session_stopped">SESIÓN DE LATIDO DETENIDA</string> <string name="socks_port">Puerto Socks:</string>
<string name="socks_user">Usuario Socks:</string>
<string name="socks_pass">Contraseña Socks:</string>
<string name="dns_ipv4">DNS IPv4:</string>
<string name="dns_ipv6">DNS IPv6:</string>
<string name="udp_in_tcp">Relé UDP sobre TCP</string>
<string name="remote_dns">DNS Remoto</string>
<string name="ipv4">IPv4</string>
<string name="ipv6">IPv6</string>
<string name="global">Global</string>
<string name="apps">Aplicaciones</string>
<string name="vpn_stopping">Deteniendo VPN...</string>
<string name="vpn_starting">Iniciando VPN...</string>
<string name="user_initiated_conn">Conexión iniciada por el usuario</string>
<string name="vpn_permission_granted">Permiso de VPN concedido. Conectando...</string>
<string name="tproxy_channel_name">socks5</string>
<!-- TermuxCallbackReceiver strings --> <!-- WatchdogService / IIABWatchdog -->
<string name="termux_stimulus_ok">[Termux] Estímulo OK (exit 0)</string> <string name="watchdog_enable">Activar\nWatchdog Maestro</string>
<string name="termux_pulse_error">[Termux] Error de pulso (exit %1$d): %2$s</string> <string name="watchdog_disable">Desactivar\nWatchdog Maestro</string>
<string name="watchdog_description">Protege Termux del modo Doze y mantiene el Wi-Fi activo.</string>
<string name="watchdog_stopped">Watchdog Detenido</string>
<string name="watchdog_started">Watchdog Iniciado</string>
<string name="watchdog_channel_name">Servicio IIAB Watchdog</string>
<string name="watchdog_channel_desc">Asegura que los servicios permanezcan activos cuando la pantalla está apagada.</string>
<string name="watchdog_notif_title">IIAB Watchdog Activo</string>
<string name="watchdog_notif_text">Protegiendo el entorno Termux...</string>
<string name="syncing_watchdog">Sincronizando estado del Watchdog. Activado: %b</string>
<string name="watchdog_thread_started">Watchdog Thread: Bucle iniciado</string>
<string name="watchdog_thread_interrupted">Watchdog Thread: Interrumpido, deteniéndose...</string>
<string name="watchdog_thread_error">Watchdog Thread: Error en el bucle</string>
<string name="watchdog_thread_ended">Watchdog Thread: Bucle finalizado</string>
<string name="cpu_wakelock_acquired">CPU WakeLock adquirido bajo protección VPN</string>
<string name="wifi_lock_acquired">Wi-Fi Lock adquirido bajo protección VPN</string>
<string name="error_acquiring_locks">Error al adquirir bloqueos</string>
<string name="cpu_wakelock_released">CPU WakeLock liberado</string>
<string name="wifi_lock_released">Wi-Fi Lock liberado</string>
<string name="log_size_format">Tamaño: %1$s / 10MB</string> <!-- Pulse / Heartbeat -->
<string name="battery_opt_xiaomi_extra">[...]</string> <string name="pulse_stimulating">Pulso: Estimulando Termux...</string>
<string name="battery_opt_denied">For the app to work 100%, please disable battery optimization.</string> <string name="critical_os_blocked">CRÍTICO: El SO bloqueó el estímulo a Termux (SecurityException).</string>
<string name="fix_action">FIX</string> <string name="ping_ok">PING 8085: OK</string>
<string name="qr_error_no_server">Please launch the server to share over the network.</string> <string name="ping_fail">PING 8085: FALLO (%s)</string>
<string name="qr_error_no_network">Please enable Wi-Fi or Hotspot to share over the network.</string> <string name="session_started">SESIÓN DE LATIDO INICIADA</string>
<string name="qr_title_wifi">Wi-Fi Network</string> <string name="session_stopped">SESIÓN DE LATIDO DETENIDA</string>
<string name="qr_title_hotspot">Hotspot Network</string> <string name="permission_denied_log">Permiso denegado: Asegúrese de que el manifiesto tiene RUN_COMMAND y la app no está restringida.</string>
<string name="qr_flip_network">Switch Network</string> <string name="unexpected_error_termux">Error inesperado enviando intent a Termux</string>
<string name="battery_opt_oppo_extra">[...]</string> <string name="pulse_error_log">Error de Pulso: %s</string>
</resources> <string name="maintenance_write_failed">Fallo en la escritura de mantenimiento</string>
<string name="failed_write_blackbox">Fallo al escribir en BlackBox</string>
<string name="recovery_pulse_received">Pulso de recuperación recibido del sistema. Forzando VPN...</string>
<!-- TermuxCallbackReceiver / Operations -->
<string name="termux_stimulus_ok">[Termux] Estímulo OK (exit 0)</string>
<string name="termux_pulse_error">[Termux] Error de pulso (exit %1$d): %2$s</string>
<string name="server_timeout_warning">Advertencia: Tiempo de espera agotado en la transición de estado del servidor.</string>
<string name="server_booting">Iniciando...</string>
<string name="server_shutting_down">Apagando...</string>
<string name="failed_termux_intent">CRÍTICO: Fallo en el Intent de Termux: %s</string>
<string name="sent_to_termux">Enviado a Termux: %s</string>
<string name="maintenance_mode_enabled">Modo de mantenimiento activado: Termux tiene acceso directo a Internet</string>
<string name="stop_server">🛑 Detener Servidor</string>
<string name="launch_server">🚀 Iniciar Servidor</string>
<string name="termux_perm_granted">Permiso de Termux concedido</string>
<string name="termux_perm_denied">Permiso de Termux denegado</string>
<string name="notif_perm_granted">Permiso de notificaciones concedido</string>
<string name="notif_perm_denied">Permiso de notificaciones denegado</string>
<!-- Logs -->
<string name="log_reset_confirm_title">¿Reiniciar historial de log?</string>
<string name="log_reset_confirm_msg">Esto borrará permanentemente todos los logs de conexión guardados. Esta acción no se puede deshacer.</string>
<string name="log_warning_rapid_growth">El archivo de log está creciendo demasiado rápido, verifique si algo está fallando</string>
<string name="reset_log">Reiniciar Log</string>
<string name="copy_all">Copiar Todo</string>
<string name="log_reset_log">Log reiniciado</string>
<string name="log_reset_user">Log reiniciado por el usuario</string>
<string name="log_copied_toast">Log copiado al portapapeles</string>
<string name="log_cleared_toast">Log borrado</string>
<string name="failed_reset_log">Fallo al reiniciar el log: %s</string>
<string name="log_size_format">Tamaño: %1$s / 10MB</string>
<string name="log_size_bytes">%d B</string>
<string name="log_size_kb">%.1f KB</string>
<string name="log_size_mb">%.2f MB</string>
<string name="no_blackbox_found">--- No se encontró el archivo BlackBox ---</string>
<string name="loading_history">--- Cargando Historial ---</string>
<string name="error_reading_history">Error al leer el historial: %s</string>
<string name="end_of_history">--- Fin del Historial ---</string>
<!-- Battery Optimizations -->
<string name="battery_opt_title">Optimización de Batería</string>
<string name="battery_opt_msg">Para que el Watchdog funcione de manera confiable, desactive las optimizaciones de batería para esta aplicación.</string>
<string name="go_to_settings">Ir a Ajustes</string>
<string name="battery_opt_oppo_extra">\n\nOPPO/Realme detectado: Asegúrese de activar \'Permitir actividad en segundo plano\' en los ajustes de esta aplicación.</string>
<string name="battery_opt_xiaomi_extra">\n\nXiaomi detectado: Establezca el ahorro de batería a \'Sin restricciones\' en los ajustes.</string>
<string name="battery_opt_denied">Para que la app funcione al 100%, desactive la optimización de batería.</string>
<!-- UI / Misc -->
<string name="browse_content">🚀 Explorar Contenido</string>
<string name="system_ready">Sistema listo...\n</string>
<string name="app_started">Aplicación Iniciada</string>
<string name="label_separator_down">▼ %s</string>
<string name="label_separator_up">▶ %s</string>
<string name="qr_error_no_server">Inicie el servidor para compartir contenido a través de la red.</string>
<string name="qr_error_no_network">Active Wi-Fi o Hotspot para compartir contenido a través de la red.</string>
<string name="qr_title_wifi">Red Wi-Fi</string>
<string name="qr_title_hotspot">Red Hotspot</string>
<string name="qr_flip_network">Cambiar Red</string>
<!-- Authentication / Security -->
<string name="unlock_watchdog_title">Desbloquear Watchdog Maestro</string>
<string name="unlock_watchdog_subtitle">Se requiere autenticación para detener la protección de Termux</string>
<string name="auth_success_disconnect">Autenticación exitosa. Desconectando...</string>
<string name="auth_required_title">Autenticación requerida</string>
<string name="auth_required_subtitle">Autentíquese para desactivar el entorno seguro</string>
<string name="security_required_title">Seguridad Requerida</string>
<string name="security_required_msg">Debe configurar un PIN, Patrón o Huella digital en su dispositivo antes de activar el entorno seguro.</string>
<!-- VPN Recovery Service -->
<string name="recovery_channel_name">Recuperación VPN</string>
<string name="recovery_notif_title">Safe Pocket Web Interrumpido</string>
<string name="recovery_notif_text">Toque para restaurar el entorno seguro inmediatamente.</string>
</resources>

View File

@ -1,98 +1,155 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="setup_title">Initial Setup</string> <!-- General App -->
<string name="setup_welcome">Welcome to the %1$s setup wizard.\n\nIn order to work properly, we need the following permissions:</string> <string name="app_name">IIAB-oA Controller</string>
<string name="setup_perm_notifications">Push Notifications</string> <string name="default_version">v0.1.x</string>
<string name="setup_perm_termux">Termux Execution</string> <string name="save">Сохранить</string>
<string name="setup_perm_vpn">Safe Pocket Web (VPN)</string> <string name="cancel">Отмена</string>
<string name="setup_perm_battery">Disable Battery Optimization</string> <string name="saved_toast">Сохранено</string>
<string name="setup_continue">Continue</string> <string name="settings_saved">Настройки сохранены</string>
<string name="app_name">IIAB-oA Controller</string> <string name="fix_action">ИСПРАВИТЬ</string>
<string name="socks_addr">Socks Address:</string> <string name="configuration_label">Конфигурация</string>
<string name="socks_udp_addr">Socks UDP Address:</string> <string name="advanced_settings_label">Настройки туннеля</string>
<string name="socks_port">Socks Port:</string> <string name="connection_log_label">Журнал подключений</string>
<string name="socks_user">Socks Username:</string> <string name="settings_label">НАСТРОЙКИ</string>
<string name="socks_pass">Socks Password:</string>
<string name="dns_ipv4">DNS IPv4:</string>
<string name="dns_ipv6">DNS IPv6:</string>
<string name="udp_in_tcp">UDP relay over TCP</string>
<string name="remote_dns">Remote DNS</string>
<string name="ipv4">IPv4</string>
<string name="ipv6">IPv6</string>
<string name="global">Global</string>
<string name="apps">Apps</string>
<string name="save">Save</string>
<string name="control_enable">Enable Safe Pocket Web</string>
<string name="control_disable">Disable Safe Pocket Web</string>
<string name="vpn_description">Enable friendly URLs. Lock out the threats.</string>
<string name="watchdog_enable">Enable\nMaster Watchdog</string>
<string name="watchdog_disable">Disable\nMaster Watchdog</string>
<string name="log_reset_confirm_title">Reset Log History?</string>
<string name="log_reset_confirm_msg">This will permanently delete all stored connection logs. This action cannot be undone.</string>
<string name="log_warning_rapid_growth">The logging file is growing too rapidly, you might want to check if something is failing</string>
<!-- New strings for translatability --> <!-- SetupActivity -->
<string name="browse_content">🚀 Explore Content</string> <string name="setup_title">Начальная настройка</string>
<string name="watchdog_description">Protects Termux from Doze mode and keeps Wi-Fi active.</string> <string name="setup_welcome">Добро пожаловать в мастер настройки %1$s.\n\nДля правильной работы нам нужны следующие разрешения:</string>
<string name="reset_log">Reset Log</string> <string name="setup_perm_notifications">Push-уведомления</string>
<string name="copy_all">Copy All</string> <string name="setup_perm_termux">Выполнение Termux</string>
<string name="system_ready">System ready...\n</string> <string name="setup_perm_vpn">Safe Pocket Web (VPN)</string>
<string name="configuration_label">Configuration</string> <string name="setup_perm_battery">Отключить оптимизацию батареи</string>
<string name="advanced_settings_label">Tunnel Settings</string> <string name="setup_continue">Продолжить</string>
<string name="connection_log_label">Connection Log</string> <string name="revoke_permission_warning">Чтобы отозвать разрешения, это нужно сделать в настройках системы.</string>
<string name="app_started">Application Started</string> <string name="termux_not_installed_error">Termux не установлен или устройство не поддерживается.</string>
<string name="no_blackbox_found">--- No BlackBox file found ---</string> <string name="termux_not_installed">Termux не установлен.</string>
<string name="loading_history">--- Loading History ---</string>
<string name="error_reading_history">Error reading history: %s</string>
<string name="end_of_history">--- End of History ---</string>
<string name="recovery_pulse_received">Recovery Pulse Received from System. Enforcing VPN...</string>
<string name="battery_opt_title">Battery Optimization</string>
<string name="battery_opt_msg">For the Watchdog to work reliably, please disable battery optimizations for this app.</string>
<string name="go_to_settings">Go to Settings</string>
<string name="cancel">Cancel</string>
<string name="saved_toast">Saved</string>
<string name="settings_saved">Settings Saved</string>
<string name="log_reset_log">Log reset</string>
<string name="log_reset_user">Log reset by user</string>
<string name="log_copied_toast">Log copied to clipboard</string>
<string name="watchdog_stopped">Watchdog Stopped</string>
<string name="watchdog_started">Watchdog Started</string>
<string name="vpn_stopping">VPN Stopping...</string>
<string name="vpn_starting">VPN Starting...</string>
<string name="log_cleared_toast">Log cleared</string>
<string name="failed_reset_log">Failed to reset log: %s</string>
<string name="unlock_watchdog_title">Unlock Master Watchdog</string>
<string name="unlock_watchdog_subtitle">Authentication required to stop Termux protection</string>
<string name="auth_success_disconnect">Authentication Success. Disconnecting...</string>
<string name="auth_required_title">Authentication required</string>
<string name="auth_required_subtitle">Authenticate to disable the secure environment</string>
<string name="security_required_title">Security Required</string>
<string name="security_required_msg">You must set up a PIN, Pattern, or Fingerprint on your device before enabling the secure environment.</string>
<string name="user_initiated_conn">User initiated connection</string>
<string name="vpn_permission_granted">VPN Permission Granted. Connecting...</string>
<!-- IIABWatchdog strings --> <!-- VPN / Socks -->
<string name="pulse_stimulating">Pulse: Stimulating Termux...</string> <string name="control_enable">Включить Safe Pocket Web</string>
<string name="critical_os_blocked">CRITICAL: OS blocked Termux stimulus (SecurityException).</string> <string name="control_disable">Выключить Safe Pocket Web</string>
<string name="ping_ok">PING 8085: OK</string> <string name="vpn_description">Включить дружественные URL. Блокировать угрозы.</string>
<string name="ping_fail">PING 8085: FAIL (%s)</string> <string name="socks_addr">Адрес Socks:</string>
<string name="session_started">HEARTBEAT SESSION STARTED</string> <string name="socks_udp_addr">UDP адрес Socks:</string>
<string name="session_stopped">HEARTBEAT SESSION STOPPED</string> <string name="socks_port">Порт Socks:</string>
<string name="socks_user">Имя пользователя Socks:</string>
<string name="socks_pass">Пароль Socks:</string>
<string name="dns_ipv4">DNS IPv4:</string>
<string name="dns_ipv6">DNS IPv6:</string>
<string name="udp_in_tcp">UDP ретрансляция через TCP</string>
<string name="remote_dns">Удаленный DNS</string>
<string name="ipv4">IPv4</string>
<string name="ipv6">IPv6</string>
<string name="global">Глобально</string>
<string name="apps">Приложения</string>
<string name="vpn_stopping">Остановка VPN...</string>
<string name="vpn_starting">Запуск VPN...</string>
<string name="user_initiated_conn">Соединение инициировано пользователем</string>
<string name="vpn_permission_granted">Разрешение VPN получено. Подключение...</string>
<string name="tproxy_channel_name">socks5</string>
<!-- TermuxCallbackReceiver strings --> <!-- WatchdogService / IIABWatchdog -->
<string name="termux_stimulus_ok">[Termux] Stimulus OK (exit 0)</string> <string name="watchdog_enable">Включить\nМастер Watchdog</string>
<string name="termux_pulse_error">[Termux] Pulse Error (exit %1$d): %2$s</string> <string name="watchdog_disable">Выключить\nМастер Watchdog</string>
<string name="watchdog_description">Защищает Termux от режима Doze и поддерживает Wi-Fi активным.</string>
<string name="watchdog_stopped">Watchdog остановлен</string>
<string name="watchdog_started">Watchdog запущен</string>
<string name="watchdog_channel_name">Служба IIAB Watchdog</string>
<string name="watchdog_channel_desc">Гарантирует, что службы остаются активными при выключенном экране.</string>
<string name="watchdog_notif_title">IIAB Watchdog активен</string>
<string name="watchdog_notif_text">Защита окружения Termux...</string>
<string name="syncing_watchdog">Синхронизация состояния Watchdog. Включено: %b</string>
<string name="watchdog_thread_started">Watchdog Thread: Цикл запущен</string>
<string name="watchdog_thread_interrupted">Watchdog Thread: Прервано, остановка...</string>
<string name="watchdog_thread_error">Watchdog Thread: Ошибка в цикле</string>
<string name="watchdog_thread_ended">Watchdog Thread: Цикл завершен</string>
<string name="cpu_wakelock_acquired">CPU WakeLock получен под защитой VPN</string>
<string name="wifi_lock_acquired">Wi-Fi Lock получен под защитой VPN</string>
<string name="error_acquiring_locks">Ошибка получения блокировок</string>
<string name="cpu_wakelock_released">CPU WakeLock освобожден</string>
<string name="wifi_lock_released">Wi-Fi Lock освобожден</string>
<string name="log_size_format">Size: %1$s / 10MB</string> <!-- Pulse / Heartbeat -->
<string name="pulse_stimulating">Пульс: Стимуляция Termux...</string>
<string name="critical_os_blocked">КРИТИЧЕСКАЯ ОШИБКА: ОС заблокировала стимуляцию Termux (SecurityException).</string>
<string name="ping_ok">PING 8085: OK</string>
<string name="ping_fail">PING 8085: ОШИБКА (%s)</string>
<string name="session_started">СЕАНС СЕРДЦЕБИЕНИЯ ЗАПУЩЕН</string>
<string name="session_stopped">СЕАНС СЕРДЦЕБИЕНИЯ ОСТАНОВЛЕН</string>
<string name="permission_denied_log">В доступе отказано: убедитесь, что в манифесте есть RUN_COMMAND и приложение не ограничено.</string>
<string name="unexpected_error_termux">Непредвиденная ошибка при отправке intent в Termux</string>
<string name="pulse_error_log">Ошибка пульса: %s</string>
<string name="maintenance_write_failed">Ошибка записи обслуживания</string>
<string name="failed_write_blackbox">Ошибка записи в BlackBox</string>
<string name="recovery_pulse_received">Пульс восстановления получен от системы. Принудительный VPN...</string>
<!-- Brand specific battery warnings --> <!-- TermuxCallbackReceiver / Operations -->
<string name="battery_opt_oppo_extra">\n\nOPPO/Realme detected: Please ensure you also enable \'Allow background activity\' in this app\'s settings.</string> <string name="termux_stimulus_ok">[Termux] Стимул OK (exit 0)</string>
<string name="battery_opt_xiaomi_extra">\n\nXiaomi detected: Please set battery saver to \'No restrictions\' in settings.</string> <string name="termux_pulse_error">[Termux] Ошибка пульса (exit %1$d): %2$s</string>
<string name="battery_opt_denied">For the app to work 100%, please disable battery optimization.</string> <string name="server_timeout_warning">Предупреждение: Время ожидания перехода состояния сервера истекло.</string>
<string name="fix_action">FIX</string> <string name="server_booting">Загрузка...</string>
<string name="qr_error_no_server">Please launch the server to share over the network.</string> <string name="server_shutting_down">Выключение...</string>
<string name="qr_error_no_network">Please enable Wi-Fi or Hotspot to share over the network.</string> <string name="failed_termux_intent">КРИТИЧЕСКАЯ ОШИБКА: Ошибка Intent Termux: %s</string>
<string name="qr_title_wifi">Wi-Fi Network</string> <string name="sent_to_termux">Отправлено в Termux: %s</string>
<string name="qr_title_hotspot">Hotspot Network</string> <string name="maintenance_mode_enabled">Режим обслуживания включен: Termux имеет прямой доступ в Интернет</string>
<string name="qr_flip_network">Switch Network</string> <string name="stop_server">🛑 Остановить сервер</string>
</resources> <string name="launch_server">🚀 Запустить сервер</string>
<string name="termux_perm_granted">Разрешение Termux предоставлено</string>
<string name="termux_perm_denied">Разрешение Termux отклонено</string>
<string name="notif_perm_granted">Разрешение на уведомления предоставлено</string>
<string name="notif_perm_denied">Разрешение на уведомления отклонено</string>
<!-- Logs -->
<string name="log_reset_confirm_title">Сбросить историю журнала?</string>
<string name="log_reset_confirm_msg">Это безвозвратно удалит все сохраненные журналы подключений. Это действие нельзя отменить.</string>
<string name="log_warning_rapid_growth">Файл журнала растет слишком быстро, возможно, стоит проверить, нет ли ошибки</string>
<string name="reset_log">Сбросить журнал</string>
<string name="copy_all">Скопировать все</string>
<string name="log_reset_log">Журнал сброшен</string>
<string name="log_reset_user">Журнал сброшен пользователем</string>
<string name="log_copied_toast">Журнал скопирован в буфер обмена</string>
<string name="log_cleared_toast">Журнал очищен</string>
<string name="failed_reset_log">Ошибка сброса журнала: %s</string>
<string name="log_size_format">Размер: %1$s / 10MB</string>
<string name="log_size_bytes">%d B</string>
<string name="log_size_kb">%.1f KB</string>
<string name="log_size_mb">%.2f MB</string>
<string name="no_blackbox_found">--- Файл BlackBox не найден ---</string>
<string name="loading_history">--- Загрузка истории ---</string>
<string name="error_reading_history">Ошибка чтения истории: %s</string>
<string name="end_of_history">--- Конец истории ---</string>
<!-- Battery Optimizations -->
<string name="battery_opt_title">Оптимизация батареи</string>
<string name="battery_opt_msg">Для надежной работы Watchdog, пожалуйста, отключите оптимизацию батареи для этого приложения.</string>
<string name="go_to_settings">Перейти к настройкам</string>
<string name="battery_opt_oppo_extra">\n\nOPPO/Realme обнаружен: Пожалуйста, убедитесь, что вы включили "Разрешить фоновую активность" в настройках этого приложения.</string>
<string name="battery_opt_xiaomi_extra">\n\nXiaomi обнаружен: Пожалуйста, установите экономию заряда батареи на "Без ограничений" в настройках.</string>
<string name="battery_opt_denied">Для 100% работы приложения, пожалуйста, отключите оптимизацию батареи.</string>
<!-- UI / Misc -->
<string name="browse_content">🚀 Исследовать контент</string>
<string name="system_ready">Система готова...\n</string>
<string name="app_started">Приложение запущено</string>
<string name="label_separator_down">▼ %s</string>
<string name="label_separator_up">▶ %s</string>
<string name="qr_error_no_server">Запустите сервер, чтобы поделиться контентом по сети.</string>
<string name="qr_error_no_network">Включите Wi-Fi или точку доступа, чтобы поделиться контентом по сети.</string>
<string name="qr_title_wifi">Сеть Wi-Fi</string>
<string name="qr_title_hotspot">Сеть точки доступа</string>
<string name="qr_flip_network">Переключить сеть</string>
<!-- Authentication / Security -->
<string name="unlock_watchdog_title">Разблокировать Мастер Watchdog</string>
<string name="unlock_watchdog_subtitle">Требуется аутентификация для остановки защиты Termux</string>
<string name="auth_success_disconnect">Аутентификация успешна. Отключение...</string>
<string name="auth_required_title">Требуется аутентификация</string>
<string name="auth_required_subtitle">Пройдите аутентификацию, чтобы отключить безопасное окружение</string>
<string name="security_required_title">Требуется безопасность</string>
<string name="security_required_msg">Перед активацией безопасного окружения необходимо установить PIN-код, графический ключ или отпечаток пальца на устройстве.</string>
<!-- VPN Recovery Service -->
<string name="recovery_channel_name">Восстановление VPN</string>
<string name="recovery_notif_title">Safe Pocket Web прерван</string>
<string name="recovery_notif_text">Нажмите, чтобы немедленно восстановить безопасное окружение.</string>
</resources>

View File

@ -1,99 +1,155 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="setup_title">Initial Setup</string> <!-- General App -->
<string name="setup_welcome">Welcome to the %1$s setup wizard.\n\nIn order to work properly, we need the following permissions:</string> <string name="app_name">IIAB-oA Controller</string>
<string name="default_version">v0.1.x</string>
<string name="save">Save</string>
<string name="cancel">Cancel</string>
<string name="saved_toast">Saved</string>
<string name="settings_saved">Settings Saved</string>
<string name="fix_action">FIX</string>
<string name="configuration_label">Configuration</string>
<string name="advanced_settings_label">Tunnel Settings</string>
<string name="connection_log_label">Connection Log</string>
<string name="settings_label">SETTINGS</string>
<!-- SetupActivity -->
<string name="setup_title">Initial Setup</string>
<string name="setup_welcome">Welcome to the %1$s setup wizard.\n\nIn order to work properly, we need the following permissions:</string>
<string name="setup_perm_notifications">Push Notifications</string> <string name="setup_perm_notifications">Push Notifications</string>
<string name="setup_perm_termux">Termux Execution</string> <string name="setup_perm_termux">Termux Execution</string>
<string name="setup_perm_vpn">Safe Pocket Web (VPN)</string> <string name="setup_perm_vpn">Safe Pocket Web (VPN)</string>
<string name="setup_perm_battery">Disable Battery Optimization</string> <string name="setup_perm_battery">Disable Battery Optimization</string>
<string name="setup_continue">Continue</string> <string name="setup_continue">Continue</string>
<string name="app_name">IIAB-oA Controller</string> <string name="revoke_permission_warning">To revoke permissions, you must do it from system settings.</string>
<string name="socks_addr">Socks Address:</string> <string name="termux_not_installed_error">Termux is not installed or device not supported.</string>
<string name="socks_udp_addr">Socks UDP Address:</string> <string name="termux_not_installed">Termux is not installed.</string>
<string name="socks_port">Socks Port:</string>
<string name="socks_user">Socks Username:</string>
<string name="socks_pass">Socks Password:</string>
<string name="dns_ipv4">DNS IPv4:</string>
<string name="dns_ipv6">DNS IPv6:</string>
<string name="udp_in_tcp">UDP relay over TCP</string>
<string name="remote_dns">Remote DNS</string>
<string name="ipv4">IPv4</string>
<string name="ipv6">IPv6</string>
<string name="global">Global</string>
<string name="apps">Apps</string>
<string name="save">Save</string>
<string name="control_enable">Enable Safe Pocket Web</string>
<string name="control_disable">Disable Safe Pocket Web</string>
<string name="vpn_description">Enable friendly URLs. Lock out the threats.</string>
<string name="watchdog_enable">Enable\nMaster Watchdog</string>
<string name="watchdog_disable">Disable\nMaster Watchdog</string>
<string name="log_reset_confirm_title">Reset Log History?</string>
<string name="log_reset_confirm_msg">This will permanently delete all stored connection logs. This action cannot be undone.</string>
<string name="log_warning_rapid_growth">The logging file is growing too rapidly, you might want to check if something is failing</string>
<!-- New strings for translatability --> <!-- VPN / Socks -->
<string name="browse_content">🚀 Explore Content</string> <string name="control_enable">Enable Safe Pocket Web</string>
<string name="watchdog_description">Protects Termux from Doze mode and keeps Wi-Fi active.</string> <string name="control_disable">Disable Safe Pocket Web</string>
<string name="reset_log">Reset Log</string> <string name="vpn_description">Enable friendly URLs. Lock out the threats.</string>
<string name="copy_all">Copy All</string> <string name="socks_addr">Socks Address:</string>
<string name="system_ready">System ready...\n</string> <string name="socks_udp_addr">Socks UDP Address:</string>
<string name="configuration_label">Configuration</string> <string name="socks_port">Socks Port:</string>
<string name="advanced_settings_label">Tunnel Settings</string> <string name="socks_user">Socks Username:</string>
<string name="connection_log_label">Connection Log</string> <string name="socks_pass">Socks Password:</string>
<string name="app_started">Application Started</string> <string name="dns_ipv4">DNS IPv4:</string>
<string name="no_blackbox_found">--- No BlackBox file found ---</string> <string name="dns_ipv6">DNS IPv6:</string>
<string name="loading_history">--- Loading History ---</string> <string name="udp_in_tcp">UDP relay over TCP</string>
<string name="error_reading_history">Error reading history: %s</string> <string name="remote_dns">Remote DNS</string>
<string name="end_of_history">--- End of History ---</string> <string name="ipv4">IPv4</string>
<string name="recovery_pulse_received">Recovery Pulse Received from System. Enforcing VPN...</string> <string name="ipv6">IPv6</string>
<string name="battery_opt_title">Battery Optimization</string> <string name="global">Global</string>
<string name="battery_opt_msg">For the Watchdog to work reliably, please disable battery optimizations for this app.</string> <string name="apps">Apps</string>
<string name="go_to_settings">Go to Settings</string> <string name="vpn_stopping">VPN Stopping...</string>
<string name="cancel">Cancel</string> <string name="vpn_starting">VPN Starting...</string>
<string name="saved_toast">Saved</string> <string name="user_initiated_conn">User initiated connection</string>
<string name="settings_saved">Settings Saved</string> <string name="vpn_permission_granted">VPN Permission Granted. Connecting...</string>
<string name="log_reset_log">Log reset</string> <string name="tproxy_channel_name">socks5</string>
<string name="log_reset_user">Log reset by user</string>
<string name="log_copied_toast">Log copied to clipboard</string>
<string name="watchdog_stopped">Watchdog Stopped</string>
<string name="watchdog_started">Watchdog Started</string>
<string name="vpn_stopping">VPN Stopping...</string>
<string name="vpn_starting">VPN Starting...</string>
<string name="log_cleared_toast">Log cleared</string>
<string name="failed_reset_log">Failed to reset log: %s</string>
<string name="unlock_watchdog_title">Unlock Master Watchdog</string>
<string name="unlock_watchdog_subtitle">Authentication required to stop Termux protection</string>
<string name="auth_success_disconnect">Authentication Success. Disconnecting...</string>
<string name="auth_required_title">Authentication required</string>
<string name="auth_required_subtitle">Authenticate to disable the secure environment</string>
<string name="security_required_title">Security Required</string>
<string name="security_required_msg">You must set up a PIN, Pattern, or Fingerprint on your device before enabling the secure environment.</string>
<string name="user_initiated_conn">User initiated connection</string>
<string name="vpn_permission_granted">VPN Permission Granted. Connecting...</string>
<!-- IIABWatchdog strings --> <!-- WatchdogService / IIABWatchdog -->
<string name="pulse_stimulating">Pulse: Stimulating Termux...</string> <string name="watchdog_enable">Enable\nMaster Watchdog</string>
<string name="critical_os_blocked">CRITICAL: OS blocked Termux stimulus (SecurityException).</string> <string name="watchdog_disable">Disable\nMaster Watchdog</string>
<string name="ping_ok">PING 8085: OK</string> <string name="watchdog_description">Protects Termux from Doze mode and keeps Wi-Fi active.</string>
<string name="ping_fail">PING 8085: FAIL (%s)</string> <string name="watchdog_stopped">Watchdog Stopped</string>
<string name="session_started">HEARTBEAT SESSION STARTED</string> <string name="watchdog_started">Watchdog Started</string>
<string name="session_stopped">HEARTBEAT SESSION STOPPED</string> <string name="watchdog_channel_name">IIAB Watchdog Service</string>
<string name="watchdog_channel_desc">Ensures services remain active when screen is off.</string>
<string name="watchdog_notif_title">IIAB Watchdog Active</string>
<string name="watchdog_notif_text">Protecting Termux environment...</string>
<string name="syncing_watchdog">Syncing Watchdog state. Enabled: %b</string>
<string name="watchdog_thread_started">Watchdog Thread: Started loop</string>
<string name="watchdog_thread_interrupted">Watchdog Thread: Interrupted, stopping...</string>
<string name="watchdog_thread_error">Watchdog Thread: Error in loop</string>
<string name="watchdog_thread_ended">Watchdog Thread: Loop ended</string>
<string name="cpu_wakelock_acquired">CPU WakeLock acquired under VPN shield</string>
<string name="wifi_lock_acquired">Wi-Fi Lock acquired under VPN shield</string>
<string name="error_acquiring_locks">Error acquiring locks</string>
<string name="cpu_wakelock_released">CPU WakeLock released</string>
<string name="wifi_lock_released">Wi-Fi Lock released</string>
<!-- TermuxCallbackReceiver strings --> <!-- Pulse / Heartbeat -->
<string name="termux_stimulus_ok">[Termux] Stimulus OK (exit 0)</string> <string name="pulse_stimulating">Pulse: Stimulating Termux...</string>
<string name="termux_pulse_error">[Termux] Pulse Error (exit %1$d): %2$s</string> <string name="critical_os_blocked">CRITICAL: OS blocked Termux stimulus (SecurityException).</string>
<string name="ping_ok">PING 8085: OK</string>
<string name="ping_fail">PING 8085: FAIL (%s)</string>
<string name="session_started">HEARTBEAT SESSION STARTED</string>
<string name="session_stopped">HEARTBEAT SESSION STOPPED</string>
<string name="permission_denied_log">Permission Denied: Ensure manifest has RUN_COMMAND and app is not restricted.</string>
<string name="unexpected_error_termux">Unexpected error sending intent to Termux</string>
<string name="pulse_error_log">Pulse Error: %s</string>
<string name="maintenance_write_failed">Maintenance write failed</string>
<string name="failed_write_blackbox">Failed to write to BlackBox</string>
<string name="recovery_pulse_received">Recovery Pulse Received from System. Enforcing VPN...</string>
<string name="log_size_format">Size: %1$s / 10MB</string> <!-- TermuxCallbackReceiver / Operations -->
<string name="termux_stimulus_ok">[Termux] Stimulus OK (exit 0)</string>
<string name="termux_pulse_error">[Termux] Pulse Error (exit %1$d): %2$s</string>
<string name="server_timeout_warning">Warning: Server state transition timed out.</string>
<string name="server_booting">Booting...</string>
<string name="server_shutting_down">Shutting down...</string>
<string name="failed_termux_intent">CRITICAL: Failed Termux Intent: %s</string>
<string name="sent_to_termux">Sent to Termux: %s</string>
<string name="maintenance_mode_enabled">Maintenance mode enabled: Termux has direct Internet access</string>
<string name="stop_server">🛑 Stop Server</string>
<string name="launch_server">🚀 Launch Server</string>
<string name="termux_perm_granted">Termux permission granted</string>
<string name="termux_perm_denied">Termux permission denied</string>
<string name="notif_perm_granted">Notification permission granted</string>
<string name="notif_perm_denied">Notification permission denied</string>
<!-- Brand specific battery warnings --> <!-- Logs -->
<string name="battery_opt_oppo_extra">\n\nOPPO/Realme detected: Please ensure you also enable \'Allow background activity\' in this app\'s settings.</string> <string name="log_reset_confirm_title">Reset Log History?</string>
<string name="battery_opt_xiaomi_extra">\n\nXiaomi detected: Please set battery saver to \'No restrictions\' in settings.</string> <string name="log_reset_confirm_msg">This will permanently delete all stored connection logs. This action cannot be undone.</string>
<string name="log_warning_rapid_growth">The logging file is growing too rapidly, you might want to check if something is failing</string>
<string name="reset_log">Reset Log</string>
<string name="copy_all">Copy All</string>
<string name="log_reset_log">Log reset</string>
<string name="log_reset_user">Log reset by user</string>
<string name="log_copied_toast">Log copied to clipboard</string>
<string name="log_cleared_toast">Log cleared</string>
<string name="failed_reset_log">Failed to reset log: %s</string>
<string name="log_size_format">Size: %1$s / 10MB</string>
<string name="log_size_bytes">%d B</string>
<string name="log_size_kb">%.1f KB</string>
<string name="log_size_mb">%.2f MB</string>
<string name="no_blackbox_found">--- No BlackBox file found ---</string>
<string name="loading_history">--- Loading History ---</string>
<string name="error_reading_history">Error reading history: %s</string>
<string name="end_of_history">--- End of History ---</string>
<!-- Battery Optimizations -->
<string name="battery_opt_title">Battery Optimization</string>
<string name="battery_opt_msg">For the Watchdog to work reliably, please disable battery optimizations for this app.</string>
<string name="go_to_settings">Go to Settings</string>
<string name="battery_opt_oppo_extra">\n\nOPPO/Realme detected: Please ensure you also enable \'Allow background activity\' in this app\'s settings.</string>
<string name="battery_opt_xiaomi_extra">\n\nXiaomi detected: Please set battery saver to \'No restrictions\' in settings.</string>
<string name="battery_opt_denied">For the app to work 100%, please disable battery optimization.</string> <string name="battery_opt_denied">For the app to work 100%, please disable battery optimization.</string>
<string name="fix_action">FIX</string>
<string name="qr_error_no_server">Please launch the server to share over the network.</string> <!-- UI / Misc -->
<string name="qr_error_no_network">Please enable Wi-Fi or Hotspot to share over the network.</string> <string name="browse_content">🚀 Explore Content</string>
<string name="qr_title_wifi">Wi-Fi Network</string> <string name="system_ready">System ready...\n</string>
<string name="qr_title_hotspot">Hotspot Network</string> <string name="app_started">Application Started</string>
<string name="qr_flip_network">Switch Network</string> <string name="label_separator_down">▼ %s</string>
</resources> <string name="label_separator_up">▶ %s</string>
<string name="qr_error_no_server">Launch the server to share content over the network.</string>
<string name="qr_error_no_network">Enable Wi-Fi or Hotspot to share content over the network.</string>
<string name="qr_title_wifi">Wi-Fi Network</string>
<string name="qr_title_hotspot">Hotspot Network</string>
<string name="qr_flip_network">Switch Network</string>
<!-- Authentication / Security -->
<string name="unlock_watchdog_title">Unlock Master Watchdog</string>
<string name="unlock_watchdog_subtitle">Authentication required to stop Termux protection</string>
<string name="auth_success_disconnect">Authentication Success. Disconnecting...</string>
<string name="auth_required_title">Authentication required</string>
<string name="auth_required_subtitle">Authenticate to disable the secure environment</string>
<string name="security_required_title">Security Required</string>
<string name="security_required_msg">You must set up a PIN, Pattern, or Fingerprint on your device before enabling the secure environment.</string>
<!-- VPN Recovery Service -->
<string name="recovery_channel_name">VPN Recovery</string>
<string name="recovery_notif_title">Safe Pocket Web Interrupted</string>
<string name="recovery_notif_text">Tap to restore secure environment immediately.</string>
</resources>