diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/core/CoreConfigManager.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/core/CoreConfigManager.kt index 2d006a8d0b..1c748df13c 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/core/CoreConfigManager.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/core/CoreConfigManager.kt @@ -5,6 +5,7 @@ import android.text.TextUtils import com.google.gson.JsonArray import com.google.gson.JsonObject import com.v2ray.ang.AppConfig +import com.v2ray.ang.R import com.v2ray.ang.dto.ConfigResult import com.v2ray.ang.dto.CoreConfigContext import com.v2ray.ang.dto.V2rayConfig @@ -34,17 +35,27 @@ object CoreConfigManager { fun getV2rayConfig(context: Context, guid: String): ConfigResult { try { val configContext = CoreConfigContextBuilder.build(context, guid) - ?: return ConfigResult(status = false, guid = guid, errorMessage = "Failed to build config context") + ?: return ConfigResult( + status = false, + guid = guid, + errorMessage = "Failed to build config context", + displayMessage = context.getString(R.string.core_error_build_config_context) + ) if (configContext.isCustom) { return buildV2rayCustomConfig(configContext) } return toConfigResult(configContext, buildUnifiedConfig(configContext)) } catch (e: Exception) { LogUtil.e(AppConfig.TAG, "Failed to get V2ray config", e) + val detail = e.message ?: e.javaClass.simpleName return ConfigResult( status = false, guid = guid, - errorMessage = "Failed to get V2ray config: ${e.message ?: e.javaClass.simpleName}" + errorMessage = "Failed to get V2ray config: $detail", + displayMessage = context.getString( + R.string.core_error_get_config_detail, + detail + ) ) } } @@ -57,7 +68,12 @@ object CoreConfigManager { fun getV2rayConfig4Speedtest(context: Context, guid: String): ConfigResult { try { val configContext = CoreConfigContextBuilder.build(context, guid) - ?: return ConfigResult(status = false, guid = guid, errorMessage = "Failed to build config context") + ?: return ConfigResult( + status = false, + guid = guid, + errorMessage = "Failed to build config context", + displayMessage = context.getString(R.string.core_error_build_config_context) + ) if (configContext.isCustom) { return buildV2rayCustomConfig(configContext) } @@ -67,10 +83,15 @@ object CoreConfigManager { return toConfigResult(configContext, v2rayConfig) } catch (e: Exception) { LogUtil.e(AppConfig.TAG, "Failed to get V2ray config for speedtest", e) + val detail = e.message ?: e.javaClass.simpleName return ConfigResult( status = false, guid = guid, - errorMessage = "Failed to get V2ray config for speedtest: ${e.message ?: e.javaClass.simpleName}" + errorMessage = "Failed to get V2ray config for speedtest: $detail", + displayMessage = context.getString( + R.string.core_error_get_speedtest_config_detail, + detail + ) ) } } @@ -81,7 +102,12 @@ object CoreConfigManager { private fun buildV2rayCustomConfig(configContext: CoreConfigContext): ConfigResult { val context = configContext.context val raw = MmkvManager.decodeServerRaw(configContext.guid) - ?: return ConfigResult(status = false, guid = configContext.guid, errorMessage = "Custom config is empty") + ?: return ConfigResult( + status = false, + guid = configContext.guid, + errorMessage = "Custom config is empty", + displayMessage = context.getString(R.string.core_error_custom_config_empty) + ) val result = ConfigResult(true, configContext.guid, raw) val json = JsonUtil.parseString(raw)?.takeIf { it.isJsonObject }?.asJsonObject ?: return result diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/core/CoreNativeManager.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/core/CoreNativeManager.kt index 663d0629d4..657961202b 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/core/CoreNativeManager.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/core/CoreNativeManager.kt @@ -58,12 +58,12 @@ object CoreNativeManager { * * @return Version string of the V2Ray core */ - fun getLibVersion(): String { + fun getLibVersion(): String? { return try { Libv2ray.checkVersionX() } catch (e: Exception) { LogUtil.e(AppConfig.TAG, "Failed to check V2Ray version", e) - "Unknown" + null } } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/core/CoreServiceManager.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/core/CoreServiceManager.kt index 21319210a3..e523b41ece 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/core/CoreServiceManager.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/core/CoreServiceManager.kt @@ -53,6 +53,11 @@ object CoreServiceManager { /** Tun descriptor the core was started with, null in the proxy only and root run modes. */ private var currentVpnInterface: ParcelFileDescriptor? = null + private class CoreStartException( + logMessage: String, + val displayMessage: String, + ) : IllegalStateException(logMessage) + var serviceControl: SoftReference? = null set(value) { field = value @@ -96,15 +101,22 @@ object CoreServiceManager { try { doStartCoreLoop(service, vpnInterface) return true + } catch (e: CoreStartException) { + reportCoreStartFailure(service, e.message.orEmpty(), e.displayMessage, e) + return false } catch (e: Exception) { val message = e.message?.takeUnless { it.isBlank() } ?: e.javaClass.simpleName - LogUtil.e(AppConfig.TAG, "StartCore-Manager: $message", e) - MessageHelper.sendMsg2UI(service, AppConfig.MSG_STATE_START_FAILURE, message) - NotificationManager.cancelNotification() + reportCoreStartFailure(service, message, message, e) return false } } + private fun reportCoreStartFailure(service: Service, logMessage: String, displayMessage: String, error: Throwable) { + LogUtil.e(AppConfig.TAG, "StartCore-Manager: $logMessage", error) + MessageHelper.sendMsg2UI(service, AppConfig.MSG_STATE_START_FAILURE, displayMessage) + NotificationManager.cancelNotification() + } + @Throws(Exception::class) private fun doStartCoreLoop(service: Service, vpnInterface: ParcelFileDescriptor?) { val mFilter = IntentFilter(AppConfig.BROADCAST_ACTION_SERVICE) @@ -120,14 +132,27 @@ object CoreServiceManager { @Throws(Exception::class) private fun launchCore(service: Service, vpnInterface: ParcelFileDescriptor?, isReload: Boolean = false) { - val guid = MmkvManager.getSelectServer() ?: error("No server selected") - val config = MmkvManager.decodeServerConfig(guid) ?: error("Failed to decode server config") + val guid = MmkvManager.getSelectServer() + ?: throw CoreStartException( + logMessage = "No server selected", + displayMessage = service.getString(R.string.core_error_no_server_selected) + ) + val config = MmkvManager.decodeServerConfig(guid) + ?: throw CoreStartException( + logMessage = "Failed to decode server config", + displayMessage = service.getString(R.string.core_error_decode_server_config) + ) LogUtil.i(AppConfig.TAG, "StartCore-Manager: Starting core loop for ${config.remarks}") val result = CoreConfigManager.getV2rayConfig(service, guid) LogUtil.d(AppConfig.TAG, result.content) if (!result.status) { - error(result.errorMessage.ifBlank { "Failed to get V2Ray config" }) + throw CoreStartException( + logMessage = result.errorMessage.ifBlank { "Failed to get V2Ray config" }, + displayMessage = result.displayMessage.ifBlank { + service.getString(R.string.core_error_get_config) + } + ) } currentConfig = config @@ -149,7 +174,10 @@ object CoreServiceManager { coreController.startLoop(result.content, tunFd) if (!isRunning()) { - error("Core failed to start") + throw CoreStartException( + logMessage = "Core failed to start", + displayMessage = service.getString(R.string.core_error_start) + ) } if (browserDialer != null) { @@ -260,6 +288,10 @@ object CoreServiceManager { LogUtil.i(AppConfig.TAG, "StartCore-Manager: Core reload finished") true + } catch (e: CoreStartException) { + LogUtil.e(AppConfig.TAG, "StartCore-Manager: Failed to reload core: ${e.message}", e) + MessageHelper.sendMsg2UI(service, AppConfig.MSG_STATE_START_FAILURE, e.displayMessage) + false } catch (e: Exception) { val message = e.message?.takeUnless { it.isBlank() } ?: e.javaClass.simpleName LogUtil.e(AppConfig.TAG, "StartCore-Manager: Failed to reload core: $message", e) @@ -321,14 +353,16 @@ object CoreServiceManager { time = coreController.measureDelay(SettingsManager.getDelayTestUrl()) } catch (e: Exception) { LogUtil.e(AppConfig.TAG, "StartCore-Manager: Failed to measure delay", e) - errorStr = e.message?.substringAfter("\":") ?: "empty message" + errorStr = e.message?.substringAfter("\":") + ?: service.getString(R.string.connection_test_empty_message) } if (time == -1L) { try { time = coreController.measureDelay(SettingsManager.getDelayTestUrl(true)) } catch (e: Exception) { LogUtil.e(AppConfig.TAG, "StartCore-Manager: Failed to measure delay", e) - errorStr = e.message?.substringAfter("\":") ?: "empty message" + errorStr = e.message?.substringAfter("\":") + ?: service.getString(R.string.connection_test_empty_message) } } @@ -492,4 +526,4 @@ object CoreServiceManager { } } } -} \ No newline at end of file +} diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/dto/ConfigResult.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/dto/ConfigResult.kt index 1f67dfa9a3..2fc695a8aa 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/dto/ConfigResult.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/dto/ConfigResult.kt @@ -4,6 +4,9 @@ data class ConfigResult( var status: Boolean, var guid: String? = null, var content: String = "", + /** Stable English diagnostic text suitable for Logcat. */ var errorMessage: String = "", + /** Localized message suitable for the UI. */ + var displayMessage: String = "", ) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/enums/PermissionType.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/enums/PermissionType.kt index ce3a05d005..4e4c065115 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/enums/PermissionType.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/enums/PermissionType.kt @@ -3,6 +3,8 @@ package com.v2ray.ang.enums import android.Manifest import android.os.Build import androidx.annotation.RequiresApi +import androidx.annotation.StringRes +import com.v2ray.ang.R /** * Permission types used in the app, handling API level differences. @@ -28,12 +30,13 @@ enum class PermissionType { /** Return the actual Android permission string */ abstract fun getPermission(): String - /** Return a human-readable label for the permission */ - fun getLabel(): String { + /** Return the string resource for the human-readable permission label. */ + @StringRes + fun getLabelRes(): Int { return when (this) { - CAMERA -> "Camera" - POST_NOTIFICATIONS -> "Notification" - ACCESS_LOCAL_NETWORK -> "Local Network" + CAMERA -> R.string.permission_camera + POST_NOTIFICATIONS -> R.string.permission_notification + ACCESS_LOCAL_NETWORK -> R.string.permission_local_network } } } \ No newline at end of file diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/helper/PermissionHelper.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/helper/PermissionHelper.kt index c7b05bc481..e9736f8260 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/helper/PermissionHelper.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/helper/PermissionHelper.kt @@ -36,7 +36,10 @@ class PermissionHelper(private val activity: ComponentActivity) { if (isGranted) { onGranted() } else { - val message = "${activity.getString(R.string.toast_permission_denied)} ${permissionType.getLabel()}" + val message = activity.getString( + R.string.toast_permission_denied_for, + activity.getString(permissionType.getLabelRes()) + ) activity.toast(message) } } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/service/SubscriptionUpdateService.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/service/SubscriptionUpdateService.kt index 68df537679..5263f13cc4 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/service/SubscriptionUpdateService.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/service/SubscriptionUpdateService.kt @@ -118,7 +118,7 @@ class SubscriptionUpdateService : Service() { showNotification( context = this, titleResId = R.string.title_pref_auto_update_subscription, - content = "Updating ${subItem.remarks}" + content = getString(R.string.subscription_update_updating, subItem.remarks) ) if (forcedUpdate || MmkvManager.decodeSettingsBool(AppConfig.PREF_UPDATE_SUBSCRIPTION, false)) { @@ -184,13 +184,17 @@ class SubscriptionUpdateService : Service() { private fun handleWorkerEvent(event: RealPingEvent, remarks: String, onWorkerDone: () -> Unit) { when (event) { is RealPingEvent.Progress -> { - val text = "${event.text} in $remarks" + val notificationText = getString( + R.string.subscription_update_progress, + event.text, + remarks + ) showNotification( context = this, titleResId = R.string.title_real_ping_all_server, - content = text + content = notificationText ) - LogUtil.i(AppConfig.TAG, "SubscriptionUpdateService: $text") + LogUtil.i(AppConfig.TAG, "SubscriptionUpdateService: ${event.text} in $remarks") } is RealPingEvent.Result -> { diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/AboutActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/AboutActivity.kt index 5bc02b8287..e45e4f7204 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/AboutActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/AboutActivity.kt @@ -53,7 +53,8 @@ fun AboutScreen(onBackClick: () -> Unit) { val context = LocalContext.current var showOssDialog by remember { mutableStateOf(false) } - val versionText = "v${BuildConfig.VERSION_NAME} (${CoreNativeManager.getLibVersion()})" + val libVersion = CoreNativeManager.getLibVersion() ?: stringResource(R.string.value_unknown) + val versionText = "v${BuildConfig.VERSION_NAME} ($libVersion)" val appIdText = BuildConfig.APPLICATION_ID Scaffold( diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ScannerActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ScannerActivity.kt index 5ecf4e11f2..816d3607e4 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ScannerActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ScannerActivity.kt @@ -179,7 +179,9 @@ fun ScannerScreen( if (isScanning) R.drawable.ic_stop_24dp else R.drawable.ic_scan_24dp ), - contentDescription = if (isScanning) "stop scan" else "start scan" + contentDescription = stringResource( + if (isScanning) R.string.acc_stop_scanner else R.string.acc_start_scanner + ) ) } if (isScanning && hasTorch) { @@ -194,14 +196,17 @@ fun ScannerScreen( if (torchEnabled) R.drawable.ic_flash_on_24dp else R.drawable.ic_flash_off_24dp ), - contentDescription = "Torch" + contentDescription = stringResource( + if (torchEnabled) R.string.acc_turn_torch_off + else R.string.acc_turn_torch_on + ) ) } } IconButton(onClick = onSelectPhoto) { Icon( painterResource(R.drawable.ic_image_24dp), - contentDescription = "select image" + contentDescription = stringResource(R.string.acc_select_image) ) } } @@ -245,7 +250,7 @@ private fun ScannerIdlePlaceholder(onStartClick: () -> Unit) { Column(horizontalAlignment = Alignment.CenterHorizontally) { Icon( painter = painterResource(R.drawable.ic_scan_24dp), - contentDescription = "Start Scanner", + contentDescription = stringResource(R.string.acc_start_scanner), modifier = Modifier.size(80.dp), tint = MaterialTheme.colorScheme.primary ) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/apppicker/AppPickerActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/apppicker/AppPickerActivity.kt index 7cc29048de..d086e281d1 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/apppicker/AppPickerActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/apppicker/AppPickerActivity.kt @@ -151,7 +151,7 @@ fun AppPickerScreen( IconButton(onClick = { showSearch = true }) { Icon( painterResource(R.drawable.ic_search_24dp), - contentDescription = stringResource(R.string.menu_item_search) + contentDescription = stringResource(R.string.acc_search) ) } } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/checkupdate/CheckUpdateActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/checkupdate/CheckUpdateActivity.kt index d70bd5f828..5917eeb319 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/checkupdate/CheckUpdateActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/checkupdate/CheckUpdateActivity.kt @@ -59,7 +59,8 @@ fun CheckUpdateScreen( val showUpdateDialog by viewModel.showUpdateDialog.collectAsStateWithLifecycle() val updateResult by viewModel.updateResult.collectAsStateWithLifecycle() - val versionText = "v${BuildConfig.VERSION_NAME} (${CoreNativeManager.getLibVersion()})" + val libVersion = CoreNativeManager.getLibVersion() ?: stringResource(R.string.value_unknown) + val versionText = "v${BuildConfig.VERSION_NAME} ($libVersion)" Scaffold( contentWindowInsets = ScaffoldDefaults.contentWindowInsets, diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/compose/Components.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/compose/Components.kt index 95d60e8de7..d3710beade 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/compose/Components.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/compose/Components.kt @@ -45,6 +45,7 @@ import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.style.TextOverflow @@ -91,7 +92,7 @@ fun AppTopBar( IconButton(onClick = if (isSearchActive) onSearchClose else onBackClick) { Icon( painter = painterResource(R.drawable.ic_arrow_back_24dp), - contentDescription = "Back" + contentDescription = stringResource(R.string.acc_back) ) } } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/compose/Dialog.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/compose/Dialog.kt index 99cb50adcd..244b16a2b7 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/compose/Dialog.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/compose/Dialog.kt @@ -175,7 +175,7 @@ fun QRCodeDialog( text = { Image( bitmap = bitmap.asImageBitmap(), - contentDescription = stringResource(R.string.title_qr_code), + contentDescription = stringResource(R.string.acc_qr_code), modifier = Modifier .fillMaxWidth() .aspectRatio(1f) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/logcat/LogcatActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/logcat/LogcatActivity.kt index 9d3c1a7418..dbf1694821 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/logcat/LogcatActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/logcat/LogcatActivity.kt @@ -159,20 +159,20 @@ fun LogcatScreen( IconButton(onClick = { showSearch = true }) { Icon( painterResource(R.drawable.ic_search_24dp), - contentDescription = "filter" + contentDescription = stringResource(R.string.acc_search) ) } } IconButton(onClick = { viewModel.copyLogcat() }) { Icon( painterResource(R.drawable.ic_copy), - contentDescription = stringResource(R.string.logcat_copy) + contentDescription = stringResource(R.string.acc_copy_log) ) } IconButton(onClick = { onShareLogcat() }) { Icon( painterResource(R.drawable.ic_share_24dp), - contentDescription = stringResource(R.string.logcat_share) + contentDescription = stringResource(R.string.acc_share_log) ) } IconButton(onClick = { @@ -180,7 +180,7 @@ fun LogcatScreen( }) { Icon( painterResource(R.drawable.ic_delete_24dp), - contentDescription = stringResource(R.string.logcat_clear) + contentDescription = stringResource(R.string.acc_clear_log) ) } } @@ -192,7 +192,7 @@ fun LogcatScreen( }) { Icon( painterResource(R.drawable.ic_restore_24dp), - contentDescription = stringResource(R.string.pull_down_to_refresh) + contentDescription = stringResource(R.string.acc_refresh) ) } } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/main/MainBottomBar.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/main/MainBottomBar.kt index 950cf69d89..ce88845557 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/main/MainBottomBar.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/main/MainBottomBar.kt @@ -24,6 +24,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.v2ray.ang.R import com.v2ray.ang.ui.compose.AppDivider @@ -75,7 +76,9 @@ fun MainBottomBar( Icon( painter = if (isRunning) painterResource(R.drawable.ic_stop_24dp) else painterResource(R.drawable.ic_play_24dp), - contentDescription = if (isRunning) "Stop" else "Start", + contentDescription = stringResource( + if (isRunning) R.string.acc_stop else R.string.acc_start + ), tint = Color.White, modifier = Modifier.size(24.dp) ) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/main/MainTopBar.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/main/MainTopBar.kt index d77aa05684..cc3b4f8467 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/main/MainTopBar.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/main/MainTopBar.kt @@ -59,23 +59,23 @@ fun MainTopBar( navigationIcon = { if (showSearch) { IconButton(onClick = onSearchClose) { - Icon(painterResource(R.drawable.ic_arrow_back_24dp), contentDescription = "Back") + Icon(painterResource(R.drawable.ic_arrow_back_24dp), contentDescription = stringResource(R.string.acc_back)) } } else { IconButton(onClick = onMenuClick) { - Icon(painterResource(R.drawable.ic_menu_24dp), contentDescription = "Menu") + Icon(painterResource(R.drawable.ic_menu_24dp), contentDescription = stringResource(R.string.acc_open_menu)) } } }, actions = { if (!showSearch) { IconButton(onClick = { onSearchToggle(true) }) { - Icon(painterResource(R.drawable.ic_search_24dp), contentDescription = "filter") + Icon(painterResource(R.drawable.ic_search_24dp), contentDescription = stringResource(R.string.acc_search)) } } Box(modifier = Modifier.wrapContentSize(Alignment.TopEnd)) { IconButton(onClick = { showImportMenu = true }) { - Icon(painterResource(R.drawable.ic_add_24dp), contentDescription = "Add") + Icon(painterResource(R.drawable.ic_add_24dp), contentDescription = stringResource(R.string.acc_add)) } DropdownMenu( expanded = showImportMenu, @@ -96,7 +96,7 @@ fun MainTopBar( } Box(modifier = Modifier.wrapContentSize(Alignment.TopEnd)) { IconButton(onClick = { showMenu = true }) { - Icon(painterResource(R.drawable.ic_more_vert_24dp), contentDescription = "More") + Icon(painterResource(R.drawable.ic_more_vert_24dp), contentDescription = stringResource(R.string.acc_more)) } DropdownMenu( expanded = showMenu, diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/perappproxy/PerAppProxyActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/perappproxy/PerAppProxyActivity.kt index ba1b0d38bb..1a16c2a768 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/perappproxy/PerAppProxyActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/perappproxy/PerAppProxyActivity.kt @@ -160,7 +160,7 @@ fun PerAppProxyScreen( IconButton(onClick = { showSearch = true }) { Icon( painterResource(R.drawable.ic_search_24dp), - contentDescription = stringResource(R.string.menu_item_search) + contentDescription = stringResource(R.string.acc_search) ) } } @@ -252,7 +252,7 @@ fun PerAppProxyScreen( IconButton(onClick = onInfoClick) { Icon( painter = painterResource(R.drawable.ic_about_24dp), - contentDescription = stringResource(R.string.summary_pref_per_app_proxy), + contentDescription = stringResource(R.string.acc_per_app_proxy_information), tint = MaterialTheme.colorScheme.onSurfaceVariant ) } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/routing/RoutingEditActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/routing/RoutingEditActivity.kt index 7c02fb9185..45d7e2ba30 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/routing/RoutingEditActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/routing/RoutingEditActivity.kt @@ -186,14 +186,14 @@ fun RoutingEditScreen( IconButton(onClick = { showDeleteConfirm = true }) { Icon( painterResource(R.drawable.ic_delete_24dp), - contentDescription = stringResource(R.string.menu_item_del_config) + contentDescription = stringResource(R.string.acc_delete) ) } } IconButton(onClick = { onSave(buildRuleset()) }) { Icon( painterResource(R.drawable.ic_fab_check), - contentDescription = stringResource(R.string.menu_item_save_config) + contentDescription = stringResource(R.string.acc_save) ) } } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/routing/RoutingSettingActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/routing/RoutingSettingActivity.kt index da73290c63..a27604013a 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/routing/RoutingSettingActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/routing/RoutingSettingActivity.kt @@ -225,7 +225,7 @@ fun RoutingSettingScreen( IconButton(onClick = onAddRule) { Icon( painterResource(R.drawable.ic_add_24dp), - contentDescription = stringResource(R.string.routing_settings_add_rule) + contentDescription = stringResource(R.string.acc_add_rule) ) } Box { @@ -342,7 +342,7 @@ private fun RoutingRulesetItem( Spacer(modifier = Modifier.width(4.dp)) Icon( painter = painterResource(R.drawable.ic_lock_24dp), - contentDescription = "Locked", + contentDescription = stringResource(R.string.acc_locked), modifier = Modifier.size(16.dp), tint = MaterialTheme.colorScheme.onSurfaceVariant ) @@ -376,7 +376,7 @@ private fun RoutingRulesetItem( IconButton(onClick = onEdit) { Icon( painter = painterResource(R.drawable.ic_edit_24dp), - contentDescription = "Edit" + contentDescription = stringResource(R.string.acc_edit) ) } Spacer(modifier = Modifier.height(4.dp)) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/server/BaseServerActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/server/BaseServerActivity.kt index 4d185c1fc7..72a73037c9 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/server/BaseServerActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/server/BaseServerActivity.kt @@ -461,14 +461,14 @@ abstract class BaseServerActivity : BaseComponentActivity() { IconButton(onClick = { showDeleteDialog = true }) { Icon( painterResource(R.drawable.ic_delete_24dp), - stringResource(R.string.menu_item_del_config) + stringResource(R.string.acc_delete) ) } } IconButton(onClick = onSaveClick) { Icon( painterResource(R.drawable.ic_fab_check), - stringResource(R.string.menu_item_save_config) + stringResource(R.string.acc_save) ) } } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/server/ServerActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/server/ServerActivity.kt index 68ac1d21b1..20247f6a0f 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/server/ServerActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/server/ServerActivity.kt @@ -347,13 +347,13 @@ fun ServerScreen( actions = { if (guid.isNotEmpty() && !isRunning) { IconButton(onClick = { showDeleteDialog = true }) { - Icon(painterResource(R.drawable.ic_delete_24dp), stringResource(R.string.menu_item_del_config)) + Icon(painterResource(R.drawable.ic_delete_24dp), stringResource(R.string.acc_delete)) } } IconButton(onClick = { onSave(buildProfileItem()) }) { - Icon(painterResource(R.drawable.ic_fab_check), stringResource(R.string.menu_item_save_config)) + Icon(painterResource(R.drawable.ic_fab_check), stringResource(R.string.acc_save)) } } ) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/server/ServerCustomConfigActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/server/ServerCustomConfigActivity.kt index a782956cf3..b968d7bcc8 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/server/ServerCustomConfigActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/server/ServerCustomConfigActivity.kt @@ -120,9 +120,14 @@ class ServerCustomConfigActivity : BaseComponentActivity() { "Failed to parse custom configuration", e ) + val detail = e.cause?.message?.takeIf { it.isNotBlank() } + ?: e.message?.takeIf { it.isNotBlank() } toast( - "${getString(R.string.toast_malformed_json)} " + - "${e.cause?.message.orEmpty()}" + if (detail.isNullOrBlank()) { + getString(R.string.toast_malformed_json) + } else { + getString(R.string.toast_malformed_json_detail, detail) + } ) return false } @@ -315,14 +320,14 @@ fun ServerCustomConfigScreen( IconButton(onClick = { showDeleteConfirm = true }) { Icon( painterResource(R.drawable.ic_delete_24dp), - contentDescription = stringResource(R.string.menu_item_del_config) + contentDescription = stringResource(R.string.acc_delete) ) } } IconButton(onClick = { onSave(remarks, textFieldState.text.toString()) }) { Icon( painterResource(R.drawable.ic_fab_check), - contentDescription = stringResource(R.string.menu_item_save_config) + contentDescription = stringResource(R.string.acc_save) ) } } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/server/ServerGroupActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/server/ServerGroupActivity.kt index 10e4b51dea..9b4dd1d59d 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/server/ServerGroupActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/server/ServerGroupActivity.kt @@ -245,7 +245,7 @@ fun ServerGroupScreen( actions = { if (showDelete) { IconButton(onClick = { showDeleteConfirm = true }) { - Icon(painterResource(R.drawable.ic_delete_24dp), contentDescription = stringResource(R.string.menu_item_del_config)) + Icon(painterResource(R.drawable.ic_delete_24dp), contentDescription = stringResource(R.string.acc_delete)) } } IconButton(onClick = { @@ -253,7 +253,7 @@ fun ServerGroupScreen( val subIdx = subDisplay.indexOf(subValue).coerceAtLeast(0) onSave(remarks, filter, typeIdx, subIdx, testOutbounds, fallbackTag) }) { - Icon(painterResource(R.drawable.ic_fab_check), contentDescription = stringResource(R.string.menu_item_save_config)) + Icon(painterResource(R.drawable.ic_fab_check), contentDescription = stringResource(R.string.acc_save)) } } ) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/server/ServerProxyChainActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/server/ServerProxyChainActivity.kt index 21e1420f48..1a10deaa25 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/server/ServerProxyChainActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/server/ServerProxyChainActivity.kt @@ -228,11 +228,11 @@ fun ProxyChainScreen( actions = { if (showDelete) { IconButton(onClick = { showProfileDeleteConfirm = true }) { - Icon(painterResource(R.drawable.ic_delete_24dp), contentDescription = stringResource(R.string.menu_item_del_config)) + Icon(painterResource(R.drawable.ic_delete_24dp), contentDescription = stringResource(R.string.acc_delete)) } } IconButton(onClick = { onSave(remarks, members) }) { - Icon(painterResource(R.drawable.ic_fab_check), contentDescription = stringResource(R.string.menu_item_save_config)) + Icon(painterResource(R.drawable.ic_fab_check), contentDescription = stringResource(R.string.acc_save)) } } ) @@ -247,7 +247,7 @@ fun ProxyChainScreen( .offset(y = -20.dp) .navigationBarsPadding() ) { - Icon(painterResource(R.drawable.ic_add_24dp), contentDescription = "Add member") + Icon(painterResource(R.drawable.ic_add_24dp), contentDescription = stringResource(R.string.acc_add_member)) } } ) { innerPadding -> @@ -320,7 +320,7 @@ fun ProxyChainScreen( }) { Icon( painterResource(R.drawable.ic_delete_24dp), - contentDescription = "Remove" + contentDescription = stringResource(R.string.acc_remove) ) } } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/shortcut/TaskerActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/shortcut/TaskerActivity.kt index 34bbd0dc3a..cc11e6baa5 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/shortcut/TaskerActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/shortcut/TaskerActivity.kt @@ -105,11 +105,10 @@ class TaskerActivity : BaseComponentActivity() { val intent = Intent() val remarks = lstData[position] - val blurb = if (switchState.value) { - "Start $remarks" - } else { - "Stop $remarks" - } + val blurb = getString( + if (switchState.value) R.string.tasker_blurb_start else R.string.tasker_blurb_stop, + remarks + ) intent.putExtra(AppConfig.TASKER_EXTRA_BUNDLE, extraBundle) intent.putExtra(AppConfig.TASKER_EXTRA_STRING_BLURB, blurb) @@ -135,7 +134,7 @@ fun TaskerScreen( onBackClick = onBackClick, actions = { IconButton(onClick = onSave) { - Icon(painterResource(R.drawable.ic_fab_check), contentDescription = stringResource(R.string.menu_item_save_config)) + Icon(painterResource(R.drawable.ic_fab_check), contentDescription = stringResource(R.string.acc_save)) } } ) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/subscription/SubEditActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/subscription/SubEditActivity.kt index 2df184bb1e..977b754fea 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/subscription/SubEditActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/subscription/SubEditActivity.kt @@ -173,11 +173,11 @@ fun SubEditScreen( IconButton(onClick = { if (confirmRemove) showDeleteConfirm = true else onDelete() }) { - Icon(painterResource(R.drawable.ic_delete_24dp), contentDescription = stringResource(R.string.menu_item_del_config)) + Icon(painterResource(R.drawable.ic_delete_24dp), contentDescription = stringResource(R.string.acc_delete)) } } IconButton(onClick = { buildSubItem()?.let { onSave(it) } }) { - Icon(painterResource(R.drawable.ic_fab_check), contentDescription = stringResource(R.string.menu_item_save_config)) + Icon(painterResource(R.drawable.ic_fab_check), contentDescription = stringResource(R.string.acc_save)) } } ) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/subscription/SubSettingActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/subscription/SubSettingActivity.kt index c0b63c3ffc..c217b37940 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/subscription/SubSettingActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/subscription/SubSettingActivity.kt @@ -135,10 +135,10 @@ fun SubSettingScreen( isLoading = isLoading, actions = { IconButton(onClick = onAddClick) { - Icon(painterResource(R.drawable.ic_add_24dp), contentDescription = stringResource(R.string.menu_item_add_config)) + Icon(painterResource(R.drawable.ic_add_24dp), contentDescription = stringResource(R.string.acc_add_subscription)) } IconButton(onClick = { showUpdateDialog = true }) { - Icon(painterResource(R.drawable.ic_restore_24dp), contentDescription = stringResource(R.string.title_sub_update)) + Icon(painterResource(R.drawable.ic_restore_24dp), contentDescription = stringResource(R.string.acc_update_subscriptions)) } } ) @@ -202,14 +202,14 @@ fun SubSettingScreen( }) { Icon( painter = painterResource(R.drawable.ic_share_24dp), - contentDescription = "Share" + contentDescription = stringResource(R.string.acc_share_subscription) ) } } IconButton(onClick = { onEditSub(subCache.guid) }) { Icon( painter = painterResource(R.drawable.ic_edit_24dp), - contentDescription = "Edit" + contentDescription = stringResource(R.string.acc_edit) ) } IconButton(onClick = { @@ -218,7 +218,7 @@ fun SubSettingScreen( }) { Icon( painter = painterResource(R.drawable.ic_delete_24dp), - contentDescription = "Delete" + contentDescription = stringResource(R.string.acc_delete) ) } } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/userasset/UserAssetActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/userasset/UserAssetActivity.kt index 9e01534698..32d80b6bd9 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/userasset/UserAssetActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/userasset/UserAssetActivity.kt @@ -280,7 +280,7 @@ fun UserAssetScreen( actions = { Box(modifier = Modifier.wrapContentSize(Alignment.TopEnd)) { IconButton(onClick = { showAddMenu = true }) { - Icon(painterResource(R.drawable.ic_add_24dp), contentDescription = stringResource(R.string.menu_item_add_asset)) + Icon(painterResource(R.drawable.ic_add_24dp), contentDescription = stringResource(R.string.acc_add_asset)) } DropdownMenu( expanded = showAddMenu, @@ -300,7 +300,7 @@ fun UserAssetScreen( } } IconButton(onClick = onDownloadClick) { - Icon(painterResource(R.drawable.ic_cloud_download_24dp), contentDescription = stringResource(R.string.menu_item_download_file)) + Icon(painterResource(R.drawable.ic_cloud_download_24dp), contentDescription = stringResource(R.string.acc_download_file)) } } ) @@ -400,7 +400,7 @@ private fun UserAssetItem( IconButton(onClick = onEdit) { Icon( painter = painterResource(R.drawable.ic_edit_24dp), - contentDescription = stringResource(R.string.menu_item_edit_config), + contentDescription = stringResource(R.string.acc_edit), modifier = Modifier.size(24.dp) ) } @@ -408,7 +408,7 @@ private fun UserAssetItem( IconButton(onClick = onDeleteClick) { Icon( painter = painterResource(R.drawable.ic_delete_24dp), - contentDescription = stringResource(R.string.menu_item_del_config), + contentDescription = stringResource(R.string.acc_delete), modifier = Modifier.size(24.dp) ) } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/userasset/UserAssetUrlActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/userasset/UserAssetUrlActivity.kt index 11649e0fdd..3bba102122 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/userasset/UserAssetUrlActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/userasset/UserAssetUrlActivity.kt @@ -152,14 +152,14 @@ fun UserAssetUrlScreen( IconButton(onClick = { showDeleteConfirm = true }) { Icon( painterResource(R.drawable.ic_delete_24dp), - contentDescription = stringResource(R.string.menu_item_del_config) + contentDescription = stringResource(R.string.acc_delete) ) } } IconButton(onClick = { onSave(remarks, url) }) { Icon( painterResource(R.drawable.ic_fab_check), - contentDescription = stringResource(R.string.menu_item_save_config) + contentDescription = stringResource(R.string.acc_save) ) } } diff --git a/V2rayNG/app/src/main/res/values-ar/strings.xml b/V2rayNG/app/src/main/res/values-ar/strings.xml index ad748712ab..65f6ab61d2 100644 --- a/V2rayNG/app/src/main/res/values-ar/strings.xml +++ b/V2rayNG/app/src/main/res/values-ar/strings.xml @@ -490,4 +490,54 @@ محلي WebDAV + تحديث السجل + تم رفض إذن %1$s + إضافة اشتراك + تنسيق التكوين غير صالح: %1$s + إضافة مصدر موارد + تنزيل ملفات الموارد + رمز QR + نسخ السجل + مسح السجل + إضافة قاعدة توجيه + لم يتم تحديد تكوين + تعذرت قراءة التكوين المحدد + تعذر إعداد التكوين المحدد + تعذر إنشاء تكوين النواة + تعذر إنشاء تكوين النواة: %1$s + تعذر إنشاء تكوين النواة لاختبار السرعة: %1$s + التكوين المخصص فارغ + تعذر تشغيل النواة + بدء الخدمة + إيقاف الخدمة + رجوع + بحث + إضافة تكوين + المزيد من الخيارات + مشاركة رابط الاشتراك + مشاركة السجل + إزالة عضو من سلسلة الوكلاء + إضافة عضو إلى سلسلة الوكلاء + بدء ماسح رمز QR + إيقاف ماسح رمز QR + تشغيل المصباح + إطفاء المصباح + اختيار صورة لمسحها + يتم الاحتفاظ بالقاعدة عند استيراد الإعدادات المسبقة + فتح قائمة التنقل + تعديل + حذف + حفظ + تحديث الاشتراكات + معلومات الوكيل لكل تطبيق + الكاميرا + الإشعارات + الشبكة المحلية + جارٍ تحديث الاشتراك: %1$s + جارٍ اختبار %2$s: %1$s + تشغيل %1$s + إيقاف %1$s + لا تتوفر تفاصيل + غير معروف + diff --git a/V2rayNG/app/src/main/res/values-bn/strings.xml b/V2rayNG/app/src/main/res/values-bn/strings.xml index 00eb6ca50e..052e6aac23 100644 --- a/V2rayNG/app/src/main/res/values-bn/strings.xml +++ b/V2rayNG/app/src/main/res/values-bn/strings.xml @@ -490,4 +490,54 @@ স্থানীয় WebDAV + লগ রিফ্রেশ করুন + %1$s ব্যবহারের অনুমতি দেওয়া হয়নি + সাবস্ক্রিপশন যোগ করুন + কনফিগারেশন ফরম্যাট সঠিক নয়: %1$s + অ্যাসেট উৎস যোগ করুন + অ্যাসেট ফাইল ডাউনলোড করুন + QR কোড + লগ কপি করুন + লগ মুছুন + রাউটিং নিয়ম যোগ করুন + কোনো কনফিগারেশন নির্বাচন করা হয়নি + নির্বাচিত কনফিগারেশন পড়তে ব্যর্থ + নির্বাচিত কনফিগারেশন প্রস্তুত করতে ব্যর্থ + কোর কনফিগারেশন তৈরি করতে ব্যর্থ + কোর কনফিগারেশন তৈরি করতে ব্যর্থ: %1$s + স্পিড টেস্টের জন্য কোর কনফিগারেশন তৈরি করতে ব্যর্থ: %1$s + কাস্টম কনফিগারেশন খালি + কোর চালু করতে ব্যর্থ + সার্ভিস শুরু করুন + সার্ভিস বন্ধ করুন + ফিরে যান + অনুসন্ধান করুন + কনফিগারেশন যোগ করুন + আরও বিকল্প + সাবস্ক্রিপশন লিংক শেয়ার করুন + লগ শেয়ার করুন + প্রক্সি চেইনের সদস্য সরান + প্রক্সি চেইনে সদস্য যোগ করুন + QR স্ক্যানার চালু করুন + QR স্ক্যানার বন্ধ করুন + ফ্ল্যাশলাইট চালু করুন + ফ্ল্যাশলাইট বন্ধ করুন + স্ক্যান করার জন্য ছবি নির্বাচন করুন + প্রিসেট আমদানি করলে নিয়মটি রাখা হবে + নেভিগেশন মেনু খুলুন + সম্পাদনা করুন + মুছুন + সংরক্ষণ করুন + সাবস্ক্রিপশন আপডেট করুন + প্রতি-অ্যাপ প্রক্সির তথ্য + ক্যামেরা + বিজ্ঞপ্তি + স্থানীয় নেটওয়ার্ক + সাবস্ক্রিপশন আপডেট করা হচ্ছে: %1$s + %2$s পরীক্ষা করা হচ্ছে: %1$s + %1$s চালু করুন + %1$s বন্ধ করুন + কোনো বিবরণ পাওয়া যায়নি + অজানা + diff --git a/V2rayNG/app/src/main/res/values-bqi-rIR/strings.xml b/V2rayNG/app/src/main/res/values-bqi-rIR/strings.xml index 4f8dbdd979..2b9bcb20f7 100644 --- a/V2rayNG/app/src/main/res/values-bqi-rIR/strings.xml +++ b/V2rayNG/app/src/main/res/values-bqi-rIR/strings.xml @@ -3,12 +3,12 @@ v2rayNG آلشت آلشت - سی کرت ٱولی و کار بوردن ای ویژیی، ٱول ز من برنومه ی سرور ازاف کۊنین + سی کرت ٱولی و کار بوردن ای ویژیی، ٱول ز من برنومه ی سرور اضاف کۊنین گۊشیڌن نومگه کشاری بستن نومگه کشاری - جاگورویی داده یل وا مووفقیت ٱنجوم وابی! + جاگورویی داڌه یل وا مووفقیت ٱنجوم وابی! واڌاشتن سرویس - جاگورویی داده یل شکست خرد! + جاگورویی داڌه یل شکست خرد! سی وانۊ کردن، بلگه ن بلم بکشین! @@ -29,7 +29,7 @@ پاک کردن کانفیگ و من ٱووردن کانفیگ ز QRcode و من ٱووردن کانفیگ ز کلیپ بورد - و من ٱووردن کانفیگ ز مهلی + و من ٱووردن کانفیگ ز محلی ٱووردن [بونکۊ سیاست] ٱووردن [زنجیره پروکسی] ٱووردن [VMess] @@ -40,16 +40,16 @@ ٱووردن [Trojan] ٱووردن [Wireguard] ٱووردن [Hysteria2] - آیا مطمئن هستید که می‌خواهید همه پروفایل‌های نمایش‌داده‌شده را حذف کنید؟ - آیا مطمئن هستید که می‌خواهید همه پروفایل‌های تکراری نمایش‌داده‌شده را حذف کنید؟ - لطفاً ابتدا پروفایل‌ها را آزمایش کنید. آیا مطمئن هستید که می‌خواهید همه پروفایل‌های نامعتبر نمایش‌داده‌شده را حذف کنید؟ - آیا مطمئن هستید که می‌خواهید این پروفایل را حذف کنید؟ - آیا مطمئن هستید که می‌خواهید این گروه سیاست را حذف کنید؟ - آیا مطمئن هستید که می‌خواهید این عضو زنجیره پراکسی را حذف کنید؟ - آیا مطمئن هستید که می‌خواهید این قانون مسیریابی را حذف کنید؟ - آیا مطمئن هستید که می‌خواهید این گروه اشتراک را حذف کنید؟ - آیا مطمئن هستید که می‌خواهید فایل دارایی \"%1$s\" را حذف کنید؟ - آیا مطمئن هستید که می‌خواهید این منبع دارایی را حذف کنید؟ + پوی کانفیگا ک هیم سکو نشووݩ داڌه ابۊن پاک ابۊن، هنی هم اخۊی پاکسووݩ کۊنی؟ + پوی کانفیگا تکراری ک هیم سکو نشووݩ داڌه ابۊن پاک ابۊن، هنی هم اخۊی پاکسووݩ کۊنی؟ + ٱول کانفیگا ن آزمایش کۊنین. پوی کانفیگا نا موئتبر ک هیم سکو نشووݩ داڌه ابۊن پاک ابۊن، هنی هم اخۊی پاکسووݩ کۊنی؟ + ای کانفیگ پاک ابۊ، هنی هم اخۊی پاکس کۊنی؟ + ای بونکۊ سیاست پاک ابۊ، هنی هم اخۊی پاکس کۊنی؟ + ای عوزو زنجیره پروکسی پاک ابۊ، هنی هم اخۊی پاکس کۊنی؟ + ای قانووݩ تور جوستن پاک ابۊ، هنی هم اخۊی پاکس کۊنی؟ + ای بونکۊ اشتراک پاک ابۊ، هنی هم اخۊی پاکس کۊنی؟ + فایل بونچک جغرافیایی «%1$s» پاک ابۊ، هنی هم اخۊی پاکس کۊنی؟ + ای بونچک فایلا جغرافیایی پاک ابۊ، هنی هم اخۊی پاکس کۊنی؟ نیشتنا نشۊوی پورت @@ -59,7 +59,7 @@ شبکه جاگورو نوع هدر - هالت gRPC + حالت gRPC هاست هاست http هاست ws @@ -73,11 +73,11 @@ تور HTTPUpgrade تور XHTTP تور H2 - تور QUIC + کیلیت QUIC KCP seed نوم سرویس gRPC TLS - Fingerprint + جا کلک ALPN تئیڌ گوواهی ن ناڌیڌه بگرین (allowInsecure) SNI @@ -96,33 +96,33 @@ mldsa65Verify کیلیت سیخومی Reserved(اختیاری، وا کاما (,) ز یک جوڌا ابۊن) - نشۊوی مهلی (اختیاری IPv4/IPv6، وا کاما (,) ز یک جوڌا ابۊن) - Mtu(اختیاری، پؽش فرز 1420) - mKCP MTU (اختیاری، پؽش فرز هسته 1350) - mKCP TTI (اختیاری، پؽش فرز هسته 50) + نشۊوی محلی (اختیاری IPv4/IPv6، وا کاما (,) ز یک جوڌا ابۊن) + MTU(اختیاری، پؽش فرض 1420) + mKCP MTU (اختیاری، پؽش فرض هسته 1350) + mKCP TTI (اختیاری، پؽش فرض هسته 50) وا مووفقیت ٱنجوم وابی شکست خرد - هیچ داده ای وۊجۊڌ نڌاره + هیچ داڌه ای وۊجۊڌ نڌاره پوروتوکول نادوروست رزم گوشایی ٱنجوم نوابی پسند فایل کانفیگ ی برنومه دؽوۉداری فایل بپۊرنین. کانفیگ سفارشی کانفیگ نا موئتبر هڌ - موئتوا - هیچ داده ای من کلیپ بورد وۊجۊڌ نڌاره + محتوا + هیچ داڌه ای من کلیپ بورد وۊجۊڌ نڌاره نشۊوی اینترنتی نا موئتبر هڌ نشۊوی اشتراک پوروتوکول نا ٱمن HTTP ن و کار مبرین - موتمعن بۊین ک پورت وۊرۊڌی وا سامووا ی جۊر هڌ + موطمئن بۊین ک پورت وۊرۊڌی وا سامووا ی جۊر هڌ کانفیگ نا موئتبر هڌ هاست(SNI)(اختیاری) ای کار ممنۊع هڌ رزم obfs پورت گوم (درگا سرورن ز نۊ هؽل اکونه) - فاسله پورت گوم (سانیه) + فاصله پورت گوم (ثانیه) ب لم ٱووڌن پئنا باند (واهڌ) وا روء رئڌن پئنا باند (واهڌ) - هالت XHTTP + حالت XHTTP XHTTP Extra خام JSON، قالوو: { XHTTPObject } finalMask خام JSON، قالوو: { FinalMaskObject } echConfigList @@ -143,20 +143,20 @@ اسکن QRcode URL دانلود فایلا - نشۊوی اینترنتی دارایی ن ازاف کۊنین + نشۊوی اینترنتی بونچک ن اضاف کۊنین فایلن نجوست ای نوم ز زیتر بیڌس - بونچک فایلا جوقرافیایی (اختیاری) + بونچک فایلا جغرافیایی (اختیاری) هونی بار ونی ابۊ... پیتینیڌن پسند پوی چواسه کردن پسندا - کلمه یل کلیدی ن بزنین - هالت دور زیڌن + کلمه یل کلیڌی ن بزنین + حالت دور زیڌن پسند خوتکار برنومه یلی ک پروکسی اخون - موئتوا هونی دانلود ابۊن... + محتوا هونی دانلود ابۊن... و در کشیڌن من کلیپ بورد و من ٱووردن ز کلیپ بورد سامووا ب تفکیک برنومه @@ -169,7 +169,7 @@ سامووا هسته سامووا VPN پروکسی و ری برنومه - پوی وولاتی: برنومه پسند وابیڌه وا ی پروکسی منپیز ابۊ، برنومه پسند نوابیڌه موستقیمن منپیز ابۊ.\nهالت دور زیڌن: برنومه پسند وابیڌه موستقیمن منپیز ابۊ، برنومه پسند نوابیڌه وا ی پروکسی منپیز ابۊ.\nپسند خوتکار برنومه یل پروکسی من نومگه امکووݩ پزیر هڌ. + پوی وولاتی: برنومه پسند وابیڌه وا ی پروکسی منپیز ابۊ، برنومه پسند نوابیڌه موستقیمن منپیز ابۊ.\nحالت دور زیڌن: برنومه پسند وابیڌه موستقیمن منپیز ابۊ، برنومه پسند نوابیڌه وا ی پروکسی منپیز ابۊ.\nپسند خوتکار برنومه یل پروکسی من نومگه امکووݩ پذیر هڌ. منپیز خوتکار مجال ره ونی مجال ره وندن، خوساخوس و سرور پسند بیڌه منپیز ابۊ که گاشڌ نا مووفق بۊ. @@ -184,7 +184,7 @@ سامووا Mux ره وندن Mux - زل تر، ٱما گاشڌ منپیز زی قت بۊ\nمخزن ترافیک TCP وا 8 منپیز پؽش فرز، بارت دؽوۉداری UDP وو QUIC ن ای لم سفارشی کۊنین. + زل تر، ٱما گاشڌ منپیز زی قط بۊ\nدؽوۉداری TCP، UDP وو QUIC ن ای لم سفارشی کۊنین. منپیزا TCP (تلایه منجا -1 تا 1024) منپیزا XUDP (تلایه منجا -1 تا 1024) دؽوۉداری QUIC من تۊنل mux @@ -197,32 +197,32 @@ ره وندن نشووݩ داڌن سورعت سورعت هیم سکویی من وارسۊوی نشووݩ داڌه ابۊ.\nنماڌ نشووݩ اڌه ک ترافیک پروکسی یا موستقیم بؽتره. - ره وندن در کشیڌن نوم دامنه موورد نزر (Sniffing) - قپ ریت سی و در کشیڌن نوم دامنه واقعی ز کتنا (پؽش فرز رۊشن هڌ) + ره وندن در کشیڌن نوم دامنه موورد نظر (Sniffing) + قپ ریت سی و در کشیڌن نوم دامنه واقعی ز کتنا (پؽش فرض رۊشن هڌ) ره وندن تینا تور جوستن routeOnly - نوم دامنه sniffed ن تینا سی تور جوستن و کار بگیرین وو نشۊوی موورد نزرن و عونوان نشۊوی IP ووردارین. + نوم دامنه sniffed ن تینا سی تور جوستن و کار بگیرین وو نشۊوی موورد نظرن و عونوان نشۊوی IP ووردارین. - ره وندن DNS مهلی - درخاستا DNS و هسته و من ایان وو و دست ماژول DNS پردازشت ابۊن (پؽشنهاڌ ابۊ ٱر لنگ تور جوستن سی دور زیڌن نشۊویا LAN وو وولات ٱسلی هڌین ره ونده بۊ) + ره وندن DNS محلی + درخواستا DNS و هسته و من ایان وو و دست ماژول DNS پردازشت ابۊن (پؽشنهاڌ ابۊ ٱر لنگ تور جوستن سی دور زیڌن نشۊویا LAN وو وولات ٱسلی هڌین ره ونده بۊ) ره وندن DNS جئلی (FakeDNS) - دی ان اس مهلی نشۊویا آی پی جئلی ن اوورگنه (زل تر، ٱما گاشڌ من ی قرده ز برنومه یل کار نکونه) + FakeDNS نشۊویا IP جئلی ن سی نوم دامنه اوورگنه (زل تر، ٱما گاشڌ من ی قرده ز برنومه یل کار نکونه). ره وندن IPv6 - نشۊویا وو تورا IPv6 ن و رابت VPN ازاف کۊنین + نشۊویا وو تورا IPv6 ن و رابط VPN اضاف کۊنین ترجی داڌن IPv6 مجال هل وو فسل نوم دامنه، نشۊویا IPv6 ن ترجی بڌین - DNS ز ره دیر (اختیاری) (udp/tcp/https/quic) (اختیاری) + DNS ز ره دیر (udp/tcp/https/quic، اختیاری) DNS VPN DNS (تینا IPv4/v6) - VPN ز شبکه مهلی اگوڌرته؟ + VPN ز شبکه محلی اگوڌرته؟ - نشۊوی رابت VPN + نشۊوی رابط VPN - VPN MTU (پؽش فرز 1500) + VPN MTU (پؽش فرض 1500) DNS منی (اختیاری) @@ -233,76 +233,76 @@ نشۊوی اینترنتی آزمایش تئخیر واقعی URL - تعداد هوم زمووی تست تئخیر واقعی + تعداڌ هوم زمووی تست تئخیر واقعی نشۊوی اینترنتی آزمایش دووسمندیا منپیز هیم سکویی URL - یک رسۊوی پروکسی من شبکه مهلی LAN - پوی دسگایل ترن وا نشۊوی IP ایسا، ز ره socks/http و پروکسی منپیز بۊن، تینا من شبکه قابل ائتماد ره ونده بۊ تا ز منپیز قیر موجاز جلو گری بۊ. - یک رسۊوی من شبکه مهلی ره وست؛ موتمعن بۊین ک من ی شبکه ٱمن هڌین. + یک رسۊوی پروکسی من شبکه محلی LAN + پوی دسگایل ترن وا نشۊوی IP ایسا، ز ره socks/http و پروکسی منپیز بۊن، تینا من شبکه قابل ائتماڌ ره ونده بۊ تا ز منپیز غیر موجاز جلو گری بۊ. + یک رسۊوی من شبکه محلی ره وست؛ موطمئن بۊین ک من ی شبکه ٱمن هڌین. - پورت پروکسی مهلی - ره وندن پروکسی مهلی + پورت پروکسی محلی + ره وندن پروکسی محلی هرسا ره نوسته بۊ، هیچ پروکسی SOCKS من دسرس نؽ، سی دل هیمو کارایی جۊر ورۊ رسۊوی یل اشتراک نترن پروکسی ن و کار گرن. SOCKS5 UDP ائراز هۊویت socks5 مجال استفاڌه ز UDP کاملن ایمن نؽ - پورت پروکسی مهلی - وورکل پورت موتقیر سی پروکسی مهلی - هر کرت ک و من ٱووڌنی وورکل ابۊ، ی پورت پروکسی مهلی تساڌۊفی وورکل اکونه. - نوم منتوری پروکسی مهلی (اختیاری) + پورت پروکسی محلی + وورکل پورت موتغیر سی پروکسی محلی + هر کرت ک و من ٱووڌنی وورکل ابۊ، ی پورت پروکسی محلی تساڌۊفی وورکل اکونه. + نوم منتوری پروکسی محلی (اختیاری) نوم منتوری - رزم پروکسی مهلی (اختیاری) + رزم پروکسی محلی (اختیاری) رزم - پورت DNS مهلی - پورت DNS مهلی + پورت DNS محلی + پورت DNS محلی قوۊل کردن پاک کردن کانفیگ سی پاک وابیڌن فایل کانفیگ، لنگ قوۊل کردن دووارته ز سمت منتور هڌ. - پروکسی HTTP ن و VPN ازاف کۊنین - پروکسی HTTP ن موسقیمن ز (مۊرۊرگر/ی قرد ز برنومه یل لادراری بیڌه)، بؽ استفاڌه ز دسگا NIC مجازی (Android 10+) استفاڌه ابۊ. + پروکسی HTTP ن و VPN اضاف کۊنین + پروکسی HTTP ن موستقیمن ز (مۊرۊرگر/ی قرد ز برنومه یل لادراری بیڌه)، بؽ استفاڌه ز دسگا NIC مجازی (Android 10+) استفاڌه ابۊ. ره وندن نشووݩ داڌن دو سۊتۊنی - نومگه کانفیگا من دو ستۊݩ نشووݩ داڌه ابۊ تا مهتووا بؽتری من بلگه جا بگره. + نومگه کانفیگا من دو ستۊݩ نشووݩ داڌه ابۊ تا محتوا بؽتری من بلگه جا بگره. نشووݩ داڌن پوی بونکۊ یل ن ره ونین - ی بلگه «پوی بونکۊ یل کانفیگ» ازاف کۊنین + ی بلگه «پوی بونکۊ یل کانفیگ» اضاف کۊنین فشناڌن منشڌ فشناڌن منشڌ یا گوزارش موشکلا من Github ٱووڌن من بونکۊ تلگرام برنومه تلگرامن نجوست - هریم سیخومی + حریم سیخومی کود QR زبار کود بونچک موجوزا کود بونچک تورگه تلگرام - تبلیقات + تبلیغات ورۊ کردن خوتکار اشتراکا - اشتراکا خوتووݩ ن و تۉر خوتکار وا فاسله زمۊوی من پس زمینه ورۊ کۊنین. ای ویژیی من پوی دسگایل گاشڌ همیشه کار نکونه - فاسله ورۊ کردن خوتکار (اقلن وا 15 دؽقه بۊ) + اشتراکا خوتووݩ ن و تۉر خوتکار وا فاصله زمۊوی من پس زمینه ورۊ کۊنین. ای ویژیی من پوی دسگایل گاشڌ همیشه کار نکونه + فاصله ورۊ کردن خوتکار (اقلن وا 15 دؽقه بۊ) سئت گوزارشا بارت پؽش هل دامنه دری (outbound) - هالت + حالت سی دووسمندیا وو هیاری قلوه، ری ای هؽل بزݩ زووݩ - سامووا رابت منتوری - سامووا هالت رابت منتوری + سامووا رابط منتوری + سامووا حالت رابط منتوری و کار گرؽڌن ویژیی Hev TUN مجالی ک ره ونده بۊ، TUN ایا hev-socks5-tunnel ن و کار اگره؛ ٱر ره نوۊفته بۊ، همو xray-core ن و کار اگره. Hev Tun سئت گوزارشا - زمووݩ مندیر بیڌن خوندن/هؽل کردن Hev Tun (سانیه) (پؽش فرز tcp، udp 300،60) - سامووا هالت - هالت رۊت ره وست (منتورووݩ رۊت) - ره وستن پروکسی شفاف سئت بلم وا امتیازا ریشه. ای هالت، VPN استاندارد سیستوم ٱندروید ن دور ازنه تا موستقیمن پوی ترافیک شبکه لمی ن وا دست بگره. بئڌ ره وندن، هالت معمۊلی ٱسلی، تور جۊری هر برنومه وو سامووا VPN مربۊته کاملن ناموعتبر ابۊن. + زمووݩ مندیر بیڌن خوندن/هؽل کردن Hev Tun (ثانیه) (پؽش فرض tcp، udp 300،60) + سامووا حالت + حالت رۊت ره وست (منتورووݩ رۊت) + ره وستن پروکسی شفاف سئت بلم وا امتیازا ریشه. ای حالت، VPN استاندارد سیستوم ٱندروید ن دور ازنه تا موستقیمن پوی ترافیک شبکه لمی ن وا دست بگره. بئڌ ره وندن، حالت معمۊلی ٱسلی، تور جۊری هر برنومه وو سامووا VPN مربۊته کاملن نا موئتبر ابۊن. دسرسی رۊت سی ای ویژیی لازوم هڌ یک رسۊوی LAN / تترینگ (منتورووݩ رۊت وابیڌه) ترافیک هات‌اسپات وای‌فای وو دسگا یل منپیز وابیڌه وا USB (تترینگ) ن ز تور VPN بفشنین. @@ -315,24 +315,24 @@ پاک کردن پوی کانفیگا بونکۊ سکویی پاک کردن کانفیگا تکراری بونکۊ سکویی پاک کردن کانفیگا نا موئتبر بونکۊ سکویی - و در کشیڌن کانفیگا قیر سفارشی بونکۊ سکویی من کلیپ بورد + و در کشیڌن کانفیگا غیر سفارشی بونکۊ سکویی من کلیپ بورد سامووا بونکۊ اشتراک نیشتنا نشۊوی اینترنتی اختیاری User Agent - سرآیندا درخاست (قالوو JSON) - نوم موستعار فیلتر + سرآیندا درخواست (قالوو JSON) + فیلتر نیشتنا وا regex ره وندن ورۊ کردن ره وندن ورۊ کردن خوتکار موجاز کردن نشۊوی HTTP نا ٱمن - نوم موستعار پروکسی دیندایی - نوم موستعار پروکسی نیایی - موتمعن بۊ ک نوم موستعار هڌس وو جۊرس نی - فاسله ورۊ کردن نا موئتبر هڌ. هدقل مقدار 15 دؽقه هڌ. + نیشتنا کانفیگ پروکسی دیندایی + نیشتنا کانفیگ پروکسی نیایی + موطمئن بۊ ک نیشتنا هڌس وو جۊرس نی + فاصله ورۊ کردن نا موئتبر هڌ. حداقل مقدار 15 دؽقه هڌ. ورۊ کردن اشتراک بونکۊ سکویی Tcping کانفیگا بونکۊ سکویی تئخیر واقعی کانفیگا بونکۊ سکویی - فایلا بونچک جوقرافیایی + فایلا بونچک جغرافیایی ترتیب و ری نتیجه یل پینگ فیلتر کردن کانفیگا پوی @@ -378,30 +378,30 @@ منپیزن واجۊری کوݩ هونی آزمایش ابۊ… %d کانفیگ هونی آزمایش ابۊ... - مووفق بی: منپیز %dms تۊل کشی + مووفق بی: منپیز %dms طۊل کشی منپیز و اینترنتن نجوست: %s اینترنت من دسرس نؽ - کود ختا: #%d + کود خطا: #%d منپیز هڌ، سی واجۊری کیلیک کوݩ منپیز نؽڌ - تعداد وزیفه یل آزمایشی ک ره اۊفتانه: %s + آزمایشا هونی ٱنجوم ابۊن: %s اشتراک وا مووفقیت زفت وابی اشتراک زفت نوابی سامووا فرگمنت (Fragment) کتنا فرگمنت - تۊل کتنا فرگمنت (هدقل-هدکسر) - فاسله منجا کتنا فرگمنت (هدقل-هدکسر) + طۊل کتنا فرگمنت (حداقل-حداکثر) + فاصله منجا کتنا فرگمنت (حداقل-حداکثر) ره وندن فرگمنت - هدکسر تقسیم فرگمنت + حداکثر تقسیم فرگمنت سامووا واجۊری منپیز (Observatory) - فاسله leastPing - فاسله leastLoad + فاصله leastPing + فاصله leastLoad روش HTTP سی leastLoad نمونه گیری leastLoad مهلت leastLoad - زما نادروسته. یه ارزشی وری 3m یا 30s بکار ببرین. - نمونه گیری نادروسته. یه شماره مثبت بکار ببرین. + زمووݩ نا موئتبر هڌ. ارزشی وری 3m یا 30s ن و کار بگیرین. + نمونه گیری نا موئتبر هڌ. شوماره ی مثبت ن و کار بگیرین. واجۊری سی ورۊ رسۊوی سکو نوسخه دیندایی پۊرنیڌه هڌ @@ -419,9 +419,9 @@ ٱئزا زنجیره پروکسی سی پسند عوزو ایچو بزنین ی عوزو پسند کۊنین - سی هر ردیف زنجیره remark پسند کۊنین - تعداد ٱئزا بس نؽ - ٱئزا ناموئتبر زنجیره: %1$s + سی هر ردیف زنجیره ی عوزو پسند کۊنین + تعداڌ ٱئزا بس نؽ + ٱئزا نا موئتبر زنجیره: %1$s لادراری گرؽڌن & وورگندن @@ -469,7 +469,7 @@ نومگه اسبؽڌ رۊسیه - پؽش فرز کانفیگ + پؽش فرض کانفیگ دور زیڌه بۊ دور زیڌه نبۊ @@ -487,7 +487,57 @@ گردشی (roundRobin) - مهلی + محلی WebDAV + وانۊ کردن گوزارش + گرؽڌن موجوز مومکن نؽڌ: %1$s + ٱووردن اشتراک + کانفیگ نا موئتبر هڌ: %1$s + ٱووردن بونچک فایلا جغرافیایی + دانلود فایلا بونچک جغرافیایی + کود QR + لف گیری گوزارش + روفتن گوزارش + ٱووردن قانووݩ + هیچ کانفیگ پسند وابیڌه نؽ + خوندن کانفیگ پسند وابیڌه مووفق نبی + پردازشت کانفیگ پسند وابیڌه مووفق نبی + ساڌن کانفیگ هسته مووفق نبی + ساڌن کانفیگ هسته مووفق نبی: %1$s + ساڌن کانفیگ هسته سی آزمایش سورعت مووفق نبی: %1$s + کانفیگ سفارشی نؽ + ره وستن هسته مووفق نبی + ره وستن سرویس + واڌاشتن سرویس + برگشت + پیتینیڌن + ٱووردن کانفیگ + امکووݩا بؽتر + یک رسۊوی لینک اشتراک + یک رسۊوی گوزارش + پاک کردن عوزو زنجیره پروکسی + ٱووردن عوزو زنجیره پروکسی + ره وستن اسکنر QR + واڌاشتن اسکنر QR + روشن کردن چراغ + خاموش کردن چراغ + پسند ٱکس سی اسکن + ای قانووݩ مجال و من ٱووردن ز پؽش سامووا زفت ابۊ + گۊشیڌن نومگه کشاری + آلشتکاری + پاک کردن + زفت کردن + ورۊ کردن اشتراکا + دووسمندی پروکسی و ری برنومه + دوربیݩ + وارسۊوی + شبکه محلی + اشتراک %1$s هونی ورۊ ابۊ + %2$s هونی آزمایش ابۊ: %1$s + ره وستن %1$s + واڌاشتن %1$s + دووسمندی نؽ + نا مؽخص + diff --git a/V2rayNG/app/src/main/res/values-fa/strings.xml b/V2rayNG/app/src/main/res/values-fa/strings.xml index 017d8ea98f..9944a53c45 100644 --- a/V2rayNG/app/src/main/res/values-fa/strings.xml +++ b/V2rayNG/app/src/main/res/values-fa/strings.xml @@ -490,4 +490,54 @@ محلی WebDAV + تازه‌سازی گزارش + مجوز %1$s داده نشد + افزودن اشتراک + قالب پیکربندی نامعتبر است: %1$s + افزودن منبع فایل‌های جغرافیایی + دانلود فایل‌های منبع + کد QR + کپی گزارش + پاک کردن گزارش + افزودن قانون مسیریابی + هیچ پیکربندی‌ای انتخاب نشده است + خواندن پیکربندی انتخاب‌شده ناموفق بود + آماده‌سازی پیکربندی انتخاب‌شده ناموفق بود + ایجاد پیکربندی هسته ناموفق بود + ایجاد پیکربندی هسته ناموفق بود: %1$s + ایجاد پیکربندی هسته برای آزمایش سرعت ناموفق بود: %1$s + پیکربندی سفارشی خالی است + راه‌اندازی هسته ناموفق بود + شروع سرویس + توقف سرویس + بازگشت + جستجو + افزودن کانفیگ + گزینه‌های بیشتر + اشتراک‌گذاری لینک اشتراک + اشتراک‌گذاری گزارش + حذف عضو زنجیره پروکسی + افزودن عضو زنجیره پروکسی + شروع اسکنر QR + توقف اسکنر QR + روشن کردن چراغ‌قوه + خاموش کردن چراغ‌قوه + انتخاب تصویر برای اسکن + این قانون هنگام وارد کردن تنظیمات از پیش تعیین‌شده حفظ می‌شود + باز کردن منوی پیمایش + ویرایش + حذف + ذخیره + به‌روزرسانی اشتراک‌ها + اطلاعات پروکسی به تفکیک برنامه + دوربین + اعلان + شبکه محلی + در حال به‌روزرسانی اشتراک: %1$s + در حال آزمایش %2$s: %1$s + شروع %1$s + توقف %1$s + جزئیاتی در دسترس نیست + ناشناخته + diff --git a/V2rayNG/app/src/main/res/values-ru/strings.xml b/V2rayNG/app/src/main/res/values-ru/strings.xml index dfff4ca4b2..a7783f2e89 100644 --- a/V2rayNG/app/src/main/res/values-ru/strings.xml +++ b/V2rayNG/app/src/main/res/values-ru/strings.xml @@ -490,4 +490,54 @@ Локально WebDAV + Обновить журнал + Нет разрешения: %1$s + Добавить подписку + Некорректная конфигурация: %1$s + Добавить источник ресурсов + Загрузить файлы ресурсов + QR-код + Копировать журнал + Очистить журнал + Добавить правило маршрутизации + Конфигурация не выбрана + Не удалось прочитать выбранную конфигурацию + Не удалось подготовить выбранную конфигурацию + Не удалось создать конфигурацию ядра + Не удалось создать конфигурацию ядра: %1$s + Не удалось создать конфигурацию ядра для теста скорости: %1$s + Пользовательская конфигурация пуста + Не удалось запустить ядро + Запустить службу + Остановить службу + Назад + Поиск + Добавить профиль + Дополнительные параметры + Поделиться ссылкой на подписку + Поделиться журналом + Удалить участника цепочки прокси + Добавить участника цепочки прокси + Запустить сканер QR-кодов + Остановить сканер QR-кодов + Включить фонарик + Выключить фонарик + Выбрать изображение для сканирования + Правило сохраняется при импорте предустановок + Открыть меню навигации + Изменить + Удалить + Сохранить + Обновить подписки + Сведения о прокси для приложений + Камера + Уведомления + Локальная сеть + Обновление подписки: %1$s + Тестирование %2$s: %1$s + Запустить %1$s + Остановить %1$s + подробности отсутствуют + неизвестно + diff --git a/V2rayNG/app/src/main/res/values-vi/strings.xml b/V2rayNG/app/src/main/res/values-vi/strings.xml index 8317cdaebc..1fc898e6e3 100644 --- a/V2rayNG/app/src/main/res/values-vi/strings.xml +++ b/V2rayNG/app/src/main/res/values-vi/strings.xml @@ -490,4 +490,54 @@ Cục bộ WebDAV + Làm mới nhật ký + Chưa cấp quyền: %1$s + Thêm gói đăng ký + Cấu hình không hợp lệ: %1$s + Thêm nguồn tệp tài nguyên + Tải xuống tệp tài nguyên + Mã QR + Sao chép nhật ký + Xóa nhật ký + Thêm quy tắc định tuyến + Chưa chọn cấu hình + Không thể đọc cấu hình đã chọn + Không thể chuẩn bị cấu hình đã chọn + Không thể tạo cấu hình lõi + Không thể tạo cấu hình lõi: %1$s + Không thể tạo cấu hình lõi để kiểm tra tốc độ: %1$s + Cấu hình tùy chỉnh đang trống + Không thể khởi động lõi + Khởi động dịch vụ + Dừng dịch vụ + Quay lại + Tìm kiếm + Thêm cấu hình + Tùy chọn khác + Chia sẻ liên kết đăng ký + Chia sẻ nhật ký + Xóa thành viên khỏi chuỗi proxy + Thêm thành viên vào chuỗi proxy + Khởi động trình quét mã QR + Dừng trình quét mã QR + Bật đèn pin + Tắt đèn pin + Chọn ảnh để quét + Giữ quy tắc khi nhập cài đặt sẵn + Mở trình đơn điều hướng + Chỉnh sửa + Xóa + Lưu + Cập nhật các gói đăng ký + Thông tin proxy theo ứng dụng + Máy ảnh + Thông báo + Mạng cục bộ + Đang cập nhật gói đăng ký: %1$s + Đang kiểm tra %2$s: %1$s + Khởi động %1$s + Dừng %1$s + không có thông tin chi tiết + không xác định + diff --git a/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml b/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml index d746681bd8..403a723170 100644 --- a/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml +++ b/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml @@ -490,4 +490,54 @@ 本地 WebDAV + 刷新日志 + %1$s权限被拒绝 + 添加订阅 + 配置格式无效:%1$s + 添加资源来源 + 下载资源文件 + 二维码 + 复制日志 + 清除日志 + 添加路由规则 + 未选择配置 + 无法读取所选配置 + 无法准备所选配置 + 无法生成核心配置 + 无法生成核心配置:%1$s + 无法生成测速用核心配置:%1$s + 自定义配置为空 + 无法启动核心 + 启动服务 + 停止服务 + 返回 + 搜索 + 添加配置 + 更多选项 + 分享订阅链接 + 分享日志 + 移除代理链成员 + 添加代理链成员 + 启动二维码扫描器 + 停止二维码扫描器 + 打开手电筒 + 关闭手电筒 + 选择要扫描的图片 + 导入预设时保留此规则 + 打开导航菜单 + 编辑 + 删除 + 保存 + 更新订阅 + 分应用代理信息 + 相机 + 通知 + 局域网 + 正在更新订阅:%1$s + 正在测试%2$s:%1$s + 启动 %1$s + 停止 %1$s + 无详细信息 + 未知 + diff --git a/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml b/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml index b335fe0ac5..504867420e 100644 --- a/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml +++ b/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml @@ -490,4 +490,54 @@ 本地 WebDAV + 重新整理日誌 + 未授予%1$s權限 + 新增訂閱 + 設定檔格式不正確:%1$s + 新增資源來源 + 下載資源檔案 + QR 碼 + 複製日誌 + 清除日誌 + 新增路由規則 + 未選取設定 + 無法讀取所選設定 + 無法準備所選設定 + 無法產生核心設定 + 無法產生核心設定:%1$s + 無法產生測速用核心設定:%1$s + 自訂設定為空 + 無法啟動核心 + 啟動服務 + 停止服務 + 返回 + 搜尋 + 新增設定 + 更多選項 + 分享訂閱連結 + 分享日誌 + 移除代理鏈成員 + 新增代理鏈成員 + 啟動 QR 碼掃描器 + 停止 QR 碼掃描器 + 開啟手電筒 + 關閉手電筒 + 選取要掃描的圖片 + 匯入預設時保留此規則 + 開啟導覽選單 + 編輯 + 刪除 + 儲存 + 更新訂閱 + 各應用程式的 Proxy 資訊 + 相機 + 通知 + 區域網路 + 正在更新訂閱:%1$s + 正在測試%2$s:%1$s + 啟動 %1$s + 停止 %1$s + 沒有詳細資訊 + 未知 + diff --git a/V2rayNG/app/src/main/res/values/strings.xml b/V2rayNG/app/src/main/res/values/strings.xml index b20996c69e..a72f4b97bf 100644 --- a/V2rayNG/app/src/main/res/values/strings.xml +++ b/V2rayNG/app/src/main/res/values/strings.xml @@ -490,4 +490,54 @@ Local WebDAV + Refresh log + %1$s permission denied + Add subscription + Invalid configuration: %1$s + Add asset source + Download asset files + QR code + Copy log + Clear log + Add routing rule + No configuration selected + Failed to read the selected configuration + Failed to prepare the selected configuration + Failed to generate the core configuration + Failed to generate the core configuration: %1$s + Failed to generate the core configuration for the speed test: %1$s + Custom configuration is empty + Failed to start the core + Start service + Stop service + Back + Search + Add configuration + More options + Share subscription link + Share log + Remove proxy chain member + Add proxy chain member + Start QR scanner + Stop QR scanner + Turn flashlight on + Turn flashlight off + Select image to scan + This rule is kept when importing presets + Open navigation menu + Edit + Delete + Save + Update subscriptions + Per-app proxy information + Camera + Notification + Local network + Updating subscription: %1$s + Testing %2$s: %1$s + Start %1$s + Stop %1$s + no details available + unknown +