Compare commits

..
28 Commits
Author SHA1 Message Date
2dust b348ca792b up 2.3.4 2026-08-14 20:33:23 +08:00
eliotcougar 1fa0ccb4f2 Make proxy-only service starts idempotent (#6071) 2026-08-14 20:26:13 +08:00
2dust 3033e471cd Use theme secondary color in Compose UI 2026-08-14 15:30:10 +08:00
Xiaochang 36796fee37 feat: replace app name with app icon in navigation drawer header - Use ic_launcher_foreground 120dp - Dark mode: icon tinted white - Light mode: original colors - Surface height 180dp (#6068) 2026-08-14 15:11:26 +08:00
Xiaochang 2607b5cbff feat: support Monet dynamic color (Android 12+) - Add toggle in UI settings, default enabled, auto-disable on unsupported devices (#6067) 2026-08-14 15:09:46 +08:00
eliotcougarand2dust 9cdbc5cebb fix: localize runtime-generated UI text (5/3) (#6049)
* Localize runtime-generated UI text

Keep connection-test and status data locale-neutral until the UI formats it, and localize delay units at their Compose presentation boundary.\n\nShow stable localized failures while retaining diagnostic exceptions in Logcat. Clarify routing rule matching and subscription entry/exit proxy behavior at the relevant UI call sites, and remove the now-unused core error resources.

* Fix Compose resource lookup in routing editor

* Adjust string

---------

Co-authored-by: 2dust <31833384+2dust@users.noreply.github.com>
2026-08-14 14:35:47 +08:00
mola f976d397e0 Make update notes scrollable (#6054) 2026-08-14 14:16:25 +08:00
DHR60 a16a7390f4 Fix kcp and sync finalmask order (#6062) 2026-08-14 14:13:09 +08:00
eliotcougar 606246f36e fix: make root service starts idempotent (#6055) 2026-08-14 14:09:31 +08:00
eliotcougar e8a82d9810 fix: refine existing locale translations (4/3) (#6048)
* Refine existing locale translations

Carry over the standalone wording and translation corrections from the combined localization audit across all nine maintained catalogs.

Keep identifiers, order, placeholders, and metadata unchanged. Exclude resource additions, removals, and wording that depends on locale API, connection-result, routing layout, subscription proxy, delay-unit, or core code changes.

* Clarify profile export actions

Distinguish copying a profile share link from copying the fully generated configuration in every maintained locale.
2026-08-10 15:03:26 +08:00
eliotcougar 739e303fc0 Fix per-app locale handling across contexts (#6047)
Use AndroidX and framework per-app locale APIs, migrate the existing language preference, and expose the generated locale config to Android 13+ settings.

Resolve resources through the selected app locale in application, ViewModel, tile, and service contexts. Replace the framework OK and Cancel labels directly implicated in the wrong-language report, and refresh retained localized UI state after locale changes.
2026-08-09 21:09:41 +08:00
2dust f63f649477 Adjust UI 2026-08-08 10:51:51 +08:00
2dust a2be68f7c5 Use internal assets directory path
https://github.com/2dust/v2rayNG/issues/6035
2026-08-08 10:12:35 +08:00
2dust 68f9e66a76 Bug fix
https://github.com/2dust/v2rayNG/issues/6027
2026-08-07 20:30:15 +08:00
2dust 9be547c3b9 up 2.3.3 2026-08-07 16:27:33 +08:00
2dust fd48dcf9e0 Simplify core error handling paths
https://github.com/2dust/v2rayNG/pull/6025
2026-08-07 16:24:20 +08:00
eliotcougarand2dust 775546ce40 fix: localize user-facing and accessibility text (2/3) (#6025)
* fix: localize UI and accessibility text

* fix: translate BQI core errors

* fix: correct Bakhtiari orthography and wording

Replace the remaining Persian confirmation fallbacks, correct stale or mismatched UI meanings, and normalize established Bakhtiari terms without translating xray-core identifiers.

Primary source: Erik Anonby and Ashraf Asadi, Bakhtiari Studies II: Orthography (2018), sections 6.1.1, 6.8.1, 6.8.2, 6.8.7, and 6.8.9. https://www.diva-portal.org/smash/get/diva2%3A1231755/FULLTEXT02.pdf

The standard recommends that "Arabic letters be retained for Bakhtiari words borrowed from Persian" and reports that speakers view soft d as "a defining feature of how the language is pronounced."

Lexicon and phonology source: Erik Anonby and Ashraf Asadi, Bakhtiari Studies: Phonology, Text, Lexicon (2014). https://uu.diva-portal.org/smash/record.jsf?pid=diva2%3A758171

Historical corroboration: D. L. R. Lorimer, The Phonology of the Bakhtiari, Badakhshani, and Madaglashti Dialects of Modern Persian (1922). https://archive.org/details/phonologyofbakht06loriuoft

* fix: keep protocol description technical

* fix: keep Logcat diagnostics unlocalized

* getRemoteIPInfo

---------

Co-authored-by: 2dust <31833384+2dust@users.noreply.github.com>
2026-08-07 15:58:11 +08:00
2dust d8b857665c Move update check out of Compose 2026-08-06 17:12:26 +08:00
eliotcougarand2dust 17d03bcc46 Optimize app picker filtering and bulk selection (#6000)
* Optimize app picker filtering and selection

Avoid per-query string copies and repeated state persistence or service restart requests during bulk selection. Preserve the active filter while apps load, calculate automatic and imported selections away from the main thread, and keep upstream's asynchronous Coil icon pipeline unchanged.

* Remove enabled: Boolean = true

---------

Co-authored-by: 2dust <31833384+2dust@users.noreply.github.com>
2026-08-06 17:04:39 +08:00
eliotcougar efb16e7979 fix: sync locale resources and translations (1/3) (#6024)
* fix: align and complete locale resources

* fix: finish locale translations

* fix: align routeOnly terminology

* fix: preserve core terminology in translations

* fix: refine localization wording

* fix: finish localization resource cleanup

* fix: standardize URL capitalization

* fix: mark technical resources non-translatable
2026-08-06 08:34:26 +08:00
eliotcougar 5ac660e395 Use typed actions for Compose menus and Material 3 drawer components (#6016)
* Use typed actions for application menus

* Use Material 3 navigation drawer components

Replace the custom drawer rows with NavigationDrawerItem and route system Back through Compose so an open drawer closes before the task is backgrounded.

* Polish typed menus and drawer integration
2026-08-05 14:59:27 +08:00
2dust 2dcc7781a5 perf: optimize app icon loading with asynchronous Coil retrieval
- Remove `appIcon: Drawable` from `AppInfo` to significantly reduce memory footprint and prevent OOM.
- Replace synchronous icon loading in `AppManagerUtil` with on-demand asynchronous loading.
- Implement custom `AppIconFetcher` using `appicon:` URI scheme for system icon retrieval.
- Use localized `fetcherFactory` in `AppListItem` to keep loading logic isolated and minimize global side effects.
- Improve app list scanning speed by skipping icon extraction during initial load.
2026-08-04 21:22:19 +08:00
Alexandr 2a51e7e767 fix(speed): resolve 0 B/s speed notification counters for custom subscription profiles (#5990)
* fix(speed): fix speed counters showing 0 for custom subscription profiles

Fix an issue where proxy speed counters in the notification widget remain at 0 B/s for custom subscription profiles.
1. NotificationManager: Accumulate traffic stats for all non-direct and non-blocked outbound tags (stat.tag != TAG_BLOCKED) into proxy stats. Custom outbound tags in subscription JSONs (e.g., 'node-1', 'vless-hk', 'auto') are now correctly accounted for instead of being ignored.
2. CoreConfigManager: Ensure stats and policy (statsOutboundUplink / statsOutboundDownlink) sections are injected into custom JSON configurations when PREF_SPEED_ENABLED is enabled, and stripped when disabled.

* Comments added
2026-08-04 20:31:26 +08:00
solokot 007e167a45 Update Russian translation (#5987) 2026-08-04 20:30:49 +08:00
dependabot[bot] 9c80ab3d44 Bump actions/setup-java from 5.6.0 to 5.7.0 (#6019)
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5.6.0 to 5.7.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/v5.6.0...v5.7.0)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-version: 5.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 20:30:35 +08:00
eliotcougar 320fb6a10b Handle padded camera rows in QR scanner (#6012)
Camera HALs may expose a Y plane whose row stride is wider than the visible image. Pass that stride to ZXing so padded rows remain aligned, and cover the vendor-layout case with a valid VLESS QR regression test.
2026-08-04 20:30:25 +08:00
2dust 559a00e66e Fix cancel signaling in measure/ping services 2026-08-03 20:48:37 +08:00
eliotcougar 31dfaeed6c Add cancel action to batch-test notification (#6009) 2026-08-03 20:42:04 +08:00
93 changed files with 3500 additions and 2480 deletions

No files matched your search

+1 -1
View File
@@ -81,7 +81,7 @@ jobs:
out-file-path: V2rayNG/app/libs/
- name: Setup Java
uses: actions/setup-java@v5.6.0
uses: actions/setup-java@v5.7.0
with:
distribution: 'temurin'
java-version: '21'
+19 -2
View File
@@ -13,8 +13,8 @@ android {
applicationId = "com.v2ray.ang"
minSdk = 24
targetSdk = 37
versionCode = 742
versionName = "2.3.2"
versionCode = 744
versionName = "2.3.4"
val abiFilterList = (properties["ABI_FILTERS"] as? String)?.split(';')
splits {
@@ -128,6 +128,21 @@ android {
compose = true
}
androidResources {
generateLocaleConfig = true
localeFilters += listOf(
"en",
"zh-rCN",
"zh-rTW",
"vi",
"ru",
"fa",
"ar",
"bn",
"bqi-rIR"
)
}
packaging {
jniLibs {
useLegacyPackaging = true
@@ -142,6 +157,7 @@ dependencies {
// AndroidX Core Libraries
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
// Compose Libraries
implementation(platform(libs.androidx.compose.bom))
@@ -153,6 +169,7 @@ dependencies {
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.ui.tooling.preview)
implementation(libs.lifecycle.runtime.compose)
implementation(libs.coil.compose)
debugImplementation(libs.androidx.compose.ui.tooling)
+9
View File
@@ -52,6 +52,15 @@
android:theme="@style/AppThemeDayNight.NoActionBar"
android:usesCleartextTraffic="true">
<service
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
android:enabled="false"
android:exported="false">
<meta-data
android:name="autoStoreLocales"
android:value="true" />
</service>
<activity
android:name=".ui.main.MainActivity"
android:exported="true"
@@ -2,10 +2,12 @@ package com.v2ray.ang
import android.app.Application
import android.content.Context
import androidx.core.content.ContextCompat
import androidx.work.Configuration
import androidx.work.WorkManager
import com.tencent.mmkv.MMKV
import com.v2ray.ang.AppConfig.ANG_PACKAGE
import com.v2ray.ang.handler.AppLocaleManager
import com.v2ray.ang.handler.SettingsManager
import com.v2ray.ang.ui.compose.ThemeManager
@@ -19,7 +21,7 @@ class AngApplication : Application() {
* @param base The base context.
*/
override fun attachBaseContext(base: Context?) {
super.attachBaseContext(base)
super.attachBaseContext(base?.let(ContextCompat::getContextForLanguage))
application = this
}
@@ -35,6 +37,8 @@ class AngApplication : Application() {
MMKV.initialize(this)
AppLocaleManager.initialize(this)
// Initialize WorkManager with the custom configuration
WorkManager.initialize(this, workManagerConfiguration)
@@ -56,7 +56,9 @@ object AppConfig {
const val PREF_DOUBLE_COLUMN_DISPLAY = "pref_double_column_display"
const val PREF_GROUP_ALL_DISPLAY = "pref_group_all_display"
const val PREF_LANGUAGE = "pref_language"
const val PREF_APP_LOCALE_MIGRATED = "pref_app_locale_migrated"
const val PREF_UI_MODE_NIGHT = "pref_ui_mode_night"
const val PREF_DYNAMIC_COLOR = "pref_dynamic_color"
const val PREF_IPV6_ENABLED = "pref_ipv6_enabled"
const val PREF_PREFER_IPV6 = "pref_prefer_ipv6"
const val PREF_PROXY_SHARING = "pref_proxy_sharing_enabled"
@@ -178,7 +180,7 @@ object AppConfig {
const val MSG_STATE_STOP_SUCCESS = 41
const val MSG_STATE_RESTART = 5
const val MSG_MEASURE_DELAY = 6
const val MSG_MEASURE_DELAY_SUCCESS = 61
const val MSG_MEASURE_DELAY_RESULT = 61
const val MSG_MEASURE_CONFIG_START = 7
const val MSG_MEASURE_CONFIG_CANCEL = 71
const val MSG_MEASURE_CONFIG_SUCCESS = 72
@@ -3,6 +3,7 @@ package com.v2ray.ang.core
import android.content.Context
import android.text.TextUtils
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import com.v2ray.ang.AppConfig
import com.v2ray.ang.dto.ConfigResult
import com.v2ray.ang.dto.CoreConfigContext
@@ -33,7 +34,11 @@ 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"
)
if (configContext.isCustom) {
return buildV2rayCustomConfig(configContext)
}
@@ -56,7 +61,11 @@ 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"
)
if (configContext.isCustom) {
return buildV2rayCustomConfig(configContext)
}
@@ -69,7 +78,7 @@ object CoreConfigManager {
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: ${e.message ?: e.javaClass.simpleName}"
)
}
}
@@ -80,14 +89,37 @@ 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 = "Failed to build config context, config is empty"
)
val result = ConfigResult(true, configContext.guid, raw)
if (!needTun()) {
return result
}
val json = JsonUtil.parseString(raw)?.takeIf { it.isJsonObject }?.asJsonObject ?: return result
// Inject or remove traffic statistics configuration based on user preference
if (MmkvManager.decodeSettingsBool(AppConfig.PREF_SPEED_ENABLED) == true) {
if (!json.has("stats")) {
json.add("stats", JsonObject())
}
if (!json.has("policy")) {
val policyObj = JsonObject()
val systemObj = JsonObject()
systemObj.addProperty("statsOutboundUplink", true)
systemObj.addProperty("statsOutboundDownlink", true)
policyObj.add("system", systemObj)
json.add("policy", policyObj)
}
} else {
json.remove("stats")
json.remove("policy")
}
if (!needTun()) {
return JsonUtil.toJsonPretty(json)?.let { ConfigResult(true, configContext.guid, it) } ?: result
}
// Check whether package names need to be replaced with UIDs
if (SettingsManager.canUseProcessRouting()) {
val rulesJson = json.get("routing")?.takeIf { it.isJsonObject }?.asJsonObject
@@ -396,6 +396,7 @@ object CoreOutboundBuilder {
)
)
}
udpMaskList.reverse()
streamSettings.finalmask = OutboundBean.StreamSettingsBean.FinalMaskBean(
udp = udpMaskList.toList()
)
@@ -635,8 +636,7 @@ object CoreOutboundBuilder {
JsonUtil.parseString(JsonUtil.toJson(existingFinalMask))
} ?: JsonObject()
// finalmask.tcp / finalmask.udp are arrays; prepend mask at index 0.
fun prependMask(scope: String, mask: OutboundBean.StreamSettingsBean.FinalMaskBean.MaskBean) {
fun appendMask(scope: String, mask: OutboundBean.StreamSettingsBean.FinalMaskBean.MaskBean) {
val current = finalMaskObj.get(scope)
if (current != null && current.isJsonArray && current.asJsonArray.size() > 0) {
return
@@ -651,8 +651,8 @@ object CoreOutboundBuilder {
finalMaskObj.add(scope, newArray)
}
prependMask("tcp", fragmentMask)
prependMask("udp", noiseMask)
appendMask("tcp", fragmentMask)
appendMask("udp", noiseMask)
streamSettings.finalmask = finalMaskObj
} catch (e: Exception) {
LogUtil.e(AppConfig.TAG, "Failed to update outbound fragment", e)
@@ -11,9 +11,9 @@ import android.os.ParcelFileDescriptor
import android.system.OsConstants
import androidx.core.content.ContextCompat
import com.v2ray.ang.AppConfig
import com.v2ray.ang.R
import com.v2ray.ang.contracts.IDialerService
import com.v2ray.ang.contracts.ServiceControl
import com.v2ray.ang.dto.ConnectionTestResult
import com.v2ray.ang.dto.OutboundTrafficStat
import com.v2ray.ang.dto.entities.ProfileItem
import com.v2ray.ang.enums.BrowserDialerMode
@@ -31,7 +31,6 @@ import com.v2ray.ang.util.Utils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlin.jvm.Volatile
import libv2ray.CoreCallbackHandler
import libv2ray.CoreController
import libv2ray.ProcessFinder
@@ -321,28 +320,34 @@ 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("\":").orEmpty()
}
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("\":").orEmpty()
}
}
val result = if (time >= 0) {
service.getString(R.string.connection_test_available, time)
} else {
service.getString(R.string.connection_test_error, errorStr)
}
MessageHelper.sendMsg2UI(service, AppConfig.MSG_MEASURE_DELAY_SUCCESS, result)
val result = ConnectionTestResult(
delayMillis = time,
errorMessage = errorStr,
)
MessageHelper.sendMsg2UI(service, AppConfig.MSG_MEASURE_DELAY_RESULT, result)
// Only fetch IP info if the delay test was successful
if (time >= 0) {
SpeedtestManager.getRemoteIPInfo()?.let { ip ->
MessageHelper.sendMsg2UI(service, AppConfig.MSG_MEASURE_DELAY_SUCCESS, "$result\n$ip")
MessageHelper.sendMsg2UI(
service,
AppConfig.MSG_MEASURE_DELAY_RESULT,
result.copy(
country = ip.country,
ipAddress = ip.ipAddress,
),
)
}
}
}
@@ -492,4 +497,4 @@ object CoreServiceManager {
}
}
}
}
}
@@ -1,11 +1,8 @@
package com.v2ray.ang.dto
import android.graphics.drawable.Drawable
data class AppInfo(
val appName: String,
val packageName: String,
val appIcon: Drawable,
val isSystemApp: Boolean,
var isSelected: Int
)
@@ -0,0 +1,11 @@
package com.v2ray.ang.dto
import java.io.Serializable
/** Locale-neutral result sent from the daemon for presentation by the UI process. */
data class ConnectionTestResult(
val delayMillis: Long,
val errorMessage: String = "",
val country: String? = null,
val ipAddress: String? = null,
) : Serializable
@@ -1,10 +1,3 @@
package com.v2ray.ang.dto.entities
data class ServerAffiliationInfo(var testDelayMillis: Long = 0L) {
fun getTestDelayString(): String {
if (testDelayMillis == 0L) {
return ""
}
return testDelayMillis.toString() + "ms"
}
}
data class ServerAffiliationInfo(var testDelayMillis: Long = 0L)
@@ -4,5 +4,4 @@ data class ServersCache(
val guid: String,
val profile: ProfileItem,
val testDelayMillis: Long = 0L,
val testDelayString: String = "",
)
@@ -1,20 +1,57 @@
package com.v2ray.ang.enums
enum class Language(val code: String) {
AUTO("auto"),
ENGLISH("en"),
CHINA("zh-rCN"),
TRADITIONAL_CHINESE("zh-rTW"),
VIETNAMESE("vi"),
RUSSIAN("ru"),
PERSIAN("fa"),
ARABIC("ar"),
BANGLA("bn"),
BAKHTIARI("bqi-rIR");
import androidx.core.os.LocaleListCompat
import java.util.Locale
enum class Language(val code: String, val languageTag: String) {
AUTO("auto", ""),
ENGLISH("en", "en"),
CHINA("zh-rCN", "zh-CN"),
TRADITIONAL_CHINESE("zh-rTW", "zh-TW"),
VIETNAMESE("vi", "vi"),
RUSSIAN("ru", "ru"),
PERSIAN("fa", "fa"),
ARABIC("ar", "ar"),
BANGLA("bn", "bn"),
BAKHTIARI("bqi-rIR", "bqi-IR");
val locale: Locale?
get() = languageTag.takeIf { it.isNotEmpty() }?.let(Locale::forLanguageTag)
fun toLocaleList(): LocaleListCompat =
if (languageTag.isEmpty()) {
LocaleListCompat.getEmptyLocaleList()
} else {
LocaleListCompat.forLanguageTags(languageTag)
}
companion object {
fun fromCode(code: String): Language {
return entries.find { it.code == code } ?: AUTO
}
fun fromLanguageTag(languageTag: String?): Language {
if (languageTag.isNullOrBlank()) return AUTO
val locale = Locale.forLanguageTag(languageTag)
return when (locale.language) {
"en" -> ENGLISH
"zh" -> if (
locale.script == "Hant" || locale.country in setOf("TW", "HK", "MO")
) {
TRADITIONAL_CHINESE
} else {
CHINA
}
"vi" -> VIETNAMESE
"ru" -> RUSSIAN
"fa" -> PERSIAN
"ar" -> ARABIC
"bn" -> BANGLA
"bqi" -> BAKHTIARI
else -> AUTO
}
}
}
}
@@ -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
}
}
}
@@ -5,18 +5,5 @@ enum class RoutingType(val fileName: String) {
BLACK("custom_routing_black"),
GLOBAL("custom_routing_global"),
WHITE_IRAN("custom_routing_white_iran"),
WHITE_RUSSIA("custom_routing_white_russia");
companion object {
fun fromIndex(index: Int): RoutingType {
return when (index) {
0 -> WHITE
1 -> BLACK
2 -> GLOBAL
3 -> WHITE_IRAN
4 -> WHITE_RUSSIA
else -> WHITE
}
}
}
WHITE_RUSSIA("custom_routing_white_russia")
}
@@ -0,0 +1,140 @@
package com.v2ray.ang.handler
import android.app.LocaleManager
import android.content.Context
import android.content.res.Configuration
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.app.LocaleManagerCompat
import androidx.core.content.ContextCompat
import androidx.core.os.ConfigurationCompat
import com.v2ray.ang.AppConfig
import com.v2ray.ang.enums.Language
/**
* Keeps the legacy in-app language preference synchronized with Android's per-app locale APIs.
*/
object AppLocaleManager {
/**
* Migrates the existing MMKV language preference and restores it before the first activity.
*/
fun initialize(context: Context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
Api33.prepareMigration(context)
} else {
initializeCompat(context)
}
}
/**
* Completes the one-time handoff after AppCompat has attached the activity context.
*/
fun onActivityCreated(context: Context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
Api33.completeMigration(context)
} else {
syncLegacyPreference(AppCompatDelegate.getApplicationLocales().get(0)?.toLanguageTag())
}
}
/**
* Applies a language selected in the app and lets AppCompat recreate the current activity.
*/
fun setApplicationLanguage(languageCode: String) {
val language = Language.fromCode(languageCode)
persistLegacyPreference(language)
AppCompatDelegate.setApplicationLocales(language.toLocaleList())
}
/**
* Returns a context suitable for resource access outside AppCompatActivity.
*/
fun localizedContext(context: Context): Context {
val localizedContext = ContextCompat.getContextForLanguage(context)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU || localizedContext !== context) {
return localizedContext
}
// During the one-time upgrade from the old picker, AppCompat has not written its locale
// record yet. Use the still-current MMKV value for non-activity contexts on that launch.
val language = storedLanguage()
language.locale ?: return context
val configuration = Configuration(context.resources.configuration)
ConfigurationCompat.setLocales(configuration, language.toLocaleList())
return context.createConfigurationContext(configuration)
}
private fun initializeCompat(context: Context) {
val storedLocales = LocaleManagerCompat.getApplicationLocales(context)
if (storedLocales.isEmpty) {
val legacyLanguage = storedLanguage()
if (legacyLanguage != Language.AUTO) {
AppCompatDelegate.setApplicationLocales(legacyLanguage.toLocaleList())
}
} else {
syncLegacyPreference(storedLocales.get(0)?.toLanguageTag())
}
}
private fun storedLanguage(): Language = Language.fromCode(
MmkvManager.decodeSettingsString(AppConfig.PREF_LANGUAGE) ?: Language.AUTO.code
)
private fun syncLegacyPreference(languageTag: String?) {
persistLegacyPreference(Language.fromLanguageTag(languageTag))
}
private fun persistLegacyPreference(language: Language) {
val current = MmkvManager.decodeSettingsString(AppConfig.PREF_LANGUAGE)
if (current != language.code) {
MmkvManager.encodeSettings(AppConfig.PREF_LANGUAGE, language.code)
SettingsChangeManager.notifySettingChanged(AppConfig.PREF_LANGUAGE)
}
}
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
private object Api33 {
fun prepareMigration(context: Context) {
if (MmkvManager.decodeSettingsBool(AppConfig.PREF_APP_LOCALE_MIGRATED, false)) {
return
}
val localeManager = context.getSystemService(LocaleManager::class.java)
val applicationLocales = localeManager.applicationLocales
if (!applicationLocales.isEmpty) {
syncLegacyPreference(applicationLocales.get(0)?.toLanguageTag())
return
}
val legacyLanguage = storedLanguage()
if (legacyLanguage != Language.AUTO) {
// Make application and service contexts correct even before the first activity.
localeManager.applicationLocales = android.os.LocaleList(
requireNotNull(legacyLanguage.locale)
)
}
}
fun completeMigration(context: Context) {
val localeManager = context.getSystemService(LocaleManager::class.java)
if (!MmkvManager.decodeSettingsBool(AppConfig.PREF_APP_LOCALE_MIGRATED, false)) {
val frameworkLanguage = Language.fromLanguageTag(
localeManager.applicationLocales.get(0)?.toLanguageTag()
)
val language = frameworkLanguage.takeUnless { it == Language.AUTO }
?: storedLanguage()
// Android's migration guidance requires this one-time AppCompat handoff after
// Activity.onCreate(), including on Android 13 and newer.
AppCompatDelegate.setApplicationLocales(language.toLocaleList())
persistLegacyPreference(language)
MmkvManager.encodeSettings(AppConfig.PREF_APP_LOCALE_MIGRATED, true)
return
}
syncLegacyPreference(localeManager.applicationLocales.get(0)?.toLanguageTag())
}
}
}
@@ -248,7 +248,8 @@ object NotificationManager {
}
}
stat.tag.startsWith(AppConfig.TAG_PROXY) -> {
// Accumulate stats for all proxy outbounds (including custom subscription tags)
stat.tag != AppConfig.TAG_BLOCKED -> {
when (stat.direction) {
AppConfig.UPLINK -> proxyUplink += stat.value
AppConfig.DOWNLINK -> proxyDownlink += stat.value
@@ -19,6 +19,7 @@ object SettingsChangeManager {
AppConfig.PREF_GROUP_ALL_DISPLAY,
AppConfig.PREF_LANGUAGE,
AppConfig.PREF_UI_MODE_NIGHT,
AppConfig.PREF_DYNAMIC_COLOR,
AppConfig.PREF_IS_BOOTED,
)
@@ -16,7 +16,6 @@ import com.v2ray.ang.dto.entities.ProfileItem
import com.v2ray.ang.dto.entities.RulesetItem
import com.v2ray.ang.dto.entities.SubscriptionItem
import com.v2ray.ang.enums.EConfigType
import com.v2ray.ang.enums.Language
import com.v2ray.ang.enums.RoutingType
import com.v2ray.ang.enums.VpnInterfaceAddressConfig
import com.v2ray.ang.extension.moveItem
@@ -31,7 +30,6 @@ import com.v2ray.ang.util.LogUtil
import com.v2ray.ang.util.Utils
import java.io.File
import java.io.FileOutputStream
import java.util.Locale
import kotlin.random.Random
object SettingsManager {
@@ -62,12 +60,11 @@ object SettingsManager {
/**
* Get preset routing rulesets.
* @param context The application context.
* @param index The index of the routing type.
* @param type The routing preset type.
* @return A mutable list of RulesetItem.
*/
private fun getPresetRoutingRulesets(context: Context, index: Int = 0): MutableList<RulesetItem>? {
val fileName = RoutingType.fromIndex(index).fileName
val assets = Utils.readTextFromAssets(context, fileName)
private fun getPresetRoutingRulesets(context: Context, type: RoutingType = RoutingType.WHITE): MutableList<RulesetItem>? {
val assets = Utils.readTextFromAssets(context, type.fileName)
if (TextUtils.isEmpty(assets)) {
return null
}
@@ -78,10 +75,10 @@ object SettingsManager {
/**
* Reset routing rulesets from presets.
* @param context The application context.
* @param index The index of the routing type.
* @param type The routing preset type.
*/
fun resetRoutingRulesetsFromPresets(context: Context, index: Int) {
val rulesetList = getPresetRoutingRulesets(context, index) ?: return
fun resetRoutingRulesetsFromPresets(context: Context, type: RoutingType) {
val rulesetList = getPresetRoutingRulesets(context, type) ?: return
resetRoutingRulesetsCommon(rulesetList)
}
@@ -389,29 +386,6 @@ object SettingsManager {
return value.coerceIn(1, 128)
}
/**
* Get the locale.
* @return The locale.
*/
fun getLocale(): Locale {
val langCode =
MmkvManager.decodeSettingsString(AppConfig.PREF_LANGUAGE) ?: Language.AUTO.code
val language = Language.fromCode(langCode)
return when (language) {
Language.AUTO -> Utils.getSysLocale()
Language.ENGLISH -> Locale.ENGLISH
Language.CHINA -> Locale.CHINA
Language.TRADITIONAL_CHINESE -> Locale.TRADITIONAL_CHINESE
Language.VIETNAMESE -> Locale.forLanguageTag("vi")
Language.RUSSIAN -> Locale.forLanguageTag("ru")
Language.PERSIAN -> Locale.forLanguageTag("fa")
Language.ARABIC -> Locale.forLanguageTag("ar")
Language.BANGLA -> Locale.forLanguageTag("bn")
Language.BAKHTIARI -> Locale.forLanguageTag("bqi-IR")
}
}
/**
* Retrieves the currently selected VPN interface address configuration.
* This method reads the user's preference for VPN interface addressing and returns
@@ -13,6 +13,11 @@ import java.net.UnknownHostException
object SpeedtestManager {
data class RemoteEndpointInfo(
val country: String?,
val ipAddress: String?,
)
/**
* Measures the time taken to establish a TCP connection to a given URL and port.
*
@@ -48,7 +53,7 @@ object SpeedtestManager {
return -1
}
fun getRemoteIPInfo(): String? {
fun getRemoteIPInfo(): RemoteEndpointInfo? {
val url = MmkvManager.decodeSettingsString(AppConfig.PREF_IP_API_URL)
.takeIf { !it.isNullOrBlank() } ?: AppConfig.IP_API_URL
@@ -81,6 +86,9 @@ object SpeedtestManager {
ipInfo.location?.country_code
).firstOrNull { !it.isNullOrBlank() }
return "(${country ?: "unknown"}) ${ip ?: "unknown"}"
return RemoteEndpointInfo(
country = country,
ipAddress = ip,
)
}
}
@@ -77,15 +77,18 @@ object NotificationHelper {
* @param channelType The notification channel type
* @param title The notification title
* @param content The notification content text
* @param action An optional action retained when the notification is updated
*/
fun startForeground(
service: Service,
channelType: NotificationChannelType,
title: String,
content: String
content: String,
action: NotificationCompat.Action? = null
) {
ensureChannelCreated(channelType, service)
val builder = buildNotificationBuilder(channelType, service, title, content)
val builder = buildNotificationBuilder(channelType, service, title, content, action)
builderCache[channelType.notificationId] = builder
service.startForeground(channelType.notificationId, builder.build())
}
@@ -141,7 +144,8 @@ object NotificationHelper {
channelType: NotificationChannelType,
context: Context,
title: String,
content: String
content: String,
action: NotificationCompat.Action? = null
): NotificationCompat.Builder {
val channelId = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
channelType.channelId
@@ -158,5 +162,6 @@ object NotificationHelper {
.setOnlyAlertOnce(true)
.setPriority(NotificationCompat.PRIORITY_LOW)
.setCategory(NotificationCompat.CATEGORY_SERVICE)
.apply { action?.let(::addAction) }
}
}
}
@@ -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)
}
}
@@ -7,10 +7,9 @@ import android.os.IBinder
import com.v2ray.ang.AppConfig
import com.v2ray.ang.contracts.ServiceControl
import com.v2ray.ang.core.CoreServiceManager
import com.v2ray.ang.handler.AppLocaleManager
import com.v2ray.ang.handler.NotificationManager
import com.v2ray.ang.handler.SettingsManager
import com.v2ray.ang.util.LogUtil
import com.v2ray.ang.util.MyContextWrapper
import java.lang.ref.SoftReference
class CoreProxyOnlyService : Service(), ServiceControl {
@@ -34,6 +33,11 @@ class CoreProxyOnlyService : Service(), ServiceControl {
NotificationManager.ensureForeground()
LogUtil.i(AppConfig.TAG, "StartCore-Proxy: Service command received")
if (CoreServiceManager.isRunning()) {
LogUtil.i(AppConfig.TAG, "StartCore-Proxy: Core is already running")
return START_STICKY
}
if (!CoreServiceManager.startCoreLoop(null)) {
LogUtil.e(AppConfig.TAG, "StartCore-Proxy: Failed to start core loop")
stopSelf()
@@ -96,9 +100,7 @@ class CoreProxyOnlyService : Service(), ServiceControl {
* @param newBase The new base context.
*/
override fun attachBaseContext(newBase: Context?) {
val context = newBase?.let {
MyContextWrapper.wrap(newBase, SettingsManager.getLocale())
}
val context = newBase?.let(AppLocaleManager::localizedContext)
super.attachBaseContext(context)
}
}
@@ -7,11 +7,10 @@ import android.os.IBinder
import com.v2ray.ang.AppConfig
import com.v2ray.ang.contracts.ServiceControl
import com.v2ray.ang.core.CoreServiceManager
import com.v2ray.ang.handler.AppLocaleManager
import com.v2ray.ang.handler.NotificationManager
import com.v2ray.ang.handler.SettingsManager
import com.v2ray.ang.root.RootProxyManager
import com.v2ray.ang.util.LogUtil
import com.v2ray.ang.util.MyContextWrapper
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
@@ -43,6 +42,11 @@ class CoreRootService : Service(), ServiceControl {
NotificationManager.ensureForeground()
LogUtil.i(AppConfig.TAG, "StartCore-Root: command received")
if (CoreServiceManager.isRunning()) {
LogUtil.i(AppConfig.TAG, "StartCore-Root: Core is already running")
return START_STICKY
}
// Start the in-process core first (this also posts the foreground notification),
// then install the root routing off the main thread.
if (!CoreServiceManager.startCoreLoop(null)) {
@@ -90,9 +94,7 @@ class CoreRootService : Service(), ServiceControl {
override fun onBind(intent: Intent?): IBinder? = null
override fun attachBaseContext(newBase: Context?) {
val context = newBase?.let {
MyContextWrapper.wrap(newBase, SettingsManager.getLocale())
}
val context = newBase?.let(AppLocaleManager::localizedContext)
super.attachBaseContext(context)
}
}
@@ -1,8 +1,11 @@
package com.v2ray.ang.service
import android.app.PendingIntent
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.IBinder
import androidx.core.app.NotificationCompat
import com.v2ray.ang.AppConfig
import com.v2ray.ang.R
import com.v2ray.ang.core.CoreNativeManager
@@ -11,6 +14,7 @@ import com.v2ray.ang.dto.TestServiceMessage
import com.v2ray.ang.enums.NotificationChannelType
import com.v2ray.ang.extension.serializable
import com.v2ray.ang.handler.AngConfigManager
import com.v2ray.ang.handler.AppLocaleManager
import com.v2ray.ang.handler.MmkvManager
import com.v2ray.ang.helper.MessageHelper
import com.v2ray.ang.helper.NotificationHelper
@@ -19,8 +23,29 @@ import java.util.Collections
class CoreTestService : Service() {
override fun attachBaseContext(newBase: Context?) {
super.attachBaseContext(newBase?.let(AppLocaleManager::localizedContext))
}
// manage active batch workers so each batch is independent and cancellable
private val activeWorkers = Collections.synchronizedList(mutableListOf<RealPingWorkerService>())
private val cancelAction by lazy {
val intent = Intent(this, CoreTestService::class.java).putExtra(
"content",
TestServiceMessage(AppConfig.MSG_MEASURE_CONFIG_CANCEL)
)
val pendingIntent = PendingIntent.getService(
this,
NotificationChannelType.CORE_TEST.notificationId,
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
NotificationCompat.Action.Builder(
R.drawable.ic_stop_24dp,
getString(R.string.action_cancel),
pendingIntent
).build()
}
/**
* Initializes the V2Ray environment.
@@ -64,7 +89,8 @@ class CoreTestService : Service() {
this,
NotificationChannelType.CORE_TEST,
getString(R.string.app_name),
getString(R.string.title_real_ping_all_server)
getString(R.string.title_real_ping_all_server),
cancelAction
)
val message = intent?.serializable<TestServiceMessage>("content")
if (message == null) {
@@ -114,7 +140,7 @@ class CoreTestService : Service() {
channelType = NotificationChannelType.CORE_TEST,
context = this,
title = getString(R.string.app_name),
content = getString(R.string.connection_runing_task_left, event.text)
content = getString(R.string.connection_running_task_left, event.text)
)
MessageHelper.sendMsg2UI(this, AppConfig.MSG_MEASURE_CONFIG_NOTIFY, event.text)
}
@@ -125,7 +151,7 @@ class CoreTestService : Service() {
}
is RealPingEvent.Finish -> {
if(message.subscriptionId.isNotEmpty()){
if (message.subscriptionId.isNotEmpty()) {
if (MmkvManager.decodeSettingsBool(AppConfig.PREF_AUTO_REMOVE_INVALID_AFTER_TEST, false)) {
AngConfigManager.removeInvalidServer(message.subscriptionId)
}
@@ -146,6 +172,7 @@ class CoreTestService : Service() {
}
private fun handleMeasureCancel() {
MessageHelper.sendMsg2UI(this, AppConfig.MSG_MEASURE_CONFIG_FINISH, "0")
LogUtil.i(AppConfig.TAG, "CoreTestService received cancel message, cancelling ${activeWorkers.size} active workers")
val snapshot = ArrayList(activeWorkers)
snapshot.forEach { it.cancel() }
@@ -17,12 +17,12 @@ import com.v2ray.ang.BuildConfig
import com.v2ray.ang.contracts.ServiceControl
import com.v2ray.ang.contracts.Tun2SocksControl
import com.v2ray.ang.core.CoreServiceManager
import com.v2ray.ang.handler.AppLocaleManager
import com.v2ray.ang.handler.MmkvManager
import com.v2ray.ang.handler.NotificationManager
import com.v2ray.ang.handler.SettingsManager
import com.v2ray.ang.root.RootLanSharing
import com.v2ray.ang.util.LogUtil
import com.v2ray.ang.util.MyContextWrapper
import com.v2ray.ang.util.Utils
import java.lang.ref.SoftReference
import java.util.concurrent.atomic.AtomicBoolean
@@ -129,9 +129,7 @@ class CoreVpnService : VpnService(), ServiceControl {
}
override fun attachBaseContext(newBase: Context?) {
val context = newBase?.let {
MyContextWrapper.wrap(newBase, SettingsManager.getLocale())
}
val context = newBase?.let(AppLocaleManager::localizedContext)
super.attachBaseContext(context)
}
@@ -12,6 +12,7 @@ import com.v2ray.ang.AppConfig
import com.v2ray.ang.R
import com.v2ray.ang.core.CoreServiceManager
import com.v2ray.ang.core.LauncherManager
import com.v2ray.ang.handler.AppLocaleManager
import com.v2ray.ang.helper.MessageHelper
import com.v2ray.ang.util.LogUtil
import com.v2ray.ang.util.Utils
@@ -19,6 +20,10 @@ import java.lang.ref.SoftReference
class QSTileService : TileService() {
override fun attachBaseContext(newBase: Context?) {
super.attachBaseContext(newBase?.let(AppLocaleManager::localizedContext))
}
/**
* Sets the state of the tile.
* @param state The state to set.
@@ -15,6 +15,7 @@ import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.isActive
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch
import java.util.concurrent.Executors
@@ -45,13 +46,17 @@ class RealPingWorkerService(
runningCount.incrementAndGet()
try {
val result = if (onlyTcp) startTcping(guid) else startRealPing(guid)
onEvent(RealPingEvent.Result(guid, result))
if (scope.isActive) {
onEvent(RealPingEvent.Result(guid, result))
}
} catch (_: Throwable) {
// ignore
} finally {
val count = totalCount.decrementAndGet()
val left = runningCount.decrementAndGet()
onEvent(RealPingEvent.Progress("$left / $count"))
if (scope.isActive) {
onEvent(RealPingEvent.Progress("$left / $count"))
}
}
}
}
@@ -59,9 +64,11 @@ class RealPingWorkerService(
scope.launch {
try {
joinAll(*jobs.toTypedArray())
onEvent(RealPingEvent.Finish("0"))
if (isActive) {
onEvent(RealPingEvent.Finish("0"))
}
} catch (_: CancellationException) {
onEvent(RealPingEvent.Finish("-1"))
// If cancelled, don't send finish event to avoid confusion
} finally {
close()
}
@@ -13,6 +13,7 @@ import com.v2ray.ang.dto.entities.SubscriptionCache
import com.v2ray.ang.enums.NotificationChannelType
import com.v2ray.ang.extension.serializable
import com.v2ray.ang.handler.AngConfigManager
import com.v2ray.ang.handler.AppLocaleManager
import com.v2ray.ang.handler.MmkvManager
import com.v2ray.ang.helper.NotificationHelper
import com.v2ray.ang.util.LogUtil
@@ -28,6 +29,10 @@ import java.util.concurrent.atomic.AtomicInteger
class SubscriptionUpdateService : Service() {
override fun attachBaseContext(newBase: Context?) {
super.attachBaseContext(newBase?.let(AppLocaleManager::localizedContext))
}
private val serviceJob = Job()
private val serviceScope = CoroutineScope(Dispatchers.IO + serviceJob)
@@ -118,7 +123,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 +189,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 -> {
@@ -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()
val versionText = "v${BuildConfig.VERSION_NAME} ($libVersion)"
val appIdText = BuildConfig.APPLICATION_ID
Scaffold(
@@ -121,7 +122,7 @@ fun AboutScreen(onBackClick: () -> Unit) {
},
confirmButton = {
TextButton(onClick = { showOssDialog = false }) {
Text(stringResource(android.R.string.ok))
Text(stringResource(R.string.action_ok))
}
},
containerColor = MaterialTheme.colorScheme.surface,
@@ -0,0 +1,50 @@
package com.v2ray.ang.ui
/**
* Pure selection operations shared by application-list screens.
*
* Keeping the calculations separate lets bulk actions build one result before it is published.
*/
internal object AppSelection {
fun invert(currentSelection: Set<String>, packageNames: Collection<String>): Set<String> {
return currentSelection.toMutableSet().apply {
packageNames.forEach { packageName ->
if (!add(packageName)) {
remove(packageName)
}
}
}
}
/**
* Builds the selected package set while preserving the legacy list matching behavior.
*
* The full list text is searched for each installed package name. This is intentionally not
* exact line matching; changing that behavior should be handled separately.
*/
fun fromProxyList(
packageNames: Collection<String>,
proxyAppList: String,
bypassApps: Boolean,
forceGoogleApps: Boolean
): Set<String> {
return buildSet(packageNames.size) {
packageNames.forEach { packageName ->
val shouldProxy = shouldProxy(packageName, proxyAppList, forceGoogleApps)
val shouldSelect = if (bypassApps) !shouldProxy else shouldProxy
if (shouldSelect) {
add(packageName)
}
}
}
}
private fun shouldProxy(packageName: String, proxyAppList: String, forceGoogleApps: Boolean): Boolean {
if (forceGoogleApps) {
if (packageName == "com.google.android.webview") return false
if (packageName.startsWith("com.google")) return true
}
return proxyAppList.contains(packageName)
}
}
@@ -69,6 +69,7 @@ import com.v2ray.ang.ui.base.HelperBaseComponentActivity
import com.v2ray.ang.ui.compose.AppTopBar
import com.v2ray.ang.util.LogUtil
import com.v2ray.ang.util.QRCodeDecoder
import java.nio.ByteBuffer
import java.util.concurrent.Executors
import java.util.concurrent.atomic.AtomicBoolean
import android.util.Size as TargetSize
@@ -178,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) {
@@ -193,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)
)
}
}
@@ -244,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
)
@@ -410,15 +416,14 @@ private fun processImageProxy(
return
}
try {
val buffer = imageProxy.planes[0].buffer
val bytes = ByteArray(buffer.remaining())
buffer.get(bytes)
val width = imageProxy.width
val height = imageProxy.height
val source = PlanarYUVLuminanceSource(
bytes, width, height,
0, 0, width, height,
false
val yPlane = imageProxy.planes[0]
val source = createYPlaneLuminanceSource(
buffer = yPlane.buffer,
width = width,
height = height,
rowStride = yPlane.rowStride,
)
val binaryBitmap = BinaryBitmap(HybridBinarizer(source))
val hints = mapOf(
@@ -437,3 +442,26 @@ private fun processImageProxy(
imageProxy.close()
}
}
internal fun createYPlaneLuminanceSource(
buffer: ByteBuffer,
width: Int,
height: Int,
rowStride: Int,
): PlanarYUVLuminanceSource {
val bufferCopy = buffer.duplicate()
val bytes = ByteArray(bufferCopy.remaining())
bufferCopy.get(bytes)
// Camera HALs may pad each Y row. ZXing advances rows by dataWidth, so the
// reported row stride must be used instead of the visible image width.
return PlanarYUVLuminanceSource(
bytes,
rowStride,
height,
0,
0,
width,
height,
false,
)
}
@@ -4,6 +4,7 @@ import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.activity.viewModels
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
@@ -11,14 +12,11 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.ScaffoldDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
@@ -33,11 +31,17 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.v2ray.ang.R
import com.v2ray.ang.dto.AppInfo
import com.v2ray.ang.ui.base.BaseComponentActivity
import com.v2ray.ang.ui.compose.AppDropdownMenuItems
import com.v2ray.ang.ui.compose.AppListItem
import com.v2ray.ang.ui.compose.AppTopBar
import com.v2ray.ang.ui.compose.ItemDivider
import com.v2ray.ang.ui.compose.verticalScrollbar
private enum class AppPickerMenuAction(@StringRes val labelRes: Int) {
SelectAll(R.string.menu_item_select_all),
InvertSelection(R.string.menu_item_invert_selection)
}
class AppPickerActivity : BaseComponentActivity() {
companion object {
@@ -101,7 +105,6 @@ class AppPickerActivity : BaseComponentActivity() {
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppPickerScreen(
title: String,
@@ -119,7 +122,7 @@ fun AppPickerScreen(
var showMenu by remember { mutableStateOf(false) }
val listState = rememberLazyListState()
LaunchedEffect(searchQuery) {
LaunchedEffect(Unit) {
onSearch(searchQuery)
}
@@ -134,9 +137,11 @@ fun AppPickerScreen(
searchQuery = searchQuery,
onSearchQueryChange = { query ->
searchQuery = query
onSearch(query)
},
onSearchClose = {
searchQuery = ""
onSearch("")
showSearch = false
},
searchPlaceholder = stringResource(R.string.menu_item_search),
@@ -145,7 +150,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)
)
}
}
@@ -161,14 +166,13 @@ fun AppPickerScreen(
onDismissRequest = { showMenu = false },
containerColor = MaterialTheme.colorScheme.surface
) {
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_item_select_all)) },
onClick = { showMenu = false; onSelectAll() }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_item_invert_selection)) },
onClick = { showMenu = false; onInvertSelection() }
)
AppDropdownMenuItems(AppPickerMenuAction.entries, { it.labelRes }) { action ->
showMenu = false
when (action) {
AppPickerMenuAction.SelectAll -> onSelectAll()
AppPickerMenuAction.InvertSelection -> onInvertSelection()
}
}
}
}
}
@@ -187,7 +191,7 @@ fun AppPickerScreen(
AppListItem(
appName = app.appName,
packageName = app.packageName,
icon = app.appIcon,
icon = null,
checked = checked,
onCheckedChange = { onToggleApp(app.packageName) }
)
@@ -5,6 +5,7 @@ import android.content.Context
import com.v2ray.ang.AppConfig
import com.v2ray.ang.R
import com.v2ray.ang.dto.AppInfo
import com.v2ray.ang.ui.AppSelection
import com.v2ray.ang.ui.base.BaseViewModel
import com.v2ray.ang.util.AppManagerUtil
import com.v2ray.ang.util.LogUtil
@@ -40,16 +41,30 @@ class AppPickerViewModel(application: Application) : BaseViewModel(application)
}
fun loadApps(context: Context) {
if (allApps != null || isAppListLoading) return
allApps?.let { apps ->
val localizedUnknownApp = getString(R.string.app_picker_unknown_app)
val updatedApps = apps.map { appInfo ->
if (appInfo.packageName == AppConfig.UNIDENTIFIED_PACKAGE) {
appInfo.copy(appName = localizedUnknownApp)
} else {
appInfo
}
}
allApps = sortApps(updatedApps)
_displayedApps.value = applyFilter(currentQuery)
return
}
if (isAppListLoading) return
val applicationContext = context.applicationContext
val localizedUnknownApp = getString(R.string.app_picker_unknown_app)
isAppListLoading = true
launchLoading {
try {
selectedSnapshot = _selectedPackages.value
val apps = withContext(Dispatchers.IO) {
val list = AppManagerUtil.loadNetworkAppList(applicationContext)
val special = createSpecialItemUnidentified(applicationContext)
val special = createSpecialItemUnidentified(localizedUnknownApp)
sortApps(list + special)
}
allApps = apps
@@ -80,15 +95,17 @@ class AppPickerViewModel(application: Application) : BaseViewModel(application)
}
fun selectAll() {
val displayedPackages = _displayedApps.value.map { it.packageName }.toSet()
_selectedPackages.value = _selectedPackages.value + displayedPackages
val displayedApps = _displayedApps.value
val currentSelection = _selectedPackages.value
_selectedPackages.value = buildSet(currentSelection.size + displayedApps.size) {
addAll(currentSelection)
displayedApps.forEach { add(it.packageName) }
}
}
fun invertSelection() {
val current = _selectedPackages.value
val displayedPackages = _displayedApps.value.map { it.packageName }.toSet()
_selectedPackages.value = (current - displayedPackages) +
(displayedPackages - current)
val packageNames = _displayedApps.value.map { it.packageName }
_selectedPackages.value = AppSelection.invert(_selectedPackages.value, packageNames)
}
fun getSelectedPackages(): List<String> = _selectedPackages.value.sorted()
@@ -97,9 +114,9 @@ class AppPickerViewModel(application: Application) : BaseViewModel(application)
val apps = allApps ?: return emptyList()
if (query.isBlank()) return apps
val key = query.uppercase()
return apps.filter {
it.appName.uppercase().contains(key) || it.packageName.uppercase().contains(key)
it.appName.contains(query, ignoreCase = true) ||
it.packageName.contains(query, ignoreCase = true)
}
}
@@ -119,14 +136,10 @@ class AppPickerViewModel(application: Application) : BaseViewModel(application)
}
}
private fun createSpecialItemUnidentified(context: Context): AppInfo {
val icon = context.getDrawable(android.R.drawable.ic_menu_help)
?: context.getDrawable(android.R.drawable.sym_def_app_icon)
?: error("No fallback drawable available")
private fun createSpecialItemUnidentified(appName: String): AppInfo {
return AppInfo(
appName = context.getString(R.string.app_picker_unknown_app),
appName = appName,
packageName = AppConfig.UNIDENTIFIED_PACKAGE,
appIcon = icon,
isSystemApp = false,
isSelected = 0
)
@@ -4,6 +4,7 @@ import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.activity.viewModels
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
@@ -48,14 +49,15 @@ import java.io.File
import java.text.SimpleDateFormat
import java.util.Locale
enum class BackupLocation(@StringRes val labelRes: Int) {
Local(R.string.backup_location_local),
WebDav(R.string.backup_location_webdav)
}
class BackupActivity : HelperBaseComponentActivity() {
private val viewModel: BackupViewModel by viewModels()
private val configBackupOptions: Array<out String> by lazy {
resources.getStringArray(R.array.config_backup_options)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
observeViewModel()
@@ -90,19 +92,17 @@ class BackupActivity : HelperBaseComponentActivity() {
BackupScreen(
isLoadingState = viewModel.isLoading,
webDavConfigState = viewModel.webDavConfig,
backupOptions = configBackupOptions.toList(),
onBackupOptionSelected = { which ->
when (which) {
0 -> backupViaLocal()
1 -> viewModel.backupViaWebDav(cacheDir, getString(R.string.app_name))
onBackupOptionSelected = { location ->
when (location) {
BackupLocation.Local -> backupViaLocal()
BackupLocation.WebDav -> viewModel.backupViaWebDav(cacheDir, getString(R.string.app_name))
}
},
onShareClick = { viewModel.shareBackup(cacheDir, getString(R.string.app_name)) },
restoreOptions = configBackupOptions.toList(),
onRestoreOptionSelected = { which ->
when (which) {
0 -> restoreViaLocal()
1 -> viewModel.restoreViaWebDav(cacheDir)
onRestoreOptionSelected = { location ->
when (location) {
BackupLocation.Local -> restoreViaLocal()
BackupLocation.WebDav -> viewModel.restoreViaWebDav(cacheDir)
}
},
onWebDavSave = { config -> viewModel.saveWebDavConfig(config) },
@@ -183,11 +183,9 @@ class BackupActivity : HelperBaseComponentActivity() {
fun BackupScreen(
isLoadingState: StateFlow<Boolean>,
webDavConfigState: StateFlow<WebDavConfig?>,
backupOptions: List<String>,
onBackupOptionSelected: (Int) -> Unit,
onBackupOptionSelected: (BackupLocation) -> Unit,
onShareClick: () -> Unit,
restoreOptions: List<String>,
onRestoreOptionSelected: (Int) -> Unit,
onRestoreOptionSelected: (BackupLocation) -> Unit,
onWebDavSave: (WebDavConfig) -> Unit,
onBackClick: () -> Unit
) {
@@ -243,10 +241,11 @@ fun BackupScreen(
if (showBackupDialog) {
SelectListDialog(
title = stringResource(R.string.title_configuration_backup),
options = backupOptions,
onSelected = { index, _ ->
options = BackupLocation.entries,
optionText = { stringResource(it.labelRes) },
onSelected = { location ->
showBackupDialog = false
onBackupOptionSelected(index)
onBackupOptionSelected(location)
},
onDismiss = { showBackupDialog = false }
)
@@ -254,10 +253,11 @@ fun BackupScreen(
if (showRestoreDialog) {
SelectListDialog(
title = stringResource(R.string.title_configuration_restore),
options = restoreOptions,
onSelected = { index, _ ->
options = BackupLocation.entries,
optionText = { stringResource(it.labelRes) },
onSelected = { location ->
showRestoreDialog = false
onRestoreOptionSelected(index)
onRestoreOptionSelected(location)
},
onDismiss = { showRestoreDialog = false }
)
@@ -317,7 +317,7 @@ private fun WebDavInputDialog(
}
},
confirmText = stringResource(R.string.menu_item_save_config),
dismissText = stringResource(android.R.string.cancel),
dismissText = stringResource(R.string.action_cancel),
onConfirm = {
onSave(
WebDavConfig(
@@ -1,23 +1,18 @@
package com.v2ray.ang.ui.base
import android.content.Context
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.runtime.Composable
import com.v2ray.ang.handler.SettingsManager
import com.v2ray.ang.handler.AppLocaleManager
import com.v2ray.ang.ui.compose.AppTheme
import com.v2ray.ang.util.MyContextWrapper
abstract class BaseComponentActivity : ComponentActivity() {
override fun attachBaseContext(newBase: Context?) {
super.attachBaseContext(MyContextWrapper.wrap(newBase ?: return, SettingsManager.getLocale()))
}
abstract class BaseComponentActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AppLocaleManager.onActivityCreated(this)
enableEdgeToEdge()
setContent {
AppTheme {
@@ -1,12 +1,14 @@
package com.v2ray.ang.ui.base
import android.app.Application
import android.content.Context
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import com.v2ray.ang.AngApplication
import com.v2ray.ang.extension.toast
import com.v2ray.ang.extension.toastError
import com.v2ray.ang.extension.toastSuccess
import com.v2ray.ang.handler.AppLocaleManager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.MutableStateFlow
@@ -27,6 +29,9 @@ abstract class BaseViewModel(application: Application) : AndroidViewModel(applic
application as AngApplication
}
protected val localizedContext: Context
get() = AppLocaleManager.localizedContext(app)
@Suppress("PropertyName")
protected val _isLoading = MutableStateFlow(false)
val isLoading: StateFlow<Boolean> = _isLoading.asStateFlow()
@@ -39,7 +44,7 @@ abstract class BaseViewModel(application: Application) : AndroidViewModel(applic
* Send neutral toast event (Resource ID).
*/
fun toast(resId: Int) {
app.toast(resId)
localizedContext.toast(resId)
}
/**
@@ -53,7 +58,7 @@ abstract class BaseViewModel(application: Application) : AndroidViewModel(applic
* Send success toast event (Resource ID).
*/
fun toastSuccess(resId: Int) {
app.toastSuccess(resId)
localizedContext.toastSuccess(resId)
}
/**
@@ -67,7 +72,7 @@ abstract class BaseViewModel(application: Application) : AndroidViewModel(applic
* Send error toast event (Resource ID).
*/
fun toastError(resId: Int) {
app.toastError(resId)
localizedContext.toastError(resId)
}
/**
@@ -81,14 +86,14 @@ abstract class BaseViewModel(application: Application) : AndroidViewModel(applic
* Get string from resource ID.
*/
fun getString(resId: Int): String {
return app.getString(resId)
return localizedContext.getString(resId)
}
/**
* Get formatted string from resource ID.
*/
fun getString(resId: Int, vararg formatArgs: Any?): String {
return app.getString(resId, *formatArgs)
return localizedContext.getString(resId, *formatArgs)
}
/**
@@ -113,4 +118,4 @@ abstract class BaseViewModel(application: Application) : AndroidViewModel(applic
}
}
}
}
}
@@ -4,6 +4,7 @@ import android.os.Bundle
import androidx.activity.viewModels
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
@@ -14,7 +15,6 @@ import androidx.compose.material3.ScaffoldDefaults
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
@@ -29,6 +29,7 @@ import com.v2ray.ang.ui.compose.AppTopBar
import com.v2ray.ang.ui.compose.SettingsMenuItem
import com.v2ray.ang.ui.compose.SettingsSwitchItem
import com.v2ray.ang.ui.compose.VersionInfoBlock
import com.v2ray.ang.ui.compose.verticalScrollbar
import com.v2ray.ang.util.Utils
class CheckUpdateActivity : BaseComponentActivity() {
@@ -37,6 +38,9 @@ class CheckUpdateActivity : BaseComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState == null) {
viewModel.checkForUpdates()
}
}
@Composable
@@ -57,11 +61,8 @@ fun CheckUpdateScreen(
val showUpdateDialog by viewModel.showUpdateDialog.collectAsStateWithLifecycle()
val updateResult by viewModel.updateResult.collectAsStateWithLifecycle()
val versionText = "v${BuildConfig.VERSION_NAME} (${CoreNativeManager.getLibVersion()})"
LaunchedEffect(Unit) {
viewModel.checkForUpdates()
}
val libVersion = CoreNativeManager.getLibVersion()
val versionText = "v${BuildConfig.VERSION_NAME} ($libVersion)"
Scaffold(
contentWindowInsets = ScaffoldDefaults.contentWindowInsets,
@@ -99,7 +100,16 @@ fun CheckUpdateScreen(
AlertDialog(
onDismissRequest = { viewModel.dismissUpdateDialog() },
title = { Text(stringResource(R.string.update_new_version_found, result.latestVersion ?: "")) },
text = { Text(result.releaseNotes ?: "") },
text = {
val scrollState = rememberScrollState()
Text(
text = result.releaseNotes.orEmpty(),
modifier = Modifier
.fillMaxWidth()
.verticalScroll(scrollState)
.verticalScrollbar(scrollState)
)
},
confirmButton = {
TextButton(onClick = {
viewModel.dismissUpdateDialog()
@@ -110,7 +120,7 @@ fun CheckUpdateScreen(
},
dismissButton = {
TextButton(onClick = { viewModel.dismissUpdateDialog() }) {
Text(stringResource(android.R.string.cancel))
Text(stringResource(R.string.action_cancel))
}
},
containerColor = MaterialTheme.colorScheme.surface
@@ -42,12 +42,8 @@ class CheckUpdateViewModel(application: Application) : BaseViewModel(application
toastSuccess(R.string.update_already_latest_version)
}
} catch (e: Exception) {
LogUtil.e(AppConfig.TAG, "Failed to check for updates: ${e.message}")
if (e.message == null) {
toastError(R.string.toast_failure)
} else {
toastError(e.message.orEmpty())
}
LogUtil.e(AppConfig.TAG, "Failed to check for updates", e)
toastError(R.string.toast_failure)
}
}
}
@@ -55,4 +51,4 @@ class CheckUpdateViewModel(application: Application) : BaseViewModel(application
fun dismissUpdateDialog() {
_showUpdateDialog.value = false
}
}
}
@@ -1,16 +1,10 @@
package com.v2ray.ang.ui.compose
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.expandVertically
import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
@@ -45,17 +39,21 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
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
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import coil.compose.AsyncImage
import coil.request.ImageRequest
import com.v2ray.ang.R
import com.v2ray.ang.util.AppIconFetcher
import sh.calvin.reorderable.ReorderableCollectionItemScope
@OptIn(ExperimentalMaterial3Api::class)
@@ -92,7 +90,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)
)
}
}
@@ -110,7 +108,7 @@ fun AppTopBar(
enter = expandVertically(),
exit = shrinkVertically()
) {
LinearProgressIndicator(modifier = Modifier.fillMaxWidth(), color = colorFabActive)
LinearProgressIndicator(modifier = Modifier.fillMaxWidth(), color = MaterialTheme.colorScheme.secondary)
}
}
}
@@ -163,6 +161,7 @@ fun AppListItem(
onCheckedChange: (Boolean) -> Unit,
modifier: Modifier = Modifier
) {
val context = LocalContext.current
Row(
modifier = modifier
.fillMaxWidth()
@@ -170,41 +169,26 @@ fun AppListItem(
.padding(horizontal = 16.dp, vertical = 12.dp),
verticalAlignment = Alignment.CenterVertically
) {
if (icon != null) {
when (icon) {
is Bitmap -> {
Image(
bitmap = icon.asImageBitmap(),
contentDescription = null,
modifier = Modifier.size(40.dp),
contentScale = ContentScale.Fit
)
}
is Int -> {
Image(
painter = painterResource(id = icon),
contentDescription = null,
modifier = Modifier.size(40.dp),
contentScale = ContentScale.Fit
)
}
is Drawable -> {
val bitmap = remember(icon) { createBitmapFromDrawable(icon) }
Image(
bitmap = bitmap.asImageBitmap(),
contentDescription = null,
modifier = Modifier.size(40.dp),
contentScale = ContentScale.Fit
)
}
else -> {
Box(modifier = Modifier.size(40.dp))
}
val model = remember(icon, packageName) {
if (icon != null) {
icon
} else {
val data = "appicon:$packageName"
ImageRequest.Builder(context)
.data(data)
.fetcherFactory(AppIconFetcher.Factory(context))
.build()
}
}
AsyncImage(
model = model,
contentDescription = null,
modifier = Modifier.size(40.dp),
contentScale = ContentScale.Fit,
error = painterResource(R.drawable.ic_image_24dp),
fallback = painterResource(R.drawable.ic_image_24dp)
)
Spacer(modifier = Modifier.width(16.dp))
Column(modifier = Modifier.weight(1f)) {
Text(
@@ -225,24 +209,11 @@ fun AppListItem(
Checkbox(
checked = checked,
onCheckedChange = onCheckedChange,
colors = CheckboxDefaults.colors(checkedColor = colorFabActive)
colors = CheckboxDefaults.colors(checkedColor = MaterialTheme.colorScheme.secondary)
)
}
}
private fun createBitmapFromDrawable(drawable: Drawable): Bitmap {
if (drawable is BitmapDrawable) {
return drawable.bitmap
}
val width = drawable.intrinsicWidth.takeIf { it > 0 } ?: 96
val height = drawable.intrinsicHeight.takeIf { it > 0 } ?: 96
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
drawable.setBounds(0, 0, canvas.width, canvas.height)
drawable.draw(canvas)
return bitmap
}
@Composable
fun ItemDivider() {
AppDivider(modifier = Modifier.padding(horizontal = 12.dp))
@@ -13,7 +13,8 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.selection.selectable
import androidx.compose.foundation.text.selection.TextSelectionColors
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Icon
@@ -34,6 +35,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.dp
import com.v2ray.ang.R
@@ -42,8 +44,8 @@ import com.v2ray.ang.R
fun ConfirmDialog(
title: String? = null,
message: String,
confirmText: String = stringResource(android.R.string.ok),
dismissText: String? = stringResource(android.R.string.cancel),
confirmText: String = stringResource(R.string.action_ok),
dismissText: String? = stringResource(R.string.action_cancel),
confirmIcon: @Composable (() -> Unit)? = null,
onConfirm: () -> Unit,
onDismiss: () -> Unit
@@ -173,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)
@@ -192,44 +194,46 @@ fun QRCodeDialog(
* The selectedOption parameter is used to highlight the selected item only when showRadio is true.
*/
@Composable
fun SelectListDialog(
title: String? = null,
options: List<String>,
selectedOption: String = "",
onSelected: (Int, String) -> Unit,
fun <T> SelectListDialog(
options: List<T>,
optionText: @Composable (T) -> String,
onSelected: (T) -> Unit,
onDismiss: () -> Unit,
title: String? = null,
selectedOption: T? = null,
showRadio: Boolean = false
) {
val selectedIndex = if (showRadio) options.indexOf(selectedOption) else -1
AlertDialog(
onDismissRequest = onDismiss,
title = title?.let { { Text(it) } },
text = {
LazyColumn {
itemsIndexed(options) { index, option ->
items(options) { option ->
val isSelected = option == selectedOption
Row(
modifier = Modifier
.fillMaxWidth()
.clickable { onSelected(index, option) }
.padding(vertical = 4.dp),
.then(
if (showRadio) Modifier.selectable(
selected = isSelected,
onClick = { onSelected(option) },
role = Role.RadioButton
) else Modifier.clickable { onSelected(option) }
)
.padding(vertical = 12.dp, horizontal = 4.dp),
verticalAlignment = Alignment.CenterVertically
) {
if (showRadio) {
RadioButton(
selected = index == selectedIndex,
onClick = { onSelected(index, option) }
selected = isSelected,
onClick = null
)
Spacer(modifier = Modifier.width(8.dp))
}
Text(
text = option,
text = optionText(option),
style = MaterialTheme.typography.bodyMedium,
modifier = if (!showRadio)
Modifier
.fillMaxWidth()
.padding(vertical = 8.dp, horizontal = 4.dp)
else Modifier
modifier = Modifier.weight(1f)
)
}
}
@@ -238,7 +242,7 @@ fun SelectListDialog(
confirmButton = {},
dismissButton = {
TextButton(onClick = onDismiss) {
Text(stringResource(android.R.string.cancel))
Text(stringResource(R.string.action_cancel))
}
},
containerColor = MaterialTheme.colorScheme.surface
@@ -78,6 +78,7 @@ fun FormDropdownField(
editable: Boolean = false,
enabled: Boolean = true,
placeholder: String? = null,
supportingText: String? = null,
) {
var expanded by rememberSaveable { mutableStateOf(false) }
val menuScrollState = rememberScrollState()
@@ -104,6 +105,7 @@ fun FormDropdownField(
enabled = enabled,
label = { Text(label) },
placeholder = { if (placeholder != null) Text(placeholder) },
supportingText = supportingText?.let { { Text(it) } },
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
colors = OutlinedTextFieldDefaults.colors(
focusedContainerColor = Color.Transparent,
@@ -0,0 +1,20 @@
package com.v2ray.ang.ui.compose
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
@Composable
fun <T> AppDropdownMenuItems(
items: List<T>,
labelRes: (T) -> Int,
onSelected: (T) -> Unit
) {
items.forEach { item ->
DropdownMenuItem(
text = { Text(stringResource(labelRes(item))) },
onClick = { onSelected(item) }
)
}
}
@@ -35,7 +35,7 @@ fun PreferenceGroupHeader(title: String, modifier: Modifier = Modifier) {
Text(
text = title,
style = MaterialTheme.typography.titleSmall,
color = colorFabActive,
color = MaterialTheme.colorScheme.secondary,
modifier = modifier
.fillMaxWidth()
.padding(start = 16.dp, end = 16.dp, top = 16.dp, bottom = 8.dp)
@@ -59,13 +59,13 @@ fun CollapsiblePreferenceGroupHeader(
Text(
text = title,
style = MaterialTheme.typography.titleSmall,
color = colorFabActive,
color = MaterialTheme.colorScheme.secondary,
modifier = Modifier.weight(1f)
)
Icon(
painter = painterResource(R.drawable.ic_expand_more_24dp),
contentDescription = null,
tint = colorFabActive,
tint = MaterialTheme.colorScheme.secondary,
modifier = Modifier
.size(24.dp)
.rotate(if (expanded) 180f else 0f)
@@ -164,8 +164,8 @@ fun SettingsEditItem(
)
),
onFieldChange = { _, v -> text = v },
confirmText = stringResource(android.R.string.ok),
dismissText = stringResource(android.R.string.cancel),
confirmText = stringResource(R.string.action_ok),
dismissText = stringResource(R.string.action_cancel),
onConfirm = { showDialog = false; onValueChanged(text) },
onDismiss = { showDialog = false }
)
@@ -184,8 +184,9 @@ fun SettingsListItem(
enabled: Boolean = true
) {
var showDialog by remember { mutableStateOf(false) }
val selectedIndex = values.indexOf(selectedValue).let { if (it >= 0) it else 0 }
val summary = entries.getOrNull(selectedIndex).orEmpty()
val options = entries.zip(values)
val selectedOption = options.find { it.second == selectedValue } ?: options.firstOrNull()
val summary = selectedOption?.first.orEmpty()
SettingsItemRow(
icon = icon,
@@ -201,11 +202,12 @@ fun SettingsListItem(
if (showDialog) {
SelectListDialog(
title = title,
options = entries,
selectedOption = summary,
onSelected = { index, _ ->
options = options,
optionText = { it.first },
selectedOption = selectedOption,
onSelected = { option ->
showDialog = false
values.getOrNull(index)?.let(onSelected)
onSelected(option.second)
},
onDismiss = { showDialog = false },
showRadio = true
@@ -1,11 +1,14 @@
package com.v2ray.ang.ui.compose
import android.app.Activity
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
@@ -15,6 +18,7 @@ import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.core.view.WindowCompat
import com.v2ray.ang.AppConfig
@@ -122,14 +126,26 @@ object ThemeManager {
)
val themeMode: StateFlow<String> = _themeMode.asStateFlow()
private val _dynamicColorEnabled = MutableStateFlow(
MmkvManager.decodeSettingsBool(AppConfig.PREF_DYNAMIC_COLOR, true)
)
val dynamicColorEnabled: StateFlow<Boolean> = _dynamicColorEnabled.asStateFlow()
fun setThemeMode(mode: String) {
MmkvManager.encodeSettings(AppConfig.PREF_UI_MODE_NIGHT, mode)
_themeMode.value = mode
}
fun setDynamicColorEnabled(enabled: Boolean) {
MmkvManager.encodeSettings(AppConfig.PREF_DYNAMIC_COLOR, enabled)
_dynamicColorEnabled.value = enabled
}
fun refresh() {
_themeMode.value =
MmkvManager.decodeSettingsString(AppConfig.PREF_UI_MODE_NIGHT, "0") ?: "0"
_dynamicColorEnabled.value =
MmkvManager.decodeSettingsBool(AppConfig.PREF_DYNAMIC_COLOR, true)
}
}
@@ -150,7 +166,16 @@ fun AppTheme(
darkTheme: Boolean = resolveDarkTheme(),
content: @Composable () -> Unit
) {
val colorScheme = if (darkTheme) DarkColor else LightColor
val dynamicColor by ThemeManager.dynamicColorEnabled.collectAsState()
val context = LocalContext.current
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColor
else -> LightColor
}
val snackbarController = rememberAppSnackbarController()
val view = LocalView.current
@@ -37,12 +37,14 @@ import androidx.compose.ui.unit.dp
import androidx.core.content.FileProvider
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import com.v2ray.ang.AppConfig
import com.v2ray.ang.R
import com.v2ray.ang.extension.toast
import com.v2ray.ang.extension.toastError
import com.v2ray.ang.ui.base.BaseComponentActivity
import com.v2ray.ang.ui.compose.AppTopBar
import com.v2ray.ang.ui.compose.ItemDivider
import com.v2ray.ang.ui.compose.verticalScrollbar
import com.v2ray.ang.util.LogUtil
import com.v2ray.ang.util.Utils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -91,8 +93,9 @@ class LogcatActivity : BaseComponentActivity() {
uri to logFile.name
} catch (e: Exception) {
LogUtil.e(AppConfig.TAG, "Failed to share Logcat", e)
withContext(Dispatchers.Main) {
toast(e.localizedMessage ?: e.toString())
toastError(R.string.toast_failure)
}
return@launch
}
@@ -159,20 +162,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 +183,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 +195,7 @@ fun LogcatScreen(
}) {
Icon(
painterResource(R.drawable.ic_restore_24dp),
contentDescription = stringResource(R.string.pull_down_to_refresh)
contentDescription = stringResource(R.string.acc_refresh)
)
}
}
@@ -5,6 +5,7 @@ import android.net.VpnService
import android.os.Build
import android.os.Bundle
import android.view.KeyEvent
import androidx.activity.compose.BackHandler
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.compose.runtime.Composable
@@ -98,6 +99,7 @@ class MainActivity : HelperBaseComponentActivity() {
@Composable
override fun ScreenContent() {
BackHandler { moveTaskToBack(false) }
MainScreen(
mainViewModel = mainViewModel,
onAction = { action ->
@@ -134,26 +136,24 @@ class MainActivity : HelperBaseComponentActivity() {
}
}
private fun navigateTo(destination: String) {
private fun navigateTo(destination: MainDestination) {
val intent = when (destination) {
"sub_setting" -> Intent(this, SubSettingActivity::class.java)
"per_app_proxy" -> Intent(this, PerAppProxyActivity::class.java)
"routing_setting" -> Intent(this, RoutingSettingActivity::class.java)
"user_asset" -> Intent(this, UserAssetActivity::class.java)
"settings" -> Intent(this, SettingsActivity::class.java)
"logcat" -> Intent(this, LogcatActivity::class.java)
"check_update" -> Intent(this, CheckUpdateActivity::class.java)
"backup_restore" -> Intent(this, BackupActivity::class.java)
"about" -> Intent(this, AboutActivity::class.java)
"promotion" -> {
MainDestination.Subscriptions -> Intent(this, SubSettingActivity::class.java)
MainDestination.PerAppProxy -> Intent(this, PerAppProxyActivity::class.java)
MainDestination.Routing -> Intent(this, RoutingSettingActivity::class.java)
MainDestination.UserAssets -> Intent(this, UserAssetActivity::class.java)
MainDestination.Settings -> Intent(this, SettingsActivity::class.java)
MainDestination.Logcat -> Intent(this, LogcatActivity::class.java)
MainDestination.CheckUpdate -> Intent(this, CheckUpdateActivity::class.java)
MainDestination.BackupRestore -> Intent(this, BackupActivity::class.java)
MainDestination.About -> Intent(this, AboutActivity::class.java)
MainDestination.Promotion -> {
Utils.openUri(
this,
"${Utils.decode(AppConfig.APP_PROMOTION_URL)}?t=${System.currentTimeMillis()}"
)
return
}
else -> return
}
settingsActivityLauncher.launch(intent)
}
@@ -280,7 +280,7 @@ class MainActivity : HelperBaseComponentActivity() {
}
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_BUTTON_B) {
if (keyCode == KeyEvent.KEYCODE_BUTTON_B) {
moveTaskToBack(false)
return true
}
@@ -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)
)
@@ -1,8 +1,18 @@
package com.v2ray.ang.ui.main
import com.v2ray.ang.dto.ConnectionTestResult
import com.v2ray.ang.dto.GroupMapItem
import com.v2ray.ang.dto.LocateTarget
/** Locale-neutral state formatted only when it reaches the main UI. */
sealed interface MainStatus {
data object Disconnected : MainStatus
data object Connected : MainStatus
data object Testing : MainStatus
data class TestProgress(val progress: String) : MainStatus
data class ConnectionTest(val result: ConnectionTestResult) : MainStatus
}
/**
* Main UI state
*/
@@ -12,7 +22,7 @@ data class MainUiState(
val selectedGuid: String? = null,
val isRunning: Boolean = false,
val isTesting: Boolean = false,
val statusText: String = "",
val status: MainStatus = MainStatus.Disconnected,
val locateTarget: LocateTarget? = null,
val confirmRemove: Boolean = false,
val doubleColumnDisplay: Boolean = false,
@@ -1,62 +1,86 @@
package com.v2ray.ang.ui.main
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.DrawerState
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalDrawerSheet
import androidx.compose.material3.NavigationDrawerItem
import androidx.compose.material3.NavigationDrawerItemDefaults
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.v2ray.ang.R
import com.v2ray.ang.ui.compose.AppDivider
import com.v2ray.ang.ui.compose.LocalDarkTheme
import com.v2ray.ang.ui.compose.verticalScrollbar
enum class MainDestination(@DrawableRes val iconRes: Int, @StringRes val labelRes: Int) {
Subscriptions(R.drawable.ic_subscriptions_24dp, R.string.title_sub_setting),
PerAppProxy(R.drawable.ic_per_apps_24dp, R.string.per_app_proxy_settings),
Routing(R.drawable.ic_routing_24dp, R.string.routing_settings_title),
UserAssets(R.drawable.ic_file_24dp, R.string.title_user_asset_setting),
Settings(R.drawable.ic_settings_24dp, R.string.title_settings),
Promotion(R.drawable.ic_promotion_24dp, R.string.title_pref_promotion),
Logcat(R.drawable.ic_logcat_24dp, R.string.title_logcat),
CheckUpdate(R.drawable.ic_check_update_24dp, R.string.update_check_for_update),
BackupRestore(R.drawable.ic_restore_24dp, R.string.title_configuration_backup_restore),
About(R.drawable.ic_about_24dp, R.string.title_about)
}
private val primaryDrawerItems = listOf(
MainDestination.Subscriptions,
MainDestination.PerAppProxy,
MainDestination.Routing,
MainDestination.UserAssets,
MainDestination.Settings
)
private val drawerItems = primaryDrawerItems + listOf(
MainDestination.Promotion,
MainDestination.Logcat,
MainDestination.CheckUpdate,
MainDestination.BackupRestore,
MainDestination.About
)
@Composable
fun MainDrawerContent(onNavigate: (String) -> Unit) {
fun MainDrawerContent(drawerState: DrawerState, onNavigate: (MainDestination) -> Unit) {
val drawerScrollState = rememberScrollState()
ModalDrawerSheet(
modifier = Modifier
.fillMaxWidth(0.75f)
.navigationBarsPadding(),
drawerState = drawerState,
modifier = Modifier.fillMaxWidth(0.75f),
drawerContainerColor = MaterialTheme.colorScheme.surface
) {
Column(
modifier = Modifier
.verticalScroll(drawerScrollState)
.verticalScrollbar(drawerScrollState)
.padding(bottom = 80.dp)
) {
Surface(
modifier = Modifier
.fillMaxWidth()
.height(160.dp)
.height(180.dp)
) {
Column(
modifier = Modifier
@@ -65,92 +89,34 @@ fun MainDrawerContent(onNavigate: (String) -> Unit) {
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
val isDarkTheme = LocalDarkTheme.current
Image(
painter = painterResource(R.mipmap.ic_launcher_foreground),
contentDescription = null,
modifier = Modifier.size(120.dp),
colorFilter = if (isDarkTheme) {
ColorFilter.tint(Color.White, BlendMode.SrcIn)
} else {
null
}
)
Text(
text = stringResource(R.string.app_name),
style = MaterialTheme.typography.headlineLarge.copy(
fontFamily = FontFamily(Font(R.font.montserrat_thin)),
fontWeight = FontWeight.Thin
),
textAlign = TextAlign.Center
style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.onSurface
)
}
}
DrawerMenuGroup(
items = listOf(
DrawerMenuItemData(R.drawable.ic_subscriptions_24dp, R.string.title_sub_setting, "sub_setting"),
DrawerMenuItemData(R.drawable.ic_per_apps_24dp, R.string.per_app_proxy_settings, "per_app_proxy"),
DrawerMenuItemData(R.drawable.ic_routing_24dp, R.string.routing_settings_title, "routing_setting"),
DrawerMenuItemData(R.drawable.ic_file_24dp, R.string.title_user_asset_setting, "user_asset"),
DrawerMenuItemData(R.drawable.ic_settings_24dp, R.string.title_settings, "settings")
),
onNavigate = onNavigate
)
AppDivider()
DrawerMenuGroup(
items = listOf(
DrawerMenuItemData(R.drawable.ic_promotion_24dp, R.string.title_pref_promotion, "promotion"),
DrawerMenuItemData(R.drawable.ic_logcat_24dp, R.string.title_logcat, "logcat"),
DrawerMenuItemData(R.drawable.ic_check_update_24dp, R.string.update_check_for_update, "check_update"),
DrawerMenuItemData(R.drawable.ic_restore_24dp, R.string.title_configuration_backup_restore, "backup_restore"),
DrawerMenuItemData(R.drawable.ic_about_24dp, R.string.title_about, "about")
),
onNavigate = onNavigate
)
drawerItems.forEachIndexed { index, item ->
if (index == primaryDrawerItems.size) AppDivider()
NavigationDrawerItem(
label = { Text(stringResource(item.labelRes)) },
selected = false,
onClick = { onNavigate(item) },
icon = { Icon(painterResource(item.iconRes), contentDescription = null) },
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
)
}
}
}
}
data class DrawerMenuItemData(
val iconRes: Int,
val labelRes: Int,
val route: String
)
@Composable
private fun DrawerMenuGroup(
items: List<DrawerMenuItemData>,
onNavigate: (String) -> Unit
) {
items.forEach { item ->
DrawerMenuItem(
icon = painterResource(item.iconRes),
label = stringResource(item.labelRes),
onClick = { onNavigate(item.route) }
)
}
}
@Composable
fun DrawerMenuItem(
icon: Painter,
label: String,
onClick: () -> Unit,
modifier: Modifier = Modifier,
selected: Boolean = false
) {
Row(
modifier = modifier
.fillMaxWidth()
.heightIn(min = 48.dp)
.clickable(onClick = onClick)
.background(
if (selected) MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.5f)
else Color.Transparent
)
.padding(horizontal = 16.dp, vertical = 0.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
painter = icon,
contentDescription = null,
modifier = Modifier.size(24.dp),
tint = MaterialTheme.colorScheme.onSurface
)
Spacer(modifier = Modifier.width(12.dp))
Text(
text = label,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurface
)
}
}
@@ -18,7 +18,6 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.v2ray.ang.dto.GroupMapItem
import com.v2ray.ang.dto.entities.ServersCache
import com.v2ray.ang.ui.compose.colorFabActive
import kotlinx.coroutines.flow.StateFlow
@Composable
@@ -45,7 +44,7 @@ fun GroupTabBar(
)
.clip(RoundedCornerShape(3.dp)),
width = Dp.Unspecified,
color = colorFabActive
color = MaterialTheme.colorScheme.secondary
)
},
divider = {}
@@ -1,16 +1,44 @@
package com.v2ray.ang.ui.main
import androidx.annotation.StringRes
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import com.v2ray.ang.R
import com.v2ray.ang.dto.entities.ProfileItem
import com.v2ray.ang.enums.EConfigType
import com.v2ray.ang.extension.isComplexType
import com.v2ray.ang.ui.compose.AppDropdownMenuItems
import com.v2ray.ang.ui.compose.SelectListDialog
private enum class ImportMenuAction(@StringRes val labelRes: Int, val action: MainAction) {
QRCode(R.string.menu_item_import_config_qrcode, MainAction.ImportQRcode),
Clipboard(R.string.menu_item_import_config_clipboard, MainAction.ImportClipboard),
LocalFile(R.string.menu_item_import_config_local, MainAction.ImportConfigLocal),
PolicyGroup(R.string.menu_item_import_config_policy_group, MainAction.ImportManually(EConfigType.POLICYGROUP.value)),
ProxyChain(R.string.menu_item_import_config_proxy_chain, MainAction.ImportManually(EConfigType.PROXYCHAIN.value)),
Vmess(R.string.menu_item_import_config_manually_vmess, MainAction.ImportManually(EConfigType.VMESS.value)),
Vless(R.string.menu_item_import_config_manually_vless, MainAction.ImportManually(EConfigType.VLESS.value)),
Shadowsocks(R.string.menu_item_import_config_manually_ss, MainAction.ImportManually(EConfigType.SHADOWSOCKS.value)),
Socks(R.string.menu_item_import_config_manually_socks, MainAction.ImportManually(EConfigType.SOCKS.value)),
Http(R.string.menu_item_import_config_manually_http, MainAction.ImportManually(EConfigType.HTTP.value)),
Trojan(R.string.menu_item_import_config_manually_trojan, MainAction.ImportManually(EConfigType.TROJAN.value)),
WireGuard(R.string.menu_item_import_config_manually_wireguard, MainAction.ImportManually(EConfigType.WIREGUARD.value)),
Hysteria2(R.string.menu_item_import_config_manually_hysteria2, MainAction.ImportManually(EConfigType.HYSTERIA2.value))
}
enum class MainMoreMenuAction(@StringRes val labelRes: Int) {
RestartService(R.string.title_service_restart),
DeleteAll(R.string.title_del_all_config),
DeleteDuplicate(R.string.title_del_duplicate_config),
DeleteInvalid(R.string.title_del_invalid_config),
ExportAll(R.string.title_export_all),
LocateSelected(R.string.title_locate_selected_config),
SortByTestResults(R.string.title_sort_by_test_results),
TestAll(R.string.title_ping_all_server),
TestAllRealPing(R.string.title_real_ping_all_server),
UpdateSubscriptions(R.string.title_sub_update)
}
internal enum class ServerMenuAction(
@StringRes val labelRes: Int,
val isShareAction: Boolean,
@@ -31,111 +59,18 @@ internal fun serverMenuActions(
}
@Composable
fun ImportMenuContent(
onAction: (MainAction) -> Unit
) {
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_item_import_config_qrcode)) },
onClick = { onAction(MainAction.ImportQRcode) }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_item_import_config_clipboard)) },
onClick = { onAction(MainAction.ImportClipboard) }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_item_import_config_local)) },
onClick = { onAction(MainAction.ImportConfigLocal) }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_item_import_config_policy_group)) },
onClick = { onAction(MainAction.ImportManually(EConfigType.POLICYGROUP.value)) }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_item_import_config_proxy_chain)) },
onClick = { onAction(MainAction.ImportManually(EConfigType.PROXYCHAIN.value)) }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_item_import_config_manually_vmess)) },
onClick = { onAction(MainAction.ImportManually(EConfigType.VMESS.value)) }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_item_import_config_manually_vless)) },
onClick = { onAction(MainAction.ImportManually(EConfigType.VLESS.value)) }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_item_import_config_manually_ss)) },
onClick = { onAction(MainAction.ImportManually(EConfigType.SHADOWSOCKS.value)) }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_item_import_config_manually_socks)) },
onClick = { onAction(MainAction.ImportManually(EConfigType.SOCKS.value)) }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_item_import_config_manually_http)) },
onClick = { onAction(MainAction.ImportManually(EConfigType.HTTP.value)) }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_item_import_config_manually_trojan)) },
onClick = { onAction(MainAction.ImportManually(EConfigType.TROJAN.value)) }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_item_import_config_manually_wireguard)) },
onClick = { onAction(MainAction.ImportManually(EConfigType.WIREGUARD.value)) }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_item_import_config_manually_hysteria2)) },
onClick = { onAction(MainAction.ImportManually(EConfigType.HYSTERIA2.value)) }
)
}
fun ImportMenuContent(onAction: (MainAction) -> Unit) = AppDropdownMenuItems(
items = ImportMenuAction.entries,
labelRes = { it.labelRes },
onSelected = { onAction(it.action) }
)
@Composable
fun MoreMenuContent(
onAction: (MainAction) -> Unit,
onDelAllConfig: () -> Unit,
onDelDuplicateConfig: () -> Unit,
onDelInvalidConfig: () -> Unit
) {
DropdownMenuItem(
text = { Text(stringResource(R.string.title_service_restart)) },
onClick = { onAction(MainAction.RestartService) }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.title_del_all_config)) },
onClick = onDelAllConfig
)
DropdownMenuItem(
text = { Text(stringResource(R.string.title_del_duplicate_config)) },
onClick = onDelDuplicateConfig
)
DropdownMenuItem(
text = { Text(stringResource(R.string.title_del_invalid_config)) },
onClick = onDelInvalidConfig
)
DropdownMenuItem(
text = { Text(stringResource(R.string.title_export_all)) },
onClick = { onAction(MainAction.ExportAll) }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.title_locate_selected_config)) },
onClick = { onAction(MainAction.LocateSelectedServer) }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.title_sort_by_test_results)) },
onClick = { onAction(MainAction.SortByTestResults) }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.title_ping_all_server)) },
onClick = { onAction(MainAction.TestAllServers) }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.title_real_ping_all_server)) },
onClick = { onAction(MainAction.TestRealAllServers) }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.title_sub_update)) },
onClick = { onAction(MainAction.UpdateSubscriptions) }
)
}
fun MoreMenuContent(onSelected: (MainMoreMenuAction) -> Unit) = AppDropdownMenuItems(
items = MainMoreMenuAction.entries,
labelRes = { it.labelRes },
onSelected = onSelected
)
@Composable
fun ShareMethodDialog(
@@ -151,10 +86,11 @@ fun ShareMethodDialog(
includeManagementActions = more,
)
SelectListDialog(
options = menuActions.map { stringResource(it.labelRes) },
onSelected = { index, _ ->
options = menuActions,
optionText = { stringResource(it.labelRes) },
onSelected = { action ->
onDismiss()
when (menuActions[index]) {
when (action) {
ServerMenuAction.ShareQRCode -> onAction(MainAction.ShareQRCode(guid))
ServerMenuAction.ShareClipboard -> onAction(MainAction.ShareClipboard(guid))
ServerMenuAction.ShareFullContent -> onAction(MainAction.ShareFullContent(guid))
@@ -8,13 +8,16 @@ import androidx.core.content.ContextCompat
import com.v2ray.ang.AngApplication
import com.v2ray.ang.AppConfig
import com.v2ray.ang.R
import com.v2ray.ang.dto.ConnectionTestResult
import com.v2ray.ang.dto.SubscriptionUpdateResult
import com.v2ray.ang.dto.TestServiceMessage
import com.v2ray.ang.dto.entities.ProfileItem
import com.v2ray.ang.dto.entities.ServerAffiliationInfo
import com.v2ray.ang.dto.entities.SubscriptionCache
import com.v2ray.ang.dto.entities.SubscriptionItem
import com.v2ray.ang.extension.serializable
import com.v2ray.ang.handler.AngConfigManager
import com.v2ray.ang.handler.AppLocaleManager
import com.v2ray.ang.handler.MmkvManager
import com.v2ray.ang.handler.SettingsManager
import com.v2ray.ang.handler.SubscriptionUpdater
@@ -31,6 +34,9 @@ class MainRepository(
private val app: AngApplication
) : MainDataSource {
private val localizedContext: Context
get() = AppLocaleManager.localizedContext(app)
private val closed = AtomicBoolean(false)
private val _mainServiceEvent = MutableSharedFlow<MainServiceEvent>(
@@ -48,14 +54,12 @@ class MainRepository(
AppConfig.MSG_STATE_RUNNING -> MainServiceEvent.StateRunning
AppConfig.MSG_STATE_NOT_RUNNING -> MainServiceEvent.StateNotRunning
AppConfig.MSG_STATE_START_SUCCESS -> MainServiceEvent.StateStartSuccess
AppConfig.MSG_STATE_START_FAILURE -> MainServiceEvent.StateStartFailure(
safeIntent.getStringExtra("content").orEmpty()
)
AppConfig.MSG_STATE_START_FAILURE -> MainServiceEvent.StateStartFailure
AppConfig.MSG_STATE_STOP_SUCCESS -> MainServiceEvent.StateStopSuccess
AppConfig.MSG_MEASURE_DELAY_SUCCESS -> MainServiceEvent.MeasureDelaySuccess(
safeIntent.getStringExtra("content").orEmpty()
)
AppConfig.MSG_MEASURE_DELAY_RESULT -> safeIntent
.serializable<ConnectionTestResult>("content")
?.let { MainServiceEvent.MeasureDelayResult(it) }
AppConfig.MSG_MEASURE_CONFIG_SUCCESS -> MainServiceEvent.MeasureConfigSuccess
AppConfig.MSG_MEASURE_CONFIG_NOTIFY -> MainServiceEvent.MeasureConfigNotify(
@@ -116,9 +120,10 @@ class MainRepository(
override fun isGroupAllDisplayEnabled(): Boolean =
MmkvManager.decodeSettingsBool(AppConfig.PREF_GROUP_ALL_DISPLAY)
override fun getString(resId: Int): String = app.getString(resId)
override fun getString(resId: Int): String = localizedContext.getString(resId)
override fun getString(resId: Int, vararg formatArgs: Any): String = app.getString(resId, *formatArgs)
override fun getString(resId: Int, vararg formatArgs: Any): String =
localizedContext.getString(resId, *formatArgs)
override fun getSubscriptions(): List<SubscriptionCache> {
val result = mutableListOf<SubscriptionCache>()
@@ -126,7 +131,7 @@ class MainRepository(
result += SubscriptionCache(
guid = "",
subscription = SubscriptionItem().apply {
remarks = app.getString(R.string.filter_config_all)
remarks = localizedContext.getString(R.string.filter_config_all)
}
)
}
@@ -9,7 +9,6 @@ import androidx.compose.foundation.lazy.grid.LazyGridState
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material3.DrawerValue
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalNavigationDrawer
import androidx.compose.material3.Scaffold
import androidx.compose.material3.ScaffoldDefaults
@@ -35,18 +34,17 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainScreen(
mainViewModel: MainViewModel,
onAction: (MainAction) -> Unit,
onNavigate: (String) -> Unit,
onNavigate: (MainDestination) -> Unit,
) {
val uiState by mainViewModel.uiState.collectAsStateWithLifecycle()
val groups = uiState.groups
val isLoading by mainViewModel.isLoading.collectAsStateWithLifecycle()
val isRunning = uiState.isRunning
val displayText = uiState.statusText
val displayText = mainViewModel.formatStatus(uiState.status)
val selectedGuid = uiState.selectedGuid
val doubleColumnDisplay = uiState.doubleColumnDisplay
val confirmRemove = uiState.confirmRemove
@@ -191,6 +189,7 @@ fun MainScreen(
drawerState = drawerState,
drawerContent = {
MainDrawerContent(
drawerState = drawerState,
onNavigate = { route ->
scope.launch { drawerState.close() }
onNavigate(route)
@@ -217,9 +216,20 @@ fun MainScreen(
onSearchToggle = { show: Boolean -> showSearch = show },
onMenuClick = { scope.launch { drawerState.open() } },
onAction = onAction,
onDelAllConfig = { showDelAllConfirm = true },
onDelDuplicateConfig = { showDelDuplicateConfirm = true },
onDelInvalidConfig = { showDelInvalidConfirm = true }
onMoreMenuAction = { action ->
when (action) {
MainMoreMenuAction.RestartService -> onAction(MainAction.RestartService)
MainMoreMenuAction.DeleteAll -> showDelAllConfirm = true
MainMoreMenuAction.DeleteDuplicate -> showDelDuplicateConfirm = true
MainMoreMenuAction.DeleteInvalid -> showDelInvalidConfirm = true
MainMoreMenuAction.ExportAll -> onAction(MainAction.ExportAll)
MainMoreMenuAction.LocateSelected -> onAction(MainAction.LocateSelectedServer)
MainMoreMenuAction.SortByTestResults -> onAction(MainAction.SortByTestResults)
MainMoreMenuAction.TestAll -> onAction(MainAction.TestAllServers)
MainMoreMenuAction.TestAllRealPing -> onAction(MainAction.TestRealAllServers)
MainMoreMenuAction.UpdateSubscriptions -> onAction(MainAction.UpdateSubscriptions)
}
}
)
},
bottomBar = {
@@ -36,6 +36,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.LineBreak
import androidx.compose.ui.text.style.TextOverflow
@@ -249,7 +250,6 @@ private fun ServerItemRow(
statistics = profile.description.nullIfBlank()
?: AngConfigManager.generateDescription(profile),
typeDescription = getProtocolDescription(profile),
testResult = serverCache.testDelayString,
testDelayMillis = serverCache.testDelayMillis,
isSelected = serverCache.guid == selectedGuid,
subscriptionRemarks = subRemarks,
@@ -283,7 +283,6 @@ private fun ServerItemColumn(
remarks = profile.remarks,
statistics = profile.description.nullIfBlank() ?: AngConfigManager.generateDescription(profile),
typeDescription = getProtocolDescription(profile),
testResult = serverCache.testDelayString,
testDelayMillis = serverCache.testDelayMillis,
isSelected = serverCache.guid == selectedGuid,
subscriptionRemarks = subRemarks,
@@ -303,7 +302,6 @@ fun ServerListItem(
remarks: String,
statistics: String,
typeDescription: String,
testResult: String,
testDelayMillis: Long,
isSelected: Boolean,
subscriptionRemarks: String,
@@ -316,6 +314,12 @@ fun ServerListItem(
modifier: Modifier = Modifier,
dragModifier: Modifier = Modifier
) {
val testResult = if (testDelayMillis == 0L) {
""
} else {
stringResource(R.string.server_test_delay_value, testDelayMillis)
}
Row(
modifier = modifier
.fillMaxWidth()
@@ -1,12 +1,14 @@
package com.v2ray.ang.ui.main
import com.v2ray.ang.dto.ConnectionTestResult
sealed class MainServiceEvent {
data object StateRunning : MainServiceEvent()
data object StateNotRunning : MainServiceEvent()
data object StateStartSuccess : MainServiceEvent()
data class StateStartFailure(val errorMessage: String) : MainServiceEvent()
data object StateStartFailure : MainServiceEvent()
data object StateStopSuccess : MainServiceEvent()
data class MeasureDelaySuccess(val content: String) : MainServiceEvent()
data class MeasureDelayResult(val result: ConnectionTestResult) : MainServiceEvent()
data object MeasureConfigSuccess : MainServiceEvent()
data class MeasureConfigNotify(val progress: String) : MainServiceEvent()
data class MeasureConfigFinish(val finishedCount: String?) : MainServiceEvent()
@@ -9,7 +9,6 @@ import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.rememberScrollState
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
@@ -28,7 +27,6 @@ import com.v2ray.ang.R
import com.v2ray.ang.ui.compose.AppTopBar
import com.v2ray.ang.ui.compose.verticalScrollbar
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainTopBar(
isLoading: Boolean,
@@ -39,9 +37,7 @@ fun MainTopBar(
onSearchToggle: (Boolean) -> Unit,
onMenuClick: () -> Unit,
onAction: (MainAction) -> Unit,
onDelAllConfig: () -> Unit,
onDelDuplicateConfig: () -> Unit,
onDelInvalidConfig: () -> Unit
onMoreMenuAction: (MainMoreMenuAction) -> Unit
) {
var showImportMenu by remember { mutableStateOf(false) }
var showMenu by remember { mutableStateOf(false) }
@@ -63,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,
@@ -100,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,
@@ -111,15 +107,10 @@ fun MainTopBar(
.heightIn(max = maxMenuHeight)
.verticalScrollbar(moreMenuScrollState)
) {
MoreMenuContent(
onAction = { action ->
showMenu = false
onAction(action)
},
onDelAllConfig = { showMenu = false; onDelAllConfig() },
onDelDuplicateConfig = { showMenu = false; onDelDuplicateConfig() },
onDelInvalidConfig = { showMenu = false; onDelInvalidConfig() }
)
MoreMenuContent { action ->
showMenu = false
onMoreMenuAction(action)
}
}
}
}
@@ -6,6 +6,7 @@ import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.v2ray.ang.AppConfig
import com.v2ray.ang.R
import com.v2ray.ang.dto.ConnectionTestResult
import com.v2ray.ang.dto.GroupMapItem
import com.v2ray.ang.dto.LocateTarget
import com.v2ray.ang.dto.TestServiceMessage
@@ -45,15 +46,11 @@ class MainViewModel(
private val defaultDispatcher: CoroutineDispatcher = Dispatchers.Default
private val preloadDispatcher: CoroutineDispatcher = Dispatchers.IO.limitedParallelism(1)
private val disconnectedText: String = dataSource.getString(R.string.connection_not_connected)
private val connectedText: String = dataSource.getString(R.string.connection_connected)
// ---------- UI state ----------
private val _uiState = MutableStateFlow(
MainUiState(
selectedGroupId = dataSource.getSelectedSubscriptionId(),
selectedGuid = dataSource.getSelectServer(),
statusText = disconnectedText,
confirmRemove = dataSource.getConfirmRemove(),
doubleColumnDisplay = dataSource.getDoubleColumnDisplay()
)
@@ -105,19 +102,14 @@ class MainViewModel(
updateRunningState(true)
}
is MainServiceEvent.StateStartFailure -> {
val error = event.errorMessage
if (error.isNotBlank()) {
toastError(error)
} else {
toastError(R.string.toast_services_failure)
}
MainServiceEvent.StateStartFailure -> {
toastError(R.string.toast_services_failure)
updateRunningState(false)
}
MainServiceEvent.StateStopSuccess -> updateRunningState(false)
is MainServiceEvent.MeasureDelaySuccess -> {
_uiState.update { it.copy(statusText = event.content) }
is MainServiceEvent.MeasureDelayResult -> {
_uiState.update { it.copy(status = MainStatus.ConnectionTest(event.result)) }
}
MainServiceEvent.MeasureConfigSuccess -> {
@@ -129,24 +121,46 @@ class MainViewModel(
}
is MainServiceEvent.MeasureConfigNotify -> {
_uiState.update {
it.copy(
statusText = dataSource.getString(
R.string.connection_runing_task_left,
event.progress
)
)
}
_uiState.update { it.copy(status = MainStatus.TestProgress(event.progress)) }
}
is MainServiceEvent.MeasureConfigFinish -> {
if (event.finishedCount == "0") {
onTestsFinished()
}
onTestsFinished()
}
}
}
internal fun formatStatus(status: MainStatus): String = when (status) {
MainStatus.Disconnected -> dataSource.getString(R.string.connection_not_connected)
MainStatus.Connected -> dataSource.getString(R.string.connection_connected)
MainStatus.Testing -> dataSource.getString(R.string.connection_test_testing)
is MainStatus.TestProgress -> dataSource.getString(
R.string.connection_running_task_left,
status.progress
)
is MainStatus.ConnectionTest -> formatConnectionTestResult(status.result)
}
private fun formatConnectionTestResult(result: ConnectionTestResult): String {
val status = if (result.delayMillis >= 0) {
val delay = dataSource.getString(R.string.server_test_delay_value, result.delayMillis)
dataSource.getString(R.string.connection_test_available, delay)
} else {
val detail = result.errorMessage.ifBlank {
dataSource.getString(R.string.connection_test_empty_message)
}
dataSource.getString(R.string.connection_test_error, detail)
}
if (result.delayMillis < 0 || (result.country == null && result.ipAddress == null)) {
return status
}
val unknown = dataSource.getString(R.string.value_unknown)
return "$status\n(${result.country ?: unknown}) ${result.ipAddress ?: unknown}"
}
// ---------- Public state accessors ----------
fun serversForGroup(groupId: String): StateFlow<List<ServersCache>> =
groupPageFlows.computeIfAbsent(groupId) { MutableStateFlow(emptyList()) }
@@ -237,8 +251,7 @@ class MainViewModel(
ServersCache(
guid = guid,
profile = profile.copy(),
testDelayMillis = affiliation?.testDelayMillis ?: 0L,
testDelayString = affiliation?.getTestDelayString().orEmpty()
testDelayMillis = affiliation?.testDelayMillis ?: 0L
)
}
@@ -667,7 +680,7 @@ class MainViewModel(
_uiState.update {
it.copy(
isTesting = false,
statusText = if (it.isRunning) connectedText else disconnectedText
status = if (it.isRunning) MainStatus.Connected else MainStatus.Disconnected
)
}
}
@@ -685,7 +698,7 @@ class MainViewModel(
_uiState.update {
it.copy(
isTesting = true,
statusText = dataSource.getString(R.string.connection_test_testing)
status = MainStatus.Testing
)
}
viewModelScope.launch(ioDispatcher) {
@@ -702,11 +715,7 @@ class MainViewModel(
}
fun testCurrentServerRealPing() {
_uiState.update {
it.copy(
statusText = dataSource.getString(R.string.connection_test_testing)
)
}
_uiState.update { it.copy(status = MainStatus.Testing) }
dataSource.testCurrentServerRealPing()
}
@@ -717,7 +726,7 @@ class MainViewModel(
_uiState.update {
it.copy(
isTesting = false,
statusText = if (it.isRunning) connectedText else disconnectedText
status = if (it.isRunning) MainStatus.Connected else MainStatus.Disconnected
)
}
reloadAllGroups(_uiState.value.groups.map { it.id })
@@ -753,8 +762,8 @@ class MainViewModel(
_uiState.update { state ->
state.copy(
isRunning = running,
statusText = if (!clearTestingText && state.isTesting) state.statusText
else if (running) connectedText else disconnectedText
status = if (!clearTestingText && state.isTesting) state.status
else if (running) MainStatus.Connected else MainStatus.Disconnected
)
}
}
@@ -2,6 +2,7 @@ package com.v2ray.ang.ui.perappproxy
import android.os.Bundle
import androidx.activity.viewModels
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@@ -15,8 +16,6 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
@@ -46,13 +45,21 @@ import com.v2ray.ang.extension.toastInfo
import com.v2ray.ang.extension.toastSuccess
import com.v2ray.ang.ui.base.BaseComponentActivity
import com.v2ray.ang.ui.compose.AppDivider
import com.v2ray.ang.ui.compose.AppDropdownMenuItems
import com.v2ray.ang.ui.compose.AppListItem
import com.v2ray.ang.ui.compose.AppTopBar
import com.v2ray.ang.ui.compose.ItemDivider
import com.v2ray.ang.ui.compose.colorFabActive
import com.v2ray.ang.ui.compose.verticalScrollbar
import com.v2ray.ang.util.Utils
private enum class PerAppMenuAction(@StringRes val labelRes: Int) {
SelectAll(R.string.menu_item_select_all),
InvertSelection(R.string.menu_item_invert_selection),
SelectProxyApps(R.string.menu_item_select_proxy_app),
ImportSelection(R.string.menu_item_import_proxy_app),
ExportSelection(R.string.menu_item_export_proxy_app)
}
class PerAppProxyActivity : BaseComponentActivity() {
private val viewModel: PerAppProxyViewModel by viewModels()
@@ -100,7 +107,6 @@ class PerAppProxyActivity : BaseComponentActivity() {
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PerAppProxyScreen(
apps: List<AppInfo>,
@@ -125,7 +131,7 @@ fun PerAppProxyScreen(
var showMenu by remember { mutableStateOf(false) }
val listState = rememberLazyListState()
LaunchedEffect(searchQuery) {
LaunchedEffect(Unit) {
onSearch(searchQuery)
}
@@ -140,9 +146,11 @@ fun PerAppProxyScreen(
searchQuery = searchQuery,
onSearchQueryChange = { query ->
searchQuery = query
onSearch(query)
},
onSearchClose = {
searchQuery = ""
onSearch("")
showSearch = false
},
searchPlaceholder = stringResource(R.string.menu_item_search),
@@ -151,7 +159,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)
)
}
}
@@ -167,26 +175,16 @@ fun PerAppProxyScreen(
onDismissRequest = { showMenu = false },
containerColor = MaterialTheme.colorScheme.surface
) {
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_item_select_all)) },
onClick = { showMenu = false; onSelectAll() }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_item_invert_selection)) },
onClick = { showMenu = false; onInvertSelection() }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_item_select_proxy_app)) },
onClick = { showMenu = false; onSelectProxyAuto() }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_item_import_proxy_app)) },
onClick = { showMenu = false; onImportProxyApp() }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_item_export_proxy_app)) },
onClick = { showMenu = false; onExportProxyApp() }
)
AppDropdownMenuItems(PerAppMenuAction.entries, { it.labelRes }) { action ->
showMenu = false
when (action) {
PerAppMenuAction.SelectAll -> onSelectAll()
PerAppMenuAction.InvertSelection -> onInvertSelection()
PerAppMenuAction.SelectProxyApps -> onSelectProxyAuto()
PerAppMenuAction.ImportSelection -> onImportProxyApp()
PerAppMenuAction.ExportSelection -> onExportProxyApp()
}
}
}
}
}
@@ -225,7 +223,7 @@ fun PerAppProxyScreen(
onCheckedChange = onPerAppProxyChanged,
colors = SwitchDefaults.colors(
checkedThumbColor = MaterialTheme.colorScheme.onSecondary,
checkedTrackColor = colorFabActive
checkedTrackColor = MaterialTheme.colorScheme.secondary
)
)
}
@@ -246,14 +244,14 @@ fun PerAppProxyScreen(
onCheckedChange = onBypassAppsChanged,
colors = SwitchDefaults.colors(
checkedThumbColor = MaterialTheme.colorScheme.onSecondary,
checkedTrackColor = colorFabActive
checkedTrackColor = MaterialTheme.colorScheme.secondary
)
)
}
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
)
}
@@ -272,7 +270,7 @@ fun PerAppProxyScreen(
AppListItem(
appName = app.appName,
packageName = app.packageName,
icon = app.appIcon,
icon = null,
checked = checked,
onCheckedChange = { onToggleApp(app.packageName) }
)
@@ -8,11 +8,13 @@ import com.v2ray.ang.dto.UrlContentRequest
import com.v2ray.ang.handler.MmkvManager
import com.v2ray.ang.handler.SettingsChangeManager
import com.v2ray.ang.handler.SettingsManager
import com.v2ray.ang.ui.AppSelection
import com.v2ray.ang.ui.base.BaseViewModel
import com.v2ray.ang.util.AppManagerUtil
import com.v2ray.ang.util.HttpUtil
import com.v2ray.ang.util.LogUtil
import com.v2ray.ang.util.Utils
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@@ -46,64 +48,30 @@ class PerAppProxyViewModel(application: Application) : BaseViewModel(application
// Cached full list for filtering
private var appsAll: List<AppInfo>? = null
private var currentQuery = ""
private var isAppListLoading = false
// Blacklist operations
fun contains(packageName: String): Boolean = _blacklist.value.contains(packageName)
fun add(packageName: String) {
val newSet = _blacklist.value + packageName
if (newSet != _blacklist.value) {
_blacklist.value = newSet
saveBlacklist()
}
}
fun remove(packageName: String) {
val newSet = _blacklist.value - packageName
if (newSet != _blacklist.value) {
_blacklist.value = newSet
saveBlacklist()
}
}
fun toggle(packageName: String) {
if (_blacklist.value.contains(packageName)) {
remove(packageName)
val currentSelection = _blacklist.value
val newSelection = if (packageName in currentSelection) {
currentSelection - packageName
} else {
add(packageName)
}
}
fun addAll(packages: Collection<String>) {
val newSet = _blacklist.value + packages
if (newSet != _blacklist.value) {
_blacklist.value = newSet
saveBlacklist()
}
}
fun removeAll(packages: Collection<String>) {
val newSet = _blacklist.value - packages.toSet()
if (newSet != _blacklist.value) {
_blacklist.value = newSet
saveBlacklist()
}
}
fun clear() {
if (_blacklist.value.isNotEmpty()) {
_blacklist.value = emptySet()
saveBlacklist()
currentSelection + packageName
}
replaceBlacklist(newSelection)
SettingsChangeManager.makeRestartService()
}
private fun loadBlacklist(): Set<String> {
return MmkvManager.decodeSettingsStringSet(AppConfig.PREF_PER_APP_PROXY_SET)?.toSet() ?: emptySet()
}
private fun saveBlacklist() {
MmkvManager.encodeSettings(AppConfig.PREF_PER_APP_PROXY_SET, _blacklist.value.toMutableSet())
SettingsChangeManager.makeRestartService()
private fun replaceBlacklist(newBlacklist: Set<String>) {
if (newBlacklist == _blacklist.value) return
_blacklist.value = newBlacklist
MmkvManager.encodeSettings(AppConfig.PREF_PER_APP_PROXY_SET, newBlacklist.toMutableSet())
}
// Per‑app proxy switch
@@ -123,36 +91,49 @@ class PerAppProxyViewModel(application: Application) : BaseViewModel(application
// Load and filter apps
fun loadApps(context: Context) {
if (appsAll != null || isAppListLoading) return
val applicationContext = context.applicationContext
isAppListLoading = true
launchLoading {
try {
val apps = withContext(Dispatchers.IO) {
val list = AppManagerUtil.loadNetworkAppList(context)
val list = AppManagerUtil.loadNetworkAppList(applicationContext)
sortApps(list)
}
appsAll = apps
_displayedApps.value = apps
_displayedApps.value = applyFilter(currentQuery)
} catch (e: CancellationException) {
throw e
} catch (e: Exception) {
LogUtil.e(AppConfig.ANG_PACKAGE, "Error loading apps", e)
} finally {
isAppListLoading = false
}
}
}
fun filterApps(query: String) {
val key = query.uppercase()
_displayedApps.value = if (key.isNotEmpty()) {
appsAll?.filter {
it.appName.uppercase().contains(key) || it.packageName.uppercase().contains(key)
} ?: emptyList()
} else {
appsAll ?: emptyList()
currentQuery = query
_displayedApps.value = applyFilter(query)
}
private fun applyFilter(query: String): List<AppInfo> {
val apps = appsAll ?: return emptyList()
if (query.isEmpty()) return apps
return apps.filter {
it.appName.contains(query, ignoreCase = true) ||
it.packageName.contains(query, ignoreCase = true)
}
}
private fun sortApps(apps: List<AppInfo>): List<AppInfo> {
val collator = Collator.getInstance()
val selectedPackages = _blacklist.value
return apps.sortedWith { p1, p2 ->
val s1 = contains(p1.packageName)
val s2 = contains(p2.packageName)
val s1 = p1.packageName in selectedPackages
val s2 = p2.packageName in selectedPackages
when {
s1 && !s2 -> -1
!s1 && s2 -> 1
@@ -165,19 +146,26 @@ class PerAppProxyViewModel(application: Application) : BaseViewModel(application
// Bulk actions
fun selectAll() {
val pkgNames = _displayedApps.value.map { it.packageName }
val allSelected = pkgNames.all { contains(it) }
if (allSelected) removeAll(pkgNames) else addAll(pkgNames)
// Enable per‑app proxy after selection
val displayedApps = _displayedApps.value
val currentSelection = _blacklist.value
val allSelected = displayedApps.all { it.packageName in currentSelection }
val newSelection = currentSelection.toMutableSet().apply {
displayedApps.forEach { app ->
if (allSelected) remove(app.packageName) else add(app.packageName)
}
}
replaceBlacklist(newSelection)
enablePerAppProxyAndRestart()
}
fun invertSelection() {
_displayedApps.value.forEach { toggle(it.packageName) }
val packageNames = _displayedApps.value.map { it.packageName }
replaceBlacklist(AppSelection.invert(_blacklist.value, packageNames))
enablePerAppProxyAndRestart()
}
fun selectProxyAppAuto(context: Context) {
val applicationContext = context.applicationContext
launchLoading {
val url = AppConfig.ANDROID_PACKAGE_NAME_LIST_URL
var content = withContext(Dispatchers.IO) {
@@ -204,7 +192,11 @@ class PerAppProxyViewModel(application: Application) : BaseViewModel(application
)
} ?: ""
}
val success = selectProxyApp(content, true, context)
val success = applyProxyAppList(
content = content,
context = applicationContext,
forceGoogleApps = true
)
if (success) {
enablePerAppProxyAndRestart()
}
@@ -213,42 +205,53 @@ class PerAppProxyViewModel(application: Application) : BaseViewModel(application
fun importProxyApp(content: String?, context: Context) {
if (content.isNullOrEmpty()) return
val success = selectProxyApp(content, false, context)
if (success) {
enablePerAppProxyAndRestart()
val applicationContext = context.applicationContext
launchLoading {
val success = applyProxyAppList(
content = content,
context = applicationContext,
forceGoogleApps = false
)
if (success) {
enablePerAppProxyAndRestart()
}
}
}
fun exportProxyApp(): String {
var result = _bypassApps.value.toString()
_blacklist.value.forEach { pkg ->
result = result + System.lineSeparator() + pkg
return buildString {
append(_bypassApps.value)
_blacklist.value.forEach { packageName ->
append(System.lineSeparator())
append(packageName)
}
}
return result
}
private fun selectProxyApp(content: String, force: Boolean, context: Context): Boolean {
try {
val proxyApps = if (content.isEmpty()) {
Utils.readTextFromAssets(context, "proxy_package_name")
} else content
if (proxyApps.isNullOrEmpty()) return false
private suspend fun applyProxyAppList(content: String, context: Context, forceGoogleApps: Boolean): Boolean {
val installedApps = appsAll ?: return false
clear()
val apps = _displayedApps.value
if (_bypassApps.value) {
apps.forEach { app ->
if (!inProxyApps(proxyApps, app.packageName, force)) {
add(app.packageName)
}
}
} else {
apps.forEach { app ->
if (inProxyApps(proxyApps, app.packageName, force)) {
add(app.packageName)
}
try {
val proxyAppList = if (content.isEmpty()) {
withContext(Dispatchers.IO) {
Utils.readTextFromAssets(context, "proxy_package_name")
}
} else content
if (proxyAppList.isNullOrEmpty()) return false
val bypassApps = _bypassApps.value
val newBlacklist = withContext(Dispatchers.Default) {
AppSelection.fromProxyList(
packageNames = installedApps.map { it.packageName },
proxyAppList = proxyAppList,
bypassApps = bypassApps,
forceGoogleApps = forceGoogleApps
)
}
replaceBlacklist(newBlacklist)
} catch (e: CancellationException) {
throw e
} catch (e: Exception) {
LogUtil.e(AppConfig.TAG, "Error selecting proxy app", e)
return false
@@ -256,16 +259,8 @@ class PerAppProxyViewModel(application: Application) : BaseViewModel(application
return true
}
private fun inProxyApps(proxyApps: String, packageName: String, force: Boolean): Boolean {
if (force) {
if (packageName == "com.google.android.webview") return false
if (packageName.startsWith("com.google")) return true
}
return proxyApps.indexOf(packageName) >= 0
}
private fun enablePerAppProxyAndRestart() {
setPerAppProxyEnabled(true)
SettingsChangeManager.makeRestartService()
}
}
}
@@ -16,6 +16,7 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.ScaffoldDefaults
import androidx.compose.material3.Text
@@ -118,6 +119,7 @@ fun RoutingEditScreen(
onDelete: () -> Unit
) {
val context = LocalContext.current
val processSelectTitle = stringResource(R.string.routing_settings_process_select)
val scrollState = rememberScrollState()
var remarks by rememberSaveable { mutableStateOf(initial?.remarks ?: "") }
@@ -186,14 +188,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)
)
}
}
@@ -220,21 +222,27 @@ fun RoutingEditScreen(
checked = locked,
onCheckedChange = { locked = it }
)
Text(
text = stringResource(R.string.routing_settings_tips),
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
FormTextField(
label = stringResource(R.string.routing_settings_domain),
placeholder = stringResource(R.string.routing_settings_tips),
placeholder = stringResource(R.string.routing_settings_comma_tip),
value = domain,
onValueChange = { domain = it }
)
FormTextField(
label = stringResource(R.string.routing_settings_ip),
placeholder = stringResource(R.string.routing_settings_tips),
placeholder = stringResource(R.string.routing_settings_comma_tip),
value = ip,
onValueChange = { ip = it }
)
FormTextField(
label = stringResource(R.string.routing_settings_process),
placeholder = stringResource(R.string.routing_settings_tips),
placeholder = stringResource(R.string.routing_settings_comma_tip),
value = processText,
onValueChange = { processText = it },
enabled = canUseProcess
@@ -251,7 +259,7 @@ fun RoutingEditScreen(
AppPickerActivity.createIntent(
context = context,
selectedPackages = current,
title = context.getString(R.string.routing_settings_process_select)
title = processSelectTitle
)
)
},
@@ -262,7 +270,7 @@ fun RoutingEditScreen(
contentDescription = null
)
Spacer(modifier = Modifier.width(8.dp))
Text(stringResource(R.string.routing_settings_process_select))
Text(processSelectTitle)
}
}
FormTextField(
@@ -284,6 +292,10 @@ fun RoutingEditScreen(
)
FormDropdownField(
label = stringResource(R.string.routing_settings_outbound_tag),
placeholder = stringResource(
R.string.routing_settings_outbound_tag_hint,
stringResource(R.string.server_lab_remarks)
),
value = outboundTag,
options = outboundSuggestions,
onValueChange = { outboundTag = it },
@@ -3,6 +3,7 @@ package com.v2ray.ang.ui.routing
import android.content.Intent
import android.os.Bundle
import androidx.activity.viewModels
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
@@ -17,8 +18,6 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
@@ -46,18 +45,19 @@ import androidx.lifecycle.lifecycleScope
import com.v2ray.ang.AppConfig
import com.v2ray.ang.R
import com.v2ray.ang.dto.entities.RulesetItem
import com.v2ray.ang.enums.RoutingType
import com.v2ray.ang.extension.toastError
import com.v2ray.ang.extension.toastSuccess
import com.v2ray.ang.handler.MmkvManager
import com.v2ray.ang.handler.SettingsManager
import com.v2ray.ang.ui.base.HelperBaseComponentActivity
import com.v2ray.ang.ui.compose.AppDropdownMenuItems
import com.v2ray.ang.ui.compose.AppTopBar
import com.v2ray.ang.ui.compose.ItemDivider
import com.v2ray.ang.ui.compose.ReorderableListItem
import com.v2ray.ang.ui.compose.SelectListDialog
import com.v2ray.ang.ui.compose.SettingsListItem
import com.v2ray.ang.ui.compose.colorConfigType
import com.v2ray.ang.ui.compose.colorFabActive
import com.v2ray.ang.ui.compose.verticalScrollbar
import com.v2ray.ang.util.JsonUtil
import com.v2ray.ang.util.LogUtil
@@ -69,6 +69,21 @@ import kotlinx.coroutines.withContext
import sh.calvin.reorderable.ReorderableItem
import sh.calvin.reorderable.rememberReorderableLazyListState
private enum class RoutingMenuAction(@StringRes val labelRes: Int) {
ImportPredefined(R.string.routing_settings_import_predefined_rulesets),
ImportClipboard(R.string.routing_settings_import_rulesets_from_clipboard),
ImportQRCode(R.string.routing_settings_import_rulesets_from_qrcode),
ExportClipboard(R.string.routing_settings_export_rulesets_to_clipboard)
}
private enum class RoutingPreset(val type: RoutingType, @StringRes val labelRes: Int) {
ChinaWhitelist(RoutingType.WHITE, R.string.routing_preset_china_whitelist),
ChinaBlacklist(RoutingType.BLACK, R.string.routing_preset_china_blacklist),
Global(RoutingType.GLOBAL, R.string.routing_preset_global),
IranWhitelist(RoutingType.WHITE_IRAN, R.string.routing_preset_iran_whitelist),
RussiaWhitelist(RoutingType.WHITE_RUSSIA, R.string.routing_preset_russia_whitelist)
}
class RoutingSettingActivity : HelperBaseComponentActivity() {
private val viewModel: RoutingSettingsViewModel by viewModels()
private val domainStrategyState = MutableStateFlow("")
@@ -92,7 +107,7 @@ class RoutingSettingActivity : HelperBaseComponentActivity() {
MmkvManager.encodeSettings(AppConfig.PREF_ROUTING_DOMAIN_STRATEGY, value)
domainStrategyState.value = value
},
onImportPredefined = { index -> importPredefined(index) },
onImportPredefined = { type -> importPredefined(type) },
onImportClipboard = { importFromClipboard() },
onImportQRcode = { importQRcode() },
onExportClipboard = { export2Clipboard() }
@@ -109,10 +124,10 @@ class RoutingSettingActivity : HelperBaseComponentActivity() {
return MmkvManager.decodeSettingsString(AppConfig.PREF_ROUTING_DOMAIN_STRATEGY) ?: strategies.first()
}
private fun importPredefined(index: Int) {
private fun importPredefined(type: RoutingType) {
lifecycleScope.launch(Dispatchers.IO) {
try {
SettingsManager.resetRoutingRulesetsFromPresets(this@RoutingSettingActivity, index)
SettingsManager.resetRoutingRulesetsFromPresets(this@RoutingSettingActivity, type)
launch(Dispatchers.Main) {
viewModel.reload()
toastSuccess(R.string.toast_success)
@@ -172,7 +187,6 @@ class RoutingSettingActivity : HelperBaseComponentActivity() {
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun RoutingSettingScreen(
viewModel: RoutingSettingsViewModel,
@@ -181,7 +195,7 @@ fun RoutingSettingScreen(
onAddRule: () -> Unit,
onEditRule: (Int) -> Unit,
onDomainStrategySelected: (String) -> Unit,
onImportPredefined: (Int) -> Unit,
onImportPredefined: (RoutingType) -> Unit,
onImportClipboard: () -> Unit,
onImportQRcode: () -> Unit,
onExportClipboard: () -> Unit
@@ -192,8 +206,6 @@ fun RoutingSettingScreen(
var showPresetDialog by remember { mutableStateOf(false) }
val domainStrategies = stringArrayResource(R.array.routing_domain_strategy).toList()
val presetRulesets = stringArrayResource(R.array.preset_rulesets).toList()
val lazyListState = rememberLazyListState()
val reorderableState = rememberReorderableLazyListState(lazyListState) { from, to ->
// Lazy list indices include the preceding non-rule content, so resolve the stable rule keys.
@@ -212,7 +224,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 {
@@ -227,22 +239,15 @@ fun RoutingSettingScreen(
onDismissRequest = { showMenu = false },
containerColor = MaterialTheme.colorScheme.surface
) {
DropdownMenuItem(
text = { Text(stringResource(R.string.routing_settings_import_predefined_rulesets)) },
onClick = { showMenu = false; showPresetDialog = true }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.routing_settings_import_rulesets_from_clipboard)) },
onClick = { showMenu = false; onImportClipboard() }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.routing_settings_import_rulesets_from_qrcode)) },
onClick = { showMenu = false; onImportQRcode() }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.routing_settings_export_rulesets_to_clipboard)) },
onClick = { showMenu = false; onExportClipboard() }
)
AppDropdownMenuItems(RoutingMenuAction.entries, { it.labelRes }) { action ->
showMenu = false
when (action) {
RoutingMenuAction.ImportPredefined -> showPresetDialog = true
RoutingMenuAction.ImportClipboard -> onImportClipboard()
RoutingMenuAction.ImportQRCode -> onImportQRcode()
RoutingMenuAction.ExportClipboard -> onExportClipboard()
}
}
}
}
}
@@ -301,10 +306,11 @@ fun RoutingSettingScreen(
if (showPresetDialog) {
SelectListDialog(
title = stringResource(R.string.routing_settings_import_predefined_rulesets),
options = presetRulesets,
onSelected = { index, _ ->
options = RoutingPreset.entries,
optionText = { stringResource(it.labelRes) },
onSelected = { preset ->
showPresetDialog = false
onImportPredefined(index)
onImportPredefined(preset.type)
},
onDismiss = { showPresetDialog = false }
)
@@ -335,7 +341,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
)
@@ -369,7 +375,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))
@@ -379,7 +385,7 @@ private fun RoutingRulesetItem(
modifier = Modifier.scale(0.7f),
colors = SwitchDefaults.colors(
checkedThumbColor = MaterialTheme.colorScheme.onSecondary,
checkedTrackColor = colorFabActive
checkedTrackColor = MaterialTheme.colorScheme.secondary
)
)
}
@@ -100,8 +100,7 @@ abstract class BaseServerActivity : BaseComponentActivity() {
@Composable
protected fun CommonBasicFields(
state: ServerUiState,
showPort: Boolean = true
state: ServerUiState
) {
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
FormTextField(
@@ -114,14 +113,12 @@ abstract class BaseServerActivity : BaseComponentActivity() {
state.address,
{ state.address = it }
)
if (showPort) {
FormTextField(
stringResource(R.string.server_lab_port),
state.port,
{ state.port = it },
keyboardType = KeyboardType.Number
)
}
FormTextField(
stringResource(R.string.server_lab_port),
state.port,
{ state.port = it },
keyboardType = KeyboardType.Number
)
}
}
@@ -461,14 +458,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)
)
}
}
@@ -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))
}
}
)
@@ -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_josn)} " +
"${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)
)
}
}
@@ -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))
}
}
)
@@ -31,7 +31,7 @@ class ServerHysteria2Activity : BaseServerActivity() {
title = serverConfigType.toString(),
onSaveClick = { saveServer(uiState) }
) {
CommonBasicFields(uiState, showPort = false)
CommonBasicFields(uiState)
Hysteria2ProtocolFields(uiState)
}
@@ -96,6 +96,12 @@ class ServerHysteria2Activity : BaseServerActivity() {
state.pinnedCA256,
{ state.pinnedCA256 = it }
)
FormTextField(
stringResource(R.string.server_lab_final_mask),
state.finalMask,
{ state.finalMask = it }
)
}
}
@@ -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)
)
}
}
@@ -1,5 +1,6 @@
package com.v2ray.ang.ui.settings
import android.os.Build
import android.os.Bundle
import androidx.activity.viewModels
import androidx.compose.foundation.layout.Column
@@ -13,8 +14,10 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.ScaffoldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
@@ -25,6 +28,8 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.v2ray.ang.AppConfig
import com.v2ray.ang.AppConfig.VPN
import com.v2ray.ang.R
import com.v2ray.ang.handler.AppLocaleManager
import com.v2ray.ang.handler.MmkvManager
import com.v2ray.ang.handler.MmkvManager.rememberMmkvBool
import com.v2ray.ang.handler.MmkvManager.rememberMmkvString
import com.v2ray.ang.handler.SettingsChangeManager
@@ -73,8 +78,8 @@ fun SettingsScreen(
var muxSettingsExpanded by rememberSaveable { mutableStateOf(false) }
var fragmentSettingsExpanded by rememberSaveable { mutableStateOf(false) }
var observatorySettingsExpanded by rememberSaveable { mutableStateOf(false) }
var advancedSettingsExpanded by rememberSaveable { mutableStateOf(false) }
var modeSettingsExpanded by rememberSaveable { mutableStateOf(false) }
var advancedSettingsExpanded by rememberSaveable { mutableStateOf(true) }
var modeSettingsExpanded by rememberSaveable { mutableStateOf(true) }
var localDns by rememberMmkvBool(AppConfig.PREF_LOCAL_DNS_ENABLED, false)
var fakeDns by rememberMmkvBool(AppConfig.PREF_FAKE_DNS_ENABLED, false)
@@ -120,8 +125,13 @@ fun SettingsScreen(
var confirmRemove by rememberMmkvBool(AppConfig.PREF_CONFIRM_REMOVE, false)
var doubleColumnDisplay by rememberMmkvBool(AppConfig.PREF_DOUBLE_COLUMN_DISPLAY, false)
var groupAllDisplay by rememberMmkvBool(AppConfig.PREF_GROUP_ALL_DISPLAY, false)
var language by rememberMmkvString(AppConfig.PREF_LANGUAGE, "auto")
var language by remember {
mutableStateOf(
MmkvManager.decodeSettingsString(AppConfig.PREF_LANGUAGE, "auto") ?: "auto"
)
}
var uiModeNight by rememberMmkvString(AppConfig.PREF_UI_MODE_NIGHT, "0")
var dynamicColor by rememberMmkvBool(AppConfig.PREF_DYNAMIC_COLOR, true)
var ipv6Enabled by rememberMmkvBool(AppConfig.PREF_IPV6_ENABLED, false)
var preferIpv6 by rememberMmkvBool(AppConfig.PREF_PREFER_IPV6, false)
@@ -144,6 +154,14 @@ fun SettingsScreen(
val effectiveLocalProxy = enableLocalProxy || localProxyForced
val muxXudpConcurrencyInt = muxXudpConcurrency.toIntOrNull() ?: 8
val dynamicColorSupported = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
LaunchedEffect(dynamicColorSupported) {
if (!dynamicColorSupported && dynamicColor) {
dynamicColor = false
ThemeManager.setDynamicColorEnabled(false)
}
}
val languageEntries = stringArrayResource(R.array.language_select).toList()
val languageValues = stringArrayResource(R.array.language_select_value).toList()
val uiModeNightEntries = stringArrayResource(R.array.ui_mode_night).toList()
@@ -220,12 +238,25 @@ fun SettingsScreen(
SettingsChangeManager.makeSetupGroupTab()
}
)
SettingsSwitchItem(
title = stringResource(R.string.title_pref_dynamic_color),
summary = stringResource(R.string.summary_pref_dynamic_color),
checked = dynamicColor,
enabled = dynamicColorSupported,
onCheckedChange = {
dynamicColor = it
ThemeManager.setDynamicColorEnabled(it)
}
)
SettingsListItem(
title = stringResource(R.string.title_language),
entries = languageEntries,
values = languageValues,
selectedValue = language,
onSelected = { language = it }
onSelected = {
language = it
AppLocaleManager.setApplicationLanguage(it)
}
)
SettingsListItem(
title = stringResource(R.string.title_pref_ui_mode_night),
@@ -453,14 +484,14 @@ fun SettingsScreen(
onCheckedChange = { mux = it }
)
SettingsEditItem(
title = stringResource(R.string.title_pref_mux_concurency),
title = stringResource(R.string.title_pref_mux_concurrency),
value = muxConcurrency,
enabled = mux,
keyboardNumber = true,
onValueChanged = { muxConcurrency = it }
)
SettingsEditItem(
title = stringResource(R.string.title_pref_mux_xudp_concurency),
title = stringResource(R.string.title_pref_mux_xudp_concurrency),
value = muxXudpConcurrency,
enabled = mux,
keyboardNumber = true,
@@ -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))
}
}
)
@@ -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))
}
}
)
@@ -227,7 +227,8 @@ fun SubEditScreen(
value = prevProfile,
options = profileSuggestions,
onValueChange = { prevProfile = it },
editable = true
editable = true,
supportingText = stringResource(R.string.sub_setting_entry_proxy_tip)
)
FormDropdownField(
label = stringResource(R.string.sub_setting_next_profile),
@@ -235,7 +236,8 @@ fun SubEditScreen(
value = nextProfile,
options = profileSuggestions,
onValueChange = { nextProfile = it },
editable = true
editable = true,
supportingText = stringResource(R.string.sub_setting_exit_proxy_tip)
)
}
}
@@ -4,6 +4,7 @@ import android.content.Intent
import android.graphics.Bitmap
import android.os.Bundle
import androidx.activity.viewModels
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
@@ -15,7 +16,6 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
@@ -51,13 +51,17 @@ import com.v2ray.ang.ui.compose.QRCodeDialog
import com.v2ray.ang.ui.compose.ReorderableListItem
import com.v2ray.ang.ui.compose.SelectListDialog
import com.v2ray.ang.ui.compose.SettingsSwitchItem
import com.v2ray.ang.ui.compose.colorFabActive
import com.v2ray.ang.ui.compose.verticalScrollbar
import com.v2ray.ang.util.QRCodeDecoder
import com.v2ray.ang.util.Utils
import sh.calvin.reorderable.ReorderableItem
import sh.calvin.reorderable.rememberReorderableLazyListState
private enum class SubscriptionShareAction(@StringRes val labelRes: Int) {
QRCode(R.string.share_subscription_qrcode),
Clipboard(R.string.share_subscription_clipboard)
}
class SubSettingActivity : BaseComponentActivity() {
private val viewModel: SubscriptionsViewModel by viewModels()
@@ -82,8 +86,7 @@ class SubSettingActivity : BaseComponentActivity() {
onShareClipboard = { url ->
Utils.setClipboard(this, url)
toast(getString(R.string.toast_success))
},
shareSubMethodEntries = resources.getStringArray(R.array.share_sub_method).toList()
}
)
}
@@ -97,7 +100,6 @@ class SubSettingActivity : BaseComponentActivity() {
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SubSettingScreen(
viewModel: SubscriptionsViewModel,
@@ -108,8 +110,7 @@ fun SubSettingScreen(
onEditSub: (String) -> Unit,
onRemoveSub: (String) -> Unit,
onShareQRCode: (String) -> Bitmap?,
onShareClipboard: (String) -> Unit,
shareSubMethodEntries: List<String>
onShareClipboard: (String) -> Unit
) {
val subscriptions by viewModel.subsFlow.collectAsStateWithLifecycle()
var showUpdateDialog by remember { mutableStateOf(false) }
@@ -133,10 +134,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))
}
}
)
@@ -200,14 +201,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 = {
@@ -216,7 +217,7 @@ fun SubSettingScreen(
}) {
Icon(
painter = painterResource(R.drawable.ic_delete_24dp),
contentDescription = "Delete"
contentDescription = stringResource(R.string.acc_delete)
)
}
}
@@ -231,7 +232,7 @@ fun SubSettingScreen(
modifier = Modifier.scale(0.7f),
colors = SwitchDefaults.colors(
checkedThumbColor = MaterialTheme.colorScheme.onSecondary,
checkedTrackColor = colorFabActive
checkedTrackColor = MaterialTheme.colorScheme.secondary
)
)
}
@@ -246,19 +247,13 @@ fun SubSettingScreen(
if (shareTarget != null) {
val (_, url) = shareTarget!!
SelectListDialog(
options = shareSubMethodEntries,
onSelected = { index, _ ->
options = SubscriptionShareAction.entries,
optionText = { stringResource(it.labelRes) },
onSelected = { action ->
shareTarget = null
when (index) {
0 -> {
// QRCode
showQRCodeBitmap = onShareQRCode(url)
}
1 -> {
// Export to clipboard
onShareClipboard(url)
}
when (action) {
SubscriptionShareAction.QRCode -> showQRCodeBitmap = onShareQRCode(url)
SubscriptionShareAction.Clipboard -> onShareClipboard(url)
}
},
onDismiss = { shareTarget = null }
@@ -327,12 +322,12 @@ fun SubSettingScreen(
showUpdateDialog = false
onSubUpdate()
}) {
Text(text = stringResource(android.R.string.ok))
Text(text = stringResource(R.string.action_ok))
}
},
dismissButton = {
TextButton(onClick = { showUpdateDialog = false }) {
Text(text = stringResource(android.R.string.cancel))
Text(text = stringResource(R.string.action_cancel))
}
}
)
@@ -5,6 +5,7 @@ import android.net.Uri
import android.os.Bundle
import android.provider.OpenableColumns
import androidx.activity.viewModels
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
@@ -20,8 +21,6 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
@@ -54,6 +53,7 @@ import com.v2ray.ang.extension.toastSuccess
import com.v2ray.ang.handler.MmkvManager
import com.v2ray.ang.handler.SettingsManager
import com.v2ray.ang.ui.base.HelperBaseComponentActivity
import com.v2ray.ang.ui.compose.AppDropdownMenuItems
import com.v2ray.ang.ui.compose.AppTopBar
import com.v2ray.ang.ui.compose.DeleteConfirmDialog
import com.v2ray.ang.ui.compose.ItemDivider
@@ -69,6 +69,12 @@ import java.io.File
import java.text.DateFormat
import java.util.Date
private enum class AddAssetMenuAction(@StringRes val labelRes: Int) {
File(R.string.menu_item_add_file),
Url(R.string.menu_item_add_url),
QRCode(R.string.menu_item_scan_qrcode)
}
class UserAssetActivity : HelperBaseComponentActivity() {
private val viewModel: UserAssetViewModel by viewModels()
@@ -238,7 +244,6 @@ class UserAssetActivity : HelperBaseComponentActivity() {
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun UserAssetScreen(
viewModel: UserAssetViewModel,
@@ -275,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,
@@ -284,22 +289,18 @@ fun UserAssetScreen(
offset = DpOffset(x = 0.dp, y = 0.dp),
modifier = Modifier.wrapContentWidth(Alignment.End)
) {
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_item_add_file)) },
onClick = { showAddMenu = false; onAddFileClick() }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_item_add_url)) },
onClick = { showAddMenu = false; onAddUrlClick() }
)
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_item_scan_qrcode)) },
onClick = { showAddMenu = false; onAddQrcodeClick() }
)
AppDropdownMenuItems(AddAssetMenuAction.entries, { it.labelRes }) { action ->
showAddMenu = false
when (action) {
AddAssetMenuAction.File -> onAddFileClick()
AddAssetMenuAction.Url -> onAddUrlClick()
AddAssetMenuAction.QRCode -> onAddQrcodeClick()
}
}
}
}
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))
}
}
)
@@ -399,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)
)
}
@@ -407,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)
)
}
@@ -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)
)
}
}
@@ -0,0 +1,46 @@
package com.v2ray.ang.util
import android.content.Context
import coil.ImageLoader
import coil.decode.DataSource
import coil.fetch.DrawableResult
import coil.fetch.FetchResult
import coil.fetch.Fetcher
import coil.request.Options
import com.v2ray.ang.AppConfig
class AppIconFetcher(
private val packageName: String,
private val context: Context
) : Fetcher {
override suspend fun fetch(): FetchResult? {
val drawable = try {
if (packageName == AppConfig.UNIDENTIFIED_PACKAGE) {
context.getDrawable(android.R.drawable.ic_menu_help)
?: context.getDrawable(android.R.drawable.sym_def_app_icon)
} else {
context.packageManager.getApplicationIcon(packageName)
}
} catch (_: Exception) {
null
} ?: return null
return DrawableResult(
drawable = drawable,
isSampled = false,
dataSource = DataSource.DISK
)
}
class Factory(private val context: Context) : Fetcher.Factory<Any> {
override fun create(data: Any, options: Options, imageLoader: ImageLoader): Fetcher? {
val dataString = data.toString()
if (dataString.startsWith("appicon:")) {
val pkg = dataString.substringAfter("appicon:")
return AppIconFetcher(pkg, context)
}
return null
}
}
}
@@ -24,10 +24,9 @@ object AppManagerUtil {
val applicationInfo = pkg.applicationInfo ?: continue
val appName = applicationInfo.loadLabel(packageManager).toString()
val appIcon = applicationInfo.loadIcon(packageManager) ?: continue
val isSystemApp = applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM > 0
val appInfo = AppInfo(appName, pkg.packageName, appIcon, isSystemApp, 0)
val appInfo = AppInfo(appName, pkg.packageName, isSystemApp, 0)
apps.add(appInfo)
}
@@ -1,34 +0,0 @@
package com.v2ray.ang.util
import android.content.Context
import android.content.ContextWrapper
import android.content.res.Configuration
import android.content.res.Resources
import android.os.LocaleList
import java.util.Locale
open class MyContextWrapper(base: Context?) : ContextWrapper(base) {
companion object {
/**
* Wraps the context with a new locale.
*
* @param context The original context.
* @param newLocale The new locale to set.
* @return A ContextWrapper with the new locale.
*/
fun wrap(context: Context, newLocale: Locale?): ContextWrapper {
var mContext = context
val res: Resources = mContext.resources
val configuration: Configuration = res.configuration
val locale = newLocale ?: Locale.getDefault()
configuration.setLocale(locale)
val localeList = LocaleList(locale)
LocaleList.setDefault(localeList)
configuration.setLocales(localeList)
mContext = mContext.createConfigurationContext(configuration)
return ContextWrapper(mContext)
}
}
}
@@ -347,8 +347,7 @@ object Utils {
if (context == null) return ""
return try {
context.getExternalFilesDir(AppConfig.DIR_ASSETS)?.absolutePath
?: context.getDir(AppConfig.DIR_ASSETS, 0).absolutePath
context.getDir(AppConfig.DIR_ASSETS, Context.MODE_PRIVATE).absolutePath
} catch (e: Exception) {
LogUtil.e(AppConfig.TAG, "Failed to get user asset path", e)
""
@@ -0,0 +1 @@
unqualifiedResLocale=en
+284 -206
View File
@@ -1,19 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" translatable="false">v2rayNG</string>
<string name="app_widget_name">التبديل</string>
<string name="app_tile_name">التبديل</string>
<string name="app_tile_first_use">أول استخدام لهذه الميزة، يرجى استخدام التطبيق لإضافة خادم</string>
<string name="navigation_drawer_open">فتح درج التنقل</string>
<string name="navigation_drawer_close">إغلاق درج التنقل</string>
<string name="migration_success">نجحت عملية ترحيل البيانات!</string>
<string name="action_stop_service">Stop service</string>
<string name="action_stop_service">إيقاف الخدمة</string>
<string name="action_ok">موافق</string>
<string name="action_cancel">إلغاء</string>
<string name="migration_fail">فشلت عملية ترحيل البيانات!</string>
<string name="pull_down_to_refresh">Please pull down to refresh!</string>
<string name="pull_down_to_refresh">اسحب لأسفل للتحديث!</string>
<!-- Notifications -->
<string name="notification_action_stop_v2ray">إيقاف</string>
<string name="toast_permission_denied">تعذر الحصول على الإذن</string>
<string name="toast_permission_denied_notification">Unable to obtain the notification permission</string>
<string name="toast_permission_denied_notification">تعذر الحصول على إذن الإشعارات</string>
<string name="notification_action_more">انقر للمزيد</string>
<string name="toast_services_start">بدء الخدمات</string>
<string name="toast_services_stop">إيقاف الخدمات</string>
@@ -24,21 +27,21 @@
<string name="title_server">ملف التكوين</string>
<string name="menu_item_add_config">إضافة تكوين</string>
<string name="menu_item_save_config">حفظ التكوين</string>
<string name="menu_item_edit_config">Edit configuration</string>
<string name="menu_item_edit_config">تعديل التكوين</string>
<string name="menu_item_del_config">حذف التكوين</string>
<string name="menu_item_import_config_qrcode">استيراد التكوين من رمز الاستجابة السريعة (QRcode)</string>
<string name="menu_item_import_config_qrcode">استيراد التكوين من رمز QR</string>
<string name="menu_item_import_config_clipboard">استيراد التكوين من الحافظة</string>
<string name="menu_item_import_config_local">Import config from locally</string>
<string name="menu_item_import_config_policy_group">Add [Policy group]</string>
<string name="menu_item_import_config_proxy_chain">Add [Proxy chain]</string>
<string name="menu_item_import_config_manually_vmess">الكتابة يدويًا [VMess]</string>
<string name="menu_item_import_config_manually_vless">الكتابة يدويًا [VLESS]</string>
<string name="menu_item_import_config_manually_ss">الكتابة يدويًا [Shadowsocks]</string>
<string name="menu_item_import_config_manually_socks">الكتابة يدويًا [SOCKS]</string>
<string name="menu_item_import_config_manually_http">Type manually[HTTP]</string>
<string name="menu_item_import_config_manually_trojan">الكتابة يدويًا [Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">الكتابة يدويًا [Wireguard]</string>
<string name="menu_item_import_config_manually_hysteria2">Type manually[Hysteria2]</string>
<string name="menu_item_import_config_local">استيراد التكوين من الجهاز</string>
<string name="menu_item_import_config_policy_group">إضافة [مجموعة سياسات]</string>
<string name="menu_item_import_config_proxy_chain">إضافة [سلسلة وكلاء]</string>
<string name="menu_item_import_config_manually_vmess">إضافة [VMess]</string>
<string name="menu_item_import_config_manually_vless">إضافة [VLESS]</string>
<string name="menu_item_import_config_manually_ss">إضافة [Shadowsocks]</string>
<string name="menu_item_import_config_manually_socks">إضافة [SOCKS]</string>
<string name="menu_item_import_config_manually_http">إضافة [HTTP]</string>
<string name="menu_item_import_config_manually_trojan">إضافة [Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">إضافة [WireGuard]</string>
<string name="menu_item_import_config_manually_hysteria2">إضافة [Hysteria2]</string>
<string name="confirm_delete_visible_profiles">هل أنت متأكد من أنك تريد حذف جميع ملفات التعريف المعروضة حاليًا؟</string>
<string name="confirm_delete_duplicate_profiles">هل أنت متأكد من أنك تريد حذف جميع ملفات التعريف المكررة المعروضة حاليًا؟</string>
<string name="confirm_delete_invalid_profiles">يرجى اختبار ملفات التعريف أولًا. هل أنت متأكد من أنك تريد حذف جميع ملفات التعريف غير الصالحة المعروضة حاليًا؟</string>
@@ -54,7 +57,6 @@
<string name="server_lab_port">المنفذ</string>
<string name="server_lab_id">المعرف</string>
<string name="server_lab_alterid">AlterId</string>
<string name="server_lab_security">الأمان</string>
<string name="server_lab_network">الشبكة</string>
<string name="server_lab_more_function">النقل</string>
@@ -71,16 +73,16 @@
<string name="server_lab_path">path</string>
<string name="server_lab_path_ws">ws path</string>
<string name="server_lab_path_httpupgrade">httpupgrade path</string>
<string name="server_lab_path_xhttp">xhttp path </string>
<string name="server_lab_path_xhttp">xhttp path</string>
<string name="server_lab_path_h2">h2 path</string>
<string name="server_lab_path_quic">QUIC key</string>
<string name="server_lab_path_kcp">kcp seed</string>
<string name="server_lab_path_grpc">gRPC serviceName</string>
<string name="server_lab_stream_security">TLS</string>
<string name="server_lab_stream_fingerprint" translatable="false">البصمة</string>
<string name="server_lab_stream_alpn" translatable="false">بروتوكول الطبقة الآخرى التالية (ALPN)</string>
<string name="server_lab_allow_insecure">السماح غير الآمن</string>
<string name="server_lab_sni">SNI</string>
<string name="server_lab_stream_security" translatable="false">TLS</string>
<string name="server_lab_stream_fingerprint">البصمة</string>
<string name="server_lab_stream_alpn" translatable="false">ALPN</string>
<string name="server_lab_allow_insecure">تخطي التحقق من الشهادة (allowInsecure)</string>
<string name="server_lab_sni" translatable="false">SNI</string>
<string name="server_lab_address3">العنوان</string>
<string name="server_lab_port3">المنفذ</string>
<string name="server_lab_id3">كلمة المرور</string>
@@ -88,16 +90,16 @@
<string name="server_lab_id4">كلمة المرور (اختياري)</string>
<string name="server_lab_security4">المستخدم (اختياري)</string>
<string name="server_lab_encryption">التشفير</string>
<string name="server_lab_flow">التدفق</string>
<string name="server_lab_public_key" translatable="false">المفتاح العام</string>
<string name="server_lab_preshared_key">PreSharedKey(optional)</string>
<string name="server_lab_short_id" translatable="false">المعرّف القصير</string>
<string name="server_lab_flow">التدفق (flow)</string>
<string name="server_lab_public_key">المفتاح العام</string>
<string name="server_lab_preshared_key">PreSharedKey (اختياري)</string>
<string name="server_lab_short_id">المعرّف القصير</string>
<string name="server_lab_spider_x" translatable="false">SpiderX</string>
<string name="server_lab_mldsa65_verify">Mldsa65Verify</string>
<string name="server_lab_secret_key" translatable="false">المفتاح السري</string>
<string name="server_lab_reserved">محجوز (اختياري)</string>
<string name="server_lab_mldsa65_verify" translatable="false">mldsa65Verify</string>
<string name="server_lab_secret_key">المفتاح السري</string>
<string name="server_lab_reserved">Reserved (اختياري، مفصول بفواصل)</string>
<string name="server_lab_local_address">العنوان المحلي (اختياري IPv4/IPv6، مفصولة بفواصل)</string>
<string name="server_lab_local_mtu">Mtu (اختياري، الافتراضي 1420)</string>
<string name="server_lab_local_mtu">MTU (اختياري، الافتراضي 1420)</string>
<string name="server_lab_kcp_mtu">mKCP MTU (اختياري، الافتراضي في النواة 1350)</string>
<string name="server_lab_kcp_tti">mKCP TTI (اختياري، الافتراضي في النواة 50)</string>
<string name="toast_success">نجاح</string>
@@ -112,38 +114,41 @@
<string name="server_lab_content">المحتوى</string>
<string name="toast_none_data_clipboard">لا توجد بيانات في الحافظة</string>
<string name="toast_invalid_url">رابط URL غير صالح</string>
<string name="toast_insecure_url_protocol">Please do not use the insecure HTTP protocol subscription address</string>
<string name="toast_insecure_url_protocol">يرجى عدم استخدام عنوان اشتراك ببروتوكول HTTP غير الآمن</string>
<string name="server_lab_need_inbound">تأكد من أن منفذ الاتصالات الواردة يتوافق مع الإعدادات</string>
<string name="toast_malformed_josn">تكوين مشوه</string>
<string name="toast_malformed_json">تنسيق التكوين غير صالح.</string>
<string name="server_lab_request_host6">مضيف (SNI) (اختياري)</string>
<string name="toast_action_not_allowed">الإجراء غير مسموح به</string>
<string name="server_obfs_password">Obfs password</string>
<string name="server_lab_port_hop">Port Hopping</string>
<string name="server_lab_port_hop_interval">Port Hopping Interval</string>
<string name="server_lab_bandwidth_down">Bandwidth down (Supported units: k/m/g/t)</string>
<string name="server_lab_bandwidth_up">Bandwidth up (Supported units: k/m/g/t)</string>
<string name="server_lab_xhttp_mode">XHTTP Mode</string>
<string name="server_lab_xhttp_extra">XHTTP Extra raw JSON, format: { XHTTPObject }</string>
<string name="server_lab_final_mask">finalMask raw JSON, format: { FinalMaskObject }</string>
<string name="server_lab_ech_config_list">EchConfigList</string>
<string name="server_lab_verify_peer_cert_by_name">Verify Peer Cert By Name</string>
<string name="server_lab_pinned_ca256">Certificate fingerprint (SHA-256)</string>
<string name="pinned_ca256_action_fetch">Fetch and fill certificate fingerprint</string>
<string name="toast_fetch_cert_sha256_success">Certificate fingerprint fetched successfully</string>
<string name="toast_fetch_cert_sha256_failed">Failed to fetch certificate fingerprint</string>
<string name="server_obfs_password">كلمة مرور Obfs</string>
<string name="server_lab_port_hop">التنقل بين المنافذ (يتجاوز قيمة المنفذ)</string>
<string name="server_lab_port_hop_interval">فاصل تبديل المنفذ (بالثواني)</string>
<string name="server_lab_bandwidth_down">عرض النطاق للتنزيل (الوحدات المدعومة: k/m/g/t)</string>
<string name="server_lab_bandwidth_up">عرض النطاق للرفع (الوحدات المدعومة: k/m/g/t)</string>
<string name="server_lab_xhttp_mode">وضع XHTTP</string>
<string name="server_lab_xhttp_extra">JSON خام لحقل XHTTP Extra، بالتنسيق: { XHTTPObject }</string>
<string name="server_lab_final_mask">JSON خام لحقل finalMask، بالتنسيق: { FinalMaskObject }</string>
<string name="server_lab_ech_config_list" translatable="false">echConfigList</string>
<string name="server_lab_verify_peer_cert_by_name">التحقق من شهادة النظير بالاسم</string>
<string name="server_lab_pinned_ca256">بصمة الشهادة (SHA-256)</string>
<string name="server_lab_browser_dialer">تمكين Browser Dialer</string>
<string name="server_lab_browser_dialer_tip">يدعم فقط اتصالات xhttp (packet-up) وws الصادرة؛ قد يتم تجاهل الإعدادات المتعلقة بـ TLS أو قد تتعارض</string>
<string name="toast_allow_insecure_deprecated">تستخدم العقدة الحالية اتصالاً غير مشفر. قد تتمكن تجهيزات الشبكة الوسيطة الخاضعة لسيطرة حكومات استبدادية من الاطلاع مباشرةً على اتصالاتك.\nلأسباب أمنية، لا يمكن الاتصال بهذه العقد عبر نواة Xray الإصدار 26.2.6 أو أحدث.\nإذا كانت العقدة من إعدادك، ففعّل تشفيراً آمناً مثل TLS أو ثبّت بصمة الشهادة pinnedCA256.\nإذا كانت العقدة تابعة لمزوّد خدمة، فتواصل معه لإكمال الترقية التقنية. إذا رفض المزوّد التعاون، فنوصي بالانتقال إلى مزوّد يهتم أكثر بأمان المستخدمين.\nلمزيد من المعلومات، تفضل بزيارة https://github.com/2dust/v2rayN/discussions/9460</string>
<string name="pinned_ca256_action_fetch">جلب بصمة الشهادة</string>
<string name="toast_fetch_cert_sha256_success">تم جلب بصمة الشهادة بنجاح</string>
<string name="toast_fetch_cert_sha256_failed">فشل جلب بصمة الشهادة</string>
<!-- UserAssetActivity -->
<string name="toast_asset_copy_failed">فشل نسخ الملف، يرجى استخدام مدير الملفات</string>
<string name="menu_item_add_asset">إضافة أصل</string>
<string name="menu_item_add_file">إضافة ملفات</string>
<string name="menu_item_add_url">إضافة URL</string>
<string name="menu_item_scan_qrcode">مسح رمز الاستجابة السريعة (QRcode)</string>
<string name="menu_item_scan_qrcode">مسح رمز QR</string>
<string name="title_url" translatable="false">URL</string>
<string name="menu_item_download_file">تنزيل الملفات</string>
<string name="title_user_asset_add_url">إضافة عنوان URL للأصل</string>
<string name="msg_file_not_found">الملف غير موجود</string>
<string name="msg_remark_is_duplicate">الملاحظات موجودة بالفعل</string>
<string name="asset_geo_files_sources">Geo files source (optional)</string>
<string name="asset_geo_files_sources">مصدر ملفات Geo (اختياري)</string>
<!-- PerAppProxyActivity -->
<string name="msg_dialog_progress">جار التحميل</string>
@@ -152,13 +157,13 @@
<string name="menu_item_invert_selection">عكس الاختيار</string>
<string name="msg_enter_keywords">أدخل الكلمات الرئيسية</string>
<string name="switch_bypass_apps_mode">وضع التجاوز</string>
<string name="menu_item_select_proxy_app">تحديد تطبيق الوكيل تلقائيًا</string>
<string name="menu_item_select_proxy_app">تحديد التطبيقات التي ستستخدم الوكيل تلقائيًا</string>
<string name="msg_downloading_content">جارٍ تنزيل المحتوى</string>
<string name="menu_item_export_proxy_app">تصدير إلى الحافظة</string>
<string name="menu_item_import_proxy_app">استيراد من الحافظة</string>
<string name="per_app_proxy_settings">Per-app settings</string>
<string name="per_app_proxy_settings_enable">Enable per-app</string>
<string name="per_app_proxy_settings">إعدادات كل تطبيق</string>
<string name="per_app_proxy_settings_enable">تمكين الإعدادات لكل تطبيق</string>
<string name="app_picker_unknown_app">تطبيق غير معروف (UID غير محدد)</string>
<!-- Preferences -->
<string name="title_settings">الإعدادات</string>
@@ -166,20 +171,24 @@
<string name="title_core_settings">إعدادات النواة</string>
<string name="title_vpn_settings">إعدادات VPN</string>
<string name="title_pref_per_app_proxy">الوكيل لكل تطبيق</string>
<string name="summary_pref_per_app_proxy">عام: التطبيق المحدد هو وكيل، غير المحدد اتصال مباشر؛ \nوضع التجاوز: التطبيق المحدد متصل مباشرة، غير المحدد وكيل. \nخيار تحديد تطبيق الوكيل تلقائيًا في القائمة</string>
<string name="title_pref_is_booted">Auto connect at startup</string>
<string name="summary_pref_is_booted">Automatically connects to the selected server at startup, which may be unsuccessful</string>
<string name="summary_pref_per_app_proxy">عام: تستخدم التطبيقات المحددة الوكيل، وتتصل التطبيقات غير المحددة مباشرة؛\nوضع التجاوز: تتصل التطبيقات المحددة مباشرة، وتستخدم التطبيقات غير المحددة الوكيل.\nيتوفر في القائمة خيار لتحديد التطبيقات التي ستستخدم الوكيل تلقائيًا.</string>
<string name="title_pref_is_booted">الاتصال تلقائياً عند بدء التشغيل</string>
<string name="summary_pref_is_booted">الاتصال تلقائياً بالخادم المحدد عند بدء التشغيل؛ قد لا تنجح المحاولة</string>
<string name="title_pref_auto_remove_invalid_after_test">Auto delete invalid config after testing</string>
<string name="summary_pref_auto_remove_invalid_after_test">Test results may not be accurate; deleted config cannot be recovered.</string>
<string name="title_pref_auto_sort_after_test">Auto sort after testing</string>
<string name="summary_pref_auto_sort_after_test">Test results may not be accurate;</string>
<string name="subscription_updater_job_tips">ستعمل المهمة في الخلفية، وسيُعرض تقدمها في الإشعار.</string>
<string name="title_pref_auto_test_after_update_subscription">اختبار تلقائي بعد تحديث الاشتراك</string>
<string name="summary_pref_auto_test_after_update_subscription">يستغرق الاختبار التلقائي وقتاً طويلاً. عند تمكينه، ستعمل المهمة في الخلفية؛ وإلا فستعمل في الصفحة الحالية.</string>
<string name="title_pref_auto_remove_invalid_after_test">حذف الإعدادات غير الصالحة تلقائياً بعد الاختبار</string>
<string name="summary_pref_auto_remove_invalid_after_test">قد لا تكون نتائج الاختبار دقيقة؛ لا يمكن استعادة الإعدادات المحذوفة.</string>
<string name="title_pref_auto_sort_after_test">الفرز تلقائياً بعد الاختبار</string>
<string name="summary_pref_auto_sort_after_test">قد لا تكون نتائج الاختبار دقيقة؛</string>
<string name="title_mux_settings">إعدادات Mux</string>
<string name="title_pref_mux_enabled">تمكين Mux</string>
<string name="summary_pref_mux_enabled">أسرع، لكن قد يتسبب في اتصال غير مستقر\nتخصيص كيفية التعامل مع TCP و UDP و QUIC أدناه</string>
<string name="title_pref_mux_concurency">اتصالات TCP(النطاق من -1 إلى 1024)</string>
<string name="title_pref_mux_xudp_concurency">اتصالات XUDP(النطاق من -1 إلى 1024)</string>
<string name="title_pref_mux_concurrency">اتصالات TCP(النطاق من -1 إلى 1024)</string>
<string name="title_pref_mux_xudp_concurrency">اتصالات XUDP(النطاق من -1 إلى 1024)</string>
<string name="title_pref_mux_xudp_quic">التعامل مع QUIC في نفق mux</string>
<string-array name="mux_xudp_quic_entries">
<item>رفض</item>
@@ -188,17 +197,18 @@
</string-array>
<string name="title_pref_speed_enabled">تمكين عرض السرعة</string>
<string name="summary_pref_speed_enabled">عرض السرعة الحالية في الإشعار.\nستتغير أيقونة الإشعار بناءً على الاستخدام.</string>
<string name="title_pref_sniffing_enabled">تفعيل استخراج الشبكة</string>
<string name="summary_pref_sniffing_enabled">محاولة استخراج النطاق من الحزمة (مفعل افتراضيًا)</string>
<string name="title_pref_route_only_enabled">تفعيل التوجيه فقط</string>
<string name="summary_pref_speed_enabled">عرض سرعات الاتصال الحالية في الإشعار.\nتوضح الأيقونة ما إذا كانت حركة الوكيل أم الحركة المباشرة هي الغالبة.</string>
<string name="title_pref_sniffing_enabled">تفعيل اكتشاف نطاقات الوجهة (Sniffing)</string>
<string name="summary_pref_sniffing_enabled">اكتشاف نطاقات الوجهة من حركة المرور (مفعّل افتراضيًا).</string>
<string name="title_pref_route_only_enabled">تمكين routeOnly</string>
<string name="summary_pref_route_only_enabled">استخدم اسم النطاق الذي تم استخراجه للتوجيه فقط، واحتفظ بعنوان الوجهة كعنوان IP.</string>
<string name="title_pref_local_dns_enabled">تفعيل DNS المحلي</string>
<string name="summary_pref_local_dns_enabled">يتم معالجة DNS بواسطة وحدة DNS الأساسية (موصى به، إذا لزم تجاوز التوجيه لشبكة LAN وعنوان البر الرئيسي)</string>
<string name="title_pref_fake_dns_enabled">تفعيل DNS وهمي</string>
<string name="summary_pref_fake_dns_enabled">يعيد DNS المحلي عنوان IP وهمي (أسرع، ولكنه قد لا يعمل مع بعض التطبيقات)</string>
<string name="title_pref_fake_dns_enabled">تفعيل DNS اصطناعي (FakeDNS)</string>
<string name="summary_pref_fake_dns_enabled">يعيد FakeDNS عناوين IP اصطناعية لاستعلامات النطاقات (أسرع، لكنه قد لا يعمل مع بعض التطبيقات).</string>
<string name="title_pref_ipv6_enabled">تفعيل IPv6</string>
<string name="summary_pref_ipv6_enabled">إضافة عنوان IPv6 والمسارات إلى واجهة VPN</string>
@@ -206,44 +216,46 @@
<string name="title_pref_prefer_ipv6">تفضيل IPv6</string>
<string name="summary_pref_prefer_ipv6">تفضيل عناوين IPv6 عند حل أسماء النطاقات</string>
<string name="title_pref_remote_dns">DNS البعيد (udp/tcp/https/quic) (اختياري)</string>
<string name="summary_pref_remote_dns">DNS</string>
<string name="title_pref_remote_dns">DNS البعيد (UDP/TCP/HTTPS/QUIC، اختياري)</string>
<string name="summary_pref_remote_dns" translatable="false">DNS</string>
<string name="title_pref_vpn_dns">VPN DNS (IPv4/v6 فقط)</string>
<string name="title_pref_vpn_bypass_lan">Does VPN bypass LAN</string>
<string name="title_pref_vpn_dns">VPN DNS (IPv4/IPv6 فقط)</string>
<string name="title_pref_vpn_bypass_lan">هل تتجاوز VPN شبكة LAN؟</string>
<string name="title_pref_vpn_interface_address">VPN Interface Address</string>
<string name="title_pref_vpn_mtu">VPN MTU (default 1500)</string>
<string name="title_pref_vpn_interface_address">عنوان واجهة VPN</string>
<string name="title_pref_domestic_dns">DNS المحلي (اختياري)</string>
<string name="summary_pref_domestic_dns">DNS</string>
<string name="title_pref_vpn_mtu">قيمة MTU لشبكة VPN (الافتراضي 1500)</string>
<string name="title_pref_dns_hosts">DNS hosts (Format: domain:address,…)</string>
<string name="title_pref_domestic_dns">DNS المباشر (اختياري)</string>
<string name="summary_pref_domestic_dns" translatable="false">DNS</string>
<string name="title_pref_dns_hosts">تعيينات مضيفي DNS (التنسيق: domain:address,…)</string>
<string name="summary_pref_dns_hosts">domain:address,…</string>
<string name="title_pref_delay_test_url">True delay test url </string>
<string name="summary_pref_delay_test_url">Url</string>
<string name="title_pref_real_ping_concurrency">True delay test concurrency</string>
<string name="title_pref_delay_test_url">عنوان URL لاختبار التأخير الحقيقي</string>
<string name="summary_pref_delay_test_url" translatable="false">URL</string>
<string name="title_pref_real_ping_concurrency">اختبارات تأخير حقيقي متزامنة</string>
<string name="title_pref_ip_api_url">Current connection info test url</string>
<string name="summary_pref_ip_api_url">Url</string>
<string name="title_pref_ip_api_url">عنوان URL لاختبار معلومات الاتصال الحالي</string>
<string name="summary_pref_ip_api_url" translatable="false">URL</string>
<string name="title_pref_proxy_sharing_enabled">السماح بالاتصالات من الشبكة المحلية</string>
<string name="summary_pref_proxy_sharing_enabled">يمكن للأجهزة الأخرى الاتصال بالبروكسي بواسطة عنوان IP الخاص بك من خلال socks/http، يتم التمكين فقط في الشبكة الموثوقة لتجنب الاتصال غير المصرح به</string>
<string name="toast_warning_pref_proxysharing_short">السماح بالاتصالات من الشبكة المحلية، تأكد من أنك في شبكة موثوقة</string>
<string name="title_pref_socks_port">منفذ بروكسي Local</string>
<string name="title_pref_socks_port">منفذ البروكسي المحلي</string>
<string name="title_pref_enable_local_proxy">تفعيل الوكيل المحلي</string>
<string name="summary_pref_enable_local_proxy">When disabled, no SOCKS proxy is available, so subscription updates and similar actions cannot use the proxy</string>
<string name="title_pref_socks_enable_udp">SOCKS5 UDP</string>
<string name="summary_pref_socks_enable_udp">مصادقة socks5 ليست آمنة تمامًا عند استخدام UDP</string>
<string name="summary_pref_socks_port">منفذ بروكسي Local</string>
<string name="title_pref_dynamic_socks_port">Enable dynamic local proxy port</string>
<string name="summary_pref_dynamic_socks_port">Generate a random local proxy port each time the inbound is created</string>
<string name="title_pref_socks_username">Local proxy username (optional)</string>
<string name="summary_pref_socks_username">Username</string>
<string name="title_pref_socks_password">Local proxy password (optional)</string>
<string name="summary_pref_socks_password">Password</string>
<string name="summary_pref_enable_local_proxy">عند التعطيل، لن يتوفر وكيل SOCKS، ولذلك لن تتمكن تحديثات الاشتراك والإجراءات المشابهة من استخدام الوكيل</string>
<string name="title_pref_socks_enable_udp" translatable="false">SOCKS5 UDP</string>
<string name="summary_pref_socks_enable_udp">مصادقة SOCKS5 ليست آمنة تمامًا عند استخدام UDP.</string>
<string name="summary_pref_socks_port">منفذ البروكسي المحلي</string>
<string name="title_pref_dynamic_socks_port">تمكين منفذ وكيل محلي ديناميكي</string>
<string name="summary_pref_dynamic_socks_port">إنشاء منفذ وكيل محلي عشوائي في كل مرة يُنشأ فيها inbound</string>
<string name="title_pref_socks_username">اسم مستخدم الوكيل المحلي (اختياري)</string>
<string name="summary_pref_socks_username">اسم المستخدم</string>
<string name="title_pref_socks_password">كلمة مرور الوكيل المحلي (اختيارية)</string>
<string name="summary_pref_socks_password">كلمة المرور</string>
<string name="title_pref_local_dns_port">منفذ DNS المحلي</string>
<string name="summary_pref_local_dns_port">منفذ DNS المحلي</string>
@@ -252,24 +264,25 @@
<string name="summary_pref_confirm_remove">ما إذا كان حذف ملف التكوين يتطلب تأكيدًا ثانيًا من قبل المستخدم</string>
<string name="title_pref_append_http_proxy">Append HTTP Proxy to VPN</string>
<string name="summary_pref_append_http_proxy">HTTP proxy will be used directly from (browser/ some supported apps), without going through the virtual NIC device (Android 10+)</string>
<string name="title_pref_append_http_proxy">إضافة وكيل HTTP إلى شبكة VPN</string>
<string name="summary_pref_append_http_proxy">سيُستخدم وكيل HTTP مباشرةً من المتصفح وبعض التطبيقات المدعومة من دون المرور بواجهة NIC الافتراضية (Android 10+)</string>
<string name="title_pref_double_column_display">Enable double column display</string>
<string name="summary_pref_double_column_display">The profile list is displayed in double columns, allowing more content to be displayed on the screen.</string>
<string name="title_pref_double_column_display">تمكين العرض بعمودين</string>
<string name="summary_pref_double_column_display">عرض قائمة التكوينات في عمودين لإظهار محتوى أكبر على الشاشة.</string>
<string name="title_pref_group_all_display">إظهار علامة تبويب «الكل»</string>
<string name="summary_pref_group_all_display">جمع تكوينات جميع مجموعات الاشتراك في علامة تبويب واحدة.</string>
<string name="title_pref_group_all_display">Enable show all groups</string>
<string name="summary_pref_group_all_display">Add an extra "All Tabs" page</string>
<!-- AboutActivity -->
<string name="title_pref_feedback">ملاحظات</string>
<string name="summary_pref_feedback">ملاحظات التحسينات أو الأخطاء إلى GitHub</string>
<string name="summary_pref_tg_group">الانضمام إلى مجموعة Telegram</string>
<string name="toast_tg_app_not_found">لم يتم العثور على تطبيق Telegram</string>
<string name="title_privacy_policy">سياسة الخصوصية</string>
<string name="title_qr_code">QR code</string>
<string name="title_about">حول\nترجمة م. ابراهيم قاسم</string>
<string name="title_qr_code">رمز QR</string>
<string name="title_about">حول التطبيق</string>
<string name="title_source_code">الكود المصدري</string>
<string name="title_oss_license">Open Source licenses</string>
<string name="title_oss_license">تراخيص المصادر المفتوحة</string>
<string name="title_tg_channel">قناة Telegram</string>
<string name="title_pref_promotion">ترويج</string>
@@ -279,57 +292,66 @@
<string name="title_pref_auto_update_interval">فاصل التحديث التلقائي (بالدقائق، الحد الأدنى للقيمة 15)</string>
<string name="title_core_loglevel">مستوى السجل</string>
<string name="title_outbound_domain_resolve_method">Outbound domain pre-resolve method</string>
<string name="title_outbound_domain_resolve_method">حل أسماء نطاقات الاتصالات الصادرة (outbound)</string>
<string name="title_mode">الوضع</string>
<string name="title_mode_help">انقر هنا للحصول على مزيد من المساعدة</string>
<string name="title_language">اللغة</string>
<string name="title_ui_settings">إعدادات واجهة المستخدم</string>
<string name="title_pref_ui_mode_night">إعدادات وضع واجهة المستخدم ليلاً</string>
<string name="title_pref_use_hev_tunnel">Enable Hev TUN Feature</string>
<string name="summary_pref_use_hev_tunnel">When enabled, TUN will use hev-socks5-tunnel; otherwise, it will use xray-core.</string>
<string name="title_pref_hev_tunnel_loglevel">Hev Tun Log Level</string>
<string name="title_pref_hev_tunnel_rw_timeout">Hev Tun read/write timeout (seconds) (tcp,udp default 300,60)</string>
<string name="title_pref_dynamic_color">تفعيل الألوان الديناميكية</string>
<string name="summary_pref_dynamic_color">يعمل فقط على أندرويد 12+</string>
<string name="title_pref_use_hev_tunnel">تمكين ميزة Hev TUN</string>
<string name="summary_pref_use_hev_tunnel">عند التمكين، سيستخدم TUN ‏hev-socks5-tunnel؛ وإلا فسيستخدم xray-core.</string>
<string name="title_pref_hev_tunnel_loglevel">مستوى سجل Hev TUN</string>
<string name="title_pref_hev_tunnel_rw_timeout">مهلة القراءة/الكتابة لـ Hev TUN (بالثواني؛ القيم الافتراضية لـ TCP/UDP: 300/60)</string>
<string name="title_mode_settings">إعدادات الوضع</string>
<string name="title_root_mode_enabled">تمكين وضع Root (لمستخدمي Root)</string>
<string name="summary_root_mode_enabled">استخدام صلاحيات Root للوكيل الشفاف منخفض المستوى. يدير وضع Root حركة مرور الشبكة مباشرةً بدلاً من استخدام خدمة VPN في Android. أثناء تفعيله، لا يعمل الوضع العادي ولا توجيه التطبيقات ولا إعدادات VPN المرتبطة.</string>
<string name="toast_root_required">تتطلب هذه الميزة صلاحيات Root</string>
<string name="title_root_lan_sharing">مشاركة VPN مع أجهزة LAN / الأجهزة المربوطة (لمستخدمي Root)</string>
<string name="summary_root_lan_sharing">توجيه حركة مرور أجهزة نقطة اتصال Wi-Fi والأجهزة المربوطة عبر USB من خلال VPN.</string>
<string name="title_logcat">Logcat</string>
<string name="title_logcat" translatable="false">Logcat</string>
<string name="logcat_copy">نسخ</string>
<string name="logcat_clear">مسح</string>
<string name="logcat_share">مشاركة السجل</string>
<string name="title_service_restart">إعادة تشغيل الخدمة</string>
<string name="title_del_all_config">حذف جميع الإعدادات (قبل أول خطوة)</string>
<string name="title_del_duplicate_config">حذف الإعدادات المكررة (2)</string>
<string name="title_del_invalid_config">حذف الإعدادات غير الصالحة (بعد الاختبار؛ 4)</string>
<string name="title_export_all">تصدير الإعدادات غير المخصصة إلى الحافظة</string>
<string name="title_sub_setting">إعداد مجموعة الاشتراك</string>
<string name="title_del_all_config">حذف جميع الإعدادات</string>
<string name="title_del_duplicate_config">حذف الإعدادات المكررة</string>
<string name="title_del_invalid_config">حذف الإعدادات غير الصالحة</string>
<string name="title_export_all">تصدير التكوينات إلى الحافظة</string>
<string name="title_sub_setting">الاشتراكات</string>
<string name="sub_setting_remarks">ملاحظات</string>
<string name="sub_setting_url">عنوان URL اختياري</string>
<string name="sub_setting_user_agent">User Agent</string>
<string name="sub_setting_filter">Remarks regular filter</string>
<string name="sub_setting_user_agent" translatable="false">User Agent</string>
<string name="sub_setting_request_headers">رؤوس الطلب (بتنسيق JSON)</string>
<string name="sub_setting_filter">مرشح تعبير نمطي للملاحظات</string>
<string name="sub_setting_enable">تفعيل التحديث</string>
<string name="sub_auto_update">تفعيل التحديث التلقائي</string>
<string name="sub_allow_insecure_url">Allow insecure HTTP address</string>
<string name="sub_setting_pre_profile">Previous proxy configuration remarks</string>
<string name="sub_setting_next_profile">Next proxy configuration remarks</string>
<string name="sub_setting_pre_profile_tip">The configuration remarks exists and is unique</string>
<string name="sub_allow_insecure_url">السماح بعنوان HTTP غير آمن</string>
<string name="sub_setting_pre_profile">وكيل الدخول</string>
<string name="sub_setting_next_profile">وكيل الخروج</string>
<string name="sub_setting_pre_profile_tip">يجب أن تكون ملاحظات التكوين موجودة وفريدة</string>
<string name="sub_setting_entry_proxy_tip">يُضاف الوكيل المحدد قبل كل ملف تعريف في هذا الاشتراك كحلقة الدخول في سلسلة الوكلاء لذلك الملف.</string>
<string name="sub_setting_exit_proxy_tip">يُضاف الوكيل المحدد بعد كل ملف تعريف في هذا الاشتراك كحلقة الخروج في سلسلة الوكلاء لذلك الملف.</string>
<string name="toast_invalid_update_interval">فاصل التحديث غير صالح. الحد الأدنى هو 15 دقيقة.</string>
<string name="title_sub_update">تحديث الاشتراك (أول خطوة)</string>
<string name="title_ping_all_server">Tcping لجميع الإعدادات</string>
<string name="title_real_ping_all_server"> اختبر جميع الإعدادات (3)</string>
<string name="title_user_asset_setting">Asset files</string>
<string name="title_sort_by_test_results">الفرز حسب نتائج الاختبار (5)</string>
<string name="title_sub_update">تحديث الاشتراك</string>
<string name="title_ping_all_server">اختبار تأخير TCP (TCPing)</string>
<string name="title_real_ping_all_server">اختبار زمن الاستجابة الفعلي</string>
<string name="title_user_asset_setting">ملفات الأصول</string>
<string name="title_sort_by_test_results">الفرز حسب نتائج الاختبار</string>
<string name="title_filter_config">تصفية ملف التكوين</string>
<string name="filter_config_all">All</string>
<string name="filter_config_all">الكل</string>
<string name="summary_scan_qrcode">انقر على الشاشة لفتح الكاميرا والمسح</string>
<string name="title_del_duplicate_config_count">حذف %d من الإعدادات المكررة</string>
<string name="summary_scan_qrcode">Click screen open the camera scan</string>
<string name="title_del_config_count">Delete %d configurations</string>
<string name="title_import_config_count">Import %d configurations</string>
<string name="title_export_config_count">Export %d configurations</string>
<string name="title_update_config_count">Update %d configurations</string>
<string name="title_update_subscription_result">Updated %1$d configs (%2$d success, %3$d failed, %4$d skipped)</string>
<string name="title_update_subscription_no_subscription">No subscriptions</string>
<string name="toast_server_not_found_in_group">Selected server not found in current group</string>
<string name="toast_fragment_not_available">Unable to locate current view</string>
<string name="title_locate_selected_config">Locate the selected config</string>
<string name="title_del_config_count">حذف %d من التكوينات</string>
<string name="title_import_config_count">استيراد %d من التكوينات</string>
<string name="title_export_config_count">تصدير %d من التكوينات</string>
<string name="title_update_config_count">تحديث %d من التكوينات</string>
<string name="title_update_subscription_result">تم تحديث %1$d إعدادات (%2$d ناجحة، %3$d فاشلة، %4$d متخطاة)</string>
<string name="title_update_subscription_no_subscription">لا توجد اشتراكات</string>
<string name="toast_server_not_found_in_group">لم يُعثر على الخادم المحدد في المجموعة الحالية</string>
<string name="title_locate_selected_config">العثور على التكوين المحدد</string>
<string name="tasker_start_service">بدء الخدمة</string>
<string name="tasker_setting_confirm">تأكيد</string>
@@ -337,46 +359,50 @@
<!-- RoutingSettingActivity -->
<string name="routing_settings_domain_strategy">استراتيجية النطاق</string>
<string name="routing_settings_title">إعدادات التوجيه</string>
<string name="routing_settings_tips">افصل بعلامة الفاصلة (,) واختر أحد: domain أو ip أو process</string>
<string name="routing_settings_tips">لا تُطبَّق القاعدة إلا إذا تحققت جميع شروط المطابقة المحددة معًا (AND). تُفحص القواعد من الأعلى إلى الأسفل، وتُطبَّق أول قاعدة متطابقة.</string>
<string name="routing_settings_comma_tip">افصل بين الإدخالات المتعددة بفواصل (,).</string>
<string name="routing_settings_save">حفظ</string>
<string name="routing_settings_delete">مسح</string>
<string name="routing_settings_rule_title">Routing Rule Settings</string>
<string name="routing_settings_add_rule">Add rule</string>
<string name="routing_settings_rule_title">إعدادات قاعدة التوجيه</string>
<string name="routing_settings_add_rule">إضافة قاعدة</string>
<string name="routing_settings_import_predefined_rulesets">استيراد مجموعات قواعد محددة مسبقاً</string>
<string name="routing_settings_import_rulesets_tip">Existing rulesets will be deleted, are you sure to continue?</string>
<string name="routing_settings_import_rulesets_from_clipboard">Import ruleset from clipboard</string>
<string name="routing_settings_import_rulesets_tip">سيتم حذف مجموعات القواعد الحالية. هل تريد المتابعة؟</string>
<string name="routing_settings_import_rulesets_from_clipboard">استيراد مجموعة قواعد من الحافظة</string>
<string name="routing_settings_import_rulesets_from_qrcode">استيراد مجموعة قواعد من رمز الاستجابة السريعة</string>
<string name="routing_settings_export_rulesets_to_clipboard">Export ruleset to clipboard</string>
<string name="routing_settings_locked">Locked, keep this rule when import presets</string>
<string name="routing_settings_domain">domain</string>
<string name="routing_settings_ip">ip</string>
<string name="routing_settings_process">process (Package Name — only supported when using Xray TUN, routeOnly enabled, and Android 10+)</string>
<string name="routing_settings_port">port</string>
<string name="routing_settings_protocol">protocol</string>
<string name="routing_settings_protocol_tip">[http,tls,bittorrent]</string>
<string name="routing_settings_network">network</string>
<string name="routing_settings_outbound_tag">outboundTag</string>
<string name="routing_settings_export_rulesets_to_clipboard">تصدير مجموعة القواعد إلى الحافظة</string>
<string name="routing_settings_locked">مقفلة؛ احتفظ بهذه القاعدة عند استيراد الإعدادات المسبقة</string>
<string name="routing_settings_domain" translatable="false">domain</string>
<string name="routing_settings_ip" translatable="false">ip</string>
<string name="routing_settings_process">process (اسم الحزمة — مدعوم فقط عند استخدام Xray TUN وتمكين routeOnly وعلى Android 10+)</string>
<string name="routing_settings_process_select">اختيار اسم الحزمة</string>
<string name="routing_settings_port" translatable="false">port</string>
<string name="routing_settings_protocol" translatable="false">protocol</string>
<string name="routing_settings_protocol_tip" translatable="false">[http,tls,bittorrent]</string>
<string name="routing_settings_network" translatable="false">network</string>
<string name="routing_settings_outbound_tag_hint">proxy / direct / block / &lt;%1$s&gt;</string>
<string name="routing_settings_outbound_tag" translatable="false">outboundTag</string>
<string name="connection_test_pending">التحقق من الاتصال</string>
<string name="connection_test_testing">يجري الاختبار…</string>
<string name="connection_test_testing_count">Testing %d configurations…</string>
<string name="connection_test_available">نجاح: استغرق اتصال HTTP %dms</string>
<string name="connection_test_error">فشل اكتشاف اتصال الإنترنت: %s</string>
<string name="connection_test_testing_count">جارٍ اختبار %d من التكوينات…</string>
<string name="connection_test_available">تم الاتصال بنجاح خلال %1$s</string>
<string name="server_test_delay_value">%1$d ملي ثانية</string>
<string name="connection_test_error">فشل اختبار الاتصال: %s</string>
<string name="connection_test_fail">الإنترنت غير متاح</string>
<string name="connection_test_error_status_code">رمز الخطأ: #%d</string>
<string name="connection_connected">متصل، انقر للتحقق من الاتصال</string>
<string name="connection_connected">متصل. اضغط للتحقق من الاتصال.</string>
<string name="connection_not_connected">غير متصل</string>
<string name="connection_runing_task_left">Number of running test tasks: %s</string>
<string name="connection_running_task_left">الاختبارات قيد التشغيل: %s</string>
<string name="import_subscription_success">تم استيراد الاشتراك بنجاح</string>
<string name="import_subscription_failure">فشل استيراد الاشتراك</string>
<string name="title_fragment_settings">إعدادات الجزء</string>
<string name="title_pref_fragment_packets">حزم الجزء</string>
<string name="title_fragment_settings">إعدادات تجزئة الحزم (Fragment)</string>
<string name="title_pref_fragment_packets">الحزم المراد تجزئتها</string>
<string name="title_pref_fragment_length">طول الجزء (الحد الأدنى - الحد الأقصى)</string>
<string name="title_pref_fragment_interval">فاصل الجزء (الحد الأدنى - الحد الأقصى)</string>
<string name="title_pref_fragment_enabled">تفعيل الجزء</string>
<string name="title_pref_fragment_maxsplit">ماكس سبليت الجزء</string>
<string name="title_observatory_settings">إعدادات مراقبة الاتصال</string>
<string name="title_pref_fragment_enabled">تفعيل تجزئة الحزم</string>
<string name="title_pref_fragment_maxsplit">الحد الأقصى لعدد الأجزاء</string>
<string name="title_observatory_settings">إعدادات مراقبة الاتصال (Observatory)</string>
<string name="title_pref_observatory_least_ping_interval">فاصل leastPing</string>
<string name="title_pref_observatory_least_load_interval">فاصل leastLoad</string>
<string name="title_pref_observatory_least_load_method">طريقة HTTP لـ leastLoad</string>
@@ -385,81 +411,133 @@
<string name="toast_invalid_observatory_duration">مدة غير صالحة. استخدم قيمة مثل 3m أو 30s.</string>
<string name="toast_invalid_observatory_sampling">عدد العينات غير صالح. استخدم رقمًا موجبًا.</string>
<string name="update_check_for_update">Check for update</string>
<string name="update_already_latest_version">Already on the latest version</string>
<string name="update_new_version_found">New version found: %s</string>
<string name="update_now">Update now</string>
<string name="update_check_pre_release">Check Pre-release</string>
<string name="update_checking_for_update">Checking for update…</string>
<string name="update_check_for_update">التحقق من وجود تحديث</string>
<string name="update_already_latest_version">أنت تستخدم أحدث إصدار بالفعل</string>
<string name="update_new_version_found">عُثر على إصدار جديد: %s</string>
<string name="update_now">التحديث الآن</string>
<string name="update_check_pre_release">التحقق من الإصدارات التجريبية</string>
<string name="update_checking_for_update">جارٍ التحقق من وجود تحديث…</string>
<string name="title_policy_group_type">Policy group type</string>
<string name="title_policy_group_subscription_id">From subscription group</string>
<string name="title_policy_group_subscription_filter">Remarks regular filter</string>
<string name="title_policy_group_test_outbounds">اختبار المخارج</string>
<string name="title_policy_group_fallback">المخرج الاحتياطي (اختياري)</string>
<string name="server_proxy_chain_members">اعضاء سلسلة الوكيل</string>
<string name="title_policy_group_type">نوع مجموعة السياسات</string>
<string name="title_policy_group_subscription_id">من مجموعة الاشتراك</string>
<string name="title_policy_group_subscription_filter">مرشح تعبير نمطي للملاحظات</string>
<string name="title_policy_group_test_outbounds">اختبار الاتصالات الصادرة (outbounds)</string>
<string name="title_policy_group_fallback">الاتصال الصادر الاحتياطي (outbound، اختياري)</string>
<string name="server_proxy_chain_members">أعضاء سلسلة الوكيل</string>
<string name="server_proxy_chain_pick_members">اضغط هنا لاختيار عضو</string>
<string name="server_proxy_chain_member_unselected">اختر عضوا</string>
<string name="server_proxy_chain_members_unselected">يرجى اختيار remark لكل صف في السلسلة</string>
<string name="server_proxy_chain_members_insufficient">عدد الاعضاء غير كاف</string>
<string name="server_proxy_chain_members_invalid">اعضاء سلسلة غير صالحين: %1$s</string>
<string name="server_proxy_chain_member_unselected">اختر عضوًا</string>
<string name="server_proxy_chain_members_unselected">يرجى اختيار عضو لكل صف في السلسلة</string>
<string name="server_proxy_chain_members_insufficient">عدد الأعضاء غير كافٍ</string>
<string name="server_proxy_chain_members_invalid">أعضاء سلسلة غير صالحين: %1$s</string>
<!-- BackupActivity -->
<string name="title_configuration_backup_restore">Backup &amp; Restore</string>
<string name="title_configuration_backup_restore">النسخ الاحتياطي والاستعادة</string>
<string name="title_configuration_backup">نسخ التكوين احتياطيًا</string>
<string name="title_configuration_restore">استعادة التكوين</string>
<string name="title_configuration_share">مشاركة التكوين</string>
<string name="title_webdav_config_setting">WebDAV Settings</string>
<string name="title_webdav_config_setting_unknown">Please configure WebDAV first.</string>
<string name="title_webdav_url">WebDAV server URL</string>
<string name="title_webdav_user">Username</string>
<string name="title_webdav_pass">Password</string>
<string name="title_webdav_remote_path">Remote directory (optional)</string>
<string name="title_webdav_config_setting">إعدادات WebDAV</string>
<string name="title_webdav_config_setting_unknown">يرجى إعداد WebDAV أولاً.</string>
<string name="title_webdav_url">عنوان URL لخادم WebDAV</string>
<string name="title_webdav_user">اسم المستخدم</string>
<string name="title_webdav_pass">كلمة المرور</string>
<string name="title_webdav_remote_path">الدليل البعيد (اختياري)</string>
<string name="share_method_qrcode">رمز استجابة سريعة (QRcode)</string>
<string name="share_method_clipboard">تصدير إلى الحافظة</string>
<string name="share_method_full_content">تصدير التكوين الكامل إلى الحافظة</string>
<string name="share_method_qrcode">رمز QR</string>
<string name="share_method_clipboard">نسخ رابط التكوين</string>
<string name="share_method_full_content">نسخ التكوين الكامل</string>
<string name="action_edit">تعديل</string>
<string name="action_delete">حذف</string>
<string name="action_close">إغلاق</string>
<string-array name="share_sub_method">
<item>رمز استجابة سريعة (QRcode)</item>
<item>تصدير إلى الحافظة</item>
</string-array>
<string name="share_subscription_qrcode">رمز QR</string>
<string name="share_subscription_clipboard">تصدير إلى الحافظة</string>
<string-array name="mode_entries">
<item>VPN</item>
<item>بروكسي فقط</item>
</string-array>
<string-array name="browser_dialer_mode">
<item>تعطيل</item>
<item>OkHttp</item>
<item>WebView</item>
</string-array>
<string-array name="ui_mode_night">
<item>اتبع النظام</item>
<item>فاتح</item>
<item>داكن</item>
</string-array>
<string name="routing_preset_china_whitelist">القائمة البيضاء للصين</string>
<string name="routing_preset_china_blacklist">القائمة السوداء للصين</string>
<string name="routing_preset_global">عالمي</string>
<string name="routing_preset_iran_whitelist">القائمة البيضاء لإيران</string>
<string name="routing_preset_russia_whitelist">القائمة البيضاء لروسيا</string>
<string-array name="vpn_bypass_lan">
<item>Follow config</item>
<item>Bypass</item>
<item>Not Bypass</item>
<item>اتباع الإعداد</item>
<item>تجاوز</item>
<item>عدم التجاوز</item>
</string-array>
<string-array name="outbound_domain_resolve_method">
<item>Do not resolve</item>
<item>Resolve and add to DNS Hosts</item>
<item>Resolve and replace domain</item>
</string-array>
<string-array name="policy_group_type">
<item>Least Ping</item>
<item>Least Load</item>
<item>Random</item>
<item>Round Robin</item>
<item>عدم الحل</item>
<item>الحل والإضافة إلى مضيفي DNS</item>
<item>الحل واستبدال النطاق</item>
</string-array>
<string-array name="config_backup_options">
<item>Local</item>
<item>WebDAV</item>
<string-array name="policy_group_type">
<item>أقل زمن استجابة (leastPing)</item>
<item>أقل حمل (leastLoad)</item>
<item>عشوائي (random)</item>
<item>تناوب دائري (roundRobin)</item>
</string-array>
<string name="backup_location_local">محلي</string>
<string name="backup_location_webdav" translatable="false">WebDAV</string>
<string name="acc_refresh">تحديث السجل</string>
<string name="toast_permission_denied_for">تم رفض إذن %1$s</string>
<string name="acc_add_subscription">إضافة اشتراك</string>
<string name="toast_malformed_json_detail">تنسيق التكوين غير صالح: %1$s</string>
<string name="acc_add_asset">إضافة مصدر موارد</string>
<string name="acc_download_file">تنزيل ملفات الموارد</string>
<string name="acc_qr_code">رمز QR</string>
<string name="acc_copy_log">نسخ السجل</string>
<string name="acc_clear_log">مسح السجل</string>
<string name="acc_add_rule">إضافة قاعدة توجيه</string>
<string name="acc_start">بدء الخدمة</string>
<string name="acc_stop">إيقاف الخدمة</string>
<string name="acc_back">رجوع</string>
<string name="acc_search">بحث</string>
<string name="acc_add">إضافة تكوين</string>
<string name="acc_more">المزيد من الخيارات</string>
<string name="acc_share_subscription">مشاركة رابط الاشتراك</string>
<string name="acc_share_log">مشاركة السجل</string>
<string name="acc_remove">إزالة عضو من سلسلة الوكلاء</string>
<string name="acc_add_member">إضافة عضو إلى سلسلة الوكلاء</string>
<string name="acc_start_scanner">بدء ماسح رمز QR</string>
<string name="acc_stop_scanner">إيقاف ماسح رمز QR</string>
<string name="acc_turn_torch_on">تشغيل المصباح</string>
<string name="acc_turn_torch_off">إطفاء المصباح</string>
<string name="acc_select_image">اختيار صورة لمسحها</string>
<string name="acc_locked">يتم الاحتفاظ بالقاعدة عند استيراد الإعدادات المسبقة</string>
<string name="acc_open_menu">فتح قائمة التنقل</string>
<string name="acc_edit">تعديل</string>
<string name="acc_delete">حذف</string>
<string name="acc_save">حفظ</string>
<string name="acc_update_subscriptions">تحديث الاشتراكات</string>
<string name="acc_per_app_proxy_information">معلومات الوكيل لكل تطبيق</string>
<string name="permission_camera">الكاميرا</string>
<string name="permission_notification">الإشعارات</string>
<string name="permission_local_network">الشبكة المحلية</string>
<string name="subscription_update_updating">جارٍ تحديث الاشتراك: %1$s</string>
<string name="subscription_update_progress">جارٍ اختبار %2$s: %1$s</string>
<string name="tasker_blurb_start">تشغيل %1$s</string>
<string name="tasker_blurb_stop">إيقاف %1$s</string>
<string name="connection_test_empty_message">لا تتوفر تفاصيل</string>
<string name="value_unknown">غير معروف</string>
</resources>
+275 -203
View File
@@ -1,19 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" translatable="false">v2rayNG</string>
<string name="app_widget_name">সুইচ</string>
<string name="app_tile_name">সুইচ</string>
<string name="app_tile_first_use">এই ফিচারটি প্রথম ব্যবহার করা হচ্ছে, সার্ভার যোগ করতে অ্যাপটি ব্যবহার করুন</string>
<string name="navigation_drawer_open">নেভিগেশন ড্রয়ার খোলুন</string>
<string name="navigation_drawer_close">নেভিগেশন ড্রয়ার বন্ধ করুন</string>
<string name="migration_success">ডেটা স্থানান্তর সফল!</string>
<string name="action_stop_service">Stop service</string>
<string name="action_stop_service">সেবা বন্ধ করুন</string>
<string name="action_ok">ঠিক আছে</string>
<string name="action_cancel">বাতিল</string>
<string name="migration_fail">ডেটা স্থানান্তর ব্যর্থ!</string>
<string name="pull_down_to_refresh">Please pull down to refresh!</string>
<string name="pull_down_to_refresh">রিফ্রেশ করতে নিচে টানুন!</string>
<!-- Notifications -->
<string name="notification_action_stop_v2ray">বন্ধ করুন</string>
<string name="toast_permission_denied">অনুমতি পাওয়া যাচ্ছে না</string>
<string name="toast_permission_denied_notification">Unable to obtain the notification permission</string>
<string name="toast_permission_denied_notification">বিজ্ঞপ্তির অনুমতি পাওয়া যায়নি</string>
<string name="notification_action_more">আরও দেখতে ক্লিক করুন</string>
<string name="toast_services_start">সার্ভিস শুরু করুন</string>
<string name="toast_services_stop">সার্ভিস বন্ধ করুন</string>
@@ -24,21 +27,21 @@
<string name="title_server">কনফিগারেশন ফাইল</string>
<string name="menu_item_add_config">কনফিগারেশন যোগ করুন</string>
<string name="menu_item_save_config">কনফিগারেশন সংরক্ষণ করুন</string>
<string name="menu_item_edit_config">Edit configuration</string>
<string name="menu_item_edit_config">কনফিগারেশন সম্পাদনা করুন</string>
<string name="menu_item_del_config">কনফিগারেশন মুছুন</string>
<string name="menu_item_import_config_qrcode">QR কোড থেকে কনফিগারেশন আমদানি করুন</string>
<string name="menu_item_import_config_clipboard">ক্লিপবোর্ড থেকে কনফিগারেশন আমদানি করুন</string>
<string name="menu_item_import_config_local">Import config from locally</string>
<string name="menu_item_import_config_policy_group">Add [Policy group]</string>
<string name="menu_item_import_config_proxy_chain">Add [Proxy chain]</string>
<string name="menu_item_import_config_manually_vmess">ম্যানুয়ালি টাইপ করুন [VMess]</string>
<string name="menu_item_import_config_manually_vless">ম্যানুয়ালি টাইপ করুন [VLESS]</string>
<string name="menu_item_import_config_manually_ss">ম্যানুয়ালি টাইপ করুন [Shadowsocks]</string>
<string name="menu_item_import_config_manually_socks">ম্যানুয়ালি টাইপ করুন [SOCKS]</string>
<string name="menu_item_import_config_manually_http">Type manually[HTTP]</string>
<string name="menu_item_import_config_manually_trojan">ম্যানুয়ালি টাইপ করুন [Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">ম্যানুয়ালি টাইপ করুন [Wireguard]</string>
<string name="menu_item_import_config_manually_hysteria2">Type manually[Hysteria2]</string>
<string name="menu_item_import_config_local">ডিভাইস থেকে কনফিগ আমদানি করুন</string>
<string name="menu_item_import_config_policy_group">[নীতি গ্রুপ] যোগ করুন</string>
<string name="menu_item_import_config_proxy_chain">[প্রক্সি চেইন] যোগ করুন</string>
<string name="menu_item_import_config_manually_vmess">[VMess] যোগ করুন</string>
<string name="menu_item_import_config_manually_vless">[VLESS] যোগ করুন</string>
<string name="menu_item_import_config_manually_ss">[Shadowsocks] যোগ করুন</string>
<string name="menu_item_import_config_manually_socks">[SOCKS] যোগ করুন</string>
<string name="menu_item_import_config_manually_http">[HTTP] যোগ করুন</string>
<string name="menu_item_import_config_manually_trojan">[Trojan] যোগ করুন</string>
<string name="menu_item_import_config_manually_wireguard">[WireGuard] যোগ করুন</string>
<string name="menu_item_import_config_manually_hysteria2">[Hysteria2] যোগ করুন</string>
<string name="confirm_delete_visible_profiles">আপনি কি বর্তমানে প্রদর্শিত সব প্রোফাইল মুছে ফেলতে চান?</string>
<string name="confirm_delete_duplicate_profiles">আপনি কি বর্তমানে প্রদর্শিত সব সদৃশ প্রোফাইল মুছে ফেলতে চান?</string>
<string name="confirm_delete_invalid_profiles">প্রথমে প্রোফাইলগুলো পরীক্ষা করুন। আপনি কি বর্তমানে প্রদর্শিত সব অবৈধ প্রোফাইল মুছে ফেলতে চান?</string>
@@ -66,7 +69,7 @@
<string name="server_lab_request_host_xhttp">xhttp হোস্ট</string>
<string name="server_lab_request_host_h2">h2 হোস্ট</string>
<string name="server_lab_request_host_quic">QUIC নিরাপত্তা</string>
<string name="server_lab_request_host_grpc">gRPC কর্তৃপক্ষ</string>
<string name="server_lab_request_host_grpc">gRPC Authority</string>
<string name="server_lab_path">পথ</string>
<string name="server_lab_path_ws">ws পথ</string>
<string name="server_lab_path_httpupgrade">httpupgrade পথ</string>
@@ -75,11 +78,11 @@
<string name="server_lab_path_quic">QUIC কী</string>
<string name="server_lab_path_kcp">kcp বীজ</string>
<string name="server_lab_path_grpc">gRPC সেবার নাম</string>
<string name="server_lab_stream_security">TLS</string>
<string name="server_lab_stream_fingerprint" translatable="false">ফিঙ্গারপ্রিন্ট</string>
<string name="server_lab_stream_alpn" translatable="false">Alpn</string>
<string name="server_lab_allow_insecure">অনিরাপদ অনুমতি দিন</string>
<string name="server_lab_sni">SNI</string>
<string name="server_lab_stream_security" translatable="false">TLS</string>
<string name="server_lab_stream_fingerprint">ফিঙ্গারপ্রিন্ট</string>
<string name="server_lab_stream_alpn" translatable="false">ALPN</string>
<string name="server_lab_allow_insecure">সার্টিফিকেট যাচাই এড়িয়ে যান (allowInsecure)</string>
<string name="server_lab_sni" translatable="false">SNI</string>
<string name="server_lab_address3">ঠিকানা</string>
<string name="server_lab_port3">পোর্ট</string>
<string name="server_lab_id3">পাসওয়ার্ড</string>
@@ -87,14 +90,14 @@
<string name="server_lab_id4">পাসওয়ার্ড (ঐচ্ছিক)</string>
<string name="server_lab_security4">ব্যবহারকারী (ঐচ্ছিক)</string>
<string name="server_lab_encryption">এনক্রিপশন</string>
<string name="server_lab_flow">ফ্লো</string>
<string name="server_lab_public_key" translatable="false">পাবলিক কী</string>
<string name="server_lab_preshared_key">PreSharedKey(optional)</string>
<string name="server_lab_short_id" translatable="false">শর্ট আইডি</string>
<string name="server_lab_flow">প্রবাহ (flow)</string>
<string name="server_lab_public_key">পাবলিক কী</string>
<string name="server_lab_preshared_key">PreSharedKey (ঐচ্ছিক)</string>
<string name="server_lab_short_id">শর্ট আইডি</string>
<string name="server_lab_spider_x" translatable="false">SpiderX</string>
<string name="server_lab_mldsa65_verify">Mldsa65Verify</string>
<string name="server_lab_secret_key" translatable="false">সিক্রেট কী</string>
<string name="server_lab_reserved">সংরক্ষিত (ঐচ্ছিক)</string>
<string name="server_lab_mldsa65_verify" translatable="false">mldsa65Verify</string>
<string name="server_lab_secret_key">সিক্রেট কী</string>
<string name="server_lab_reserved">Reserved (ঐচ্ছিক, কমা দিয়ে পৃথক)</string>
<string name="server_lab_local_address">স্থানীয় ঠিকানা (ঐচ্ছিক IPv4/IPv6, কমা দ্বারা পৃথক করা)</string>
<string name="server_lab_local_mtu">MTU (ঐচ্ছিক, ডিফল্ট 1420)</string>
<string name="server_lab_kcp_mtu">mKCP MTU (ঐচ্ছিক, কোর ডিফল্ট 1350)</string>
@@ -111,25 +114,28 @@
<string name="server_lab_content">কনটেন্ট</string>
<string name="toast_none_data_clipboard">ক্লিপবোর্ডে কোনও তথ্য নেই</string>
<string name="toast_invalid_url">অবৈধ URL</string>
<string name="toast_insecure_url_protocol">Please do not use the insecure HTTP protocol subscription address</string>
<string name="toast_insecure_url_protocol">অনিরাপদ HTTP প্রোটোকলের সাবস্ক্রিপশন ঠিকানা ব্যবহার করবেন না</string>
<string name="server_lab_need_inbound">ইনবাউন্ড পোর্ট নিশ্চিত করুন সেটিংসের সাথে সামঞ্জস্যপূর্ণ</string>
<string name="toast_malformed_josn">কনফিগারেশন বিকৃত</string>
<string name="toast_malformed_json">কনফিগারেশন ফরম্যাট সঠিক নয়।</string>
<string name="server_lab_request_host6">হোস্ট (SNI) (ঐচ্ছিক)</string>
<string name="toast_action_not_allowed">অ্যাকশন অনুমোদিত নয়</string>
<string name="server_obfs_password">Obfs password</string>
<string name="server_lab_port_hop">Port Hopping</string>
<string name="server_lab_port_hop_interval">Port Hopping Interval</string>
<string name="server_lab_bandwidth_down">Bandwidth down (Supported units: k/m/g/t)</string>
<string name="server_lab_bandwidth_up">Bandwidth up (Supported units: k/m/g/t)</string>
<string name="server_lab_xhttp_mode">XHTTP Mode</string>
<string name="server_lab_xhttp_extra">XHTTP Extra raw JSON, format: { XHTTPObject }</string>
<string name="server_lab_final_mask">finalMask raw JSON, format: { FinalMaskObject }</string>
<string name="server_lab_ech_config_list">EchConfigList</string>
<string name="server_lab_verify_peer_cert_by_name">Verify Peer Cert By Name</string>
<string name="server_lab_pinned_ca256">Certificate fingerprint (SHA-256)</string>
<string name="pinned_ca256_action_fetch">Fetch and fill certificate fingerprint</string>
<string name="toast_fetch_cert_sha256_success">Certificate fingerprint fetched successfully</string>
<string name="toast_fetch_cert_sha256_failed">Failed to fetch certificate fingerprint</string>
<string name="server_obfs_password">Obfs পাসওয়ার্ড</string>
<string name="server_lab_port_hop">পোর্ট হপিং (পোর্টের মান প্রতিস্থাপন করবে)</string>
<string name="server_lab_port_hop_interval">পোর্ট পরিবর্তনের বিরতি (সেকেন্ড)</string>
<string name="server_lab_bandwidth_down">ডাউনলোড ব্যান্ডউইডথ (সমর্থিত একক: k/m/g/t)</string>
<string name="server_lab_bandwidth_up">আপলোড ব্যান্ডউইডথ (সমর্থিত একক: k/m/g/t)</string>
<string name="server_lab_xhttp_mode">XHTTP মোড</string>
<string name="server_lab_xhttp_extra">XHTTP Extra-এর কাঁচা JSON, ফরম্যাট: { XHTTPObject }</string>
<string name="server_lab_final_mask">finalMask-এর কাঁচা JSON, ফরম্যাট: { FinalMaskObject }</string>
<string name="server_lab_ech_config_list" translatable="false">echConfigList</string>
<string name="server_lab_verify_peer_cert_by_name">নাম দিয়ে পিয়ার সার্টিফিকেট যাচাই করুন</string>
<string name="server_lab_pinned_ca256">সার্টিফিকেট ফিঙ্গারপ্রিন্ট (SHA-256)</string>
<string name="server_lab_browser_dialer">Browser Dialer চালু করুন</string>
<string name="server_lab_browser_dialer_tip">শুধু xhttp (packet-up) ও ws আউটবাউন্ড সমর্থিত; TLS-সংক্রান্ত সেটিং উপেক্ষিত হতে পারে বা পরস্পরের সঙ্গে বিরোধ করতে পারে</string>
<string name="toast_allow_insecure_deprecated">বর্তমান নোডটি এনক্রিপশনবিহীন সংযোগ ব্যবহার করে। কর্তৃত্ববাদী সরকারের নিয়ন্ত্রণাধীন মধ্যবর্তী নেটওয়ার্ক অবকাঠামো আপনার যোগাযোগ সরাসরি দেখতে পারে।\nনিরাপত্তার কারণে Xray কোরের 26.2.6 বা পরবর্তী সংস্করণ দিয়ে এ ধরনের নোডে সংযোগ করা যায় না।\nনোডটি নিজে তৈরি করে থাকলে TLS-এর মতো নিরাপদ এনক্রিপশন চালু করুন অথবা pinnedCA256 সার্টিফিকেট ফিঙ্গারপ্রিন্ট পিন করুন।\nনোডটি কোনো সেবা প্রদানকারীর হলে প্রযুক্তিগত আপগ্রেডের জন্য তাদের সঙ্গে যোগাযোগ করুন। তারা সহযোগিতা না করলে ব্যবহারকারীর নিরাপত্তাকে বেশি গুরুত্ব দেয় এমন প্রদানকারীর কাছে যাওয়ার পরামর্শ দেওয়া হয়।\nআরও তথ্যের জন্য দেখুন https://github.com/2dust/v2rayN/discussions/9460</string>
<string name="pinned_ca256_action_fetch">সার্টিফিকেট ফিঙ্গারপ্রিন্ট আনুন</string>
<string name="toast_fetch_cert_sha256_success">সার্টিফিকেট ফিঙ্গারপ্রিন্ট সফলভাবে আনা হয়েছে</string>
<string name="toast_fetch_cert_sha256_failed">সার্টিফিকেট ফিঙ্গারপ্রিন্ট আনা ব্যর্থ হয়েছে</string>
<!-- UserAssetActivity -->
<string name="toast_asset_copy_failed">ফাইল কপি ব্যর্থ, অনুগ্রহ করে ফাইল ম্যানেজার ব্যবহার করুন</string>
@@ -142,21 +148,22 @@
<string name="title_user_asset_add_url">অ্যাসেট URL যোগ করুন</string>
<string name="msg_file_not_found">ফাইল খুঁজে পাওয়া যায়নি</string>
<string name="msg_remark_is_duplicate">মন্তব্য ইতিমধ্যে বিদ্যমান</string>
<string name="asset_geo_files_sources">Geo files source (optional)</string>
<string name="asset_geo_files_sources">Geo ফাইলের উৎস (ঐচ্ছিক)</string>
<!-- PerAppProxyActivity -->
<string name="msg_dialog_progress">লোড হচ্ছে</string>
<string name="menu_item_search">অনুসন্ধান করুন</string>
<string name="menu_item_select_all">সবকিছু নির্বাচন করুন</string>
<string name="menu_item_invert_selection">Invert selection</string>
<string name="menu_item_invert_selection">নির্বাচন উল্টে দিন</string>
<string name="msg_enter_keywords">কিওয়ার্ড লিখুন</string>
<string name="switch_bypass_apps_mode">বাইপাস মোড</string>
<string name="menu_item_select_proxy_app">অটো সিলেক্ট প্রক্সি অ্যাপ</string>
<string name="menu_item_select_proxy_app">প্রক্সি ব্যবহার করবে এমন অ্যাপ স্বয়ংক্রিয়ভাবে নির্বাচন করুন</string>
<string name="msg_downloading_content">বিষয়বস্তু ডাউনলোড হচ্ছে</string>
<string name="menu_item_export_proxy_app">ক্লিপবোর্ডে রপ্তানি করুন</string>
<string name="menu_item_import_proxy_app">ক্লিপবোর্ড থেকে আমদানি করুন</string>
<string name="per_app_proxy_settings">Per-app settings</string>
<string name="per_app_proxy_settings_enable">Enable per-app</string>
<string name="per_app_proxy_settings">অ্যাপভিত্তিক সেটিংস</string>
<string name="per_app_proxy_settings_enable">অ্যাপভিত্তিক সেটিংস চালু করুন</string>
<string name="app_picker_unknown_app">অজানা অ্যাপ (UID শনাক্ত করা যায়নি)</string>
<!-- Preferences -->
<string name="title_settings">সেটিংস</string>
@@ -164,20 +171,24 @@
<string name="title_core_settings">কোর সেটিংস</string>
<string name="title_vpn_settings">VPN সেটিংস</string>
<string name="title_pref_per_app_proxy">প্রতি-অ্যাপ প্রক্সি</string>
<string name="summary_pref_per_app_proxy">সাধারণ: চেকড অ্যাপ প্রক্সি, আনচেকড সরাসরি সংযোগ; \nবাইপাস মোড: চেকড অ্যাপ সরাসরি সংযুক্ত, আনচেকড প্রক্সি। \nমেনুতে প্রক্সি অ্যাপ্লিকেশন স্বয়ংক্রিয়ভাবে নির্বাচন করার বিকল্প</string>
<string name="title_pref_is_booted">Auto connect at startup</string>
<string name="summary_pref_is_booted">Automatically connects to the selected server at startup, which may be unsuccessful</string>
<string name="summary_pref_per_app_proxy">সাধারণ: নির্বাচিত অ্যাপ প্রক্সি ব্যবহার করে, অনির্বাচিত অ্যাপ সরাসরি সংযুক্ত হয়;\nবাইপাস মোড: নির্বাচিত অ্যাপ সরাসরি সংযুক্ত হয়, অনির্বাচিত অ্যাপ প্রক্সি ব্যবহার করে।\nযেসব অ্যাপ প্রক্সি ব্যবহার করবে, সেগুলি স্বয়ংক্রিয়ভাবে নির্বাচনের বিকল্পটি মেনুতে আছে।</string>
<string name="title_pref_is_booted">চালুর সময় স্বয়ংক্রিয় সংযোগ</string>
<string name="summary_pref_is_booted">চালুর সময় নির্বাচিত সার্ভারে স্বয়ংক্রিয়ভাবে সংযোগ করে; সংযোগ ব্যর্থ হতে পারে</string>
<string name="title_pref_auto_remove_invalid_after_test">Auto delete invalid config after testing</string>
<string name="summary_pref_auto_remove_invalid_after_test">Test results may not be accurate; deleted config cannot be recovered.</string>
<string name="title_pref_auto_sort_after_test">Auto sort after testing</string>
<string name="summary_pref_auto_sort_after_test">Test results may not be accurate;</string>
<string name="subscription_updater_job_tips">কাজটি ব্যাকগ্রাউন্ডে চলবে এবং অগ্রগতির তথ্য বিজ্ঞপ্তিতে দেখানো হবে।</string>
<string name="title_pref_auto_test_after_update_subscription">সাবস্ক্রিপশন আপডেটের পর স্বয়ংক্রিয় পরীক্ষা</string>
<string name="summary_pref_auto_test_after_update_subscription">স্বয়ংক্রিয় পরীক্ষায় অনেক সময় লাগে। চালু থাকলে কাজটি ব্যাকগ্রাউন্ডে চলবে; অন্যথায় বর্তমান পৃষ্ঠায় চলবে।</string>
<string name="title_pref_auto_remove_invalid_after_test">পরীক্ষার পর অবৈধ কনফিগ স্বয়ংক্রিয়ভাবে মুছুন</string>
<string name="summary_pref_auto_remove_invalid_after_test">পরীক্ষার ফল সঠিক নাও হতে পারে; মুছে ফেলা কনফিগ ফেরত আনা যাবে না।</string>
<string name="title_pref_auto_sort_after_test">পরীক্ষার পর স্বয়ংক্রিয়ভাবে সাজান</string>
<string name="summary_pref_auto_sort_after_test">পরীক্ষার ফল সঠিক নাও হতে পারে;</string>
<string name="title_mux_settings">Mux সেটিংস</string>
<string name="title_pref_mux_enabled">Mux সক্রিয় করুন</string>
<string name="summary_pref_mux_enabled">দ্রুত, তবে এটি অস্থিতিশীল সংযোগ সৃষ্টি করতে পারে\nTCP, UDP এবং QUIC পরিচালনা কাস্টমাইজ করুন</string>
<string name="title_pref_mux_concurency">TCP সংযোগ (পরিসর -1 থেকে 1024)</string>
<string name="title_pref_mux_xudp_concurency">XUDP সংযোগ (পরিসর -1 থেকে 1024)</string>
<string name="title_pref_mux_concurrency">TCP সংযোগ (পরিসর -1 থেকে 1024)</string>
<string name="title_pref_mux_xudp_concurrency">XUDP সংযোগ (পরিসর -1 থেকে 1024)</string>
<string name="title_pref_mux_xudp_quic">Mux টানেলে QUIC পরিচালনা</string>
<string-array name="mux_xudp_quic_entries">
<item>অস্বীকার করুন</item>
@@ -186,19 +197,18 @@
</string-array>
<string name="title_pref_speed_enabled">গতি প্রদর্শন সক্রিয় করুন</string>
<string name="summary_pref_speed_enabled">বিজ্ঞপ্তিতে বর্তমান গতি প্রদর্শন করুন।\nব্যবহারের উপর ভিত্তি করে বিজ্ঞপ্তি আইকন পরিবর্তিত হবে।</string>
<string name="summary_pref_speed_enabled">বিজ্ঞপ্তিতে বর্তমান সংযোগের গতি দেখান।\nআইকনটি প্রক্সি বা সরাসরি ট্রাফিকের মধ্যে কোনটি বেশি তা দেখায়।</string>
<string name="title_pref_sniffing_enabled">স্নিফিং সক্রিয় করুন</string>
<string name="summary_pref_sniffing_enabled">প্যাকেট থেকে ডোমেইন স্নিফ করার চেষ্টা করুন (ডিফল্টভাবে চালু)</string>
<string name="title_pref_route_only_enabled">রুটঅনলি সক্রিয় করুন</string>
<string name="title_pref_sniffing_enabled">ট্রাফিকের গন্তব্য ডোমেইন শনাক্তকরণ চালু করুন (Sniffing)</string>
<string name="summary_pref_sniffing_enabled">ট্রাফিক থেকে গন্তব্য ডোমেইন শনাক্ত করুন (ডিফল্টভাবে চালু)।</string>
<string name="title_pref_route_only_enabled">routeOnly সক্রিয় করুন</string>
<string name="summary_pref_route_only_enabled">রুটিংয়ের জন্য শুধুমাত্র স্নিফড ডোমেইন নাম ব্যবহার করুন, এবং লক্ষ্য ঠিকানা হিসেবে আইপি ঠিকানা রাখুন।</string>
<string name="title_pref_local_dns_enabled">স্থানীয় DNS সক্রিয় করুন</string>
<string name="summary_pref_local_dns_enabled">DNS মূল DNS মডিউল দ্বারা প্রক্রিয়া করা হয় (প্রস্তাবিত, যদি LAN এবং মূলভূমি ঠিকানার বাইপাসিং প্রয়োজন হয়)</string>
<string name="title_pref_fake_dns_enabled">ভুয়া DNS সক্রিয় করুন</string>
<string name="summary_pref_fake_dns_enabled">স্থানীয় DNS মিথ্যা আইপি ঠিকানা ফেরত দেয় (দ্রুত, তবে এটি কিছু অ্যাপের জন্য কাজ নাও করতে পারে)</string>
<string name="title_pref_fake_dns_enabled">কৃত্রিম DNS চালু করুন (FakeDNS)</string>
<string name="summary_pref_fake_dns_enabled">ডোমেইন রেজলভের সময় FakeDNS কৃত্রিম IP ঠিকানা ফেরত দেয় (দ্রুত, তবে কিছু অ্যাপে কাজ নাও করতে পারে)।</string>
<string name="title_pref_ipv6_enabled">IPv6 সক্রিয় করুন</string>
<string name="summary_pref_ipv6_enabled">VPN ইন্টারফেসে IPv6 ঠিকানা এবং রুট যোগ করুন</string>
@@ -206,44 +216,46 @@
<string name="title_pref_prefer_ipv6">IPv6 অগ্রাধিকার দিন</string>
<string name="summary_pref_prefer_ipv6">ডোমেইন নাম রেজোলিউশনে IPv6 ঠিকানাকে অগ্রাধিকার দিন</string>
<string name="title_pref_remote_dns">রিমোট DNS (udp/tcp/https/quic)(ঐচ্ছিক)</string>
<string name="summary_pref_remote_dns">DNS</string>
<string name="title_pref_remote_dns">রিমোট DNS (UDP/TCP/HTTPS/QUIC, ঐচ্ছিক)</string>
<string name="summary_pref_remote_dns" translatable="false">DNS</string>
<string name="title_pref_vpn_dns">VPN DNS (শুধুমাত্র IPv4/v6)</string>
<string name="title_pref_vpn_bypass_lan">Does VPN bypass LAN</string>
<string name="title_pref_vpn_dns">VPN DNS (শুধুমাত্র IPv4/IPv6)</string>
<string name="title_pref_vpn_bypass_lan">VPN কি LAN এড়িয়ে যাবে?</string>
<string name="title_pref_vpn_interface_address">VPN Interface Address</string>
<string name="title_pref_vpn_mtu">VPN MTU (default 1500)</string>
<string name="title_pref_vpn_interface_address">VPN ইন্টারফেসের ঠিকানা</string>
<string name="title_pref_domestic_dns">ঘরোয়া DNS (ঐচ্ছিক)</string>
<string name="summary_pref_domestic_dns">DNS</string>
<string name="title_pref_vpn_mtu">VPN MTU (ডিফল্ট 1500)</string>
<string name="title_pref_dns_hosts">DNS hosts (Format: domain:address,…)</string>
<string name="title_pref_domestic_dns">সরাসরি DNS (ঐচ্ছিক)</string>
<string name="summary_pref_domestic_dns" translatable="false">DNS</string>
<string name="title_pref_dns_hosts">DNS হোস্ট ম্যাপিং (বিন্যাস: domain:address,…)</string>
<string name="summary_pref_dns_hosts">domain:address,…</string>
<string name="title_pref_delay_test_url">সঠিক বিলম্ব পরীক্ষা ইউআরএল </string>
<string name="summary_pref_delay_test_url">ইউআরএল</string>
<string name="title_pref_real_ping_concurrency">True delay test concurrency</string>
<string name="title_pref_delay_test_url">প্রকৃত বিলম্ব পরীক্ষার URL</string>
<string name="summary_pref_delay_test_url" translatable="false">URL</string>
<string name="title_pref_real_ping_concurrency">একযোগে প্রকৃত বিলম্ব পরীক্ষা</string>
<string name="title_pref_ip_api_url">Current connection info test url</string>
<string name="summary_pref_ip_api_url">Url</string>
<string name="title_pref_ip_api_url">বর্তমান সংযোগের তথ্য পরীক্ষার URL</string>
<string name="summary_pref_ip_api_url" translatable="false">URL</string>
<string name="title_pref_proxy_sharing_enabled">LAN থেকে সংযোগ অনুমোদন করুন</string>
<string name="summary_pref_proxy_sharing_enabled">অন্যান্য ডিভাইসগুলি আপনার আইপি ঠিকানা ব্যবহার করে প্রক্সিতে সংযুক্ত হতে পারে, শুধুমাত্র বিশ্বস্ত নেটওয়ার্কে সক্রিয় করুন যাতে অনুমোদিত সংযোগ এড়ানো যায়</string>
<string name="toast_warning_pref_proxysharing_short">LAN থেকে সংযোগ অনুমোদন করুন, নিশ্চিত করুন যে আপনি একটি বিশ্বস্ত নেটওয়ার্কে আছেন</string>
<string name="title_pref_socks_port">Local প্রক্সি পোর্ট</string>
<string name="title_pref_socks_port">স্থানীয় প্রক্সি পোর্ট</string>
<string name="title_pref_enable_local_proxy">লোকাল প্রক্সি সক্ষম করুন</string>
<string name="summary_pref_enable_local_proxy">When disabled, no SOCKS proxy is available, so subscription updates and similar actions cannot use the proxy</string>
<string name="title_pref_socks_enable_udp">SOCKS5 UDP</string>
<string name="summary_pref_socks_enable_udp">UDP ব্যবহার করার সময় socks5 প্রমাণীকরণ সম্পূর্ণরূপে নিরাপদ নয়</string>
<string name="summary_pref_socks_port">Local প্রক্সি পোর্ট</string>
<string name="title_pref_dynamic_socks_port">Enable dynamic local proxy port</string>
<string name="summary_pref_dynamic_socks_port">Generate a random local proxy port each time the inbound is created</string>
<string name="title_pref_socks_username">Local proxy username (optional)</string>
<string name="summary_pref_socks_username">Username</string>
<string name="title_pref_socks_password">Local proxy password (optional)</string>
<string name="summary_pref_socks_password">Password</string>
<string name="summary_pref_enable_local_proxy">বন্ধ থাকলে কোনো SOCKS প্রক্সি পাওয়া যাবে না, তাই সাবস্ক্রিপশন আপডেট ও অনুরূপ কাজ প্রক্সি ব্যবহার করতে পারবে না</string>
<string name="title_pref_socks_enable_udp" translatable="false">SOCKS5 UDP</string>
<string name="summary_pref_socks_enable_udp">UDP ব্যবহার করার সময় SOCKS5 প্রমাণীকরণ সম্পূর্ণরূপে নিরাপদ নয়।</string>
<string name="summary_pref_socks_port">স্থানীয় প্রক্সি পোর্ট</string>
<string name="title_pref_dynamic_socks_port">গতিশীল স্থানীয় প্রক্সি পোর্ট চালু করুন</string>
<string name="summary_pref_dynamic_socks_port">প্রতিবার inbound তৈরি হলে একটি এলোমেলো স্থানীয় প্রক্সি পোর্ট তৈরি করুন</string>
<string name="title_pref_socks_username">স্থানীয় প্রক্সির ব্যবহারকারীর নাম (ঐচ্ছিক)</string>
<string name="summary_pref_socks_username">ব্যবহারকারীর নাম</string>
<string name="title_pref_socks_password">স্থানীয় প্রক্সির পাসওয়ার্ড (ঐচ্ছিক)</string>
<string name="summary_pref_socks_password">পাসওয়ার্ড</string>
<string name="title_pref_local_dns_port">স্থানীয় DNS পোর্ট</string>
<string name="summary_pref_local_dns_port">স্থানীয় DNS পোর্ট</string>
@@ -252,83 +264,94 @@
<string name="summary_pref_confirm_remove">কনফিগারেশন ফাইল মুছে ফেলার জন্য ব্যবহারকারীর দ্বিতীয় নিশ্চিতকরণের প্রয়োজন</string>
<string name="title_pref_append_http_proxy">Append HTTP Proxy to VPN</string>
<string name="summary_pref_append_http_proxy">HTTP proxy will be used directly from (browser/ some supported apps), without going through the virtual NIC device (Android 10+)</string>
<string name="title_pref_append_http_proxy">VPN-এ HTTP প্রক্সি যুক্ত করুন</string>
<string name="summary_pref_append_http_proxy">ভার্চুয়াল NIC ডিভাইসের মধ্য দিয়ে না গিয়ে ব্রাউজার ও কিছু সমর্থিত অ্যাপ সরাসরি HTTP প্রক্সি ব্যবহার করবে (Android 10+)</string>
<string name="title_pref_double_column_display">Enable double column display</string>
<string name="summary_pref_double_column_display">The profile list is displayed in double columns, allowing more content to be displayed on the screen.</string>
<string name="title_pref_double_column_display">দুই কলামে প্রদর্শন চালু করুন</string>
<string name="summary_pref_double_column_display">প্রোফাইল তালিকা দুই কলামে দেখায়, ফলে পর্দায় আরও বিষয়বস্তু দেখা যায়।</string>
<string name="title_pref_group_all_display">“সব” গ্রুপ ট্যাব দেখান</string>
<string name="summary_pref_group_all_display">সব সাবস্ক্রিপশন গ্রুপের কনফিগ একটি ট্যাবে দেখান।</string>
<string name="title_pref_group_all_display">Enable show all groups</string>
<string name="summary_pref_group_all_display">Add an extra "All Tabs" page</string>
<!-- AboutActivity -->
<string name="title_pref_feedback">মতামত</string>
<string name="summary_pref_feedback">মতামত উন্নয়ন বা বাগগুলি GitHub-এ পাঠান</string>
<string name="summary_pref_tg_group">টেলিগ্রাম গ্রুপে যোগদান করুন</string>
<string name="toast_tg_app_not_found">টেলিগ্রাম অ্যাপ পাওয়া যায়নি</string>
<string name="title_privacy_policy">গোপনীয়তা নীতি</string>
<string name="title_qr_code">QR code</string>
<string name="title_qr_code">QR কোড</string>
<string name="title_about">সম্পর্কিত</string>
<string name="title_source_code">সোর্স কোড</string>
<string name="title_oss_license">Open Source licenses</string>
<string name="title_oss_license">ওপেন সোর্স লাইসেন্স</string>
<string name="title_tg_channel">টেলিগ্রাম চ্যানেল</string>
<string name="title_pref_promotion">প্রচার</string>
<string name="title_pref_auto_update_subscription">স্বয়ংক্রিয় আপডেট সাবস্ক্রিপশন</string>
<string name="summary_pref_auto_update_subscription">পটভূমিতে একটি নির্দিষ্ট সময় পর পর আপনার সাবস্ক্রিপশন স্বয়ংক্রিয়ভাবে আপডেট করুন। ডিভাইসের উপর নির্ভর করে, এই বৈশিষ্ট্যটি সবসময় কাজ নাও করতে পারে</string>
<string name="title_pref_auto_update_interval">অটো আপডেট ইন্টারভ্যাল (মিনিট, সর্বনিম্ন মান ১৫)</string>
<string name="title_pref_auto_update_interval">স্বয়ংক্রিয় আপডেটের বিরতি (মিনিট; সর্বনিম্ন ১৫)</string>
<string name="title_core_loglevel">লগ স্তর</string>
<string name="title_outbound_domain_resolve_method">Outbound domain pre-resolve method</string>
<string name="title_outbound_domain_resolve_method">বহির্গামী সংযোগের ডোমেইন রেজলভ পদ্ধতি (outbound)</string>
<string name="title_mode">মোড</string>
<string name="title_mode_help">আরো সাহায্যের জন্য ক্লিক করুন</string>
<string name="title_language">ভাষা</string>
<string name="title_ui_settings">ইউআই সেটিংস</string>
<string name="title_pref_ui_mode_night">ইউআই মোড সেটিংস</string>
<string name="title_pref_use_hev_tunnel">Enable Hev TUN Feature</string>
<string name="summary_pref_use_hev_tunnel">When enabled, TUN will use hev-socks5-tunnel; otherwise, it will use xray-core.</string>
<string name="title_pref_hev_tunnel_loglevel">Hev Tun Log Level</string>
<string name="title_pref_hev_tunnel_rw_timeout">Hev Tun read/write timeout (seconds) (tcp,udp default 300,60)</string>
<string name="title_pref_dynamic_color">ডায়নামিক রঙ চালু করুন</string>
<string name="summary_pref_dynamic_color">শুধুমাত্র Android 12+ ডিভাইসে কাজ করে</string>
<string name="title_pref_use_hev_tunnel">Hev TUN সুবিধা চালু করুন</string>
<string name="summary_pref_use_hev_tunnel">চালু থাকলে TUN hev-socks5-tunnel ব্যবহার করবে; অন্যথায় xray-core ব্যবহার করবে।</string>
<string name="title_pref_hev_tunnel_loglevel">Hev TUN লগ স্তর</string>
<string name="title_pref_hev_tunnel_rw_timeout">Hev TUN পড়া/লেখার সময়সীমা (সেকেন্ড; TCP/UDP-এর ডিফল্ট: 300/60)</string>
<string name="title_mode_settings">মোড সেটিংস</string>
<string name="title_root_mode_enabled">Root মোড চালু (Root ব্যবহারকারীদের জন্য)</string>
<string name="summary_root_mode_enabled">Root সুবিধা ব্যবহার করে নিম্ন-স্তরের স্বচ্ছ প্রক্সি চালু করুন। এই মোডটি Android-এর মানক সিস্টেম VPN এড়িয়ে সরাসরি অন্তর্নিহিত সব নেটওয়ার্ক ট্রাফিক নিয়ন্ত্রণ করে। চালু করার পর আগের সাধারণ মোড, অ্যাপভিত্তিক রাউটিং এবং সংশ্লিষ্ট VPN সেটিংস আর কার্যকর থাকবে না।</string>
<string name="toast_root_required">এই সুবিধার জন্য Root অ্যাক্সেস প্রয়োজন</string>
<string name="title_root_lan_sharing">LAN / টেদার করা ডিভাইসে VPN শেয়ার করুন (Root ব্যবহারকারীদের জন্য)</string>
<string name="summary_root_lan_sharing">Wi-Fi হটস্পট ও USB-টেদার করা ডিভাইসের ট্রাফিক VPN-এর মাধ্যমে রাউট করুন।</string>
<string name="title_logcat">লগক্যাট</string>
<string name="title_logcat" translatable="false">Logcat</string>
<string name="logcat_copy">কপি করুন</string>
<string name="logcat_clear">স্পষ্ট করুন</string>
<string name="logcat_clear">পরিষ্কার করুন</string>
<string name="logcat_share">লগ শেয়ার করুন</string>
<string name="title_service_restart">সার্ভিস পুনরায় চালু করুন</string>
<string name="title_del_all_config">সব কনফিগারেশন মুছে ফেলুন</string>
<string name="title_del_duplicate_config">ডুপ্লিকেট কনফিগারেশন মুছে ফেলুন</string>
<string name="title_del_invalid_config">অবৈধ কনফিগারেশন মুছে ফেলুন (প্রথমে পরীক্ষা করুন)</string>
<string name="title_export_all">কাস্টম না করা কনফিগারেশনগুলি ক্লিপবোর্ডে রপ্তানি করুন</string>
<string name="title_sub_setting">সাবস্ক্রিপশন গ্রুপ সেটিং</string>
<string name="title_export_all">কনফিগারেশন ক্লিপবোর্ডে রপ্তানি করুন</string>
<string name="title_sub_setting">সাবস্ক্রিপশন</string>
<string name="sub_setting_remarks">মন্তব্য</string>
<string name="sub_setting_url">ঐচ্ছিক URL</string>
<string name="sub_setting_user_agent">User Agent</string>
<string name="sub_setting_filter">Remarks regular filter</string>
<string name="sub_setting_user_agent" translatable="false">User Agent</string>
<string name="sub_setting_request_headers">রিকোয়েস্ট হেডার (JSON ফরম্যাট)</string>
<string name="sub_setting_filter">মন্তব্যের রেগুলার এক্সপ্রেশন ফিল্টার</string>
<string name="sub_setting_enable">আপডেট সক্রিয় করুন</string>
<string name="sub_auto_update">স্বয়ংক্রিয় আপডেট সক্রিয় করুন</string>
<string name="sub_allow_insecure_url">Allow insecure HTTP address</string>
<string name="sub_setting_pre_profile">Previous proxy configuration remarks</string>
<string name="sub_setting_next_profile">Next proxy configuration remarks</string>
<string name="sub_setting_pre_profile_tip">The configuration remarks exists and is unique</string>
<string name="sub_allow_insecure_url">অনিরাপদ HTTP ঠিকানা অনুমোদন করুন</string>
<string name="sub_setting_pre_profile">প্রবেশ প্রক্সি</string>
<string name="sub_setting_next_profile">প্রস্থান প্রক্সি</string>
<string name="sub_setting_pre_profile_tip">কনফিগারেশনের মন্তব্যটি বিদ্যমান ও অনন্য হতে হবে</string>
<string name="sub_setting_entry_proxy_tip">নির্বাচিত প্রক্সিটি এই সাবস্ক্রিপশনের প্রতিটি প্রোফাইলের আগে সেই প্রোফাইলের প্রক্সি চেইনের প্রবেশ লিঙ্ক হিসেবে যোগ করা হবে।</string>
<string name="sub_setting_exit_proxy_tip">নির্বাচিত প্রক্সিটি এই সাবস্ক্রিপশনের প্রতিটি প্রোফাইলের পরে সেই প্রোফাইলের প্রক্সি চেইনের প্রস্থান লিঙ্ক হিসেবে যোগ করা হবে।</string>
<string name="toast_invalid_update_interval">আপডেটের বিরতি সঠিক নয়। সর্বনিম্ন ১৫ মিনিট।</string>
<string name="title_sub_update">সাবস্ক্রিপশন আপডেট</string>
<string name="title_ping_all_server">সব কনফিগারেশন TCPing</string>
<string name="title_real_ping_all_server">সব কনফিগারেশন প্রকৃত বিলম্ব</string>
<string name="title_user_asset_setting">Asset files</string>
<string name="title_ping_all_server">TCP বিলম্ব পরীক্ষা করুন (TCPing)</string>
<string name="title_real_ping_all_server">প্রকৃত বিলম্ব পরীক্ষা করুন</string>
<string name="title_user_asset_setting">অ্যাসেট ফাইল</string>
<string name="title_sort_by_test_results">টেস্ট ফলাফল দ্বারা সাজানো</string>
<string name="title_filter_config">কনফিগারেশন ফাইল ফিল্টার করুন</string>
<string name="filter_config_all">All</string>
<string name="filter_config_all">সব</string>
<string name="summary_scan_qrcode">ক্যামেরা স্ক্যান খুলতে পর্দায় ট্যাপ করুন</string>
<string name="title_del_duplicate_config_count">%d ডুপ্লিকেট কনফিগারেশন মুছে ফেলুন</string>
<string name="summary_scan_qrcode">Click screen open the camera scan</string>
<string name="title_del_config_count">Delete %d configurations</string>
<string name="title_import_config_count">Import %d configurations</string>
<string name="title_export_config_count">Export %d configurations</string>
<string name="title_update_config_count">Update %d configurations</string>
<string name="title_update_subscription_result">Updated %1$d configs (%2$d success, %3$d failed, %4$d skipped)</string>
<string name="title_update_subscription_no_subscription">No subscriptions</string>
<string name="toast_server_not_found_in_group">Selected server not found in current group</string>
<string name="toast_fragment_not_available">Unable to locate current view</string>
<string name="title_locate_selected_config">Locate the selected config</string>
<string name="title_del_config_count">%dটি কনফিগারেশন মুছুন</string>
<string name="title_import_config_count">%dটি কনফিগারেশন আমদানি করুন</string>
<string name="title_export_config_count">%dটি কনফিগারেশন রপ্তানি করুন</string>
<string name="title_update_config_count">%dটি কনফিগারেশন আপডেট করুন</string>
<string name="title_update_subscription_result">%1$dটি কনফিগ আপডেট হয়েছে (%2$d সফল, %3$d ব্যর্থ, %4$d এড়ানো)</string>
<string name="title_update_subscription_no_subscription">কোনো সাবস্ক্রিপশন নেই</string>
<string name="toast_server_not_found_in_group">বর্তমান গ্রুপে নির্বাচিত সার্ভারটি পাওয়া যায়নি</string>
<string name="title_locate_selected_config">নির্বাচিত কনফিগটি খুঁজুন</string>
<string name="tasker_start_service">সার্ভিস শুরু করুন</string>
<string name="tasker_setting_confirm">নিশ্চিত করুন</string>
@@ -336,46 +359,50 @@
<!-- RoutingSettingActivity -->
<string name="routing_settings_domain_strategy">ডোমেইন কৌশল</string>
<string name="routing_settings_title">রাউটিং সেটিংস</string>
<string name="routing_settings_tips">কমা (,) দিয়ে আলাদা করুন। domain, ip বা process-এ একটি নির্বাচন করুন</string>
<string name="routing_settings_tips">সব নির্ধারিত মিলের শর্ত একসঙ্গে পূরণ হলেই কেবল নিয়মটি প্রয়োগ হবে (AND)। নিয়মগুলি ওপর থেকে নিচে পরীক্ষা করা হয়; প্রথম মিলে যাওয়া নিয়মটি প্রয়োগ করা হয়।</string>
<string name="routing_settings_comma_tip">একাধিক এন্ট্রি কমা (,) দিয়ে আলাদা করুন।</string>
<string name="routing_settings_save">সেভ করুন</string>
<string name="routing_settings_delete">মুছে ফেলুন</string>
<string name="routing_settings_rule_title">Routing Rule Settings</string>
<string name="routing_settings_add_rule">Add rule</string>
<string name="routing_settings_rule_title">রাউটিং নিয়মের সেটিংস</string>
<string name="routing_settings_add_rule">নিয়ম যোগ করুন</string>
<string name="routing_settings_import_predefined_rulesets">পূর্বনির্ধারিত নিয়মাবলী আমদানি করুন</string>
<string name="routing_settings_import_rulesets_tip">Existing rulesets will be deleted, are you sure to continue?</string>
<string name="routing_settings_import_rulesets_from_clipboard">Import ruleset from clipboard</string>
<string name="routing_settings_import_rulesets_from_qrcode">QRcode থেকে রুলসেট আমদানি করুন</string>
<string name="routing_settings_export_rulesets_to_clipboard">Export ruleset to clipboard</string>
<string name="routing_settings_locked">Locked, keep this rule when import presets</string>
<string name="routing_settings_domain">domain</string>
<string name="routing_settings_ip">ip</string>
<string name="routing_settings_process">process (Package Name — only supported when using Xray TUN, routeOnly enabled, and Android 10+)</string>
<string name="routing_settings_port">port</string>
<string name="routing_settings_protocol">protocol</string>
<string name="routing_settings_protocol_tip">[http,tls,bittorrent]</string>
<string name="routing_settings_network">network</string>
<string name="routing_settings_outbound_tag">outboundTag</string>
<string name="routing_settings_import_rulesets_tip">বিদ্যমান নিয়মসমূহ মুছে যাবে। চালিয়ে যেতে চান?</string>
<string name="routing_settings_import_rulesets_from_clipboard">ক্লিপবোর্ড থেকে নিয়মসমূহ আমদানি করুন</string>
<string name="routing_settings_import_rulesets_from_qrcode">QR কোড থেকে রুলসেট আমদানি করুন</string>
<string name="routing_settings_export_rulesets_to_clipboard">নিয়মসমূহ ক্লিপবোর্ডে রপ্তানি করুন</string>
<string name="routing_settings_locked">লক করা; প্রিসেট আমদানির সময় এই নিয়মটি রাখুন</string>
<string name="routing_settings_domain" translatable="false">domain</string>
<string name="routing_settings_ip" translatable="false">ip</string>
<string name="routing_settings_process">process (প্যাকেজের নাম — শুধু Xray TUN ব্যবহার, routeOnly চালু এবং Android 10+ হলে সমর্থিত)</string>
<string name="routing_settings_process_select">প্যাকেজের নাম নির্বাচন করুন</string>
<string name="routing_settings_port" translatable="false">port</string>
<string name="routing_settings_protocol" translatable="false">protocol</string>
<string name="routing_settings_protocol_tip" translatable="false">[http,tls,bittorrent]</string>
<string name="routing_settings_network" translatable="false">network</string>
<string name="routing_settings_outbound_tag_hint">proxy / direct / block / &lt;%1$s&gt;</string>
<string name="routing_settings_outbound_tag" translatable="false">outboundTag</string>
<string name="connection_test_pending">সংযোগ পরীক্ষা করুন</string>
<string name="connection_test_testing">পরীক্ষা চলছে…</string>
<string name="connection_test_testing_count">Testing %d configurations…</string>
<string name="connection_test_available">সফল: HTTP সংযোগ নিয়েছে %dms</string>
<string name="connection_test_error">ইন্টারনেট সংযোগ সনাক্ত করতে ব্যর্থ: %s</string>
<string name="connection_test_testing_count">%dটি কনফিগারেশন পরীক্ষা করা হচ্ছে…</string>
<string name="connection_test_available">সংযোগ সফল হয়েছে; সময় লেগেছে %1$s</string>
<string name="server_test_delay_value">%1$d মিলিসেকেন্ড</string>
<string name="connection_test_error">সংযোগ পরীক্ষা ব্যর্থ: %s</string>
<string name="connection_test_fail">ইন্টারনেট উপলব্ধ নয়</string>
<string name="connection_test_error_status_code">ত্রুটি কোড: #%d</string>
<string name="connection_connected">সংযুক্ত, সংযোগ পরীক্ষা করতে ট্যাপ করুন</string>
<string name="connection_connected">সংযুক্ত।\nসংযোগ পরীক্ষা করতে ট্যাপ করুন।</string>
<string name="connection_not_connected">সংযুক্ত নয়</string>
<string name="connection_runing_task_left">Number of running test tasks: %s</string>
<string name="connection_running_task_left">চলমান পরীক্ষা: %s</string>
<string name="import_subscription_success">সাবস্ক্রিপশন সফলভাবে আমদানি করা হয়েছে</string>
<string name="import_subscription_failure">সাবস্ক্রিপশন আমদানি ব্যর্থ</string>
<string name="title_fragment_settings">ফ্র্যাগমেন্ট সেটিংস</string>
<string name="title_fragment_settings">প্যাকেট বিভাজন সেটিংস (Fragment)</string>
<string name="title_pref_fragment_packets">ফ্র্যাগমেন্ট প্যাকেটস</string>
<string name="title_pref_fragment_length">ফ্র্যাগমেন্ট দৈর্ঘ্য (ন্যূনতম-সর্বাধিক)</string>
<string name="title_pref_fragment_interval">ফ্র্যাগমেন্ট ইন্টারভ্যাল (ন্যূনতম-সর্বাধিক)</string>
<string name="title_pref_fragment_enabled">ফ্র্যাগমেন্ট সক্রিয় করুন</string>
<string name="title_pref_fragment_maxsplit">ফ্র্যাগমেন্ট ম্যাক্স স্প্লিট</string>
<string name="title_observatory_settings">সংযোগ পর্যবেক্ষণ সেটিংস</string>
<string name="title_observatory_settings">সংযোগ পর্যবেক্ষণ সেটিংস (Observatory)</string>
<string name="title_pref_observatory_least_ping_interval">leastPing ইন্টারভ্যাল</string>
<string name="title_pref_observatory_least_load_interval">leastLoad ইন্টারভ্যাল</string>
<string name="title_pref_observatory_least_load_method">leastLoad HTTP পদ্ধতি</string>
@@ -384,88 +411,133 @@
<string name="toast_invalid_observatory_duration">অবৈধ সময়কাল। 3m বা 30s-এর মতো মান ব্যবহার করুন।</string>
<string name="toast_invalid_observatory_sampling">অবৈধ স্যাম্পলিং। একটি ধনাত্মক সংখ্যা ব্যবহার করুন।</string>
<string name="update_check_for_update">Check for update</string>
<string name="update_already_latest_version">Already on the latest version</string>
<string name="update_new_version_found">New version found: %s</string>
<string name="update_now">Update now</string>
<string name="update_check_pre_release">Check Pre-release</string>
<string name="update_checking_for_update">Checking for update…</string>
<string name="update_check_for_update">আপডেট পরীক্ষা করুন</string>
<string name="update_already_latest_version">ইতিমধ্যে সর্বশেষ সংস্করণ ব্যবহার করছেন</string>
<string name="update_new_version_found">নতুন সংস্করণ পাওয়া গেছে: %s</string>
<string name="update_now">এখনই আপডেট করুন</string>
<string name="update_check_pre_release">প্রাক্‌-রিলিজ পরীক্ষা করুন</string>
<string name="update_checking_for_update">আপডেট পরীক্ষা করা হচ্ছে…</string>
<string name="title_policy_group_type">Policy group type</string>
<string name="title_policy_group_subscription_id">From subscription group</string>
<string name="title_policy_group_subscription_filter">Remarks regular filter</string>
<string name="title_policy_group_test_outbounds">আউটবাউন্ড পরীক্ষা করুন</string>
<string name="title_policy_group_fallback">ফলব্যাক আউটবাউন্ড (ঐচ্ছিক)</string>
<string name="server_proxy_chain_members">Proxy chain members</string>
<string name="server_proxy_chain_pick_members">Tap here to pick member</string>
<string name="server_proxy_chain_member_unselected">Select a member</string>
<string name="server_proxy_chain_members_unselected">Please select member for each chain row</string>
<string name="server_proxy_chain_members_insufficient">Insufficient members</string>
<string name="server_proxy_chain_members_invalid">Invalid chain members: %1$s</string>
<string name="title_policy_group_type">নীতি গ্রুপের ধরন</string>
<string name="title_policy_group_subscription_id">সাবস্ক্রিপশন গ্রুপ থেকে</string>
<string name="title_policy_group_subscription_filter">মন্তব্যের রেগুলার এক্সপ্রেশন ফিল্টার</string>
<string name="title_policy_group_test_outbounds">বহির্গামী সংযোগ পরীক্ষা করুন (outbounds)</string>
<string name="title_policy_group_fallback">বিকল্প বহির্গামী সংযোগ (outbound, ঐচ্ছিক)</string>
<string name="server_proxy_chain_members">প্রক্সি চেইনের সদস্য</string>
<string name="server_proxy_chain_pick_members">সদস্য বাছতে এখানে ট্যাপ করুন</string>
<string name="server_proxy_chain_member_unselected">চেইনের সদস্য নির্বাচন করুন</string>
<string name="server_proxy_chain_members_unselected">চেইনের প্রতিটি সারির জন্য সদস্য নির্বাচন করুন</string>
<string name="server_proxy_chain_members_insufficient">পর্যাপ্ত সদস্য নেই</string>
<string name="server_proxy_chain_members_invalid">অবৈধ চেইন সদস্য: %1$s</string>
<!-- BackupActivity -->
<string name="title_configuration_backup_restore">Backup &amp; Restore</string>
<string name="title_configuration_backup_restore">ব্যাকআপ ও পুনরুদ্ধার</string>
<string name="title_configuration_backup">কনফিগারেশন ব্যাকআপ</string>
<string name="title_configuration_restore">কনফিগারেশন পুনরুদ্ধার</string>
<string name="title_configuration_share">কনফিগারেশন শেয়ার করুন</string>
<string name="title_webdav_config_setting">WebDAV Settings</string>
<string name="title_webdav_config_setting_unknown">Please configure WebDAV first.</string>
<string name="title_webdav_url">WebDAV server URL</string>
<string name="title_webdav_user">Username</string>
<string name="title_webdav_pass">Password</string>
<string name="title_webdav_remote_path">Remote directory (optional)</string>
<string name="title_webdav_config_setting">WebDAV সেটিংস</string>
<string name="title_webdav_config_setting_unknown">প্রথমে WebDAV কনফিগার করুন।</string>
<string name="title_webdav_url">WebDAV সার্ভারের URL</string>
<string name="title_webdav_user">ব্যবহারকারীর নাম</string>
<string name="title_webdav_pass">পাসওয়ার্ড</string>
<string name="title_webdav_remote_path">দূরবর্তী ডিরেক্টরি (ঐচ্ছিক)</string>
<string name="share_method_qrcode">QR কোড</string>
<string name="share_method_clipboard">ক্লিপবোর্ডে রপ্তানি করুন</string>
<string name="share_method_full_content">পূর্ণ কনফিগারেশন ক্লিপবোর্ডে রপ্তানি করুন</string>
<string name="share_method_clipboard">প্রোফাইল লিংক কপি করুন</string>
<string name="share_method_full_content">পূর্ণ কনফিগারেশন কপি করুন</string>
<string name="action_edit">সম্পাদনা</string>
<string name="action_delete">মুছুন</string>
<string name="action_close">বন্ধ করুন</string>
<string-array name="share_sub_method">
<item>QR কোড</item>
<item>ক্লিপবোর্ডে রপ্তানি করুন</item>
</string-array>
<string name="share_subscription_qrcode">QR কোড</string>
<string name="share_subscription_clipboard">ক্লিপবোর্ডে রপ্তানি করুন</string>
<string-array name="mode_entries">
<item>VPN</item>
<item>শুধুমাত্র প্রোক্সি</item>
</string-array>
<string-array name="browser_dialer_mode">
<item>নিষ্ক্রিয়</item>
<item>OkHttp</item>
<item>WebView</item>
</string-array>
<string-array name="ui_mode_night">
<item>সিস্টেম অনুসরণ করুন</item>
<item>লাইট</item>
<item>ডার্ক</item>
</string-array>
<string-array name="preset_rulesets">
<item>চায়না হোয়াইটলিস্ট</item>
<item>চায়না ব্ল্যাকলিস্ট</item>
<item>গ্লোবাল</item>
<item>ইরান হোয়াইটলিস্ট</item>
<item>রাশিয়া হোয়াইটলিস্ট</item>
</string-array>
<string name="routing_preset_china_whitelist">চায়না হোয়াইটলিস্ট</string>
<string name="routing_preset_china_blacklist">চায়না ব্ল্যাকলিস্ট</string>
<string name="routing_preset_global">গ্লোবাল</string>
<string name="routing_preset_iran_whitelist">ইরান হোয়াইটলিস্ট</string>
<string name="routing_preset_russia_whitelist">রাশিয়া হোয়াইটলিস্ট</string>
<string-array name="vpn_bypass_lan">
<item>Follow config</item>
<item>Bypass</item>
<item>Not Bypass</item>
<item>কনফিগ অনুসরণ করুন</item>
<item>বাইপাস</item>
<item>বাইপাস নয়</item>
</string-array>
<string-array name="outbound_domain_resolve_method">
<item>Do not resolve</item>
<item>Resolve and add to DNS Hosts</item>
<item>Resolve and replace domain</item>
</string-array>
<string-array name="policy_group_type">
<item>Least Ping</item>
<item>Least Load</item>
<item>Random</item>
<item>Round Robin</item>
<item>রেজলভ করবেন না</item>
<item>রেজলভ করে DNS Hosts-এ যোগ করুন</item>
<item>রেজলভ করে ডোমেইন প্রতিস্থাপন করুন</item>
</string-array>
<string-array name="config_backup_options">
<item>Local</item>
<item>WebDAV</item>
<string-array name="policy_group_type">
<item>সর্বনিম্ন পিং (leastPing)</item>
<item>সর্বনিম্ন লোড (leastLoad)</item>
<item>এলোমেলো (random)</item>
<item>রাউন্ড রবিন (roundRobin)</item>
</string-array>
<string name="backup_location_local">স্থানীয়</string>
<string name="backup_location_webdav" translatable="false">WebDAV</string>
<string name="acc_refresh">লগ রিফ্রেশ করুন</string>
<string name="toast_permission_denied_for">%1$s ব্যবহারের অনুমতি দেওয়া হয়নি</string>
<string name="acc_add_subscription">সাবস্ক্রিপশন যোগ করুন</string>
<string name="toast_malformed_json_detail">কনফিগারেশন ফরম্যাট সঠিক নয়: %1$s</string>
<string name="acc_add_asset">অ্যাসেট উৎস যোগ করুন</string>
<string name="acc_download_file">অ্যাসেট ফাইল ডাউনলোড করুন</string>
<string name="acc_qr_code">QR কোড</string>
<string name="acc_copy_log">লগ কপি করুন</string>
<string name="acc_clear_log">লগ মুছুন</string>
<string name="acc_add_rule">রাউটিং নিয়ম যোগ করুন</string>
<string name="acc_start">সার্ভিস শুরু করুন</string>
<string name="acc_stop">সার্ভিস বন্ধ করুন</string>
<string name="acc_back">ফিরে যান</string>
<string name="acc_search">অনুসন্ধান করুন</string>
<string name="acc_add">কনফিগারেশন যোগ করুন</string>
<string name="acc_more">আরও বিকল্প</string>
<string name="acc_share_subscription">সাবস্ক্রিপশন লিংক শেয়ার করুন</string>
<string name="acc_share_log">লগ শেয়ার করুন</string>
<string name="acc_remove">প্রক্সি চেইনের সদস্য সরান</string>
<string name="acc_add_member">প্রক্সি চেইনে সদস্য যোগ করুন</string>
<string name="acc_start_scanner">QR স্ক্যানার চালু করুন</string>
<string name="acc_stop_scanner">QR স্ক্যানার বন্ধ করুন</string>
<string name="acc_turn_torch_on">ফ্ল্যাশলাইট চালু করুন</string>
<string name="acc_turn_torch_off">ফ্ল্যাশলাইট বন্ধ করুন</string>
<string name="acc_select_image">স্ক্যান করার জন্য ছবি নির্বাচন করুন</string>
<string name="acc_locked">প্রিসেট আমদানি করলে নিয়মটি রাখা হবে</string>
<string name="acc_open_menu">নেভিগেশন মেনু খুলুন</string>
<string name="acc_edit">সম্পাদনা করুন</string>
<string name="acc_delete">মুছুন</string>
<string name="acc_save">সংরক্ষণ করুন</string>
<string name="acc_update_subscriptions">সাবস্ক্রিপশন আপডেট করুন</string>
<string name="acc_per_app_proxy_information">প্রতি-অ্যাপ প্রক্সির তথ্য</string>
<string name="permission_camera">ক্যামেরা</string>
<string name="permission_notification">বিজ্ঞপ্তি</string>
<string name="permission_local_network">স্থানীয় নেটওয়ার্ক</string>
<string name="subscription_update_updating">সাবস্ক্রিপশন আপডেট করা হচ্ছে: %1$s</string>
<string name="subscription_update_progress">%2$s পরীক্ষা করা হচ্ছে: %1$s</string>
<string name="tasker_blurb_start">%1$s চালু করুন</string>
<string name="tasker_blurb_stop">%1$s বন্ধ করুন</string>
<string name="connection_test_empty_message">কোনো বিবরণ পাওয়া যায়নি</string>
<string name="value_unknown">অজানা</string>
</resources>
@@ -1,16 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" translatable="false">v2rayNG</string>
<string name="app_widget_name">آلشت</string>
<string name="app_tile_name">آلشت</string>
<string name="app_tile_first_use">سی کرت ٱولی و کار بوردن ای ویژیی، ٱول ز من برنومه ی سرور ازاف کۊنین</string>
<string name="app_tile_first_use">سی کرت ٱولی و کار بوردن ای ویژیی، ٱول ز من برنومه ی سرور اضاف کۊنین</string>
<string name="navigation_drawer_open">گۊشیڌن نومگه کشاری</string>
<string name="navigation_drawer_close">بستن نومگه کشاری</string>
<string name="migration_success">جاگورویی داده یل وا مووفقیت ٱنجوم وابی!</string>
<string name="migration_success">جاگورویی داڌه یل وا مووفقیت ٱنجوم وابی!</string>
<string name="action_stop_service">واڌاشتن سرویس</string>
<string name="migration_fail">جاگورویی داده یل شکست خرد!</string>
<string name="action_ok">قوۊل</string>
<string name="action_cancel">لغو</string>
<string name="migration_fail">جاگورویی داڌه یل شکست خرد!</string>
<string name="pull_down_to_refresh">سی وانۊ کردن، بلگه ن بلم بکشین!</string>
<!-- Notifications -->↓
<!-- Notifications -->
<string name="notification_action_stop_v2ray">واڌاشتن</string>
<string name="toast_permission_denied">گرؽڌن موجوز مومکن نؽڌ</string>
<string name="toast_permission_denied_notification">گرؽڌن موجوز وارسۊوی مومکن نؽڌ</string>
@@ -26,9 +29,9 @@
<string name="menu_item_save_config">زفت کردن کانفیگ</string>
<string name="menu_item_edit_config">آلشتکاری کانفیگ</string>
<string name="menu_item_del_config">پاک کردن کانفیگ</string>
<string name="menu_item_import_config_qrcode">و من ٱووردن کانفیگ ز QRcode</string>
<string name="menu_item_import_config_qrcode">و من ٱووردن کانفیگ ز کود QR</string>
<string name="menu_item_import_config_clipboard">و من ٱووردن کانفیگ ز کلیپ بورد</string>
<string name="menu_item_import_config_local">و من ٱووردن کانفیگ ز مهلی</string>
<string name="menu_item_import_config_local">و من ٱووردن کانفیگ ز محلی</string>
<string name="menu_item_import_config_policy_group">ٱووردن [بونکۊ سیاست]</string>
<string name="menu_item_import_config_proxy_chain">ٱووردن [زنجیره پروکسی]</string>
<string name="menu_item_import_config_manually_vmess">ٱووردن [VMess]</string>
@@ -37,18 +40,18 @@
<string name="menu_item_import_config_manually_socks">ٱووردن [SOCKS]</string>
<string name="menu_item_import_config_manually_http">ٱووردن [HTTP]</string>
<string name="menu_item_import_config_manually_trojan">ٱووردن [Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">ٱووردن [Wireguard]</string>
<string name="menu_item_import_config_manually_wireguard">ٱووردن [WireGuard]</string>
<string name="menu_item_import_config_manually_hysteria2">ٱووردن [Hysteria2]</string>
<string name="confirm_delete_visible_profiles">آیا مطمئن هستید که می‌خواهید همه پروفایل‌های نمایش‌داده‌شده را حذف کنید؟</string>
<string name="confirm_delete_duplicate_profiles">آیا مطمئن هستید که می‌خواهید همه پروفایل‌های تکراری نمایش‌داده‌شده را حذف کنید؟</string>
<string name="confirm_delete_invalid_profiles">لطفاً ابتدا پروفایل‌ها را آزمایش کنید. آیا مطمئن هستید که می‌خواهید همه پروفایل‌های نامعتبر نمایش‌داده‌شده را حذف کنید؟</string>
<string name="confirm_delete_profile">آیا مطمئن هستید که می‌خواهید این پروفایل را حذف کنید؟</string>
<string name="confirm_delete_policy_group">آیا مطمئن هستید که می‌خواهید این گروه سیاست را حذف کنید؟</string>
<string name="confirm_delete_proxy_chain_member">آیا مطمئن هستید که می‌خواهید این عضو زنجیره پراکسی را حذف کنید؟</string>
<string name="confirm_delete_routing_rule">آیا مطمئن هستید که می‌خواهید این قانون مسیریابی را حذف کنید؟</string>
<string name="confirm_delete_subscription_group">آیا مطمئن هستید که می‌خواهید این گروه اشتراک را حذف کنید؟</string>
<string name="confirm_delete_asset_file">آیا مطمئن هستید که می‌خواهید فایل دارایی \"%1$s\" را حذف کنید؟</string>
<string name="confirm_delete_asset_source">آیا مطمئن هستید که می‌خواهید این منبع دارایی را حذف کنید؟</string>
<string name="confirm_delete_visible_profiles">پوی کانفیگا ک هیم سکو نشووݩ داڌه ابۊن پاک ابۊن، هنی هم اخۊی پاکسووݩ کۊنی؟</string>
<string name="confirm_delete_duplicate_profiles">پوی کانفیگا تکراری ک هیم سکو نشووݩ داڌه ابۊن پاک ابۊن، هنی هم اخۊی پاکسووݩ کۊنی؟</string>
<string name="confirm_delete_invalid_profiles">ٱول کانفیگا ن آزمایش کۊنین. پوی کانفیگا نا موئتبر ک هیم سکو نشووݩ داڌه ابۊن پاک ابۊن، هنی هم اخۊی پاکسووݩ کۊنی؟</string>
<string name="confirm_delete_profile">ای کانفیگ پاک ابۊ، هنی هم اخۊی پاکس کۊنی؟</string>
<string name="confirm_delete_policy_group">ای بونکۊ سیاست پاک ابۊ، هنی هم اخۊی پاکس کۊنی؟</string>
<string name="confirm_delete_proxy_chain_member">ای عوزو زنجیره پروکسی پاک ابۊ، هنی هم اخۊی پاکس کۊنی؟</string>
<string name="confirm_delete_routing_rule">ای قانووݩ تور جوستن پاک ابۊ، هنی هم اخۊی پاکس کۊنی؟</string>
<string name="confirm_delete_subscription_group">ای بونکۊ اشتراک پاک ابۊ، هنی هم اخۊی پاکس کۊنی؟</string>
<string name="confirm_delete_asset_file">فایل بونچک جغرافیایی «%1$s» پاک ابۊ، هنی هم اخۊی پاکس کۊنی؟</string>
<string name="confirm_delete_asset_source">ای بونچک فایلا جغرافیایی پاک ابۊ، هنی هم اخۊی پاکس کۊنی؟</string>
<string name="server_lab_remarks">نیشتنا</string>
<string name="server_lab_address">نشۊوی</string>
<string name="server_lab_port">پورت</string>
@@ -58,7 +61,7 @@
<string name="server_lab_network">شبکه</string>
<string name="server_lab_more_function">جاگورو</string>
<string name="server_lab_head_type">نوع هدر</string>
<string name="server_lab_mode_type">هالت gRPC</string>
<string name="server_lab_mode_type">حالت gRPC</string>
<string name="server_lab_request_host">هاست</string>
<string name="server_lab_request_host_http">هاست http</string>
<string name="server_lab_request_host_ws">هاست ws</string>
@@ -72,14 +75,14 @@
<string name="server_lab_path_httpupgrade">تور HTTPUpgrade</string>
<string name="server_lab_path_xhttp">تور XHTTP</string>
<string name="server_lab_path_h2">تور H2</string>
<string name="server_lab_path_quic">تور QUIC</string>
<string name="server_lab_path_quic">کیلیت QUIC</string>
<string name="server_lab_path_kcp">KCP seed</string>
<string name="server_lab_path_grpc">نوم سرویس gRPC</string>
<string name="server_lab_stream_security">TLS</string>
<string name="server_lab_stream_fingerprint" translatable="false">Fingerprint</string>
<string name="server_lab_stream_alpn">Alpn</string>
<string name="server_lab_allow_insecure">هشتن SSL نا ٱمن</string>
<string name="server_lab_sni">SNI</string>
<string name="server_lab_stream_security" translatable="false">TLS</string>
<string name="server_lab_stream_fingerprint">جا کلک</string>
<string name="server_lab_stream_alpn" translatable="false">ALPN</string>
<string name="server_lab_allow_insecure">تئیڌ گوواهی ن ناڌیڌه بگرین (allowInsecure)</string>
<string name="server_lab_sni" translatable="false">SNI</string>
<string name="server_lab_address3">نشۊوی</string>
<string name="server_lab_port3">پورت</string>
<string name="server_lab_id3">رزم</string>
@@ -87,46 +90,49 @@
<string name="server_lab_id4">رزم (اختیاری)</string>
<string name="server_lab_security4">نوم منتوری (اختیاری)</string>
<string name="server_lab_encryption">رزم نگاری</string>
<string name="server_lab_flow">جریان</string>
<string name="server_lab_flow">جریان (flow)</string>
<string name="server_lab_public_key">کیلیت پوی وولاتی</string>
<string name="server_lab_preshared_key">کیلیت پؽش اشتراکی (اختیاری)</string>
<string name="server_lab_short_id">شناسه کۊتال</string>
<string name="server_lab_spider_x">SpiderX</string>
<string name="server_lab_mldsa65_verify">تاییدیه Mldsa65Verify</string>
<string name="server_lab_spider_x" translatable="false">SpiderX</string>
<string name="server_lab_mldsa65_verify" translatable="false">mldsa65Verify</string>
<string name="server_lab_secret_key">کیلیت سیخومی</string>
<string name="server_lab_reserved">Reserved(اختیاری، وا کاما (,) ز یک جوڌا ابۊن)</string>
<string name="server_lab_local_address">نشۊوی مهلی (اختیاری IPv4/IPv6، وا کاما (,) ز یک جوڌا ابۊن)</string>
<string name="server_lab_local_mtu">Mtu(اختیاری، پؽش فرز 1420)</string>
<string name="server_lab_kcp_mtu">mKCP MTU (اختیاری، پؽش فرز هسته 1350)</string>
<string name="server_lab_kcp_tti">mKCP TTI (اختیاری، پؽش فرز هسته 50)</string>
<string name="server_lab_local_address">نشۊوی محلی (اختیاری IPv4/IPv6، وا کاما (,) ز یک جوڌا ابۊن)</string>
<string name="server_lab_local_mtu">MTU(اختیاری، پؽش فرض 1420)</string>
<string name="server_lab_kcp_mtu">mKCP MTU (اختیاری، پؽش فرض هسته 1350)</string>
<string name="server_lab_kcp_tti">mKCP TTI (اختیاری، پؽش فرض هسته 50)</string>
<string name="toast_success">وا مووفقیت ٱنجوم وابی</string>
<string name="toast_failure">شکست خرد</string>
<string name="toast_none_data">هیچ داده ای وۊجۊڌ نڌاره</string>
<string name="toast_none_data">هیچ داڌه ای وۊجۊڌ نڌاره</string>
<string name="toast_incorrect_protocol">پوروتوکول نادوروست</string>
<string name="toast_decoding_failed">رزم گوشایی ٱنجوم نوابی</string>
<string name="title_file_chooser">پسند فایل کانفیگ</string>
<string name="toast_require_file_manager">ی برنومه دؽوۉداری فایل بپۊرنین.</string>
<string name="server_customize_config">کانفیگ سفارشی</string>
<string name="toast_config_file_invalid">کانفیگ نا موئتبر هڌ</string>
<string name="server_lab_content">موئتوا</string>
<string name="toast_none_data_clipboard">هیچ داده ای من کلیپ بورد وۊجۊڌ نڌاره</string>
<string name="server_lab_content">محتوا</string>
<string name="toast_none_data_clipboard">هیچ داڌه ای من کلیپ بورد وۊجۊڌ نڌاره</string>
<string name="toast_invalid_url">نشۊوی اینترنتی نا موئتبر هڌ</string>
<string name="toast_insecure_url_protocol">نشۊوی اشتراک پوروتوکول نا ٱمن HTTP ن و کار مبرین</string>
<string name="server_lab_need_inbound">موتمعن بۊین ک پورت وۊرۊڌی وا سامووا ی جۊر هڌ</string>
<string name="toast_malformed_josn">کانفیگ زبال نؽڌ</string>
<string name="server_lab_need_inbound">موطمئن بۊین ک پورت وۊرۊڌی وا سامووا ی جۊر هڌ</string>
<string name="toast_malformed_json">کانفیگ نا موئتبر هڌ</string>
<string name="server_lab_request_host6">هاست(SNI)(اختیاری)</string>
<string name="toast_action_not_allowed">ای کار ممنۊع هڌ</string>
<string name="server_obfs_password">رزم obfs</string>
<string name="server_lab_port_hop">پورت گوم (درگا سرورن ز نۊ هؽل اکونه)</string>
<string name="server_lab_port_hop_interval">فاسله پورت گوم (سانیه)</string>
<string name="server_lab_port_hop_interval">فاصله پورت گوم (ثانیه)</string>
<string name="server_lab_bandwidth_down">ب لم ٱووڌن پئنا باند (واهڌ)</string>
<string name="server_lab_bandwidth_up">وا روء رئڌن پئنا باند (واهڌ)</string>
<string name="server_lab_xhttp_mode">هالت XHTTP</string>
<string name="server_lab_xhttp_mode">حالت XHTTP</string>
<string name="server_lab_xhttp_extra">XHTTP Extra خام JSON، قالوو: { XHTTPObject }</string>
<string name="server_lab_final_mask">finalMask خام JSON، قالوو: { FinalMaskObject }</string>
<string name="server_lab_ech_config_list">نومگه کانفیگ Ech</string>
<string name="server_lab_ech_config_list" translatable="false">echConfigList</string>
<string name="server_lab_verify_peer_cert_by_name">تئیڌ گوواهی هومتا و ری نوم</string>
<string name="server_lab_pinned_ca256">جا کلک گوواهی (SHA-256)</string>
<string name="server_lab_browser_dialer">Browser Dialer ن ره وستین</string>
<string name="server_lab_browser_dialer_tip">تینا وۊرۊیا xhttp (packet-up) وو ws ن پوشتؽووی اکونه؛ گاشڌ سامووا وابسته و TLS ناڌیڌه گرفته ابۊن یا وا همن جۊر نین</string>
<string name="toast_allow_insecure_deprecated">ای گر ز منپیز بی رمزنگاری کار اگیره. گاشڌ منپیزا شمو و دست دسگایل میووݩ شبکه ک و دست دولتا استبداڌی کنتورول ابۊن موستقیمن دیڌه ابۊ.\nسی ٱمنیت، ای جۊر گر یل وا هسته Xray نوسخه 26.2.6+ منپیز نابۊن.\nٱر گر خوتووݩ هڌ، رمزنگاری ٱمنی وری TLS ن ره وستین یا اثر انگشت گوواهی pinnedCA256 ن چفت کۊنین.\nٱر گر مال سرویس ڌهنده هڌ، ز سرویس ڌهنده بخواین ٱرتقا فنی ن ٱنجوم بڌه. ٱر همکاری نکونه، بئتره سرویس ڌهنده ی ک ب ٱمنیت کارورووݩ بؽتر اهمیت اڌه پسند کۊنین.\nسی دووسته بؽتر ورین و https://github.com/2dust/v2rayN/discussions/9460</string>
<string name="pinned_ca256_action_fetch">گرؽڌن وو پور کردن جا کلک گوواهی</string>
<string name="toast_fetch_cert_sha256_success">جا کلک گوواهی وا مووفقیت گرؽڌه وابی</string>
<string name="toast_fetch_cert_sha256_failed">گرؽڌن جا کلک گوواهی مووفق نبی</string>
@@ -136,28 +142,28 @@
<string name="menu_item_add_asset">ٱووردن دارایی</string>
<string name="menu_item_add_file">ٱووردن فایل</string>
<string name="menu_item_add_url">ٱووردن لینگ</string>
<string name="menu_item_scan_qrcode">اسکن QRcode</string>
<string name="title_url">نشۊوی اینترنتی</string>
<string name="menu_item_scan_qrcode">اسکن کود QR</string>
<string name="title_url" translatable="false">URL</string>
<string name="menu_item_download_file">دانلود فایلا</string>
<string name="title_user_asset_add_url">نشۊوی اینترنتی دارایی ن ازاف کۊنین</string>
<string name="title_user_asset_add_url">نشۊوی اینترنتی بونچک ن اضاف کۊنین</string>
<string name="msg_file_not_found">فایلن نجوست</string>
<string name="msg_remark_is_duplicate">ای نوم ز زیتر بیڌس</string>
<string name="asset_geo_files_sources">بونچک فایلا جوقرافیایی (اختیاری)</string>
<string name="asset_geo_files_sources">بونچک فایلا جغرافیایی (اختیاری)</string>
<!-- PerAppProxyActivity -->
<string name="msg_dialog_progress">هونی بار ونی ابۊ...</string>
<string name="msg_dialog_progress">هونی بار ونی ابۊ…</string>
<string name="menu_item_search">پیتینیڌن</string>
<string name="menu_item_select_all">پسند پوی</string>
<string name="menu_item_invert_selection">چواسه کردن پسندا</string>
<string name="msg_enter_keywords">کلمه یل کلیدی ن بزنین</string>
<string name="switch_bypass_apps_mode">هالت دور زیڌن</string>
<string name="msg_enter_keywords">کلمه یل کلیڌی ن بزنین</string>
<string name="switch_bypass_apps_mode">حالت دور زیڌن</string>
<string name="menu_item_select_proxy_app">پسند خوتکار برنومه یلی ک پروکسی اخون</string>
<string name="msg_downloading_content">موئتوا هونی دانلود ابۊن...</string>
<string name="msg_downloading_content">محتوا هونی دانلود ابۊن…</string>
<string name="menu_item_export_proxy_app">و در کشیڌن من کلیپ بورد</string>
<string name="menu_item_import_proxy_app">و من ٱووردن ز کلیپ بورد</string>
<string name="per_app_proxy_settings">سامووا ب تفکیک برنومه</string>
<string name="per_app_proxy_settings_enable">ره وندن ب تفکیک برنومه</string>
<string name="app_picker_unknown_app">برنومه ناناس (UID ناساڌه)</string>
<!-- Preferences -->
<string name="title_settings">سامووا</string>
@@ -165,10 +171,14 @@
<string name="title_core_settings">سامووا هسته</string>
<string name="title_vpn_settings">سامووا VPN</string>
<string name="title_pref_per_app_proxy">پروکسی و ری برنومه</string>
<string name="summary_pref_per_app_proxy">پوی وولاتی: برنومه پسند وابیڌه وا ی پروکسی منپیز ابۊ، برنومه پسند نوابیڌه موستقیمن منپیز ابۊ.\nهالت دور زیڌن: برنومه پسند وابیڌه موستقیمن منپیز ابۊ، برنومه پسند نوابیڌه وا ی پروکسی منپیز ابۊ.\nپسند خوتکار برنومه یل پروکسی من نومگه امکووݩ پزیر هڌ.</string>
<string name="summary_pref_per_app_proxy">پوی وولاتی: برنومه پسند وابیڌه وا ی پروکسی منپیز ابۊ، برنومه پسند نوابیڌه موستقیمن منپیز ابۊ.\nحالت دور زیڌن: برنومه پسند وابیڌه موستقیمن منپیز ابۊ، برنومه پسند نوابیڌه وا ی پروکسی منپیز ابۊ.\nپسند خوتکار برنومه یلی ک وا ی پروکسی منپیز ابۊن من نومگه امکووݩ پذیر هڌ.</string>
<string name="title_pref_is_booted">منپیز خوتکار مجال ره ونی</string>
<string name="summary_pref_is_booted">مجال ره وندن، خوساخوس و سرور پسند بیڌه منپیز ابۊ که گاشڌ نا مووفق بۊ.</string>
<string name="subscription_updater_job_tips">وزیفه من پس زمینه کار اکونه وو ایلاعات پؽشرفت من اعلان نشووݩ داڌه ابۊ.</string>
<string name="title_pref_auto_test_after_update_subscription">تست خوتکار بئڌ و رۊز کۊنی اشتراک</string>
<string name="summary_pref_auto_test_after_update_subscription">تست خوتکار زمووݩ زیاڌی ابره. ٱر ره وست بۊ، وزیفه من پس زمینه کار اکونه؛ وگرنه من همین بلگه کار اکونه.</string>
<string name="title_pref_auto_remove_invalid_after_test">پاک کردن خوتکار کانفیگا نا موئتبر بئڌ پینگ</string>
<string name="summary_pref_auto_remove_invalid_after_test">نتیجه یل پینگ گاشڌ دییق نبۊن؛ کانفیگا پاک وابیڌه ن نتری وورگنی.</string>
<string name="title_pref_auto_sort_after_test">ترتیب خوتکار بئڌ پینگ گرؽڌن</string>
@@ -176,9 +186,9 @@
<string name="title_mux_settings">سامووا Mux</string>
<string name="title_pref_mux_enabled">ره وندن Mux</string>
<string name="summary_pref_mux_enabled">زل تر، ٱما گاشڌ منپیز زی قت بۊ\nمخزن ترافیک TCP وا 8 منپیز پؽش فرز، بارت دؽوۉداری UDP وو QUIC ن ای لم سفارشی کۊنین.</string>
<string name="title_pref_mux_concurency">منپیزا TCP (تلایه منجا 1-1024)</string>
<string name="title_pref_mux_xudp_concurency">منپیزا XUDP (تلایه منجا 1-1024)</string>
<string name="summary_pref_mux_enabled">زل تر، ٱما گاشڌ منپیز زی قط بۊ\nدؽوۉداری TCP، UDP وو QUIC ن ای لم سفارشی کۊنین.</string>
<string name="title_pref_mux_concurrency">منپیزا TCP (تلایه منجا -1 تا 1024)</string>
<string name="title_pref_mux_xudp_concurrency">منپیزا XUDP (تلایه منجا -1 تا 1024)</string>
<string name="title_pref_mux_xudp_quic">دؽوۉداری QUIC من تۊنل mux</string>
<string-array name="mux_xudp_quic_entries">
<item>رڌ کردن</item>
@@ -187,116 +197,121 @@
</string-array>
<string name="title_pref_speed_enabled">ره وندن نشووݩ داڌن سورعت</string>
<string name="summary_pref_speed_enabled">نشووݩ داڌن سورعت هیم سکویی من وارسۊویا.\nنماڌ وارسۊوی و ری و کار گرؽڌن کانفیگ آلشت ابۊ.</string>
<string name="summary_pref_speed_enabled">سورعت هیم سکویی من وارسۊوی نشووݩ داڌه ابۊ.\nنماڌ نشووݩ اڌه ک ترافیک پروکسی یا موستقیم بؽتره.</string>
<string name="title_pref_sniffing_enabled">ره وندن تجزیه وو تئلیل کتنا (Sniffing)</string>
<string name="summary_pref_sniffing_enabled">قپ ریت سی و در کشیڌن نوم دامنه واقعی ز کتنا (پؽش فرز رۊشن هڌ)</string>
<string name="title_pref_sniffing_enabled">ره وندن در کشیڌن نوم دامنه موورد نظر (Sniffing)</string>
<string name="summary_pref_sniffing_enabled">قپ ریت سی و در کشیڌن نوم دامنه واقعی ز کتنا (پؽش فرض رۊشن هڌ)</string>
<string name="title_pref_route_only_enabled">ره وندن تینا تور جوستن routeOnly</string>
<string name="summary_pref_route_only_enabled">نوم دامنه sniffed ن تینا سی تور جوستن و کار بگیرین وو نشۊوی موورد نزرن و عونوان نشۊوی IP ووردارین.</string>
<string name="summary_pref_route_only_enabled">نوم دامنه sniffed ن تینا سی تور جوستن و کار بگیرین وو نشۊوی موورد نظرن و عونوان نشۊوی IP ووردارین.</string>
<string name="title_pref_local_dns_enabled">ره وندن DNS مهلی</string>
<string name="summary_pref_local_dns_enabled">درخاستا DNS و هسته و من ایان وو و دست ماژول DNS پردازشت ابۊن (پؽشنهاڌ ابۊ ٱر لنگ تور جوستن سی دور زیڌن نشۊویا LAN وو وولات ٱسلی هڌین ره ونده بۊ)</string>
<string name="title_pref_local_dns_enabled">ره وندن DNS محلی</string>
<string name="summary_pref_local_dns_enabled">درخواستا DNS و هسته و من ایان وو و دست ماژول DNS پردازشت ابۊن (پؽشنهاڌ ابۊ ٱر لنگ تور جوستن سی دور زیڌن نشۊویا LAN وو وولات ٱسلی هڌین ره ونده بۊ)</string>
<string name="title_pref_fake_dns_enabled">ره وندن DNS جئلی</string>
<string name="summary_pref_fake_dns_enabled">دی ان اس مهلی نشۊویا آی پی جئلی ن اوورگنه (زل تر، ٱما گاشڌ من ی قرده ز برنومه یل کار نکونه)</string>
<string name="title_pref_fake_dns_enabled">ره وندن DNS جئلی (FakeDNS)</string>
<string name="summary_pref_fake_dns_enabled">FakeDNS نشۊویا IP جئلی ن سی نوم دامنه اوورگنه (زل تر، ٱما گاشڌ من ی قرده ز برنومه یل کار نکونه).</string>
<string name="title_pref_ipv6_enabled">ره وندن IPv6</string>
<string name="summary_pref_ipv6_enabled">نشۊویا وو تورا IPv6 ن و رابت VPN ازاف کۊنین</string>
<string name="summary_pref_ipv6_enabled">نشۊویا وو تورا IPv6 ن و رابط VPN اضاف کۊنین</string>
<string name="title_pref_prefer_ipv6">ترجی داڌن IPv6</string>
<string name="summary_pref_prefer_ipv6">مجال هل وو فسل نوم دامنه، نشۊویا IPv6 ن ترجی بڌین</string>
<string name="title_pref_remote_dns">DNS ز ره دیر (اختیاری) (udp/tcp/https/quic) (اختیاری)</string>
<string name="summary_pref_remote_dns">DNS</string>
<string name="title_pref_remote_dns">DNS ز ره دیر (UDP/TCP/HTTPS/QUIC، اختیاری)</string>
<string name="summary_pref_remote_dns" translatable="false">DNS</string>
<string name="title_pref_vpn_dns">VPN DNS (تینا IPv4/v6)</string>
<string name="title_pref_vpn_bypass_lan">VPN ز شبکه مهلی اگوڌرته؟</string>
<string name="title_pref_vpn_dns">VPN DNS (تینا IPv4/IPv6)</string>
<string name="title_pref_vpn_bypass_lan">VPN ز شبکه محلی اگوڌرته؟</string>
<string name="title_pref_vpn_interface_address">نشۊوی رابت VPN</string>
<string name="title_pref_vpn_mtu">VPN MTU (پؽش فرز 1500)</string>
<string name="title_pref_vpn_interface_address">نشۊوی رابط VPN</string>
<string name="title_pref_domestic_dns">DNS منی (اختیاری)</string>
<string name="summary_pref_domestic_dns">DNS</string>
<string name="title_pref_vpn_mtu">VPN MTU (پؽش فرض 1500)</string>
<string name="title_pref_dns_hosts">DNS هاست موستقیم (قالوو: دامنه: نشۊوی،...)</string>
<string name="summary_pref_dns_hosts">دامنه:نشۊوی،...</string>
<string name="title_pref_domestic_dns">DNS موستقیم (اختیاری)</string>
<string name="summary_pref_domestic_dns" translatable="false">DNS</string>
<string name="title_pref_dns_hosts">هاستا DNS (قالوو: domain:address,…)</string>
<string name="summary_pref_dns_hosts">دامنه:نشۊوی،…</string>
<string name="title_pref_delay_test_url">نشۊوی اینترنتی آزمایش تئخیر واقعی</string>
<string name="summary_pref_delay_test_url">نشۊوی اینترنتی</string>
<string name="title_pref_real_ping_concurrency">تعداد هوم زمووی تست تئخیر واقعی</string>
<string name="summary_pref_delay_test_url" translatable="false">URL</string>
<string name="title_pref_real_ping_concurrency">تعداڌ هوم زمووی تست تئخیر واقعی</string>
<string name="title_pref_ip_api_url">نشۊوی اینترنتی آزمایش دووسمندیا منپیز هیم سکویی</string>
<string name="summary_pref_ip_api_url">نشۊوی اینترنتی</string>
<string name="summary_pref_ip_api_url" translatable="false">URL</string>
<string name="title_pref_proxy_sharing_enabled">یک رسۊوی پروکسی من شبکه مهلی LAN</string>
<string name="summary_pref_proxy_sharing_enabled">پوی دسگایل ترن وا نشۊوی IP ایسا، ز ره socks/http و پروکسی منپیز بۊن، تینا من شبکه قابل ائتماد ره ونده بۊ تا ز منپیز قیر موجاز جلو گری بۊ.</string>
<string name="toast_warning_pref_proxysharing_short">یک رسۊوی من شبکه مهلی ره وست؛ موتمعن بۊین ک من ی شبکه ٱمن هڌین.</string>
<string name="title_pref_proxy_sharing_enabled">یک رسۊوی پروکسی من شبکه محلی LAN</string>
<string name="summary_pref_proxy_sharing_enabled">پوی دسگایل ترن وا نشۊوی IP ایسا، ز ره socks/http و پروکسی منپیز بۊن، تینا من شبکه قابل ائتماڌ ره ونده بۊ تا ز منپیز غیر موجاز جلو گری بۊ.</string>
<string name="toast_warning_pref_proxysharing_short">یک رسۊوی من شبکه محلی ره وست؛ موطمئن بۊین ک من ی شبکه ٱمن هڌین.</string>
<string name="title_pref_socks_port">پورت پروکسی مهلی</string>
<string name="title_pref_enable_local_proxy">ره وندن پروکسی مهلی</string>
<string name="title_pref_socks_port">پورت پروکسی محلی</string>
<string name="title_pref_enable_local_proxy">ره وندن پروکسی محلی</string>
<string name="summary_pref_enable_local_proxy">هرسا ره نوسته بۊ، هیچ پروکسی SOCKS من دسرس نؽ، سی دل هیمو کارایی جۊر ورۊ رسۊوی یل اشتراک نترن پروکسی ن و کار گرن.</string>
<string name="title_pref_socks_enable_udp">SOCKS5 UDP</string>
<string name="summary_pref_socks_enable_udp">ائراز هۊویت socks5 مجال استفاڌه ز UDP کاملن ایمن نؽ</string>
<string name="summary_pref_socks_port">پورت پروکسی مهلی</string>
<string name="title_pref_dynamic_socks_port">وورکل پورت موتقیر سی پروکسی مهلی</string>
<string name="summary_pref_dynamic_socks_port">هر کرت ک و من ٱووڌنی وورکل ابۊ، ی پورت پروکسی مهلی تساڌۊفی وورکل اکونه.</string>
<string name="title_pref_socks_username">نوم منتوری پروکسی مهلی (اختیاری)</string>
<string name="title_pref_socks_enable_udp" translatable="false">SOCKS5 UDP</string>
<string name="summary_pref_socks_enable_udp">ائراز هۊویت SOCKS5 مجال استفاڌه ز UDP کاملن ایمن نؽ.</string>
<string name="summary_pref_socks_port">پورت پروکسی محلی</string>
<string name="title_pref_dynamic_socks_port">وورکل پورت موتغیر سی پروکسی محلی</string>
<string name="summary_pref_dynamic_socks_port">هر کرت ک و من ٱووڌنی وورکل ابۊ، ی پورت پروکسی محلی تساڌۊفی وورکل اکونه.</string>
<string name="title_pref_socks_username">نوم منتوری پروکسی محلی (اختیاری)</string>
<string name="summary_pref_socks_username">نوم منتوری</string>
<string name="title_pref_socks_password">رزم پروکسی مهلی (اختیاری)</string>
<string name="title_pref_socks_password">رزم پروکسی محلی (اختیاری)</string>
<string name="summary_pref_socks_password">رزم</string>
<string name="title_pref_local_dns_port">پورت DNS مهلی</string>
<string name="summary_pref_local_dns_port">پورت DNS مهلی</string>
<string name="title_pref_local_dns_port">پورت DNS محلی</string>
<string name="summary_pref_local_dns_port">پورت DNS محلی</string>
<string name="title_pref_confirm_remove">قوۊل کردن پاک کردن کانفیگ</string>
<string name="summary_pref_confirm_remove">سی پاک وابیڌن فایل کانفیگ، لنگ قوۊل کردن دووارته ز سمت منتور هڌ.</string>
<string name="title_pref_append_http_proxy">پروکسی HTTP ن و VPN ازاف کۊنین</string>
<string name="summary_pref_append_http_proxy">پروکسی HTTP ن موسقیمن ز (مۊرۊرگر/ی قرد ز برنومه یل لادراری بیڌه)، بؽ استفاڌه ز دسگا NIC مجازی (Android 10+) استفاڌه ابۊ.</string>
<string name="title_pref_append_http_proxy">پروکسی HTTP ن و VPN اضاف کۊنین</string>
<string name="summary_pref_append_http_proxy">پروکسی HTTP ن موستقیمن ز (مۊرۊرگر/ی قرد ز برنومه یل لادراری بیڌه)، بؽ استفاڌه ز دسگا NIC مجازی (Android 10+) استفاڌه ابۊ.</string>
<string name="title_pref_double_column_display">ره وندن نشووݩ داڌن دو سۊتۊنی</string>
<string name="summary_pref_double_column_display">The profile list is displayed in double columns, allowing more content to be displayed on the screen.</string>
<string name="summary_pref_double_column_display">نومگه کانفیگا من دو ستۊݩ نشووݩ داڌه ابۊ تا محتوا بؽتری من بلگه جا بگره.</string>
<string name="title_pref_group_all_display">نشووݩ داڌن پوی بونکۊ یل ن ره ونین</string>
<string name="summary_pref_group_all_display">ی بلگه «پوی بونکۊ یل کانفیگ» ازاف کۊنین</string>
<string name="summary_pref_group_all_display">ی بلگه «پوی بونکۊ یل کانفیگ» اضاف کۊنین</string>
<!-- AboutActivity -->
<string name="title_pref_feedback">فشناڌن منشڌ</string>
<string name="summary_pref_feedback">فشناڌن منشڌ یا گوزارش موشکلا من Github</string>
<string name="summary_pref_feedback">فشناڌن منشڌ یا گوزارش موشکلا من GitHub</string>
<string name="summary_pref_tg_group">ٱووڌن من بونکۊ تلگرام</string>
<string name="toast_tg_app_not_found">برنومه تلگرامن نجوست</string>
<string name="title_privacy_policy">هریم سیخومی</string>
<string name="title_qr_code">QR code</string>
<string name="title_privacy_policy">حریم سیخومی</string>
<string name="title_qr_code">کود QR</string>
<string name="title_about">زبار</string>
<string name="title_source_code">کود بونچک</string>
<string name="title_oss_license">موجوزا کود بونچک</string>
<string name="title_tg_channel">تورگه تلگرام</string>
<string name="title_pref_promotion">تبلیقات</string>
<string name="title_pref_promotion">تبلیغات</string>
<string name="title_pref_auto_update_subscription">ورۊ کردن خوتکار اشتراکا</string>
<string name="summary_pref_auto_update_subscription">اشتراکا خوتووݩ ن و تۉر خوتکار وا فاسله زمۊوی من پس زمینه ورۊ کۊنین. ای ویژیی من پوی دسگایل گاشڌ همیشه کار نکونه</string>
<string name="title_pref_auto_update_interval">فاسله ورۊ کردن خوتکار (اقلن وا 15 دؽقه بۊ)</string>
<string name="summary_pref_auto_update_subscription">اشتراکا خوتووݩ ن و تۉر خوتکار وا فاصله زمۊوی من پس زمینه ورۊ کۊنین. ای ویژیی من پوی دسگایل گاشڌ همیشه کار نکونه</string>
<string name="title_pref_auto_update_interval">فاصله ورۊ کردن خوتکار (اقلن وا 15 دؽقه بۊ)</string>
<string name="title_core_loglevel">سئت گوزارشا</string>
<string name="title_outbound_domain_resolve_method">بارت پؽش هل دامنه دری</string>
<string name="title_mode">هالت</string>
<string name="title_outbound_domain_resolve_method">بارت پؽش هل دامنه دری (outbound)</string>
<string name="title_mode">حالت</string>
<string name="title_mode_help">سی دووسمندیا وو هیاری قلوه، ری ای هؽل بزݩ</string>
<string name="title_language">زووݩ</string>
<string name="title_ui_settings">سامووا رابت منتوری</string>
<string name="title_pref_ui_mode_night">سامووا هالت رابت منتوری</string>
<string name="title_ui_settings">سامووا رابط منتوری</string>
<string name="title_pref_ui_mode_night">سامووا حالت رابط منتوری</string>
<string name="title_pref_dynamic_color">فعال‌سازی رنگ پویا</string>
<string name="summary_pref_dynamic_color">فقط روی اندروید ۱۲+ کار می‌کند</string>
<string name="title_pref_use_hev_tunnel">و کار گرؽڌن ویژیی Hev TUN</string>
<string name="summary_pref_use_hev_tunnel">مجالی ک ره ونده بۊ، TUN ایا hev-socks5-tunnel ن و کار اگره؛ ٱر ره نوۊفته بۊ، همو xray-core ن و کار اگره.</string>
<string name="title_pref_hev_tunnel_loglevel">Hev Tun سئت گوزارشا</string>
<string name="title_pref_hev_tunnel_rw_timeout">زمووݩ مندیر بیڌن خوندن/هؽل کردن Hev Tun (سانیه) (پؽش فرز tcp، udp 300،60)</string>
<string name="title_mode_settings">سامووا هالت</string>
<string name="title_root_mode_enabled">هالت رۊت ره وست (منتورووݩ رۊت)</string>
<string name="summary_root_mode_enabled">ره وستن پروکسی شفاف سئت بلم وا امتیازا ریشه. ای هالت، VPN استاندارد سیستوم ٱندروید ن دور ازنه تا موستقیمن پوی ترافیک شبکه لمی ن وا دست بگره. بئڌ ره وندن، هالت معمۊلی ٱسلی، تور جۊری هر برنومه وو سامووا VPN مربۊته کاملن ناموعتبر ابۊن.</string>
<string name="title_pref_hev_tunnel_loglevel">Hev TUN سئت گوزارشا</string>
<string name="title_pref_hev_tunnel_rw_timeout">زمووݩ مندیر بیڌن خوندن/هؽل کردن Hev TUN (ثانیه؛ پؽش‌فرض TCP/UDP: 300/60)</string>
<string name="title_mode_settings">سامووا حالت</string>
<string name="title_root_mode_enabled">حالت رۊت ره وست (منتورووݩ رۊت)</string>
<string name="summary_root_mode_enabled">ره وستن پروکسی شفاف سئت بلم وا امتیازا ریشه. ای حالت، VPN استاندارد سیستوم ٱندروید ن دور ازنه تا موستقیمن پوی ترافیک شبکه لمی ن وا دست بگره. بئڌ ره وندن، حالت معمۊلی ٱسلی، تور جۊری هر برنومه وو سامووا VPN مربۊته کاملن نا موئتبر ابۊن.</string>
<string name="toast_root_required">دسرسی رۊت سی ای ویژیی لازوم هڌ</string>
<string name="title_root_lan_sharing">یک رسۊوی LAN / تترینگ (منتورووݩ رۊت وابیڌه)</string>
<string name="summary_root_lan_sharing">ترافیک هات‌اسپات وای‌فای وو دسگا یل منپیز وابیڌه وا USB (تترینگ) ن ز تور VPN بفشنین.</string>
<string name="title_logcat">گوزارشا</string>
<string name="title_logcat" translatable="false">Logcat</string>
<string name="logcat_copy">لف گیری</string>
<string name="logcat_clear">روفتن</string>
<string name="logcat_share">یک رسۊوی گوزارش</string>
@@ -304,29 +319,31 @@
<string name="title_del_all_config">پاک کردن پوی کانفیگا بونکۊ سکویی</string>
<string name="title_del_duplicate_config">پاک کردن کانفیگا تکراری بونکۊ سکویی</string>
<string name="title_del_invalid_config">پاک کردن کانفیگا نا موئتبر بونکۊ سکویی</string>
<string name="title_export_all">و در کشیڌن کانفیگا قیر سفارشی بونکۊ سکویی من کلیپ بورد</string>
<string name="title_sub_setting">سامووا بونکۊ اشتراک</string>
<string name="title_export_all">و در کشیڌن کانفیگا من کلیپ بورد</string>
<string name="title_sub_setting">اشتراکا</string>
<string name="sub_setting_remarks">نیشتنا</string>
<string name="sub_setting_url">نشۊوی اینترنتی اختیاری</string>
<string name="sub_setting_user_agent">User Agent</string>
<string name="sub_setting_filter">نوم موستعار فیلتر</string>
<string name="sub_setting_user_agent" translatable="false">User Agent</string>
<string name="sub_setting_request_headers">سرآیندا درخواست (قالوو JSON)</string>
<string name="sub_setting_filter">فیلتر نیشتنا وا regex</string>
<string name="sub_setting_enable">ره وندن ورۊ کردن</string>
<string name="sub_auto_update">ره وندن ورۊ کردن خوتکار</string>
<string name="sub_allow_insecure_url">موجاز کردن نشۊوی HTTP نا ٱمن</string>
<string name="sub_setting_pre_profile">نوم موستعار پروکسی دیندایی</string>
<string name="sub_setting_next_profile">نوم موستعار پروکسی نیایی</string>
<string name="sub_setting_pre_profile_tip">موتمعن بۊ ک نوم موستعار هڌس وو جۊرس نی</string>
<string name="toast_invalid_update_interval">فاسله ورۊ کردن نا موئتبر هڌ. هدقل مقدار 15 دؽقه هڌ.</string>
<string name="sub_setting_pre_profile">پروکسی وۊرۊی</string>
<string name="sub_setting_next_profile">پروکسی دری</string>
<string name="sub_setting_pre_profile_tip">موطمئن بۊ ک نیشتنا هڌس وو جۊرس نی</string>
<string name="sub_setting_entry_proxy_tip">ای پروکسی پؽش ز هر کانفیگ من ای اشتراک، وری ٱول عوزو زنجیره پروکسی اضاف ابۊ.</string>
<string name="sub_setting_exit_proxy_tip">ای پروکسی بئڌ ز هر کانفیگ من ای اشتراک، وری آخر عوزو زنجیره پروکسی اضاف ابۊ.</string>
<string name="toast_invalid_update_interval">فاصله ورۊ کردن نا موئتبر هڌ. حداقل مقدار 15 دؽقه هڌ.</string>
<string name="title_sub_update">ورۊ کردن اشتراک بونکۊ سکویی</string>
<string name="title_ping_all_server">Tcping کانفیگا بونکۊ سکویی</string>
<string name="title_real_ping_all_server">تئخیر واقعی کانفیگا بونکۊ سکویی</string>
<string name="title_user_asset_setting">فایلا بونچک جوقرافیایی</string>
<string name="title_ping_all_server">آزمایش تئخیر TCP (TCPing)</string>
<string name="title_real_ping_all_server">آزمایش تئخیر واقعی</string>
<string name="title_user_asset_setting">فایلا بونچک جغرافیایی</string>
<string name="title_sort_by_test_results">ترتیب و ری نتیجه یل پینگ</string>
<string name="title_filter_config">فیلتر کردن کانفیگا</string>
<string name="filter_config_all">پوی</string>
<string name="summary_scan_qrcode">سی وا کردن دوربیݩ وو ٱسکووݩ، و ری بلگه بزنین</string>
<string name="title_del_duplicate_config_count">پاک کردن %d کانفیگ تکراری</string>
<string name="summary_scan_qrcode">Click screen open the camera scan</string>
<string name="title_del_config_count">پاک کردن %d کانفیگ</string>
<string name="title_import_config_count">و من ٱووردن %d کانفیگ</string>
<string name="title_export_config_count">و در کشیڌن %d کانفیگ</string>
@@ -334,7 +351,6 @@
<string name="title_update_subscription_result">%1$d کانفیگ ورۊ وابی (مووفق: %2$d، شکست خرده: %3$d، رڌ وابیڌه: %4$d)</string>
<string name="title_update_subscription_no_subscription">بؽ اشتراک</string>
<string name="toast_server_not_found_in_group">سرور پسند وابیڌه من بونکۊ سکویی نجۊرست</string>
<string name="toast_fragment_not_available">نتره نما سکویی ن بجۊره</string>
<string name="title_locate_selected_config">کانفیگ پسند وابیڌه ن بجۊرین</string>
<string name="tasker_start_service">ره وندن سرویس</string>
@@ -343,7 +359,8 @@
<!-- RoutingSettingActivity -->
<string name="routing_settings_domain_strategy">نشقه دامنه</string>
<string name="routing_settings_title">سامووا تور جوستن</string>
<string name="routing_settings_tips">وا کاما (,) ز یک جوڌا ابۊن؛ یکی ن بزنین: domain، ip یا process</string>
<string name="routing_settings_tips">پوی شرطا سئت بیڌه بایڌ هوم زمووی جور ابۊن (AND). قانووݩ یل ز سر و ته وارس ابۊن؛ ٱولی قانووݩ جور وابیڌه و کار ابسته ابۊ.</string>
<string name="routing_settings_comma_tip">چنتا مقدار ن وا کاما (,) ز یک جوڌا کۊنین.</string>
<string name="routing_settings_save">زفت کردن</string>
<string name="routing_settings_delete">روفتن</string>
<string name="routing_settings_rule_title">سامووا قانووݩ تور جوستن</string>
@@ -351,63 +368,68 @@
<string name="routing_settings_import_predefined_rulesets">و من ٱووردن قانووا</string>
<string name="routing_settings_import_rulesets_tip">قانووایی ک هیم سکو هڌسووݩ پاک ابۊن، هنی هم اخۊی پاکسووݩ کۊنی؟</string>
<string name="routing_settings_import_rulesets_from_clipboard">و من ٱووردن قانووا ز کلیپ بورد</string>
<string name="routing_settings_import_rulesets_from_qrcode">و من ٱووردن قانووا ز QRcode</string>
<string name="routing_settings_import_rulesets_from_qrcode">و من ٱووردن قانووا ز کود QR</string>
<string name="routing_settings_export_rulesets_to_clipboard">و در کشیڌن قانووا وو زفت من کلیپ بورد</string>
<string name="routing_settings_locked">چفت هڌ، ای قانووݩ ن مجال و من ٱووردن ز پؽش سامووا زفت کۊنین</string>
<string name="routing_settings_domain" translatable="false">domain</string>
<string name="routing_settings_ip" translatable="false">ip</string>
<string name="routing_settings_process">process (نوم بسته — تینا مجال کار بوردن Xray TUN، ره بیڌن routeOnly وو Android 10+ پوشتؽووی ابۊ)</string>
<string name="routing_settings_process_select">نوم بسته ن پسند کۊنین</string>
<string name="routing_settings_port" translatable="false">port</string>
<string name="routing_settings_protocol" translatable="false">protocol</string>
<string name="routing_settings_protocol_tip" translatable="false">[http,tls,bittorrent]</string>
<string name="routing_settings_network" translatable="false">network</string>"[udp|tcp]"
<string name="routing_settings_network" translatable="false">network</string>
<string name="routing_settings_outbound_tag_hint">proxy / direct / block / &lt;%1$s&gt;</string>
<string name="routing_settings_outbound_tag" translatable="false">outboundTag</string>
<string name="connection_test_pending">منپیزن واجۊری کوݩ</string>
<string name="connection_test_testing">هونی آزمایش ابۊ…</string>
<string name="connection_test_testing_count">%d کانفیگ هونی آزمایش ابۊ...</string>
<string name="connection_test_available">مووفق بی: منپیز %dms تۊل کشی</string>
<string name="connection_test_testing_count">%d کانفیگ هونی آزمایش ابۊ…</string>
<string name="connection_test_available">مووفق بی: منپیز %1$s طۊل کشی</string>
<string name="server_test_delay_value">%1$d میلی‌ثانیه</string>
<string name="connection_test_error">منپیز و اینترنتن نجوست: %s</string>
<string name="connection_test_fail">اینترنت من دسرس نؽ</string>
<string name="connection_test_error_status_code">کود ختا: #%d</string>
<string name="connection_connected">منپیز هڌ، سی واجۊری کیلیک کوݩ</string>
<string name="connection_test_error_status_code">کود خطا: #%d</string>
<string name="connection_connected">منپیز هڌ. سی واجۊری کیلیک کوݩ.</string>
<string name="connection_not_connected">منپیز نؽڌ</string>
<string name="connection_runing_task_left">تعداد وزیفه یل آزمایشی ک ره اۊفتانه: %s</string>
<string name="connection_running_task_left">آزمایشا هونی ٱنجوم ابۊن: %s</string>
<string name="import_subscription_success">اشتراک وا مووفقیت زفت وابی</string>
<string name="import_subscription_failure">اشتراک زفت نوابی</string>
<string name="title_fragment_settings">سامووا فرگمنت</string>
<string name="import_subscription_success">اشتراک وا مووفقیت و من ٱووڌه وابی</string>
<string name="import_subscription_failure">و من ٱووردن اشتراک مووفق نبی</string>
<string name="title_fragment_settings">سامووا فرگمنت (Fragment)</string>
<string name="title_pref_fragment_packets">کتنا فرگمنت</string>
<string name="title_pref_fragment_length">تۊل کتنا فرگمنت (هدقل-هدکسر)</string>
<string name="title_pref_fragment_interval">فاسله منجا کتنا فرگمنت (هدقل-هدکسر)</string>
<string name="title_pref_fragment_length">طۊل کتنا فرگمنت (حداقل-حداکثر)</string>
<string name="title_pref_fragment_interval">فاصله منجا کتنا فرگمنت (حداقل-حداکثر)</string>
<string name="title_pref_fragment_enabled">ره وندن فرگمنت</string>
<string name="title_pref_fragment_maxsplit">هدکسر تقسیم فرگمنت</string>
<string name="title_observatory_settings">سامووا واجۊری منپیز</string>
<string name="title_pref_observatory_least_ping_interval">فاسله leastPing</string>
<string name="title_pref_observatory_least_load_interval">فاسله leastLoad</string>
<string name="title_pref_fragment_maxsplit">حداکثر تقسیم فرگمنت</string>
<string name="title_observatory_settings">سامووا واجۊری منپیز (Observatory)</string>
<string name="title_pref_observatory_least_ping_interval">فاصله leastPing</string>
<string name="title_pref_observatory_least_load_interval">فاصله leastLoad</string>
<string name="title_pref_observatory_least_load_method">روش HTTP سی leastLoad</string>
<string name="title_pref_observatory_least_load_sampling">نمونه گیری leastLoad</string>
<string name="title_pref_observatory_least_load_timeout">مهلت leastLoad</string>
<string name="toast_invalid_observatory_duration">زما نادروسته. یه ارزشی وری 3m یا 30s بکار ببرین.</string>
<string name="toast_invalid_observatory_sampling">نمونه گیری نادروسته. یه شماره مثبت بکار ببرین.</string>
<string name="toast_invalid_observatory_duration">زمووݩ نا موئتبر هڌ. ارزشی وری 3m یا 30s ن و کار بگیرین.</string>
<string name="toast_invalid_observatory_sampling">نمونه گیری نا موئتبر هڌ. شوماره ی مثبت ن و کار بگیرین.</string>
<string name="update_check_for_update">واجۊری سی ورۊ رسۊوی</string>
<string name="update_already_latest_version">سکو نوسخه دیندایی پۊرنیڌه هڌ</string>
<string name="update_new_version_found">نوسخه نۊ ن جوست: %s</string>
<string name="update_now">سکو ورۊ رسۊوی کۊنین</string>
<string name="update_check_pre_release">واجۊری نوسخه یل پؽش ز تیجنیڌن</string>
<string name="update_checking_for_update">ورۊ رسۊوی ن هونی واجۊری اکونه...</string>
<string name="update_checking_for_update">ورۊ رسۊوی ن هونی واجۊری اکونه…</string>
<string name="title_policy_group_type">نوع بونکۊ سیاست</string>
<string name="title_policy_group_subscription_id">ز بونکۊ اشتراک</string>
<string name="title_policy_group_subscription_filter">توزیهات فیلتر معمۊلی</string>
<string name="title_policy_group_test_outbounds">آزمایش بارتا</string>
<string name="title_policy_group_fallback">بارت جایگزین (اختیاری)</string>
<string name="title_policy_group_subscription_filter">فیلتر نیشتنا وا regex</string>
<string name="title_policy_group_test_outbounds">آزمایش بارتا (outbounds)</string>
<string name="title_policy_group_fallback">بارت جایگزین (outbound، اختیاری)</string>
<string name="server_proxy_chain_members">ٱئزا زنجیره پروکسی</string>
<string name="server_proxy_chain_pick_members">سی پسند عوزو ایچو بزنین</string>
<string name="server_proxy_chain_member_unselected">ی عوزو پسند کۊنین</string>
<string name="server_proxy_chain_members_unselected">سی هر ردیف زنجیره remark پسند کۊنین</string>
<string name="server_proxy_chain_members_insufficient">تعداد ٱئزا بس نؽ</string>
<string name="server_proxy_chain_members_invalid">ٱئزا ناموئتبر زنجیره: %1$s</string>
<string name="server_proxy_chain_members_unselected">سی هر ردیف زنجیره ی عوزو پسند کۊنین</string>
<string name="server_proxy_chain_members_insufficient">تعداڌ ٱئزا بس نؽ</string>
<string name="server_proxy_chain_members_invalid">ٱئزا نا موئتبر زنجیره: %1$s</string>
<!-- BackupActivity -->
<string name="title_configuration_backup_restore">لادراری گرؽڌن &amp; وورگندن</string>
@@ -421,39 +443,41 @@
<string name="title_webdav_pass">رزم</string>
<string name="title_webdav_remote_path">دایرکتوری ره دیر (اختیاری)</string>
<string name="share_method_qrcode">QRcode</string>
<string name="share_method_clipboard">و در کشیڌن من کلیپ بورد</string>
<string name="share_method_full_content">و در کشیڌن پوی کانفیگ من کلیپ بورد</string>
<string name="share_method_qrcode">کود QR</string>
<string name="share_method_clipboard">لف گیری لینک کانفیگ</string>
<string name="share_method_full_content">لف گیری پوی کانفیگ</string>
<string name="action_edit">آلشتکاری</string>
<string name="action_delete">پاک کردن</string>
<string name="action_close">بستن</string>
<string-array name="share_sub_method">
<item>QRcode</item>
<item>و در کشیڌن من کلیپ بورد</item>
</string-array>
<string name="share_subscription_qrcode">کود QR</string>
<string name="share_subscription_clipboard">و در کشیڌن من کلیپ بورد</string>
<string-array name="mode_entries">
<item>VPN</item>
<item>تینا پروکسی</item>
</string-array>
<string-array name="browser_dialer_mode">
<item>خامۊش</item>
<item>OkHttp</item>
<item>WebView</item>
</string-array>
<string-array name="ui_mode_night">
<item>و دین کردن سیستوم</item>
<item>رۊشنا</item>
<item>تاریک</item>
</string-array>
<string-array name="preset_rulesets">
<item>نومگه اسبؽڌ چین</item>
<item>نومگه شه چین</item>
<item>جهۊوی (Global)</item>
<item>نومگه اسبؽڌ ایران</item>
<item>نومگه اسبؽڌ رۊسیه</item>
</string-array>
<string name="routing_preset_china_whitelist">نومگه اسبؽڌ چین</string>
<string name="routing_preset_china_blacklist">نومگه شه چین</string>
<string name="routing_preset_global">جهۊوی (Global)</string>
<string name="routing_preset_iran_whitelist">نومگه اسبؽڌ ایران</string>
<string name="routing_preset_russia_whitelist">نومگه اسبؽڌ رۊسیه</string>
<string-array name="vpn_bypass_lan">
<item>پؽش فرز کانفیگ</item>
<item>پؽش فرض کانفیگ</item>
<item>دور زیڌه بۊ</item>
<item>دور زیڌه نبۊ</item>
</string-array>
@@ -463,16 +487,57 @@
<item>هل وو ٱووردن و میزبووݩ یل دامنه DNS</item>
<item>هل وو جایونی دامنه</item>
</string-array>
<string-array name="policy_group_type">
<item>کم ترین پینگ</item>
<item>کم ترین بار (لود)</item>
<item>تساڌۊفی</item>
<item>گردشی</item>
<item>کم ترین پینگ (leastPing)</item>
<item>کم ترین بار (leastLoad)</item>
<item>تساڌۊفی (random)</item>
<item>گردشی (roundRobin)</item>
</string-array>
<string-array name="config_backup_options">
<item>مهلی</item>
<item>WebDAV</item>
</string-array>
<string name="backup_location_local">محلی</string>
<string name="backup_location_webdav" translatable="false">WebDAV</string>
<string name="acc_refresh">وانۊ کردن گوزارش</string>
<string name="toast_permission_denied_for">گرؽڌن موجوز مومکن نؽڌ: %1$s</string>
<string name="acc_add_subscription">ٱووردن اشتراک</string>
<string name="toast_malformed_json_detail">کانفیگ نا موئتبر هڌ: %1$s</string>
<string name="acc_add_asset">ٱووردن بونچک فایلا جغرافیایی</string>
<string name="acc_download_file">دانلود فایلا بونچک جغرافیایی</string>
<string name="acc_qr_code">کود QR</string>
<string name="acc_copy_log">لف گیری گوزارش</string>
<string name="acc_clear_log">روفتن گوزارش</string>
<string name="acc_add_rule">ٱووردن قانووݩ</string>
<string name="acc_start">ره وستن سرویس</string>
<string name="acc_stop">واڌاشتن سرویس</string>
<string name="acc_back">برگشت</string>
<string name="acc_search">پیتینیڌن</string>
<string name="acc_add">ٱووردن کانفیگ</string>
<string name="acc_more">امکووݩا بؽتر</string>
<string name="acc_share_subscription">یک رسۊوی لینک اشتراک</string>
<string name="acc_share_log">یک رسۊوی گوزارش</string>
<string name="acc_remove">پاک کردن عوزو زنجیره پروکسی</string>
<string name="acc_add_member">ٱووردن عوزو زنجیره پروکسی</string>
<string name="acc_start_scanner">ره وستن اسکنر QR</string>
<string name="acc_stop_scanner">واڌاشتن اسکنر QR</string>
<string name="acc_turn_torch_on">روشن کردن چراغ</string>
<string name="acc_turn_torch_off">خاموش کردن چراغ</string>
<string name="acc_select_image">پسند ٱکس سی اسکن</string>
<string name="acc_locked">ای قانووݩ مجال و من ٱووردن ز پؽش سامووا زفت ابۊ</string>
<string name="acc_open_menu">گۊشیڌن نومگه کشاری</string>
<string name="acc_edit">آلشتکاری</string>
<string name="acc_delete">پاک کردن</string>
<string name="acc_save">زفت کردن</string>
<string name="acc_update_subscriptions">ورۊ کردن اشتراکا</string>
<string name="acc_per_app_proxy_information">دووسمندی پروکسی و ری برنومه</string>
<string name="permission_camera">دوربیݩ</string>
<string name="permission_notification">وارسۊوی</string>
<string name="permission_local_network">شبکه محلی</string>
<string name="subscription_update_updating">اشتراک %1$s هونی ورۊ ابۊ</string>
<string name="subscription_update_progress">%2$s هونی آزمایش ابۊ: %1$s</string>
<string name="tasker_blurb_start">ره وستن %1$s</string>
<string name="tasker_blurb_stop">واڌاشتن %1$s</string>
<string name="connection_test_empty_message">دووسمندی نؽ</string>
<string name="value_unknown">نا مؽخص</string>
</resources>
+213 -141
View File
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" translatable="false">v2rayNG</string>
<string name="app_widget_name">تعویض</string>
<string name="app_tile_name">تعویض</string>
<string name="app_tile_first_use">برای اولین استفاده از این قابلیت، لطفاً ابتدا از داخل برنامه یک سرور اضافه کنید</string>
@@ -7,6 +8,8 @@
<string name="navigation_drawer_close">بستن منو کشویی</string>
<string name="migration_success">انتقال داده‌ها با موفقیت انجام شد!</string>
<string name="action_stop_service">توقف سرویس</string>
<string name="action_ok">تأیید</string>
<string name="action_cancel">لغو</string>
<string name="migration_fail">انتقال داده‌ها با شکست مواجه شد!</string>
<string name="pull_down_to_refresh">برای بروزرسانی، صفحه را به پایین بکشید!</string>
@@ -26,10 +29,10 @@
<string name="menu_item_save_config">ذخیره کانفیگ</string>
<string name="menu_item_edit_config">ویرایش کردن کانفیگ</string>
<string name="menu_item_del_config">حذف کانفیگ</string>
<string name="menu_item_import_config_qrcode">کانفیگ را از QRcode وارد کنید</string>
<string name="menu_item_import_config_qrcode">کانفیگ را از کد QR وارد کنید</string>
<string name="menu_item_import_config_clipboard">کانفیگ را از کلیپ ‌بورد وارد کنید</string>
<string name="menu_item_import_config_local">کانفیگ را از محلی وارد کنید</string>
<string name="menu_item_import_config_policy_group">افزودن [گروه خط‌‌ مشی]</string>
<string name="menu_item_import_config_policy_group">افزودن [گروه خط‌‌ مشی]</string>
<string name="menu_item_import_config_proxy_chain">افزودن [زنجیره پروکسی]</string>
<string name="menu_item_import_config_manually_vmess">افزودن [VMess]</string>
<string name="menu_item_import_config_manually_vless">افزودن [VLESS]</string>
@@ -37,7 +40,7 @@
<string name="menu_item_import_config_manually_socks">افزودن [SOCKS]</string>
<string name="menu_item_import_config_manually_http">افزودن [HTTP]</string>
<string name="menu_item_import_config_manually_trojan">افزودن [Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">افزودن [Wireguard]</string>
<string name="menu_item_import_config_manually_wireguard">افزودن [WireGuard]</string>
<string name="menu_item_import_config_manually_hysteria2">افزودن [Hysteria2]</string>
<string name="confirm_delete_visible_profiles">آیا مطمئن هستید که می‌خواهید همه پروفایل‌های نمایش‌داده‌شده را حذف کنید؟</string>
<string name="confirm_delete_duplicate_profiles">آیا مطمئن هستید که می‌خواهید همه پروفایل‌های تکراری نمایش‌داده‌شده را حذف کنید؟</string>
@@ -72,14 +75,14 @@
<string name="server_lab_path_httpupgrade">مسیر HTTPUpgrade</string>
<string name="server_lab_path_xhttp">مسیر XHTTP</string>
<string name="server_lab_path_h2">مسیر H2</string>
<string name="server_lab_path_quic">مسیر QUIC</string>
<string name="server_lab_path_quic">کلید QUIC</string>
<string name="server_lab_path_kcp">KCP سید</string>
<string name="server_lab_path_grpc">gRPC نام سرویس</string>
<string name="server_lab_stream_security">TLS</string>
<string name="server_lab_stream_security" translatable="false">TLS</string>
<string name="server_lab_stream_fingerprint">اثرانگشت</string>
<string name="server_lab_stream_alpn">Alpn</string>
<string name="server_lab_allow_insecure">مجوز SSL ناامن</string>
<string name="server_lab_sni">SNI</string>
<string name="server_lab_stream_alpn" translatable="false">ALPN</string>
<string name="server_lab_allow_insecure">نادیده گرفتن تأیید گواهی (allowInsecure)</string>
<string name="server_lab_sni" translatable="false">SNI</string>
<string name="server_lab_address3">نشانی</string>
<string name="server_lab_port3">پورت</string>
<string name="server_lab_id3">رمز عبور</string>
@@ -87,12 +90,12 @@
<string name="server_lab_id4">رمز عبور (اختیاری)</string>
<string name="server_lab_security4">نام‌ کاربری (اختیاری)</string>
<string name="server_lab_encryption">رمزنگاری</string>
<string name="server_lab_flow">جریان</string>
<string name="server_lab_flow">حالت جریان (flow)</string>
<string name="server_lab_public_key">کلید عمومی</string>
<string name="server_lab_preshared_key">کلید پیش‌اشتراکی (اختیاری)</string>
<string name="server_lab_short_id">شناسه کوتاه</string>
<string name="server_lab_spider_x">SpiderX</string>
<string name="server_lab_mldsa65_verify">تاییدیه Mldsa65Verify</string>
<string name="server_lab_spider_x" translatable="false">SpiderX</string>
<string name="server_lab_mldsa65_verify" translatable="false">mldsa65Verify</string>
<string name="server_lab_secret_key">کلید خصوصی</string>
<string name="server_lab_reserved">Reserved (اختیاری، جدا شده با کاما)</string>
<string name="server_lab_local_address">آدرس محلی (IPv4/IPv6 اختیاری، جدا شده با کاما)</string>
@@ -113,48 +116,54 @@
<string name="toast_invalid_url">نشانی اینترنتی نامعتبر است</string>
<string name="toast_insecure_url_protocol">لطفاً از آدرس های اشتراک پروتکل HTTP ناامن استفاده نکنید</string>
<string name="server_lab_need_inbound">اطمینان حاصل کنید که پورت ورودی با تنظیمات مطابقت دارد</string>
<string name="toast_malformed_josn">کانفیگ درست نیست</string>
<string name="toast_malformed_json">قالب پیکربندی نامعتبر است.</string>
<string name="server_lab_request_host6">هاست (SNI) (اختیاری)</string>
<string name="toast_action_not_allowed">این عمل ممنوع است</string>
<string name="server_obfs_password">رمز عبور obfs</string>
<string name="server_lab_port_hop">پورت پرش (درگاه سرور را بازنویسی می کند)</string>
<string name="server_lab_port_hop">پرش پورت (پورت سرور را بازنویسی می‌کند)</string>
<string name="server_lab_port_hop_interval">فاصله پورت پرش (ثانیه)</string>
<string name="server_lab_bandwidth_down">کاهش پهنای باند (واحد)</string>
<string name="server_lab_bandwidth_up">افزایش پهنای باند (واحد)</string>
<string name="server_lab_bandwidth_down">پهنای باند دانلود (واحدهای پشتیبانی‌شده: k/m/g/t)</string>
<string name="server_lab_bandwidth_up">پهنای باند آپلود (واحدهای پشتیبانی‌شده: k/m/g/t)</string>
<string name="server_lab_xhttp_mode">حالت XHTTP</string>
<string name="server_lab_xhttp_extra">خام JSON XHTTP Extra، قالب: { XHTTPObject }</string>
<string name="server_lab_final_mask">finalMask raw JSON, format: { FinalMaskObject }</string>
<string name="server_lab_ech_config_list">لیست کانفیگ Ech</string>
<string name="server_lab_verify_peer_cert_by_name">Verify Peer Cert By Name</string>
<string name="server_lab_pinned_ca256">Certificate fingerprint (SHA-256)</string>
<string name="pinned_ca256_action_fetch">Fetch and fill certificate fingerprint</string>
<string name="toast_fetch_cert_sha256_success">Certificate fingerprint fetched successfully</string>
<string name="toast_fetch_cert_sha256_failed">Failed to fetch certificate fingerprint</string>
<string name="server_lab_final_mask">JSON خام finalMask، قالب: { FinalMaskObject }</string>
<string name="server_lab_ech_config_list" translatable="false">echConfigList</string>
<string name="server_lab_verify_peer_cert_by_name">تأیید گواهی همتا بر اساس نام</string>
<string name="server_lab_pinned_ca256">اثر انگشت گواهی (SHA-256)</string>
<string name="server_lab_browser_dialer">فعال‌سازی Browser Dialer</string>
<string name="server_lab_browser_dialer_tip">فقط خروجی‌های xhttp (packet-up) و ws پشتیبانی می‌شوند؛ تنظیمات مرتبط با TLS ممکن است نادیده گرفته شوند یا تداخل داشته باشند</string>
<string name="toast_allow_insecure_deprecated">گره فعلی از اتصال رمزنگاری‌نشده استفاده می‌کند. زیرساخت‌های واسط شبکه که در کنترل حکومت‌های اقتدارگرا هستند ممکن است ارتباطات شما را مستقیماً مشاهده کنند.\nبه‌دلایل امنیتی، اتصال به چنین گره‌هایی با هسته Xray نسخه 26.2.6 و بالاتر امکان‌پذیر نیست.\nاگر گره را خودتان راه‌اندازی کرده‌اید، رمزنگاری امنی مانند TLS را فعال کنید یا اثر انگشت گواهی pinnedCA256 را پین کنید.\nاگر گره متعلق به ارائه‌دهنده خدمات است، برای ارتقای فنی با آن‌ها تماس بگیرید. اگر ارائه‌دهنده همکاری نمی‌کند، توصیه می‌شود به ارائه‌دهنده‌ای بروید که برای امنیت کاربران اهمیت بیشتری قائل است.\nبرای اطلاعات بیشتر به https://github.com/2dust/v2rayN/discussions/9460 مراجعه کنید</string>
<string name="pinned_ca256_action_fetch">دریافت اثر انگشت گواهی</string>
<string name="toast_fetch_cert_sha256_success">اثر انگشت گواهی با موفقیت دریافت شد</string>
<string name="toast_fetch_cert_sha256_failed">دریافت اثر انگشت گواهی ناموفق بود</string>
<!-- UserAssetActivity -->
<string name="toast_asset_copy_failed">کپی فایل شکست خورد، لطفا از برنامه مدیریت فایل استفاده کنید</string>
<string name="menu_item_add_asset">افزودن منبع</string>
<string name="menu_item_add_file">افزودن فایل ‌ها</string>
<string name="menu_item_scan_qrcode">اسکن QRcode</string>
<string name="title_url">URL</string>
<string name="menu_item_add_url">افزودن URL</string>
<string name="menu_item_scan_qrcode">اسکن کد QR</string>
<string name="title_url" translatable="false">URL</string>
<string name="menu_item_download_file">دانلود فایل‌ ها</string>
<string name="title_user_asset_add_url">آدرس اینترنتی را اضافه کنید</string>
<string name="title_user_asset_add_url">افزودن URL منبع</string>
<string name="msg_file_not_found">فایل پیدا نشد</string>
<string name="msg_remark_is_duplicate">این نام از قبل وجود دارد</string>
<string name="asset_geo_files_sources">منبع فایل های جغرافیایی (اختیاری)</string>
<!-- PerAppProxyActivity -->
<string name="msg_dialog_progress">در حال بارگذاری...</string>
<string name="msg_dialog_progress">در حال بارگذاری…</string>
<string name="menu_item_search">جستجو</string>
<string name="menu_item_select_all">انتخاب همه</string>
<string name="menu_item_invert_selection">معکوس کردن انتخاب‌ها</string>
<string name="msg_enter_keywords">کلمات کلیدی را وارد کنید</string>
<string name="switch_bypass_apps_mode">حالت دور زدن</string>
<string name="menu_item_select_proxy_app">انتخاب خودکار برنامه‌های نیازمند پروکسی</string>
<string name="msg_downloading_content">در حال دانلود محتوا...</string>
<string name="msg_downloading_content">در حال دانلود محتوا…</string>
<string name="menu_item_export_proxy_app">خروجی گرفتن در کلیپ‌ بورد</string>
<string name="menu_item_import_proxy_app">وارد کردن از کلیپ‌ بورد</string>
<string name="per_app_proxy_settings">تنظیمات به تفکیک برنامه</string>
<string name="per_app_proxy_settings_enable">فعال‌سازی به تفکیک برنامه</string>
<string name="app_picker_unknown_app">برنامه ناشناس (UID شناسایی‌نشده)</string>
<!-- Preferences -->
<string name="title_settings">تنظیمات</string>
@@ -162,20 +171,24 @@
<string name="title_core_settings">تنظیمات هسته</string>
<string name="title_vpn_settings">تنظیمات VPN</string>
<string name="title_pref_per_app_proxy">پروکسی به تفکیک برنامه</string>
<string name="summary_pref_per_app_proxy">عمومی: برنامه انتخاب شده از طریق یک پروکسی متصل می شود، برنامه انتخاب نشده مستقیماً متصل می شود. \nحالت دور زدن: برنامه انتخاب شده مستقیماً متصل می شود، برنامه انتخاب نشده از طریق یک پروکسی متصل می شود. \nانتخاب خودکار برنامه های پراکسی در منو امکان پذیر است.</string>
<string name="summary_pref_per_app_proxy">حالت عادی: برنامه‌های انتخاب‌شده از پروکسی استفاده می‌کنند و برنامه‌های انتخاب‌نشده مستقیماً متصل می‌شوند؛\nحالت دور زدن: برنامه‌های انتخاب‌شده مستقیماً متصل می‌شوند و برنامه‌های انتخاب‌نشده از پروکسی استفاده می‌کنند.\nگزینهٔ انتخاب خودکار برنامه‌هایی که باید از پروکسی استفاده کنند در منو قرار دارد.</string>
<string name="title_pref_is_booted">اتصال خودکار هنگام راه اندازی</string>
<string name="summary_pref_is_booted">هنگام راه اندازی به طور خودکار به سرور انتخابی متصل می شود که ممکن است ناموفق باشد.</string>
<string name="subscription_updater_job_tips">این کار در پس‌زمینه اجرا می‌شود و پیشرفت آن در اعلان نمایش داده خواهد شد.</string>
<string name="title_pref_auto_test_after_update_subscription">آزمایش خودکار پس از به‌روزرسانی اشتراک</string>
<string name="summary_pref_auto_test_after_update_subscription">آزمایش خودکار زمان زیادی می‌برد. در صورت فعال بودن، این کار در پس‌زمینه اجرا می‌شود؛ در غیر این صورت در صفحهٔ فعلی اجرا خواهد شد.</string>
<string name="title_pref_auto_remove_invalid_after_test">حذف خودکار کانفیگ‌های نامعتبر بعد از پینگ</string>
<string name="summary_pref_auto_remove_invalid_after_test">نتایج پینگ ممکن است همیشه دقیق نباشند؛ کانفیگ‌های حذف‌شده قابل بازیابی نیستند.</string>
<string name="title_pref_auto_sort_after_test">مرتب‌سازی خودکار بعد از پینگ گرفتن</string>
<string name="summary_pref_auto_sort_after_test">نتایج آزمایش ممکن است کاملاً دقیق نباشند.</string>
<string name="title_mux_settings">تنظیمات MUX</string>
<string name="title_pref_mux_enabled">فعال کردن MUX</string>
<string name="summary_pref_mux_enabled">سریعتر است، اما ممکن است باعث اتصال ناپایدار شود\nمخزن ترافیک TCP با 8 اتصال پیش‌فرض، نحوه مدیریت UDP و QUIC را در زیر سفارشی کنید.</string>
<string name="title_pref_mux_concurency">اتصالات TCP (محدوده -1 تا 1024)</string>
<string name="title_pref_mux_xudp_concurency">اتصالات XUDP (محدوده -1 تا 1024)</string>
<string name="title_mux_settings">تنظیمات Mux</string>
<string name="title_pref_mux_enabled">فعال کردن Mux</string>
<string name="summary_pref_mux_enabled">سریع‌تر است، اما ممکن است اتصال را ناپایدار کند.\nدر ادامه می‌توانید نحوهٔ پردازش TCP، UDP و QUIC را تنظیم کنید.</string>
<string name="title_pref_mux_concurrency">اتصالات TCP (محدوده -1 تا 1024)</string>
<string name="title_pref_mux_xudp_concurrency">اتصالات XUDP (محدوده -1 تا 1024)</string>
<string name="title_pref_mux_xudp_quic">مدیریت QUIC در تونل MUX</string>
<string-array name="mux_xudp_quic_entries">
<item>رد کردن</item>
@@ -184,47 +197,48 @@
</string-array>
<string name="title_pref_speed_enabled">فعال کردن نمایش سرعت</string>
<string name="summary_pref_speed_enabled">نمایش سرعت فعلی در قسمت اعلان. \nآیکون اعلان بر اساس استفاده تغییر می‌کند.</string>
<string name="title_pref_sniffing_enabled">فعال کردن تجزیه و تحلیل بسته ها (Sniffing)</string>
<string name="summary_pref_sniffing_enabled">تلاش برای استخراج نام دامنه واقعی از بسته‌های ترافیک (به‌طور پیش‌فرض روشن است)</string>
<string name="title_pref_route_only_enabled">فعال‌سازی فقط مسیر یابی (RouteOnly)</string>
<string name="summary_pref_route_only_enabled">از نام دامنه (Snnifed) فقط برای مسیریابی استفاده کنید و آدرس مقصد را به عنوان IP ذخیره کنید.</string>
<string name="summary_pref_speed_enabled">نمایش سرعت‌های فعلی در اعلان.\nنماد نشان می‌دهد ترافیک پروکسی بیشتر است یا ترافیک مستقیم.</string>
<string name="title_pref_sniffing_enabled">فعال‌سازی تشخیص دامنهٔ مقصد در ترافیک (Sniffing)</string>
<string name="summary_pref_sniffing_enabled">شناسایی دامنه‌های مقصد از ترافیک (به‌طور پیش‌فرض فعال است).</string>
<string name="title_pref_route_only_enabled">فعال‌سازی routeOnly</string>
<string name="summary_pref_route_only_enabled">از نام دامنهٔ شناسایی‌شده فقط برای مسیریابی استفاده کنید و آدرس مقصد را به‌صورت IP نگه دارید.</string>
<string name="title_pref_local_dns_enabled">فعال کردن DNS محلی</string>
<string name="summary_pref_local_dns_enabled">درخواست های DNS به هسته وارد شده و توسط ماژول DNS پردازش می شوند (توصیه می شود در صورت نیاز به مسیریابی برای دور زدن آدرس های LAN و سرزمین اصلی فعال شود)</string>
<string name="title_pref_fake_dns_enabled">فعال کردن DNS جعلی</string>
<string name="summary_pref_fake_dns_enabled">دی ان اس محلی آدرس های آیپی جعلی را بر می گرداند (سریع تر می باشد و تاخیر را کاهش می دهد اما ممکن است برای برخی از برنامه ها کار نکند)</string>
<string name="title_pref_fake_dns_enabled">فعال‌سازی DNS مجازی (FakeDNS)</string>
<string name="summary_pref_fake_dns_enabled">FakeDNS برای نام‌گشایی دامنه‌ها نشانی‌های IP مجازی برمی‌گرداند (سریع‌تر است، اما ممکن است با برخی برنامه‌ها کار نکند).</string>
<string name="title_pref_ipv6_enabled">فعال کردن IPv6</string>
<string name="summary_pref_ipv6_enabled">آدرس و مسیرهای IPv6 را به رابط VPN اضافه کنید</string>
<string name="title_pref_prefer_ipv6">ترجیح دادن IPV6</string>
<string name="title_pref_prefer_ipv6">ترجیح دادن IPv6</string>
<string name="summary_pref_prefer_ipv6">هنگام بازیابی نام دامنه، آدرس‌های IPv6 را ترجیح دهید</string>
<string name="title_pref_remote_dns">DNS از راه دور (اختیاری) (udp/tcp/https/quic)</string>
<string name="summary_pref_remote_dns">DNS</string>
<string name="title_pref_remote_dns">DNS راه دور (UDP/TCP/HTTPS/QUIC، اختیاری)</string>
<string name="summary_pref_remote_dns" translatable="false">DNS</string>
<string name="title_pref_vpn_dns">VPN DNS (فقط IPv4/v6)</string>
<string name="title_pref_vpn_dns">VPN DNS (فقط IPv4/IPv6)</string>
<string name="title_pref_vpn_bypass_lan">آیا VPN از شبکه محلی عبور می کند؟</string>
<string name="title_pref_vpn_interface_address">آدرس واسط VPN</string>
<string name="title_pref_vpn_mtu">VPN MTU (default 1500)</string>
<string name="title_pref_domestic_dns">DNS داخلی (اختیاری)</string>
<string name="summary_pref_domestic_dns">DNS</string>
<string name="title_pref_vpn_mtu">VPN MTU (پیش‌فرض 1500)</string>
<string name="title_pref_dns_hosts">DNS مستقیم هاست (فرمت: دامنه:آدرس،…)</string>
<string name="title_pref_domestic_dns">DNS مستقیم (اختیاری)</string>
<string name="summary_pref_domestic_dns" translatable="false">DNS</string>
<string name="title_pref_dns_hosts">نگاشت‌های میزبان DNS (قالب: domain:address,…)</string>
<string name="summary_pref_dns_hosts">دامنه:آدرس،…</string>
<string name="title_pref_delay_test_url">آدرس اینترنتی آزمایش تاخیر واقعی کانفیگ ها </string>
<string name="summary_pref_delay_test_url">URL</string>
<string name="title_pref_real_ping_concurrency">تعداد همزمانی تست تأخیر واقعی</string>
<string name="title_pref_delay_test_url">URL آزمایش تأخیر واقعی</string>
<string name="summary_pref_delay_test_url" translatable="false">URL</string>
<string name="title_pref_real_ping_concurrency">آزمایش‌های هم‌زمان تأخیر واقعی</string>
<string name="title_pref_ip_api_url">تست اطلاعات اتصال فعلی url</string>
<string name="summary_pref_ip_api_url">Url</string>
<string name="title_pref_ip_api_url">URL آزمایش اطلاعات اتصال فعلی</string>
<string name="summary_pref_ip_api_url" translatable="false">URL</string>
<string name="title_pref_proxy_sharing_enabled">اشتراک‌گذاری پروکسی در شبکه محلی (LAN)</string>
<string name="summary_pref_proxy_sharing_enabled">دستگاه‌های دیگر می‌توانند با وارد کردن IP شما، از پروکسی‌تان استفاده کنند. برای جلوگیری از سوءاستفاده، فقط در شبکه‌های امن و قابل اعتماد این گزینه را روشن کنید.</string>
@@ -233,8 +247,8 @@
<string name="title_pref_socks_port">پورت پروکسی محلی</string>
<string name="title_pref_enable_local_proxy">فعال‌سازی پروکسی محلی</string>
<string name="summary_pref_enable_local_proxy">اگر غیرفعال باشد، هیچ پروکسی SOCKS در دسترس نخواهد بود و کارهایی مثل آپدیت اشتراک‌ها نمی‌توانند از پروکسی استفاده کنند.</string>
<string name="title_pref_socks_enable_udp">SOCKS5 UDP</string>
<string name="summary_pref_socks_enable_udp">احراز هویت socks5 هنگام استفاده از UDP کاملاً ایمن نیست</string>
<string name="title_pref_socks_enable_udp" translatable="false">SOCKS5 UDP</string>
<string name="summary_pref_socks_enable_udp">احراز هویت SOCKS5 هنگام استفاده از UDP کاملاً ایمن نیست.</string>
<string name="summary_pref_socks_port">پورت پروکسی محلی</string>
<string name="title_pref_dynamic_socks_port">تولید پورت متغیر برای پروکسی محلی</string>
<string name="summary_pref_dynamic_socks_port">با هر بار ایجاد یک کانکشن ورودی، یک پورت تصادفی تولید می‌کند.</string>
@@ -251,43 +265,53 @@
<string name="title_pref_append_http_proxy">پروکسی HTTP را به VPN اضافه کنید</string>
<string name="summary_pref_append_http_proxy">پروکسی HTTP مستقیماً از (مرورگر/برخی برنامه‌های پشتیبانی‌شده)، بدون استفاده از دستگاه NIC مجازی (Android 10+) استفاده می‌شود.</string>
<string name="summary_pref_append_http_proxy">مرورگر و برنامه‌های پشتیبانی‌شده می‌توانند بدون عبور از رابط شبکهٔ مجازی، مستقیماً از پروکسی HTTP استفاده کنند (Android 10+).</string>
<string name="title_pref_double_column_display">فعال کردن نمایش دو ستون</string>
<string name="summary_pref_double_column_display">The profile list is displayed in double columns, allowing more content to be displayed on the screen.</string>
<string name="summary_pref_double_column_display">فهرست پروفایل‌ها در دو ستون نمایش داده می‌شود تا محتوای بیشتری در صفحه دیده شود.</string>
<string name="title_pref_group_all_display">نمایش زبانهٔ «همه»</string>
<string name="summary_pref_group_all_display">نمایش پروفایل‌های همهٔ گروه‌های اشتراک در یک زبانه.</string>
<string name="title_pref_group_all_display">Enable show all groups</string>
<string name="summary_pref_group_all_display">Add an extra "All Tabs" page</string>
<!-- AboutActivity -->
<string name="title_pref_feedback">بازخورد</string>
<string name="summary_pref_feedback">بازخورد یا گزارش اشکالات در گیت‌ هاب</string>
<string name="summary_pref_tg_group">عضویت در گروه تلگرام</string>
<string name="toast_tg_app_not_found">برنامه تلگرام پیدا نشد</string>
<string name="title_privacy_policy">حریم خصوصی</string>
<string name="title_qr_code">QR code</string>
<string name="title_qr_code">کد QR</string>
<string name="title_about">درباره</string>
<string name="title_source_code">کد منبع</string>
<string name="title_oss_license">مجوز های منبع باز</string>
<string name="title_tg_channel">کانال تلگرام</string>
<string name="title_pref_promotion">تبلیغات</string>
<string name="title_pref_auto_update_subscription">به‌ روزرسانی خودکار اشتراک ها</string>
<string name="summary_pref_auto_update_subscription">اشتراک های خود را به طور خودکار با فاصله زمانی در پس زمینه به روز کنید. بسته به دستگاه، این ویژگی ممکن است همیشه کار نکند.</string>
<string name="title_pref_auto_update_interval">فاصله به‌ روزرسانی خودکار ( حداقل مقدار ، 15 دقیقه )</string>
<string name="title_pref_auto_update_interval">فاصلهٔ به‌روزرسانی خودکار (دقیقه؛ حداقل 15)</string>
<string name="title_core_loglevel">سطح گزارشات</string>
<string name="title_outbound_domain_resolve_method">Outbound domain pre-resolve method</string>
<string name="title_outbound_domain_resolve_method">روش نام‌گشایی دامنهٔ خروجی (outbound)</string>
<string name="title_mode">حالت</string>
<string name="title_mode_help">برای اطلاعات و راهنمایی بیشتر، روی این متن کلیک کنید</string>
<string name="title_language">زبان</string>
<string name="title_ui_settings">تنظیمات رابط کاربری</string>
<string name="title_pref_ui_mode_night">تنظیمات حالت رابط کاربری</string>
<string name="title_pref_use_hev_tunnel">استفاده از قابلیت Hev TUN</string>
<string name="title_pref_dynamic_color">فعال‌سازی رنگ پویا</string>
<string name="summary_pref_dynamic_color">فقط روی اندروید ۱۲+ کار می‌کند</string>
<string name="title_pref_use_hev_tunnel">استفاده از Hev TUN</string>
<string name="summary_pref_use_hev_tunnel">اگر فعال باشد، تونل VPN از hev-socks5-tunnel استفاده می‌کند؛ در غیر این صورت از xray-core استفاده خواهد شد.</string>
<string name="title_pref_hev_tunnel_loglevel">سطح گزارشات Hev Tun</string>
<string name="title_pref_hev_tunnel_rw_timeout">زمان انتظار خواندن/نوشتن Hev Tun (ثانیه) (پیش‌فرض tcp,udp 300،60)</string>
<string name="title_pref_hev_tunnel_loglevel">سطح گزارش‌های Hev TUN</string>
<string name="title_pref_hev_tunnel_rw_timeout">مهلت خواندن/نوشتن Hev TUN (ثانیه؛ پیش‌فرض TCP/UDP: 300/60)</string>
<string name="title_mode_settings">تنظیمات حالت</string>
<string name="title_root_mode_enabled">فعال‌سازی حالت Root (کاربران Root)</string>
<string name="summary_root_mode_enabled">برای پروکسی شفاف سطح پایین از دسترسی Root استفاده می‌کند. حالت Root به‌جای سرویس VPN در Android، ترافیک شبکه را مستقیماً مدیریت می‌کند. هنگام فعال بودن این حالت، حالت عادی، مسیریابی جداگانهٔ برنامه‌ها و تنظیمات مرتبط با VPN اعمال نمی‌شوند.</string>
<string name="toast_root_required">این قابلیت به دسترسی Root نیاز دارد</string>
<string name="title_root_lan_sharing">اشتراک VPN با شبکهٔ محلی / دستگاه‌های متصل (کاربران Root)</string>
<string name="summary_root_lan_sharing">ترافیک دستگاه‌های متصل به نقطهٔ اتصال Wi-Fi و USB را از VPN عبور می‌دهد.</string>
<string name="title_logcat">گزارشات</string>
<string name="title_logcat" translatable="false">Logcat</string>
<string name="logcat_copy">کپی</string>
<string name="logcat_clear">پاک کردن</string>
<string name="logcat_share">اشتراک‌گذاری گزارش</string>
@@ -295,29 +319,31 @@
<string name="title_del_all_config">حذف تمام کانفیگ های گروه فعلی</string>
<string name="title_del_duplicate_config">حذف کانفیگ های تکراری گروه فعلی</string>
<string name="title_del_invalid_config">حذف کانفیگ های نامعتبر گروه فعلی (ابتدا آزمایش کنید)</string>
<string name="title_export_all">خروجی گرفتن کانفیگ های غیرسفارشی گروه فعلی در کلیپ ‌بورد</string>
<string name="title_sub_setting">تنظیمات گروه‌ اشتراک</string>
<string name="title_export_all">صادر کردن کانفیگ‌ها به کلیپ‌بورد</string>
<string name="title_sub_setting">اشتراک‌ها</string>
<string name="sub_setting_remarks">ملاحظات</string>
<string name="sub_setting_url">نشانی اینترنتی اختیاری</string>
<string name="sub_setting_user_agent">User Agent</string>
<string name="sub_setting_filter">نام مستعار فیلتر</string>
<string name="sub_setting_url">URL اختیاری</string>
<string name="sub_setting_user_agent" translatable="false">User Agent</string>
<string name="sub_setting_request_headers">سرآیندهای درخواست (قالب JSON)</string>
<string name="sub_setting_filter">فیلتر عبارت منظم برای نام‌ها</string>
<string name="sub_setting_enable">فعال کردن به‌روزرسانی</string>
<string name="sub_auto_update">فعال سازی به‌روزرسانی خودکار</string>
<string name="sub_allow_insecure_url">مجاز کردن آدرس HTTP ناامن</string>
<string name="sub_setting_pre_profile">نام مستعار پروکسی قبلی</string>
<string name="sub_setting_next_profile">نام مستعار پروکسی بعدی</string>
<string name="sub_setting_pre_profile">پروکسی ورودی</string>
<string name="sub_setting_next_profile">پروکسی خروجی</string>
<string name="sub_setting_pre_profile_tip">لطفاً مطمئن شوید که نام مستعار وجود دارد و منحصر به فرد است</string>
<string name="sub_setting_entry_proxy_tip">پروکسی انتخاب‌شده پیش از هر پروفایل این اشتراک، به‌عنوان حلقهٔ ورودی زنجیرهٔ پروکسی آن پروفایل اضافه می‌شود.</string>
<string name="sub_setting_exit_proxy_tip">پروکسی انتخاب‌شده پس از هر پروفایل این اشتراک، به‌عنوان حلقهٔ خروجی زنجیرهٔ پروکسی آن پروفایل اضافه می‌شود.</string>
<string name="toast_invalid_update_interval">بازه بروزرسانی نامعتبر است. حداقل مقدار 15 دقیقه است.</string>
<string name="title_sub_update">به‌روزرسانی گروه فعلی اشتراک</string>
<string name="title_ping_all_server">TCPING کانفیگ های گروه فعلی</string>
<string name="title_real_ping_all_server">تاخیر واقعی کانفیگ های گروه فعلی</string>
<string name="title_ping_all_server">آزمایش تأخیر TCP (TCPing)</string>
<string name="title_real_ping_all_server">آزمایش تأخیر واقعی</string>
<string name="title_user_asset_setting">فایل های منبع جغرافیایی</string>
<string name="title_sort_by_test_results">مرتب‌ سازی بر اساس نتایج آزمایش</string>
<string name="title_sort_by_test_results">مرتب‌سازی بر اساس نتایج آزمایش</string>
<string name="title_filter_config">فیلتر کردن کانفیگ‌ها</string>
<string name="filter_config_all">همه</string>
<string name="summary_scan_qrcode">برای باز کردن دوربین و اسکن، روی صفحه بزنید</string>
<string name="title_del_duplicate_config_count">حذف %d کانفیگ تکراری</string>
<string name="summary_scan_qrcode">Click screen open the camera scan</string>
<string name="title_del_config_count">حذف %d کانفیگ</string>
<string name="title_import_config_count">وارد کردن %d کانفیگ</string>
<string name="title_export_config_count">صادر کردن %d کانفیگ</string>
@@ -325,8 +351,7 @@
<string name="title_update_subscription_result">بروزرسانی %1$d کانفیگ انجام شد (%2$d موفق، %3$d شکست خورده، %4$d نادیده گرفته شده)</string>
<string name="title_update_subscription_no_subscription">هیچ اشتراکی وجود ندارد</string>
<string name="toast_server_not_found_in_group">سرور انتخاب‌شده در گروه فعلی پیدا نشد</string>
<string name="toast_fragment_not_available">موقعیت صفحه فعلی پیدا نشد</string>
<string name="title_locate_selected_config">پیدا کردن کانفیگ متصل‌شده در لیست</string>
<string name="title_locate_selected_config">یافتن پیکربندی انتخاب‌شده</string>
<string name="tasker_start_service">شروع خدمات</string>
<string name="tasker_setting_confirm">تایید</string>
@@ -334,7 +359,8 @@
<!-- RoutingSettingActivity -->
<string name="routing_settings_domain_strategy">استراتژی دامنه</string>
<string name="routing_settings_title">تنظیمات مسیریابی</string>
<string name="routing_settings_tips">با کاما (,) جدا کنید. یکی از موارد domain، ip یا process را وارد کنید</string>
<string name="routing_settings_tips">یک قانون فقط زمانی اعمال می‌شود که همهٔ شرط‌های تطبیق واردشده هم‌زمان برقرار باشند (AND). قوانین از بالا به پایین بررسی می‌شوند و نخستین قانون منطبق اعمال می‌شود.</string>
<string name="routing_settings_comma_tip">چند ورودی را با کاما (,) جدا کنید.</string>
<string name="routing_settings_save">ذخیره</string>
<string name="routing_settings_delete">حذف</string>
<string name="routing_settings_rule_title">تنظیمات قانون مسیریابی</string>
@@ -342,37 +368,41 @@
<string name="routing_settings_import_predefined_rulesets">وارد کردن مجموعه قوانین از پیش تعریف شده</string>
<string name="routing_settings_import_rulesets_tip">مجموعه قوانین موجود حذف خواهند شد، آیا مطمئن هستید که ادامه می دهید؟</string>
<string name="routing_settings_import_rulesets_from_clipboard">وارد کردن مجموعه قوانین از کلیپ بورد</string>
<string name="routing_settings_import_rulesets_from_qrcode">وارد کردن مجموعه قوانین از QRcode</string>
<string name="routing_settings_import_rulesets_from_qrcode">وارد کردن مجموعه قوانین از کد QR</string>
<string name="routing_settings_export_rulesets_to_clipboard">صادر کردن مجموعه قوانین به کلیپ بورد</string>
<string name="routing_settings_locked">قفل است، این قانون را هنگام وارد کردن از پیش تنظیم‌ ها حفظ کنید</string>
<string name="routing_settings_domain">دامنه</string>
<string name="routing_settings_ip">آیپی</string>
<string name="routing_settings_port">پورت</string>
<string name="routing_settings_protocol">پورتکل</string>
<string name="routing_settings_protocol_tip">[http,tls,bittorrent]</string>
<string name="routing_settings_network">شبکه</string>
<string name="routing_settings_outbound_tag">برچسب خروجی</string>
<string name="routing_settings_domain" translatable="false">domain</string>
<string name="routing_settings_ip" translatable="false">ip</string>
<string name="routing_settings_process">process (نام بسته — فقط هنگام استفاده از Xray TUN، فعال بودن routeOnly و Android 10+ پشتیبانی می‌شود)</string>
<string name="routing_settings_process_select">انتخاب نام بسته</string>
<string name="routing_settings_port" translatable="false">port</string>
<string name="routing_settings_protocol" translatable="false">protocol</string>
<string name="routing_settings_protocol_tip" translatable="false">[http,tls,bittorrent]</string>
<string name="routing_settings_network" translatable="false">network</string>
<string name="routing_settings_outbound_tag_hint">proxy / direct / block / &lt;%1$s&gt;</string>
<string name="routing_settings_outbound_tag" translatable="false">outboundTag</string>
<string name="connection_test_pending">اتصال را بررسی کنید</string>
<string name="connection_test_testing">در حال آزمایش...</string>
<string name="connection_test_testing">در حال آزمایش…</string>
<string name="connection_test_testing_count">تست کردن %d کانفیگ…</string>
<string name="connection_test_available">موفقیت: اتصال %dms طول کشید</string>
<string name="connection_test_error">اتصال به اینترنت شناسایی نشد: %s</string>
<string name="connection_test_available">اتصال در %1$s با موفقیت برقرار شد</string>
<string name="server_test_delay_value">%1$d میلی‌ثانیه</string>
<string name="connection_test_error">آزمایش اتصال ناموفق بود: %s</string>
<string name="connection_test_fail">اینترنت در دسترس نیست</string>
<string name="connection_test_error_status_code">کد خطا: #%d</string>
<string name="connection_connected">متصل است، برای بررسی اتصال ضربه بزنید</string>
<string name="connection_connected">متصل است.\nبرای بررسی اتصال ضربه بزنید.</string>
<string name="connection_not_connected">متصل نیست</string>
<string name="connection_runing_task_left">تعداد وظایف آزمایشی در حال اجرا: %s</string>
<string name="connection_running_task_left">آزمایش‌های در حال اجرا: %s</string>
<string name="import_subscription_success">اشتراک با موفقیت ذخیره شد</string>
<string name="import_subscription_failure">ذخیره اشتراک ناموفق بود</string>
<string name="title_fragment_settings">تنظیمات فرگمنت</string>
<string name="title_pref_fragment_packets">بسته های فرگمنت</string>
<string name="title_pref_fragment_length">طول بسته های فرگمنت (حداقل-حداکثر)</string>
<string name="title_pref_fragment_interval">فاصله بین بسته های فرگمنت (حداقل-حداکثر)</string>
<string name="title_pref_fragment_enabled">فعال کردن فرگمنت</string>
<string name="title_pref_fragment_maxsplit">حداکثر تقسیم فرگمنت</string>
<string name="title_observatory_settings">تنظیمات پایش اتصال</string>
<string name="import_subscription_success">اشتراک با موفقیت وارد شد</string>
<string name="import_subscription_failure">وارد کردن اشتراک ناموفق بود</string>
<string name="title_fragment_settings">تنظیمات قطعه‌بندی بسته‌ها (Fragment)</string>
<string name="title_pref_fragment_packets">بسته‌های مورد قطعه‌بندی (Fragment)</string>
<string name="title_pref_fragment_length">طول قطعه (حداقل-حداکثر)</string>
<string name="title_pref_fragment_interval">فاصلهٔ قطعه‌ها (حداقل-حداکثر)</string>
<string name="title_pref_fragment_enabled">فعال کردن Fragment</string>
<string name="title_pref_fragment_maxsplit">حداکثر تعداد قطعه‌ها</string>
<string name="title_observatory_settings">تنظیمات پایش اتصال (Observatory)</string>
<string name="title_pref_observatory_least_ping_interval">فاصله leastPing</string>
<string name="title_pref_observatory_least_load_interval">فاصله leastLoad</string>
<string name="title_pref_observatory_least_load_method">روش HTTP برای leastLoad</string>
@@ -390,13 +420,14 @@
<string name="title_policy_group_type">نوع گروه خط مشی</string>
<string name="title_policy_group_subscription_id">از گروه اشتراک</string>
<string name="title_policy_group_subscription_filter">توضیحات فیلتر معمولی</string>
<string name="title_policy_group_test_outbounds">آزمایش خروجی‌ها</string>
<string name="title_policy_group_fallback">خروجی جایگزین (اختیاری)</string>
<string name="title_policy_group_subscription_filter">فیلتر توضیحات با عبارت منظم</string>
<string name="title_policy_group_test_outbounds">آزمایش خروجی‌ها (outbounds)</string>
<string name="title_policy_group_fallback">خروجی پشتیبان (outbound، اختیاری)</string>
<string name="server_proxy_chain_members">اعضای زنجیره پروکسی</string>
<string name="server_proxy_chain_pick_members">برای انتخاب عضو اینجا بزنید</string>
<string name="server_proxy_chain_member_unselected">یک عضو را انتخاب کنید</string>
<string name="server_proxy_chain_members_unselected">لطفا برای هر ردیف زنجیره remark انتخاب کنید</string>
<string name="server_proxy_chain_members_unselected">لطفاً برای هر ردیف زنجیره یک عضو انتخاب کنید</string>
<string name="server_proxy_chain_members_insufficient">تعداد اعضا کافی نیست</string>
<string name="server_proxy_chain_members_invalid">اعضای نامعتبر زنجیره: %1$s</string>
@@ -406,30 +437,32 @@
<string name="title_configuration_restore">بازیابی پیکربندی</string>
<string name="title_configuration_share">اشتراک گذاری پیکربندی</string>
<string name="title_webdav_config_setting">تنظیمات WebDAV</string>
<string name="title_webdav_config_setting_unknown">لطفا ابتدا WebDAV را پیکربندی کنید.</string>
<string name="title_webdav_url">لینک سرور WebDAV</string>
<string name="title_webdav_user">یوزرنیم</string>
<string name="title_webdav_pass">پسورد</string>
<string name="title_webdav_config_setting_unknown">لطفاً ابتدا WebDAV را پیکربندی کنید.</string>
<string name="title_webdav_url">URL سرور WebDAV</string>
<string name="title_webdav_user">نام کاربری</string>
<string name="title_webdav_pass">رمز عبور</string>
<string name="title_webdav_remote_path">دایرکتوری راه دور (اختیاری)</string>
<string name="share_method_qrcode">QRcode</string>
<string name="share_method_clipboard">خروجی گرفتن در کلیپ‌ بورد</string>
<string name="share_method_full_content">خروجی گرفتن کانفیگ کامل در کلیپ بورد</string>
<string name="share_method_qrcode">کد QR</string>
<string name="share_method_clipboard">کپی لینک کانفیگ</string>
<string name="share_method_full_content">کپی کانفیگ کامل</string>
<string name="action_edit">ویرایش</string>
<string name="action_delete">حذف</string>
<string name="action_close">بستن</string>
<string-array name="share_sub_method">
<item>QRcode</item>
<item>خروجی گرفتن در کلیپ‌ بورد</item>
</string-array>
<string name="share_subscription_qrcode">کد QR</string>
<string name="share_subscription_clipboard">خروجی گرفتن در کلیپ‌ بورد</string>
<string-array name="mode_entries">
<item>VPN</item>
<item>فقط پروکسی</item>
</string-array>
<string name="menu_item_add_asset">افزودن منبع</string>
<string name="menu_item_add_url">افزودن لینک</string>
<string-array name="browser_dialer_mode">
<item>غیرفعال</item>
<item>OkHttp</item>
<item>WebView</item>
</string-array>
<string-array name="ui_mode_night">
<item>پیش فرض سیستم</item>
@@ -437,13 +470,11 @@
<item>تاریک</item>
</string-array>
<string-array name="preset_rulesets">
<item>لیست سفید چین ( دور زدن سرزمین اصلی )</item>
<item>لیست سیاه چین</item>
<item>جهانی(GLOBAL)</item>
<item>ایران</item>
<item>لیست سفید روسیه</item>
</string-array>
<string name="routing_preset_china_whitelist">لیست سفید چین ( دور زدن سرزمین اصلی )</string>
<string name="routing_preset_china_blacklist">لیست سیاه چین</string>
<string name="routing_preset_global">جهانی (Global)</string>
<string name="routing_preset_iran_whitelist">فهرست سفید ایران</string>
<string name="routing_preset_russia_whitelist">لیست سفید روسیه</string>
<string-array name="vpn_bypass_lan">
<item>پیش فرض کانفیگ</item>
@@ -452,20 +483,61 @@
</string-array>
<string-array name="outbound_domain_resolve_method">
<item>Do not resolve</item>
<item>Resolve and add to DNS Hosts</item>
<item>Resolve and replace domain</item>
</string-array>
<string-array name="policy_group_type">
<item>کمترین پینگ</item>
<item>کمترین بار(لود)</item>
<item>تصادفی</item>
<item>گردشی</item>
<item>نام‌گشایی نشود</item>
<item>نام‌گشایی و به DNS Hosts افزوده شود</item>
<item>نام‌گشایی و جایگزین دامنه شود</item>
</string-array>
<string-array name="config_backup_options">
<item>محلی</item>
<item>WebDAV</item>
<string-array name="policy_group_type">
<item>کمترین پینگ (leastPing)</item>
<item>کمترین بار (leastLoad)</item>
<item>تصادفی (random)</item>
<item>چرخشی (roundRobin)</item>
</string-array>
<string name="backup_location_local">محلی</string>
<string name="backup_location_webdav" translatable="false">WebDAV</string>
<string name="acc_refresh">تازه‌سازی گزارش</string>
<string name="toast_permission_denied_for">مجوز %1$s داده نشد</string>
<string name="acc_add_subscription">افزودن اشتراک</string>
<string name="toast_malformed_json_detail">قالب پیکربندی نامعتبر است: %1$s</string>
<string name="acc_add_asset">افزودن منبع فایل‌های جغرافیایی</string>
<string name="acc_download_file">دانلود فایل‌های منبع</string>
<string name="acc_qr_code">کد QR</string>
<string name="acc_copy_log">کپی گزارش</string>
<string name="acc_clear_log">پاک کردن گزارش</string>
<string name="acc_add_rule">افزودن قانون مسیریابی</string>
<string name="acc_start">شروع سرویس</string>
<string name="acc_stop">توقف سرویس</string>
<string name="acc_back">بازگشت</string>
<string name="acc_search">جستجو</string>
<string name="acc_add">افزودن کانفیگ</string>
<string name="acc_more">گزینه‌های بیشتر</string>
<string name="acc_share_subscription">اشتراک‌گذاری لینک اشتراک</string>
<string name="acc_share_log">اشتراک‌گذاری گزارش</string>
<string name="acc_remove">حذف عضو زنجیره پروکسی</string>
<string name="acc_add_member">افزودن عضو زنجیره پروکسی</string>
<string name="acc_start_scanner">شروع اسکنر QR</string>
<string name="acc_stop_scanner">توقف اسکنر QR</string>
<string name="acc_turn_torch_on">روشن کردن چراغ‌قوه</string>
<string name="acc_turn_torch_off">خاموش کردن چراغ‌قوه</string>
<string name="acc_select_image">انتخاب تصویر برای اسکن</string>
<string name="acc_locked">این قانون هنگام وارد کردن تنظیمات از پیش تعیین‌شده حفظ می‌شود</string>
<string name="acc_open_menu">باز کردن منوی پیمایش</string>
<string name="acc_edit">ویرایش</string>
<string name="acc_delete">حذف</string>
<string name="acc_save">ذخیره</string>
<string name="acc_update_subscriptions">به‌روزرسانی اشتراک‌ها</string>
<string name="acc_per_app_proxy_information">اطلاعات پروکسی به تفکیک برنامه</string>
<string name="permission_camera">دوربین</string>
<string name="permission_notification">اعلان</string>
<string name="permission_local_network">شبکه محلی</string>
<string name="subscription_update_updating">در حال به‌روزرسانی اشتراک: %1$s</string>
<string name="subscription_update_progress">در حال آزمایش %2$s: %1$s</string>
<string name="tasker_blurb_start">شروع %1$s</string>
<string name="tasker_blurb_stop">توقف %1$s</string>
<string name="connection_test_empty_message">جزئیاتی در دسترس نیست</string>
<string name="value_unknown">ناشناخته</string>
</resources>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Night theme: override window background and status bar flags for dark mode -->
<style name="AppThemeBase" parent="@android:style/Theme.Material.NoActionBar">
<style name="AppThemeBase" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:windowLightStatusBar">false</item>
+178 -127
View File
@@ -1,12 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" translatable="false">v2rayNG</string>
<string name="app_widget_name">v2rayNG</string>
<string name="app_tile_name">v2rayNG</string>
<string name="app_tile_first_use">Первое использование этой функции, пожалуйста, используйте приложение, чтобы добавить профиль</string>
<string name="app_tile_first_use">Добавьте профиль в приложении перед использованием этой функции.</string>
<string name="navigation_drawer_open">Открыть панель навигации</string>
<string name="navigation_drawer_close">Закрыть панель навигации</string>
<string name="migration_success">Успешный перенос данных!</string>
<string name="migration_success">Данные успешно перенесены!</string>
<string name="action_stop_service">Остановить службу</string>
<string name="action_ok">ОК</string>
<string name="action_cancel">Отмена</string>
<string name="migration_fail">Перенос данных не выполнен!</string>
<string name="pull_down_to_refresh">Потяните вниз для обновления!</string>
@@ -39,16 +42,16 @@
<string name="menu_item_import_config_manually_trojan">Добавить Trojan</string>
<string name="menu_item_import_config_manually_wireguard">Добавить WireGuard</string>
<string name="menu_item_import_config_manually_hysteria2">Добавить Hysteria2</string>
<string name="confirm_delete_visible_profiles">Вы уверены, что хотите удалить все отображаемые профили?</string>
<string name="confirm_delete_duplicate_profiles">Вы уверены, что хотите удалить все отображаемые дубликаты профилей?</string>
<string name="confirm_delete_invalid_profiles">Сначала проверьте профили. Вы уверены, что хотите удалить все отображаемые недействительные профили?</string>
<string name="confirm_delete_profile">Вы уверены, что хотите удалить этот профиль?</string>
<string name="confirm_delete_policy_group">Вы уверены, что хотите удалить эту группу политик?</string>
<string name="confirm_delete_proxy_chain_member">Вы уверены, что хотите удалить этот элемент цепочки прокси?</string>
<string name="confirm_delete_routing_rule">Вы уверены, что хотите удалить это правило маршрутизации?</string>
<string name="confirm_delete_subscription_group">Вы уверены, что хотите удалить эту группу подписки?</string>
<string name="confirm_delete_asset_file">Вы уверены, что хотите удалить файл ресурсов \"%1$s\"?</string>
<string name="confirm_delete_asset_source">Вы уверены, что хотите удалить этот источник ресурсов?</string>
<string name="confirm_delete_visible_profiles">Удалить все отображаемые профили?</string>
<string name="confirm_delete_duplicate_profiles">Удалить все отображаемые дубликаты профилей?</string>
<string name="confirm_delete_invalid_profiles">Выполните проверку перед удалением! Удалить все отображаемые нерабочие профили?</string>
<string name="confirm_delete_profile">Удалить этот профиль?</string>
<string name="confirm_delete_policy_group">Удалить эту политику группы?</string>
<string name="confirm_delete_proxy_chain_member">Удалить этого участника цепочки прокси?</string>
<string name="confirm_delete_routing_rule">Удалить это правило маршрутизации?</string>
<string name="confirm_delete_subscription_group">Удалить эту подписку?</string>
<string name="confirm_delete_asset_file">Удалить файл ресурсов «%1$s»?</string>
<string name="confirm_delete_asset_source">Удалить этот источник ресурсов?</string>
<string name="server_lab_remarks">Название</string>
<string name="server_lab_address">Адрес</string>
<string name="server_lab_port">Порт</string>
@@ -66,7 +69,7 @@
<string name="server_lab_request_host_xhttp">Узел XHTTP</string>
<string name="server_lab_request_host_h2">Узел H2</string>
<string name="server_lab_request_host_quic">Шифрование QUIC</string>
<string name="server_lab_request_host_grpc">Полномочия gRPC</string>
<string name="server_lab_request_host_grpc">gRPC Authority</string>
<string name="server_lab_path">Путь</string>
<string name="server_lab_path_ws">Путь WS</string>
<string name="server_lab_path_httpupgrade">Путь HTTPUpgrade</string>
@@ -75,11 +78,11 @@
<string name="server_lab_path_quic">Ключ QUIC</string>
<string name="server_lab_path_kcp">Сид KCP</string>
<string name="server_lab_path_grpc">Служба gRPC</string>
<string name="server_lab_stream_security">TLS</string>
<string name="server_lab_stream_security" translatable="false">TLS</string>
<string name="server_lab_stream_fingerprint">Отпечаток</string>
<string name="server_lab_stream_alpn">ALPN</string>
<string name="server_lab_allow_insecure">Разрешать небезопасные соединения</string>
<string name="server_lab_sni">SNI</string>
<string name="server_lab_stream_alpn" translatable="false">ALPN</string>
<string name="server_lab_allow_insecure">Пропускать проверку сертификата (allowInsecure)</string>
<string name="server_lab_sni" translatable="false">SNI</string>
<string name="server_lab_address3">Адрес</string>
<string name="server_lab_port3">Порт</string>
<string name="server_lab_id3">Пароль</string>
@@ -87,12 +90,12 @@
<string name="server_lab_id4">Пароль (необязательно)</string>
<string name="server_lab_security4">Пользователь (необязательно)</string>
<string name="server_lab_encryption">Шифрование</string>
<string name="server_lab_flow">Поток</string>
<string name="server_lab_flow">Режим потока (flow)</string>
<string name="server_lab_public_key">Открытый ключ</string>
<string name="server_lab_preshared_key">Дополнительный ключ шифрования (необязательно)</string>
<string name="server_lab_short_id">ShortID</string>
<string name="server_lab_spider_x">SpiderX</string>
<string name="server_lab_mldsa65_verify">mldsa65Verify</string>
<string name="server_lab_spider_x" translatable="false">SpiderX</string>
<string name="server_lab_mldsa65_verify" translatable="false">mldsa65Verify</string>
<string name="server_lab_secret_key">Закрытый ключ</string>
<string name="server_lab_reserved">Reserved (необязательно, через запятую)</string>
<string name="server_lab_local_address">Локальный адрес (необязательно, IPv4/IPv6 через запятую)</string>
@@ -113,24 +116,24 @@
<string name="toast_invalid_url">Неправильный URL</string>
<string name="toast_insecure_url_protocol">Не используйте небезопасный HTTP-протокол в адресе подписки</string>
<string name="server_lab_need_inbound">Убедитесь, что входящий порт соответствует настройкам</string>
<string name="toast_malformed_josn">Профиль повреждён</string>
<string name="toast_malformed_json">Некорректная конфигурация.</string>
<string name="server_lab_request_host6">Узел (SNI) (необязательно)</string>
<string name="toast_action_not_allowed">Это действие запрещено</string>
<string name="server_obfs_password">Пароль obfs</string>
<string name="server_lab_port_hop">Смена портов (переопределяет порт)</string>
<string name="server_lab_port_hop_interval">Интервал смены портов</string>
<string name="server_lab_port_hop_interval">Интервал смены портов (секунды)</string>
<string name="server_lab_bandwidth_down">Входящая пропускная способность (допускаются: k/m/g/t)</string>
<string name="server_lab_bandwidth_up">Исходящая пропускная способность (допускаются: k/m/g/t)</string>
<string name="server_lab_xhttp_mode">Режим XHTTP</string>
<string name="server_lab_xhttp_extra">Необработанный JSON XHTTP Extra, формат: { XHTTPObject }</string>
<string name="server_lab_final_mask">Необработанный JSON FinalMask, формат: { FinalMaskObject }</string>
<string name="server_lab_ech_config_list">ECHConfigList</string>
<string name="server_lab_ech_config_list" translatable="false">echConfigList</string>
<string name="server_lab_verify_peer_cert_by_name">Проверять сертификат узла по имени</string>
<string name="server_lab_pinned_ca256">Отпечаток сертификата (SHA-256)</string>
<string name="server_lab_browser_dialer">Использовать переадресацию браузера</string>
<string name="server_lab_browser_dialer">Включить Browser Dialer</string>
<string name="server_lab_browser_dialer_tip">Поддерживаются только исходящие соединения XHTTP (packet-up) и WS; настройки, связанные с TLS, могут быть проигнорированы или конфликтовать</string>
<string name="toast_allow_insecure_deprecated">Этот узел использует незашифрованное соединение. Ваши данные могут быть перехвачены и просмотрены государственными структурами через промежуточное сетевое оборудование.\nВ целях безопасности такие узлы больше не поддерживаются в Xray core версии 26.2.6+.\nДля исправления: включите TLS (или другое шифрование) на своем сервере или используйте Certificate Pinning (pinnedCA256).\nЕсли вы используете платный сервис, обратитесь в поддержку для обновления. Если провайдер отказывается, рекомендуем сменить его на более безопасный.\nПодробнее: https://github.com/2dust/v2rayN/discussions/9460</string>
<string name="pinned_ca256_action_fetch">Получить и заполнить отпечаток сертификата</string>
<string name="toast_allow_insecure_deprecated">Этот узел использует незашифрованное соединение. Ваши данные могут быть перехвачены и просмотрены государственными структурами через промежуточное сетевое оборудование.\nВ целях безопасности такие узлы больше не поддерживаются ядром Xray версии 26.2.6+.\nДля исправления: включите TLS (или другое шифрование) на своём сервере или используйте отпечаток сертификата (pinnedCA256).\nЕсли вы используете платный сервис, обратитесь в поддержку для обновления. Если провайдер отказывается, рекомендуется сменить его на более безопасный.\nПодробнее: https://github.com/2dust/v2rayN/discussions/9460</string>
<string name="pinned_ca256_action_fetch">Получить отпечаток сертификата</string>
<string name="toast_fetch_cert_sha256_success">Отпечаток сертификата успешно получен</string>
<string name="toast_fetch_cert_sha256_failed">Отпечаток сертификата не получен</string>
@@ -140,7 +143,7 @@
<string name="menu_item_add_file">Добавить файлы</string>
<string name="menu_item_add_url">Добавить URL</string>
<string name="menu_item_scan_qrcode">Сканировать QR-код</string>
<string name="title_url">URL</string>
<string name="title_url" translatable="false">URL</string>
<string name="menu_item_download_file">Загрузить файлы</string>
<string name="title_user_asset_add_url">Добавить URL ресурса</string>
<string name="msg_file_not_found">Файл не найден</string>
@@ -154,7 +157,7 @@
<string name="menu_item_invert_selection">Инвертировать выбор</string>
<string name="msg_enter_keywords">Введите ключевое слово</string>
<string name="switch_bypass_apps_mode">Режим обхода</string>
<string name="menu_item_select_proxy_app">Автовыбор приложений</string>
<string name="menu_item_select_proxy_app">Автовыбор проксируемых приложений</string>
<string name="msg_downloading_content">Загрузка данных</string>
<string name="menu_item_export_proxy_app">Экспорт в буфер обмена</string>
<string name="menu_item_import_proxy_app">Импорт из буфера обмена</string>
@@ -168,20 +171,24 @@
<string name="title_core_settings">Настройки ядра</string>
<string name="title_vpn_settings">Настройки VPN</string>
<string name="title_pref_per_app_proxy">Прокси для выбранных приложений</string>
<string name="summary_pref_per_app_proxy">Основной: выбранное приложение соединяется через прокси, не выбранное — напрямую;\nРежим обхода: выбранное приложение соединяется напрямую, не выбранное — через прокси.\nЕсть возможность автоматического выбора проксируемых приложений в меню.</string>
<string name="summary_pref_per_app_proxy">Основной: выбранное приложение соединяется через прокси, не выбранное — напрямую;\nРежим обхода: выбранное приложение соединяется напрямую, не выбранное — через прокси.\nВ меню можно автоматически выбрать приложения, которые должны использовать прокси.</string>
<string name="title_pref_is_booted">Автоподключение при запуске</string>
<string name="summary_pref_is_booted">Автоматически подключаться к выбранному серверу при запуске приложения (может оказаться неудачным)</string>
<string name="title_pref_auto_remove_invalid_after_test">Автоудаление нерабочих профилей</string>
<string name="summary_pref_auto_remove_invalid_after_test">Автоматическое удаление нерабочих профилей после проверки (результаты проверки могут быть неточными; восстановить удалённые профили невозможно)</string>
<string name="subscription_updater_job_tips">Задача будет выполняться в фоновом режиме, информация о ходе выполнения будет отображаться в уведомлении.</string>
<string name="title_pref_auto_test_after_update_subscription">Автопроверка после обновления подписки</string>
<string name="summary_pref_auto_test_after_update_subscription">Автоматическая проверка занимает много времени. Если параметр включён, задача выполняется в фоновом режиме; иначе — на текущей странице.</string>
<string name="title_pref_auto_remove_invalid_after_test">Автоудаление нерабочих профилей после проверки</string>
<string name="summary_pref_auto_remove_invalid_after_test">Результаты проверки могут быть неточными, восстановление удалённых профилей невозможно</string>
<string name="title_pref_auto_sort_after_test">Автосортировка профилей</string>
<string name="summary_pref_auto_sort_after_test">Автоматическая сортировка профилей после проверки (результаты проверки могут быть неточными)</string>
<string name="title_mux_settings">Настройки мультиплексирования</string>
<string name="title_pref_mux_enabled">Использовать мультиплексирование</string>
<string name="title_mux_settings">Настройки мультиплексирования (Mux)</string>
<string name="title_pref_mux_enabled">Использовать мультиплексирование (Mux)</string>
<string name="summary_pref_mux_enabled">Быстрее, но это может привести к нестабильному соединению.\nНиже можно настроить обработку TCP, UDP и QUIC.</string>
<string name="title_pref_mux_concurency">TCP-соединения (диапазон от 1 до 1024)</string>
<string name="title_pref_mux_xudp_concurency">XUDP-соединения (диапазон от 1 до 1024)</string>
<string name="title_pref_mux_concurrency">TCP-соединения (диапазон от -1 до 1024)</string>
<string name="title_pref_mux_xudp_concurrency">XUDP-соединения (диапазон от -1 до 1024)</string>
<string name="title_pref_mux_xudp_quic">Обработка QUIC в мультиплексном туннеле</string>
<string-array name="mux_xudp_quic_entries">
<item>Отклонять</item>
@@ -190,18 +197,18 @@
</string-array>
<string name="title_pref_speed_enabled">Показывать скорость</string>
<string name="summary_pref_speed_enabled">Показывать текущую скорость в уведомлении.\nЗначок будет меняться в зависимости от использования.</string>
<string name="summary_pref_speed_enabled">Показывать текущую скорость в уведомлении.\nЗначок указывает, какой трафик преобладает: через прокси или напрямую.</string>
<string name="title_pref_sniffing_enabled">Анализировать пакеты</string>
<string name="summary_pref_sniffing_enabled">Пытаться определять доменные имена в пакетах (по умолчанию включено)</string>
<string name="title_pref_route_only_enabled">Домен только для маршрутизации</string>
<string name="title_pref_sniffing_enabled">Определять домены в трафике (Sniffing)</string>
<string name="summary_pref_sniffing_enabled">Определять домены назначения в трафике (по умолчанию включено).</string>
<string name="title_pref_route_only_enabled">Включить routeOnly</string>
<string name="summary_pref_route_only_enabled">Использовать доменное имя только для маршрутизации и сохранять целевой адрес в виде IP.</string>
<string name="title_pref_local_dns_enabled">Использовать локальную DNS</string>
<string name="title_pref_local_dns_enabled">Использовать локальный DNS</string>
<string name="summary_pref_local_dns_enabled">Обслуживание выполняется DNS-модулем ядра (в настройках маршрутизации рекомендуется выбрать режим «Все, кроме LAN и Китая»)</string>
<string name="title_pref_fake_dns_enabled">Использовать поддельную DNS</string>
<string name="summary_pref_fake_dns_enabled">Локальная DNS возвращает поддельные IP-адреса (быстрее, но может не работать с некоторыми приложениями)</string>
<string name="title_pref_fake_dns_enabled">Использовать виртуальный DNS (FakeDNS)</string>
<string name="summary_pref_fake_dns_enabled">FakeDNS возвращает виртуальные IP-адреса при разрешении доменов (быстрее, но может не работать с некоторыми приложениями).</string>
<string name="title_pref_ipv6_enabled">Включить IPv6</string>
<string name="summary_pref_ipv6_enabled">Добавить IPv6-адрес и маршруты в VPN-интерфейс</string>
@@ -209,10 +216,10 @@
<string name="title_pref_prefer_ipv6">Предпочитать IPv6</string>
<string name="summary_pref_prefer_ipv6">Предпочитать IPv6-адреса при определении доменных имён</string>
<string name="title_pref_remote_dns">Удалённая DNS (UDP/TCP/HTTPS/QUIC) (необязательно)</string>
<string name="summary_pref_remote_dns">DNS</string>
<string name="title_pref_remote_dns">Удалённый DNS (UDP/TCP/HTTPS/QUIC) (необязательно)</string>
<string name="summary_pref_remote_dns" translatable="false">DNS</string>
<string name="title_pref_vpn_dns">VPN DNS (только IPv4/v6)</string>
<string name="title_pref_vpn_dns">VPN DNS (только IPv4/IPv6)</string>
<string name="title_pref_vpn_bypass_lan">VPN обходит LAN</string>
<string name="title_pref_vpn_interface_address">Адрес интерфейса VPN</string>
@@ -220,18 +227,18 @@
<string name="title_pref_vpn_mtu">VPN MTU (по умолчанию 1500)</string>
<string name="title_pref_domestic_dns">Внутренняя DNS (необязательно)</string>
<string name="summary_pref_domestic_dns">DNS</string>
<string name="title_pref_domestic_dns">DNS для прямых подключений (необязательно)</string>
<string name="summary_pref_domestic_dns" translatable="false">DNS</string>
<string name="title_pref_dns_hosts">Узлы DNS (формат: домен:адрес,…)</string>
<string name="title_pref_dns_hosts">Сопоставления DNS (формат: domain:address,…)</string>
<string name="summary_pref_dns_hosts">домен:адрес,…</string>
<string name="title_pref_delay_test_url">Сервис проверки задержки</string>
<string name="summary_pref_delay_test_url">URL</string>
<string name="summary_pref_delay_test_url" translatable="false">URL</string>
<string name="title_pref_real_ping_concurrency">Параллельная проверка задержки</string>
<string name="title_pref_ip_api_url">Сервис проверки текущего соединения</string>
<string name="summary_pref_ip_api_url">URL</string>
<string name="summary_pref_ip_api_url" translatable="false">URL</string>
<string name="title_pref_proxy_sharing_enabled">Разрешать соединения из LAN</string>
<string name="summary_pref_proxy_sharing_enabled">Другие устройства могут подключаться, используя ваш IP-адрес, чтобы использовать локальный прокси. Используйте только в доверенной сети, чтобы избежать несанкционированного подключения.</string>
@@ -240,31 +247,31 @@
<string name="title_pref_socks_port">Порт локального прокси</string>
<string name="title_pref_enable_local_proxy">Использовать локальный прокси</string>
<string name="summary_pref_enable_local_proxy">Если отключено, SOCKS-прокси недоступен, поэтому обновления подписки и подобные действия не смогут использовать прокси</string>
<string name="title_pref_socks_enable_udp">SOCKS5 UDP</string>
<string name="title_pref_socks_enable_udp" translatable="false">SOCKS5 UDP</string>
<string name="summary_pref_socks_enable_udp">Аутентификация SOCKS5 не полностью безопасна при использовании UDP</string>
<string name="summary_pref_socks_port">Порт локального прокси</string>
<string name="title_pref_dynamic_socks_port">Динамически менять порт локального прокси</string>
<string name="summary_pref_dynamic_socks_port">Использовать случайный порт локального прокси при каждом создании соединения</string>
<string name="summary_pref_dynamic_socks_port">Использовать случайный порт локального прокси для каждого входящего подключения (inbound)</string>
<string name="title_pref_socks_username">Пользователь локального прокси (необязательно)</string>
<string name="summary_pref_socks_username">Имя пользователя</string>
<string name="title_pref_socks_password">Пароль локального прокси (необязательно)</string>
<string name="summary_pref_socks_password">Пароль</string>
<string name="title_pref_local_dns_port">Порт локальной DNS</string>
<string name="summary_pref_local_dns_port">Порт локальной DNS</string>
<string name="title_pref_local_dns_port">Порт локального DNS</string>
<string name="summary_pref_local_dns_port">Порт локального DNS</string>
<string name="title_pref_confirm_remove">Подтверждать удаление профиля</string>
<string name="summary_pref_confirm_remove">Обязательное подтверждение удаления профиля</string>
<string name="title_pref_append_http_proxy">Дополнительный HTTP-прокси</string>
<string name="summary_pref_append_http_proxy">HTTP-прокси будет использоваться напрямую (из браузера и других поддерживающих приложений), минуя виртуальный сетевой адаптер (Android 10+)</string>
<string name="title_pref_append_http_proxy">Добавить HTTP-прокси в VPN</string>
<string name="summary_pref_append_http_proxy">Браузеры и поддерживаемые приложения смогут использовать HTTP-прокси напрямую, минуя виртуальный сетевой адаптер (Android 10+).</string>
<string name="title_pref_double_column_display">Профили в два столбца</string>
<string name="summary_pref_double_column_display">The profile list is displayed in double columns, allowing more content to be displayed on the screen.</string>
<string name="summary_pref_double_column_display">Список профилей отображается двумя столбцами, что позволяет показать больше информации на экране.</string>
<string name="title_pref_group_all_display">Общая вкладка групп</string>
<string name="summary_pref_group_all_display">Показывать дополнительную вкладку со всеми профилями групп</string>
<string name="title_pref_group_all_display">Показывать вкладку «Все»</string>
<string name="summary_pref_group_all_display">Объединять профили из всех групп подписок на одной вкладке.</string>
<!-- AboutActivity -->
<string name="title_pref_feedback">Обратная связь</string>
@@ -278,31 +285,33 @@
<string name="title_oss_license">Лицензии открытого исходного кода</string>
<string name="title_tg_channel">Telegram-канал</string>
<string name="title_pref_promotion">Содействие</string>
<string name="title_pref_promotion">Предложения</string>
<string name="title_pref_auto_update_subscription">Автоматически обновлять подписки</string>
<string name="summary_pref_auto_update_subscription">Автоматическое обновление подписок в фоновом режиме с указанным интервалом. В зависимости от устройства эта функция может работать не всегда.</string>
<string name="title_pref_auto_update_interval">Интервал автообновления (минут, не менее 15)</string>
<string name="title_core_loglevel">Подробность ведения журнала</string>
<string name="title_outbound_domain_resolve_method">Предопределение исходящего домена</string>
<string name="title_outbound_domain_resolve_method">Разрешение доменов исходящих подключений (outbound)</string>
<string name="title_mode">Режим</string>
<string name="title_mode_help">Нажмите для получения дополнительной информации</string>
<string name="title_language">Язык</string>
<string name="title_ui_settings">Настройки интерфейса</string>
<string name="title_pref_ui_mode_night">Тема интерфейса</string>
<string name="title_pref_dynamic_color">Включить динамические цвета</string>
<string name="summary_pref_dynamic_color">Работает только на Android 12+</string>
<string name="title_pref_use_hev_tunnel">Использовать Hev TUN</string>
<string name="summary_pref_use_hev_tunnel">Если включено, TUN будет использовать hev-socks5-tunnel; иначе будет использован xray-core</string>
<string name="title_pref_hev_tunnel_loglevel">Подробность журнала HevTun</string>
<string name="title_pref_hev_tunnel_rw_timeout">Ожидание чтения/записи HevTun (секунд, по умолчанию TCP,UDP 300,60)</string>
<string name="title_pref_hev_tunnel_loglevel">Уровень журналирования Hev TUN</string>
<string name="title_pref_hev_tunnel_rw_timeout">Тайм-аут чтения/записи Hev TUN (секунды; значения TCP/UDP по умолчанию: 300/60)</string>
<string name="title_mode_settings">Настройки режима</string>
<string name="title_root_mode_enabled">Использовать root-режим</string>
<string name="summary_root_mode_enabled">Низкоуровневое прозрачное проксирование с помощью привилегий root. Этот режим обходит стандартный VPN системы Android, чтобы напрямую управлять всем сетевым трафиком. После включения первоначальный обычный режим, маршрутизация отдельных приложений и связанные с ними настройки VPN станут полностью недействительными.</string>
<string name="summary_root_mode_enabled">Использовать root-доступ для низкоуровневого прозрачного проксирования. Root-режим управляет сетевым трафиком напрямую вместо службы VPN Android. Пока он включён, обычный режим, маршрутизация отдельных приложений и связанные настройки VPN не действуют.</string>
<string name="toast_root_required">Для этой функции требуется доступ с правами root</string>
<string name="title_root_lan_sharing">Совместное использование LAN/точки доступа (root)</string>
<string name="summary_root_lan_sharing">Маршрутизация точек доступа Wi-Fi и устройств, подключённых к USB, через VPN</string>
<string name="title_root_lan_sharing">Доступ к VPN для устройств LAN/точки доступа (root)</string>
<string name="summary_root_lan_sharing">Направлять через VPN трафик устройств, подключённых к точке доступа Wi-Fi или по USB.</string>
<string name="title_logcat">Журнал</string>
<string name="title_logcat" translatable="false">Logcat</string>
<string name="logcat_copy">Копировать</string>
<string name="logcat_clear">Очистить</string>
<string name="logcat_share">Поделиться журналом</string>
@@ -310,28 +319,31 @@
<string name="title_del_all_config">Удалить профили</string>
<string name="title_del_duplicate_config">Удалить дубликаты профилей</string>
<string name="title_del_invalid_config">Удалить нерабочие профили</string>
<string name="title_export_all">Экспорт профилей в буфер обмена</string>
<string name="title_sub_setting">Группы</string>
<string name="title_export_all">Экспортировать профили в буфер обмена</string>
<string name="title_sub_setting">Подписки</string>
<string name="sub_setting_remarks">Название</string>
<string name="sub_setting_url">URL (необязательно)</string>
<string name="sub_setting_user_agent">User Agent</string>
<string name="sub_setting_filter">Название фильтра</string>
<string name="sub_setting_enable">Использовать обновление</string>
<string name="sub_setting_user_agent" translatable="false">User Agent</string>
<string name="sub_setting_request_headers">Заголовки запроса (формат JSON)</string>
<string name="sub_setting_filter">Фильтр названий (регулярное выражение)</string>
<string name="sub_setting_enable">Включить обновление</string>
<string name="sub_auto_update">Использовать автообновление</string>
<string name="sub_allow_insecure_url">Разрешать незащищённые HTTP-адреса</string>
<string name="sub_setting_pre_profile">Предыдущий профиль прокси</string>
<string name="sub_setting_next_profile">Следующий профиль прокси</string>
<string name="sub_setting_pre_profile_tip">Профиль должен быть уникальным</string>
<string name="sub_setting_pre_profile">Входной прокси</string>
<string name="sub_setting_next_profile">Выходной прокси</string>
<string name="sub_setting_pre_profile_tip">Убедитесь, что профиль с таким названием существует и его название уникально</string>
<string name="sub_setting_entry_proxy_tip">Выбранный прокси добавляется перед каждым профилем подписки и становится входным звеном цепочки прокси для этого профиля.</string>
<string name="sub_setting_exit_proxy_tip">Выбранный прокси добавляется после каждого профиля подписки и становится выходным звеном цепочки прокси для этого профиля.</string>
<string name="toast_invalid_update_interval">Неправильный интервал обновления. Минимум 15 минут.</string>
<string name="title_sub_update">Обновить подписку</string>
<string name="title_ping_all_server">Проверить профили</string>
<string name="title_real_ping_all_server">Проверить задержку профилей</string>
<string name="title_ping_all_server">Проверить TCP-задержку (TCPing)</string>
<string name="title_real_ping_all_server">Проверить реальную задержку</string>
<string name="title_user_asset_setting">Файлы ресурсов</string>
<string name="title_sort_by_test_results">Сортировать по результатам теста</string>
<string name="title_filter_config">Фильтр профилей</string>
<string name="filter_config_all">Все</string>
<string name="summary_scan_qrcode">Нажмите на экран, чтобы открыть камеру для сканирования</string>
<string name="title_del_duplicate_config_count">Удалено дубликатов профилей: %d</string>
<string name="summary_scan_qrcode">Click screen open the camera scan</string>
<string name="title_del_config_count">Удалено профилей: %d</string>
<string name="title_import_config_count">Импортировано профилей: %d</string>
<string name="title_export_config_count">Экспортировано профилей: %d</string>
@@ -339,7 +351,6 @@
<string name="title_update_subscription_result">Обновлено профилей: %1$d (успешно: %2$d, ошибки: %3$d, пропущено: %4$d)</string>
<string name="title_update_subscription_no_subscription">Нет подписок</string>
<string name="toast_server_not_found_in_group">Выбранный профиль не найден в текущей группе</string>
<string name="toast_fragment_not_available">Фрагмент недоступен</string>
<string name="title_locate_selected_config">Найти выбранный профиль</string>
<string name="tasker_start_service">Запуск службы</string>
@@ -348,7 +359,8 @@
<!-- RoutingSettingActivity -->
<string name="routing_settings_domain_strategy">Доменная стратегия</string>
<string name="routing_settings_title">Маршрутизация</string>
<string name="routing_settings_tips">Через запятую (,)\nЧто-то одно: домен, IP или процесс</string>
<string name="routing_settings_tips">Правило применяется, только если одновременно выполняются все заданные условия сопоставления (AND). Правила проверяются сверху вниз; применяется первое совпавшее правило.</string>
<string name="routing_settings_comma_tip">Разделяйте несколько значений запятыми (,).</string>
<string name="routing_settings_save">Сохранить</string>
<string name="routing_settings_delete">Очистить</string>
<string name="routing_settings_rule_title">Настройка правил маршрутизации</string>
@@ -359,55 +371,58 @@
<string name="routing_settings_import_rulesets_from_qrcode">Импорт правил из QR-кода</string>
<string name="routing_settings_export_rulesets_to_clipboard">Экспорт правил в буфер обмена</string>
<string name="routing_settings_locked">Постоянное (сохранится при импорте правил)</string>
<string name="routing_settings_domain">Домен</string>
<string name="routing_settings_ip">IP</string>
<string name="routing_settings_process">Процесс (название пакета; поддерживается только при использовании Xray TUN, включённой функции «Домен только для маршрутизации» и ОС Android 10+)</string>
<string name="routing_settings_port">Порт</string>
<string name="routing_settings_protocol">Протокол</string>
<string name="routing_settings_protocol_tip">[http,tls,bittorrent]</string>
<string name="routing_settings_network">Сеть</string>
<string name="routing_settings_outbound_tag">Исходящее соединение</string>
<string name="routing_settings_domain" translatable="false">domain</string>
<string name="routing_settings_ip" translatable="false">ip</string>
<string name="routing_settings_process">process (имя пакета — поддерживается только при использовании Xray TUN, включённом routeOnly и Android 10+)</string>
<string name="routing_settings_process_select">Выбор названия пакета</string>
<string name="routing_settings_port" translatable="false">port</string>
<string name="routing_settings_protocol" translatable="false">protocol</string>
<string name="routing_settings_protocol_tip" translatable="false">[http,tls,bittorrent]</string>
<string name="routing_settings_network" translatable="false">network</string>
<string name="routing_settings_outbound_tag_hint">proxy / direct / block / &lt;%1$s&gt;</string>
<string name="routing_settings_outbound_tag" translatable="false">outboundTag</string>
<string name="connection_test_pending">Проверить соединение</string>
<string name="connection_test_testing">Проверка…</string>
<string name="connection_test_testing_count">Проверка профилей (%d)</string>
<string name="connection_test_available">Успешно: соединение заняло %d мс</string>
<string name="connection_test_error">Сбой проверки интернет-соединения: %s</string>
<string name="connection_test_testing_count">Проверка профилей (%d)…</string>
<string name="connection_test_available">Соединение установлено за %1$s</string>
<string name="server_test_delay_value">%1$d мс</string>
<string name="connection_test_error">Ошибка проверки соединения: %s</string>
<string name="connection_test_fail">Интернет недоступен</string>
<string name="connection_test_error_status_code">Код ошибки: #%d</string>
<string name="connection_connected">Соединено, нажмите для проверки</string>
<string name="connection_connected">Подключено.\nНажмите, чтобы проверить соединение.</string>
<string name="connection_not_connected">Нет соединения</string>
<string name="connection_runing_task_left">Запущено проверок: %s</string>
<string name="connection_running_task_left">Выполняется проверок: %s</string>
<string name="import_subscription_success">Подписка импортирована</string>
<string name="import_subscription_failure">Невозможно импортировать подписку</string>
<string name="title_fragment_settings">Настройки фрагментирования</string>
<string name="title_fragment_settings">Настройки фрагментирования (Fragment)</string>
<string name="title_pref_fragment_packets">Фрагментирование пакетов</string>
<string name="title_pref_fragment_length">Длина фрагмента (от — до)</string>
<string name="title_pref_fragment_interval">Интервал фрагментов (от — до)</string>
<string name="title_pref_fragment_enabled">Использовать фрагментирование</string>
<string name="title_pref_fragment_maxsplit">Максимальное число фрагментов</string>
<string name="title_observatory_settings">Настройки наблюдения соединений</string>
<string name="title_observatory_settings">Настройки мониторинга соединений (Observatory)</string>
<string name="title_pref_observatory_least_ping_interval">Интервал leastPing</string>
<string name="title_pref_observatory_least_load_interval">Интервал leastLoad</string>
<string name="title_pref_observatory_least_load_method">HTTP-метод leastLoad</string>
<string name="title_pref_observatory_least_load_sampling">Выборка leastLoad</string>
<string name="title_pref_observatory_least_load_timeout">Тайм-аут leastLoad</string>
<string name="title_pref_observatory_least_load_timeout">Время ожидания leastLoad</string>
<string name="toast_invalid_observatory_duration">Недопустимая длительность. Используйте значение вроде 3m или 30s.</string>
<string name="toast_invalid_observatory_sampling">Недопустимая выборка. Используйте положительное число.</string>
<string name="toast_invalid_observatory_sampling">Недопустимый размер выборки. Используйте положительное число.</string>
<string name="update_check_for_update">Проверить обновление</string>
<string name="update_already_latest_version">Установлена последняя версия</string>
<string name="update_new_version_found">Найдена новая версия: %s</string>
<string name="update_now">Обновить</string>
<string name="update_check_pre_release">Искать предварительный выпуск</string>
<string name="update_check_pre_release">Проверять предварительные версии</string>
<string name="update_checking_for_update">Проверка обновления…</string>
<string name="title_policy_group_type">Тип политики группы</string>
<string name="title_policy_group_subscription_id">Из группы подписки</string>
<string name="title_policy_group_subscription_filter">Название фильтра</string>
<string name="title_policy_group_test_outbounds">Проверять исходящие соединения</string>
<string name="title_policy_group_fallback">Резервное исходящее соединение (необязательно)</string>
<string name="title_policy_group_subscription_filter">Фильтр примечаний (регулярное выражение)</string>
<string name="title_policy_group_test_outbounds">Тестировать исходящие подключения (outbounds)</string>
<string name="title_policy_group_fallback">Резервное исходящее подключение (outbound, необязательно)</string>
<string name="server_proxy_chain_members">Участники цепочки прокси</string>
<string name="server_proxy_chain_pick_members">Нажмите здесь, чтобы выбрать участника</string>
@@ -417,8 +432,8 @@
<string name="server_proxy_chain_members_invalid">Недопустимые участники цепочки: %1$s</string>
<!-- BackupActivity -->
<string name="title_configuration_backup_restore">Резервное копирование</string>
<string name="title_configuration_backup">Резервирование конфигурации</string>
<string name="title_configuration_backup_restore">Резервное копирование и восстановление</string>
<string name="title_configuration_backup">Создать резервную копию</string>
<string name="title_configuration_restore">Восстановление конфигурации</string>
<string name="title_configuration_share">Поделиться конфигурацией</string>
<string name="title_webdav_config_setting">Настройки WebDAV</string>
@@ -429,16 +444,14 @@
<string name="title_webdav_remote_path">Удалённый путь (необязательно)</string>
<string name="share_method_qrcode">QR-код</string>
<string name="share_method_clipboard">Экспорт в буфер обмена</string>
<string name="share_method_full_content">Экспорт конфигурации в буфер обмена</string>
<string name="share_method_clipboard">Копировать ссылку профиля</string>
<string name="share_method_full_content">Копировать полную конфигурацию</string>
<string name="action_edit">Изменить</string>
<string name="action_delete">Удалить</string>
<string name="action_close">Закрыть</string>
<string-array name="share_sub_method">
<item>QR-код</item>
<item>Экспорт в буфер обмена</item>
</string-array>
<string name="share_subscription_qrcode">QR-код</string>
<string name="share_subscription_clipboard">Экспорт в буфер обмена</string>
<string-array name="mode_entries">
<item>VPN</item>
@@ -457,13 +470,11 @@
<item>Тёмная</item>
</string-array>
<string-array name="preset_rulesets">
<item>Белый список Китая</item>
<item>Чёрный список Китая</item>
<item>Общие</item>
<item>Белый список Ирана</item>
<item>Белый список России</item>
</string-array>
<string name="routing_preset_china_whitelist">Белый список Китая</string>
<string name="routing_preset_china_blacklist">Чёрный список Китая</string>
<string name="routing_preset_global">Глобальная</string>
<string name="routing_preset_iran_whitelist">Белый список Ирана</string>
<string name="routing_preset_russia_whitelist">Белый список России</string>
<string-array name="vpn_bypass_lan">
<item>Как в профиле</item>
@@ -472,21 +483,61 @@
</string-array>
<string-array name="outbound_domain_resolve_method">
<item>Не определять</item>
<item>Определять и добавлять к узлам DNS</item>
<item>Определять и заменять домен</item>
<item>Не разрешать</item>
<item>Разрешать и добавлять в DNS Hosts</item>
<item>Разрешать и заменять домен</item>
</string-array>
<string-array name="policy_group_type">
<item>Наименьшая задержка</item>
<item>Наименьшая нагрузка</item>
<item>Случайно</item>
<item>По очереди</item>
<item>Наименьшая задержка (leastPing)</item>
<item>Наименьшая нагрузка (leastLoad)</item>
<item>Случайный выбор (random)</item>
<item>Циклический выбор (roundRobin)</item>
</string-array>
<string-array name="config_backup_options">
<item>Локально</item>
<item>WebDAV</item>
</string-array>
<string name="backup_location_local">Локально</string>
<string name="backup_location_webdav" translatable="false">WebDAV</string>
<string name="acc_refresh">Обновить журнал</string>
<string name="toast_permission_denied_for">Нет разрешения: %1$s</string>
<string name="acc_add_subscription">Добавить подписку</string>
<string name="toast_malformed_json_detail">Некорректная конфигурация: %1$s</string>
<string name="acc_add_asset">Добавить источник ресурсов</string>
<string name="acc_download_file">Загрузить файлы ресурсов</string>
<string name="acc_qr_code">QR-код</string>
<string name="acc_copy_log">Копировать журнал</string>
<string name="acc_clear_log">Очистить журнал</string>
<string name="acc_add_rule">Добавить правило маршрутизации</string>
<string name="acc_start">Запустить службу</string>
<string name="acc_stop">Остановить службу</string>
<string name="acc_back">Назад</string>
<string name="acc_search">Поиск</string>
<string name="acc_add">Добавить профиль</string>
<string name="acc_more">Дополнительные параметры</string>
<string name="acc_share_subscription">Поделиться ссылкой на подписку</string>
<string name="acc_share_log">Поделиться журналом</string>
<string name="acc_remove">Удалить участника цепочки прокси</string>
<string name="acc_add_member">Добавить участника цепочки прокси</string>
<string name="acc_start_scanner">Запустить сканер QR-кодов</string>
<string name="acc_stop_scanner">Остановить сканер QR-кодов</string>
<string name="acc_turn_torch_on">Включить фонарик</string>
<string name="acc_turn_torch_off">Выключить фонарик</string>
<string name="acc_select_image">Выбрать изображение для сканирования</string>
<string name="acc_locked">Правило сохраняется при импорте предустановок</string>
<string name="acc_open_menu">Открыть меню навигации</string>
<string name="acc_edit">Изменить</string>
<string name="acc_delete">Удалить</string>
<string name="acc_save">Сохранить</string>
<string name="acc_update_subscriptions">Обновить подписки</string>
<string name="acc_per_app_proxy_information">Сведения о прокси для приложений</string>
<string name="permission_camera">Камера</string>
<string name="permission_notification">Уведомления</string>
<string name="permission_local_network">Локальная сеть</string>
<string name="subscription_update_updating">Обновление подписки: %1$s</string>
<string name="subscription_update_progress">Тестирование %2$s: %1$s</string>
<string name="tasker_blurb_start">Запустить %1$s</string>
<string name="tasker_blurb_stop">Остановить %1$s</string>
<string name="connection_test_empty_message">подробности отсутствуют</string>
<string name="value_unknown">неизвестно</string>
</resources>
+313 -237
View File
@@ -1,21 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" translatable="false">v2rayNG</string>
<string name="app_widget_name">Kết nối ngay</string>
<string name="app_tile_name">Kết nối ngay</string>
<string name="app_tile_first_use">Vui lòng thêm một cấu hình vào v2rayNG để sử dụng!</string>
<string name="navigation_drawer_open">Mở Menu ứng dụng</string>
<string name="navigation_drawer_close">Đóng Menu ứng dụng</string>
<string name="migration_success">Đã chuyển dữ liệu!</string>
<string name="action_stop_service">Stop service</string>
<string name="action_stop_service">Dừng dịch vụ</string>
<string name="action_ok">OK</string>
<string name="action_cancel">Hủy</string>
<string name="migration_fail">Không thể chuyển dữ liệu!</string>
<string name="pull_down_to_refresh">Please pull down to refresh!</string>
<string name="pull_down_to_refresh">Kéo xuống để làm mới!</string>
<!-- Notifications -->
<string name="notification_action_stop_v2ray">Ngắt kết nối v2rayNG</string>
<string name="toast_permission_denied">Vui lòng cấp quyền cần thiết cho v2rayNG! Bạn đã từ chối các quyền cần thiết như Camera hay Bộ nhớ?</string>
<string name="toast_permission_denied_notification">Unable to obtain the notification permission</string>
<string name="notification_action_more">Nhấn để biết thêm...</string>
<string name="toast_services_start">Đang khởi động v2rayNG...</string>
<string name="toast_permission_denied">Vui lòng cấp các quyền cần thiết cho v2rayNG. Bạn có thể đã từ chối quyền truy cập máy ảnh hoặc bộ nhớ.</string>
<string name="toast_permission_denied_notification">Không thể nhận quyền thông báo</string>
<string name="notification_action_more">Nhấn để biết thêm…</string>
<string name="toast_services_start">Đang khởi động v2rayNG…</string>
<string name="toast_services_stop">Đã dừng v2rayNG!</string>
<string name="toast_services_success">Đã khởi động v2rayNG!</string>
<string name="toast_services_failure">Không thể khởi động v2rayNG, kiểm tra lại cấu hình!</string>
@@ -24,21 +27,21 @@
<string name="title_server">v2rayNG</string>
<string name="menu_item_add_config">Thêm cấu hình</string>
<string name="menu_item_save_config">Lưu cấu hình</string>
<string name="menu_item_edit_config">Edit configuration</string>
<string name="menu_item_edit_config">Chỉnh sửa cấu hình</string>
<string name="menu_item_del_config">Xoá cấu hình</string>
<string name="menu_item_import_config_qrcode">Nhập cấu hình từ mã QR</string>
<string name="menu_item_import_config_clipboard">Nhập cấu hình từ Clipboard</string>
<string name="menu_item_import_config_local">Import config from locally</string>
<string name="menu_item_import_config_policy_group">Add [Policy group]</string>
<string name="menu_item_import_config_proxy_chain">Add [Proxy chain]</string>
<string name="menu_item_import_config_manually_vmess">Nhập thủ công [VMess]</string>
<string name="menu_item_import_config_manually_vless">Nhập thủ công [VLESS]</string>
<string name="menu_item_import_config_manually_ss">Nhập thủ công [ShadowSocks]</string>
<string name="menu_item_import_config_manually_socks">Nhập thủ công [SOCKS]</string>
<string name="menu_item_import_config_manually_http">Type manually[HTTP]</string>
<string name="menu_item_import_config_manually_trojan">Nhập thủ công [Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">Nhập thủ công [WireGuard]</string>
<string name="menu_item_import_config_manually_hysteria2">Type manually[Hysteria2]</string>
<string name="menu_item_import_config_clipboard">Nhập cấu hình từ bảng tạm</string>
<string name="menu_item_import_config_local">Nhập cấu hình từ thiết bị</string>
<string name="menu_item_import_config_policy_group">Thêm [Nhóm chính sách]</string>
<string name="menu_item_import_config_proxy_chain">Thêm [Chuỗi proxy]</string>
<string name="menu_item_import_config_manually_vmess">Thêm [VMess]</string>
<string name="menu_item_import_config_manually_vless">Thêm [VLESS]</string>
<string name="menu_item_import_config_manually_ss">Thêm [Shadowsocks]</string>
<string name="menu_item_import_config_manually_socks">Thêm [SOCKS]</string>
<string name="menu_item_import_config_manually_http">Thêm [HTTP]</string>
<string name="menu_item_import_config_manually_trojan">Thêm [Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">Thêm [WireGuard]</string>
<string name="menu_item_import_config_manually_hysteria2">Thêm [Hysteria2]</string>
<string name="confirm_delete_visible_profiles">Bạn có chắc muốn xóa tất cả cấu hình đang hiển thị không?</string>
<string name="confirm_delete_duplicate_profiles">Bạn có chắc muốn xóa tất cả cấu hình trùng lặp đang hiển thị không?</string>
<string name="confirm_delete_invalid_profiles">Vui lòng kiểm tra các cấu hình trước. Bạn có chắc muốn xóa tất cả cấu hình không hợp lệ đang hiển thị không?</string>
@@ -56,7 +59,7 @@
<string name="server_lab_alterid">ID bổ sung (AlterID)</string>
<string name="server_lab_security">Thuật toán mã hóa</string>
<string name="server_lab_network">Giao thức truyền tải (Network)</string>
<string name="server_lab_more_function">Nâng cao</string>
<string name="server_lab_more_function">Truyền tải</string>
<string name="server_lab_head_type">Kiểu ngụy trang (Type)</string>
<string name="server_lab_mode_type">Chế độ gRPC</string>
<string name="server_lab_request_host">host</string>
@@ -70,16 +73,16 @@
<string name="server_lab_path">path</string>
<string name="server_lab_path_ws">ws path</string>
<string name="server_lab_path_httpupgrade">httpupgrade path</string>
<string name="server_lab_path_xhttp">xhttp path </string>
<string name="server_lab_path_xhttp">xhttp path</string>
<string name="server_lab_path_h2">h2 path</string>
<string name="server_lab_path_quic">QUIC key</string>
<string name="server_lab_path_kcp">kcp seed</string>
<string name="server_lab_path_grpc">gRPC serviceName</string>
<string name="server_lab_stream_security">TLS</string>
<string name="server_lab_stream_security" translatable="false">TLS</string>
<string name="server_lab_stream_fingerprint">Fingerprint</string>
<string name="server_lab_stream_alpn">Alpn</string>
<string name="server_lab_allow_insecure">Bỏ qua xác minh chứng chỉ</string>
<string name="server_lab_sni">SNI</string>
<string name="server_lab_stream_alpn" translatable="false">ALPN</string>
<string name="server_lab_allow_insecure">Bỏ qua xác minh chứng chỉ (allowInsecure)</string>
<string name="server_lab_sni" translatable="false">SNI</string>
<string name="server_lab_address3">Địa chỉ</string>
<string name="server_lab_port3">Cổng</string>
<string name="server_lab_id3">Mật khẩu</string>
@@ -87,96 +90,105 @@
<string name="server_lab_id4">Mật khẩu (Không bắt buộc)</string>
<string name="server_lab_security4">Tên người dùng (Không bắt buộc)</string>
<string name="server_lab_encryption">Mã hóa</string>
<string name="server_lab_flow">Kiểm soát lưu lượng (Flow)</string>
<string name="server_lab_flow">Kiểm soát lưu lượng (flow)</string>
<string name="server_lab_public_key">PublicKey</string>
<string name="server_lab_preshared_key">PreSharedKey(optional)</string>
<string name="server_lab_preshared_key">PreSharedKey (không bắt buộc)</string>
<string name="server_lab_short_id">ShortId</string>
<string name="server_lab_spider_x">SpiderX</string>
<string name="server_lab_mldsa65_verify">Mldsa65Verify</string>
<string name="server_lab_spider_x" translatable="false">SpiderX</string>
<string name="server_lab_mldsa65_verify" translatable="false">mldsa65Verify</string>
<string name="server_lab_secret_key">SecretKey</string>
<string name="server_lab_reserved">Reserved (Không bắt buộc)</string>
<string name="server_lab_local_address">Địa chỉ cục bộ (IPv4 / IPv6, phân cách bằng dấu phẩy)</string>
<string name="server_lab_local_mtu">MTU (Không bắt buộc, mặc định là 1420)</string>
<string name="server_lab_kcp_mtu">mKCP MTU (Không bắt buộc, mặc định core là 1350)</string>
<string name="server_lab_kcp_tti">mKCP TTI (Không bắt buộc, mặc định core là 50)</string>
<string name="server_lab_reserved">Reserved (không bắt buộc, phân cách bằng dấu phẩy)</string>
<string name="server_lab_local_address">Địa chỉ cục bộ (IPv4/IPv6 không bắt buộc, phân cách bằng dấu phẩy)</string>
<string name="server_lab_local_mtu">MTU (không bắt buộc, mặc định 1420)</string>
<string name="server_lab_kcp_mtu">mKCP MTU (không bắt buộc, mặc định của core là 1350)</string>
<string name="server_lab_kcp_tti">mKCP TTI (không bắt buộc, mặc định của core là 50)</string>
<string name="toast_success">Thành công!</string>
<string name="toast_failure">Đã xảy ra lỗi, vui lòng thử lại!</string>
<string name="toast_none_data">Không có gì ở đây!</string>
<string name="toast_incorrect_protocol">Protocol không đúng!</string>
<string name="toast_incorrect_protocol">Giao thức không hợp lệ.</string>
<string name="toast_decoding_failed">Không thể giải mã!</string>
<string name="title_file_chooser">Vui lòng chọn tệp cấu hình!</string>
<string name="toast_require_file_manager">Vui lòng cài đặt trình quản lý tệp để tiếp tục!</string>
<string name="server_customize_config">Cấu hình tùy chỉnh</string>
<string name="toast_config_file_invalid">Cấu hình không hợp lệ!</string>
<string name="server_lab_content">Nội dung</string>
<string name="toast_none_data_clipboard">Không có dữ liệu nào trong Clipboard!</string>
<string name="toast_none_data_clipboard">Không có dữ liệu trong bảng tạm!</string>
<string name="toast_invalid_url">URL không hợp lệ hoặc trống!</string>
<string name="toast_insecure_url_protocol">Please do not use the insecure HTTP protocol subscription address</string>
<string name="server_lab_need_inbound">Vui lòng đảm bảo cấu hình tùy chỉnh này không bị lỗi trước khi sử dụng!</string>
<string name="toast_malformed_josn">Cấu hình không hợp lệ!</string>
<string name="server_lab_request_host6">Host (SNI) (Không bắt buộc)</string>
<string name="toast_insecure_url_protocol">Vui lòng không dùng địa chỉ đăng ký với giao thức HTTP không an toàn</string>
<string name="server_lab_need_inbound">Đảm bảo cổng inbound khớp với cài đặt</string>
<string name="toast_malformed_json">Cấu hình không hợp lệ.</string>
<string name="server_lab_request_host6">Host (SNI) (không bắt buộc)</string>
<string name="toast_action_not_allowed">Hành động này bị cấm!</string>
<string name="server_obfs_password">Obfs password</string>
<string name="server_lab_port_hop">Port Hopping</string>
<string name="server_lab_port_hop_interval">Port Hopping Interval</string>
<string name="server_lab_bandwidth_down">Bandwidth down (Supported units: k/m/g/t)</string>
<string name="server_lab_bandwidth_up">Bandwidth up (Supported units: k/m/g/t)</string>
<string name="server_lab_xhttp_mode">XHTTP Mode</string>
<string name="server_lab_xhttp_extra">XHTTP Extra raw JSON, format: { XHTTPObject }</string>
<string name="server_lab_final_mask">finalMask raw JSON, format: { FinalMaskObject }</string>
<string name="server_lab_ech_config_list">EchConfigList</string>
<string name="server_lab_verify_peer_cert_by_name">Verify Peer Cert By Name</string>
<string name="server_lab_pinned_ca256">Certificate fingerprint (SHA-256)</string>
<string name="pinned_ca256_action_fetch">Fetch and fill certificate fingerprint</string>
<string name="toast_fetch_cert_sha256_success">Certificate fingerprint fetched successfully</string>
<string name="toast_fetch_cert_sha256_failed">Failed to fetch certificate fingerprint</string>
<string name="server_obfs_password">Mật khẩu Obfs</string>
<string name="server_lab_port_hop">Nhảy cổng (sẽ ghi đè cổng)</string>
<string name="server_lab_port_hop_interval">Khoảng thời gian đổi cổng (giây)</string>
<string name="server_lab_bandwidth_down">Băng thông tải xuống (đơn vị hỗ trợ: k/m/g/t)</string>
<string name="server_lab_bandwidth_up">Băng thông tải lên (đơn vị hỗ trợ: k/m/g/t)</string>
<string name="server_lab_xhttp_mode">Chế độ XHTTP</string>
<string name="server_lab_xhttp_extra">JSON thô của XHTTP Extra, định dạng: { XHTTPObject }</string>
<string name="server_lab_final_mask">JSON thô của finalMask, định dạng: { FinalMaskObject }</string>
<string name="server_lab_ech_config_list" translatable="false">echConfigList</string>
<string name="server_lab_verify_peer_cert_by_name">Xác minh chứng chỉ ngang hàng theo tên</string>
<string name="server_lab_pinned_ca256">Dấu vân tay chứng chỉ (SHA-256)</string>
<string name="server_lab_browser_dialer">Bật Browser Dialer</string>
<string name="server_lab_browser_dialer_tip">Chỉ hỗ trợ đầu ra xhttp (packet-up) và ws; các cài đặt liên quan đến TLS có thể bị bỏ qua hoặc xung đột</string>
<string name="toast_allow_insecure_deprecated">Nút hiện tại sử dụng kết nối không mã hóa. Hạ tầng trung gian mạng do các chính phủ độc tài kiểm soát có thể xem trực tiếp nội dung liên lạc của bạn.\nVì lý do bảo mật, không thể kết nối đến các nút như vậy bằng Xray core phiên bản 26.2.6 trở lên.\nNếu đây là nút do bạn tự dựng, hãy bật mã hóa an toàn như TLS hoặc ghim dấu vân tay chứng chỉ pinnedCA256.\nNếu đây là nút của nhà cung cấp dịch vụ, hãy liên hệ với họ để hoàn tất nâng cấp kỹ thuật. Nếu nhà cung cấp từ chối hợp tác, bạn nên chuyển sang nhà cung cấp coi trọng bảo mật người dùng hơn.\nĐể biết thêm thông tin, hãy truy cập https://github.com/2dust/v2rayN/discussions/9460</string>
<string name="pinned_ca256_action_fetch">Lấy dấu vân tay chứng chỉ</string>
<string name="toast_fetch_cert_sha256_success">Đã lấy dấu vân tay chứng chỉ thành công</string>
<string name="toast_fetch_cert_sha256_failed">Không thể lấy dấu vân tay chứng chỉ</string>
<!-- UserAssetActivity -->
<string name="toast_asset_copy_failed">Không thể sao chép tệp tin, hãy dùng trình quản lý tệp!</string>
<string name="menu_item_add_asset">Thêm tài nguyên</string>
<string name="menu_item_add_file">Thêm tệp</string>
<string name="menu_item_add_url">Thêm URL</string>
<string name="menu_item_scan_qrcode">Quét mã QR</string>
<string name="title_url">URL</string>
<string name="title_url" translatable="false">URL</string>
<string name="menu_item_download_file">Tải xuống tệp tin</string>
<string name="title_user_asset_add_url">Thêm URL nội dung</string>
<string name="title_user_asset_add_url">Thêm URL tài nguyên</string>
<string name="msg_file_not_found">Không tìm thấy tập tin!</string>
<string name="msg_remark_is_duplicate">Nhận xét đã tồn tại!</string>
<string name="asset_geo_files_sources">Geo files source (optional)</string>
<string name="msg_remark_is_duplicate">Tên này đã tồn tại!</string>
<string name="asset_geo_files_sources">Nguồn tệp Geo (tùy chọn)</string>
<!-- PerAppProxyActivity -->
<string name="msg_dialog_progress">Đang tải...</string>
<string name="msg_dialog_progress">Đang tải…</string>
<string name="menu_item_search">Tìm kiếm</string>
<string name="menu_item_select_all">Chọn tất cả</string>
<string name="menu_item_invert_selection">Đảo chọn</string>
<string name="msg_enter_keywords">Nhập từ khoá</string>
<string name="switch_bypass_apps_mode">Chế độ Bypass</string>
<string name="menu_item_select_proxy_app">Tự động chọn ứng dụng Proxy</string>
<string name="msg_downloading_content">Đang tải xuống nội dung...</string>
<string name="switch_bypass_apps_mode">Chế độ bỏ qua</string>
<string name="menu_item_select_proxy_app">Tự động chọn ứng dụng cần dùng proxy</string>
<string name="msg_downloading_content">Đang tải xuống nội dung…</string>
<string name="menu_item_export_proxy_app">Xuất và Sao chép</string>
<string name="menu_item_import_proxy_app">Nhập từ Clipboard</string>
<string name="per_app_proxy_settings">Per-app settings</string>
<string name="per_app_proxy_settings_enable">Enable per-app</string>
<string name="menu_item_import_proxy_app">Nhập từ bảng tạm</string>
<string name="per_app_proxy_settings">Cài đặt theo ứng dụng</string>
<string name="per_app_proxy_settings_enable">Bật cài đặt theo ứng dụng</string>
<string name="app_picker_unknown_app">Ứng dụng không xác định (không nhận dạng được UID)</string>
<!-- Preferences -->
<string name="title_settings">Cài đặt</string>
<string name="title_advanced">Cài đặt nâng cao</string>
<string name="title_core_settings">Cài đặt lõi</string>
<string name="title_vpn_settings">Cài đặt VPN</string>
<string name="title_pref_per_app_proxy">Proxy theo Ứng dụng</string>
<string name="summary_pref_per_app_proxy">- Bình thường: Ứng dụng đã chọn sẽ kết nối thông qua Proxy, chưa chọn sẽ kết nối trực tiếp. \n- Chế độ Bypass: Ứng dụng đã chọn sẽ kết nối trực tiếp, chưa chọn sẽ kết nối qua Proxy. \n- Nếu bạn đang ở Trung Quốc thì vào Menu, chọn Tự động chọn ứng dụng Proxy.</string>
<string name="title_pref_is_booted">Auto connect at startup</string>
<string name="summary_pref_is_booted">Automatically connects to the selected server at startup, which may be unsuccessful</string>
<string name="title_pref_per_app_proxy">Proxy theo từng ứng dụng</string>
<string name="summary_pref_per_app_proxy">Thông thường: ứng dụng đã chọn dùng proxy, ứng dụng chưa chọn kết nối trực tiếp;\nChế độ bỏ qua: ứng dụng đã chọn kết nối trực tiếp, ứng dụng chưa chọn dùng proxy.\nTrong trình đơn có tùy chọn tự động chọn các ứng dụng sẽ dùng proxy.</string>
<string name="title_pref_is_booted">Tự động kết nối khi khởi động</string>
<string name="summary_pref_is_booted">Tự động kết nối với máy chủ đã chọn khi khởi động; thao tác này có thể không thành công</string>
<string name="title_pref_auto_remove_invalid_after_test">Auto delete invalid config after testing</string>
<string name="summary_pref_auto_remove_invalid_after_test">Test results may not be accurate; deleted config cannot be recovered.</string>
<string name="title_pref_auto_sort_after_test">Auto sort after testing</string>
<string name="summary_pref_auto_sort_after_test">Test results may not be accurate;</string>
<string name="subscription_updater_job_tips">Tác vụ sẽ chạy trong nền và thông tin tiến độ sẽ hiển thị trong thông báo.</string>
<string name="title_pref_auto_test_after_update_subscription">Tự động kiểm tra sau khi cập nhật đăng ký</string>
<string name="summary_pref_auto_test_after_update_subscription">Quá trình kiểm tra tự động mất nhiều thời gian. Nếu bật, tác vụ sẽ chạy trong nền; nếu không, tác vụ sẽ chạy trên trang hiện tại.</string>
<string name="title_pref_auto_remove_invalid_after_test">Tự động xóa cấu hình không hợp lệ sau khi kiểm tra</string>
<string name="summary_pref_auto_remove_invalid_after_test">Kết quả kiểm tra có thể không chính xác; cấu hình đã xóa không thể khôi phục.</string>
<string name="title_pref_auto_sort_after_test">Tự động sắp xếp sau khi kiểm tra</string>
<string name="summary_pref_auto_sort_after_test">Kết quả kiểm tra có thể không chính xác;</string>
<string name="title_mux_settings">Cài đặt Mux</string>
<string name="title_pref_mux_enabled">Bật Mux</string>
<string name="summary_pref_mux_enabled">Giảm độ trễ nhưng có thể làm gián đoạn luồng, vì vậy không nên kích hoạt nó. \nCác phương pháp xử lý lưu lượng truy cập TCP, UDP và QUIC có sẵn bên dưới.</string>
<string name="title_pref_mux_concurency">Số lượng liên kết con tái sử dụng TCP (-1 đến 1024)</string>
<string name="title_pref_mux_xudp_concurency">Số lượng liên kết con tái sử dụng XUDP (-1 đến 1024)</string>
<string name="summary_pref_mux_enabled">Nhanh hơn nhưng có thể làm kết nối không ổn định.\nTùy chỉnh cách xử lý TCP, UDP và QUIC bên dưới.</string>
<string name="title_pref_mux_concurrency">Số kết nối con TCP được ghép kênh (-1 đến 1024)</string>
<string name="title_pref_mux_xudp_concurrency">Số kết nối con XUDP được ghép kênh (-1 đến 1024)</string>
<string name="title_pref_mux_xudp_quic">Phương pháp xử lý lưu lượng QUIC</string>
<string-array name="mux_xudp_quic_entries">
<item>Từ chối</item>
@@ -184,21 +196,19 @@
<item>Bỏ qua</item>
</string-array>
<string name="title_pref_speed_enabled">Hiển thị tốc độ mạng</string>
<string name="summary_pref_speed_enabled">Hiển thị tốc độ mạng hiện tại trên thanh thông báo. \nBiểu tượng trên thanh trạng thái có thể thay đổi tùy vào mức sử dụng.</string>
<string name="summary_pref_speed_enabled">Hiển thị tốc độ hiện tại trong thông báo.\nBiểu tượng cho biết lưu lượng proxy hay trực tiếp đang chiếm ưu thế.</string>
<string name="title_pref_sniffing_enabled">Bật Sniffing</string>
<string name="summary_pref_sniffing_enabled">Phát hiện tên miền từ lưu lượng truy cập (Được bật theo mặc định). \nỞ Việt Nam: tắt để sử dụng Zalo.</string>
<string name="title_pref_route_only_enabled">Bật RouteOnly</string>
<string name="summary_pref_route_only_enabled">Chỉ sử dụng tên miền được đánh dấu để định tuyến và giữ địa chỉ đích làm địa chỉ IP.</string>
<string name="summary_pref_sniffing_enabled">Phát hiện tên miền đích từ lưu lượng truy cập (bật theo mặc định).</string>
<string name="title_pref_route_only_enabled">Bật routeOnly</string>
<string name="summary_pref_route_only_enabled">Chỉ dùng tên miền phát hiện được để định tuyến và giữ địa chỉ đích ở dạng địa chỉ IP.</string>
<string name="title_pref_local_dns_enabled">Bật DNS cục bộ</string>
<string name="summary_pref_local_dns_enabled">DNS được xử lý bởi mô-đun DNS của Xray-core (khuyên dùng nếu cần định tuyến bỏ qua mạng LAN và địa chỉ ở Trung Quốc đại lục).</string>
<string name="title_pref_local_dns_enabled">Bật Local DNS</string>
<string name="summary_pref_local_dns_enabled">DNS được xử lý bởi module DNS của Xray-Core (Dùng nếu cần định tuyến Bypass cho mạng LAN và Địa chỉ nội địa).</string>
<string name="title_pref_fake_dns_enabled">Bật FakeDNS</string>
<string name="summary_pref_fake_dns_enabled">FakeDNS lấy tên miền mục tiêu bằng cách giả mạo DNS (Nhanh hơn, nhưng có thể không hoạt động cho một số ứng dụng).</string>
<string name="title_pref_fake_dns_enabled">Bật DNS ảo (FakeDNS)</string>
<string name="summary_pref_fake_dns_enabled">FakeDNS trả về địa chỉ IP ảo khi phân giải tên miền (nhanh hơn nhưng có thể không hoạt động với một số ứng dụng).</string>
<string name="title_pref_ipv6_enabled">Bật IPv6</string>
<string name="summary_pref_ipv6_enabled">Thêm địa chỉ và tuyến IPv6 vào giao diện VPN</string>
@@ -206,91 +216,102 @@
<string name="title_pref_prefer_ipv6">Ưu tiên IPv6</string>
<string name="summary_pref_prefer_ipv6">Ưu tiên địa chỉ IPv6 khi phân giải tên miền</string>
<string name="title_pref_remote_dns">DNS ngoại quốc (UDP / TCP / HTTPS / QUIC) (Không bắt buộc)</string>
<string name="summary_pref_remote_dns">DNS</string>
<string name="title_pref_remote_dns">DNS từ xa (UDP/TCP/HTTPS/QUIC) (không bắt buộc)</string>
<string name="summary_pref_remote_dns" translatable="false">DNS</string>
<string name="title_pref_vpn_dns">VPN DNS (Chỉ IPv4 / IPv6)</string>
<string name="title_pref_vpn_bypass_lan">Does VPN bypass LAN</string>
<string name="title_pref_vpn_dns">VPN DNS (chỉ IPv4/IPv6)</string>
<string name="title_pref_vpn_bypass_lan">VPN có bỏ qua LAN không</string>
<string name="title_pref_vpn_interface_address">VPN Interface Address</string>
<string name="title_pref_vpn_mtu">VPN MTU (default 1500)</string>
<string name="title_pref_vpn_interface_address">Địa chỉ giao diện VPN</string>
<string name="title_pref_domestic_dns">DNS nội địa (Không bắt buộc)</string>
<string name="summary_pref_domestic_dns">DNS</string>
<string name="title_pref_vpn_mtu">VPN MTU (mặc định 1500)</string>
<string name="title_pref_dns_hosts">DNS hosts (Format: domain:address,…)</string>
<string name="title_pref_domestic_dns">DNS cho kết nối trực tiếp (không bắt buộc)</string>
<string name="summary_pref_domestic_dns" translatable="false">DNS</string>
<string name="title_pref_dns_hosts">Ánh xạ máy chủ DNS (định dạng: domain:address,…)</string>
<string name="summary_pref_dns_hosts">domain:address,…</string>
<string name="title_pref_delay_test_url">URL kiểm tra độ trễ thực </string>
<string name="summary_pref_delay_test_url">URL</string>
<string name="title_pref_real_ping_concurrency">Số luồng kiểm tra độ trễ thực</string>
<string name="title_pref_delay_test_url">URL kiểm tra độ trễ thực</string>
<string name="summary_pref_delay_test_url" translatable="false">URL</string>
<string name="title_pref_real_ping_concurrency">Số lượt kiểm tra độ trễ thực đồng thời</string>
<string name="title_pref_ip_api_url">Current connection info test url</string>
<string name="summary_pref_ip_api_url">Url</string>
<string name="title_pref_ip_api_url">URL kiểm tra thông tin kết nối hiện tại</string>
<string name="summary_pref_ip_api_url" translatable="false">URL</string>
<string name="title_pref_proxy_sharing_enabled">Cho phép kết nối từ mạng LAN</string>
<string name="summary_pref_proxy_sharing_enabled">Các thiết bị khác trong cùng mạng LAN có thể kết nối đến SOCKS / HTTP proxy trên thiết bị của bạn. \nChỉ bật tính năng này trong các mạng đáng tin cậy để tránh kết nối trái phép.</string>
<string name="toast_warning_pref_proxysharing_short">Đang bật cho phép kết nối từ mạng LAN</string>
<string name="summary_pref_proxy_sharing_enabled">Các thiết bị khác có thể kết nối với proxy SOCKS/HTTP trên thiết bị của bạn qua mạng LAN.\nChỉ bật tính năng này trong các mạng đáng tin cậy để tránh kết nối trái phép.</string>
<string name="toast_warning_pref_proxysharing_short">Đã cho phép kết nối từ mạng LAN. Hãy đảm bảo bạn đang dùng mạng đáng tin cậy.</string>
<string name="title_pref_socks_port">Cổng Proxy Local</string>
<string name="title_pref_socks_port">Cổng proxy cục bộ</string>
<string name="title_pref_enable_local_proxy">Bật proxy cục bộ</string>
<string name="summary_pref_enable_local_proxy">When disabled, no SOCKS proxy is available, so subscription updates and similar actions cannot use the proxy</string>
<string name="title_pref_socks_enable_udp">SOCKS5 UDP</string>
<string name="summary_pref_socks_enable_udp">Xác thực socks5 không hoàn toàn an toàn khi sử dụng UDP</string>
<string name="summary_pref_socks_port">Cổng Proxy Local</string>
<string name="title_pref_dynamic_socks_port">Enable dynamic local proxy port</string>
<string name="summary_pref_dynamic_socks_port">Generate a random local proxy port each time the inbound is created</string>
<string name="title_pref_socks_username">Tên người dùng Proxy Local (Không bắt buộc)</string>
<string name="summary_pref_enable_local_proxy">Khi tắt, proxy SOCKS sẽ không khả dụng nên việc cập nhật đăng ký và các thao tác tương tự không thể dùng proxy</string>
<string name="title_pref_socks_enable_udp" translatable="false">SOCKS5 UDP</string>
<string name="summary_pref_socks_enable_udp">Xác thực SOCKS5 không hoàn toàn an toàn khi sử dụng UDP.</string>
<string name="summary_pref_socks_port">Cổng proxy cục bộ</string>
<string name="title_pref_dynamic_socks_port">Bật cổng proxy cục bộ động</string>
<string name="summary_pref_dynamic_socks_port">Tạo một cổng proxy cục bộ ngẫu nhiên mỗi khi inbound được tạo</string>
<string name="title_pref_socks_username">Tên người dùng proxy cục bộ (Không bắt buộc)</string>
<string name="summary_pref_socks_username">Tên người dùng</string>
<string name="title_pref_socks_password">Mật khẩu Proxy Local (Không bắt buộc)</string>
<string name="title_pref_socks_password">Mật khẩu proxy cục bộ (Không bắt buộc)</string>
<string name="summary_pref_socks_password">Mật khẩu</string>
<string name="title_pref_local_dns_port">Cổng Local DNS</string>
<string name="summary_pref_local_dns_port">Cổng Local DNS</string>
<string name="title_pref_local_dns_port">Cổng DNS cục bộ</string>
<string name="summary_pref_local_dns_port">Cổng DNS cục bộ</string>
<string name="title_pref_confirm_remove">Xác nhận xóa tệp cấu hình</string>
<string name="summary_pref_confirm_remove">Yêu cầu xác nhận từ người dùng khi thực hiện xóa tệp cấu hình.</string>
<string name="title_pref_append_http_proxy">Append HTTP Proxy to VPN</string>
<string name="summary_pref_append_http_proxy">HTTP proxy will be used directly from (browser/ some supported apps), without going through the virtual NIC device (Android 10+)</string>
<string name="title_pref_append_http_proxy">Thêm proxy HTTP vào VPN</string>
<string name="summary_pref_append_http_proxy">Proxy HTTP sẽ được trình duyệt hoặc một số ứng dụng hỗ trợ dùng trực tiếp mà không đi qua thiết bị NIC ảo (Android 10+)</string>
<string name="title_pref_double_column_display">Enable double column display</string>
<string name="summary_pref_double_column_display">The profile list is displayed in double columns, allowing more content to be displayed on the screen.</string>
<string name="title_pref_double_column_display">Bật hiển thị hai cột</string>
<string name="summary_pref_double_column_display">Danh sách hồ sơ được hiển thị thành hai cột để màn hình chứa được nhiều nội dung hơn.</string>
<string name="title_pref_group_all_display">Hiển thị thẻ nhóm “Tất cả”</string>
<string name="summary_pref_group_all_display">Gộp cấu hình từ mọi nhóm đăng ký vào một thẻ.</string>
<string name="title_pref_group_all_display">Enable show all groups</string>
<string name="summary_pref_group_all_display">Add an extra "All Tabs" page</string>
<!-- AboutActivity -->
<string name="title_pref_feedback">Phản hồi lỗi</string>
<string name="summary_pref_feedback">Phản hồi cải tiến hoặc lỗi lên GitHub</string>
<string name="summary_pref_tg_group">Tham gia nhóm Telegram</string>
<string name="toast_tg_app_not_found">Không tìm thấy ứng dụng Telegram!</string>
<string name="title_privacy_policy">Chính sách bảo mật</string>
<string name="title_qr_code">Mã QR</string>
<string name="title_about">Giới thiệu</string>
<string name="title_source_code">Mã nguồn</string>
<string name="title_oss_license">Open Source licenses</string>
<string name="title_oss_license">Giấy phép mã nguồn mở</string>
<string name="title_tg_channel">Kênh Telegram</string>
<string name="title_pref_promotion">Quảng bá server</string>
<string name="title_pref_promotion">Ưu đãi</string>
<string name="title_pref_auto_update_subscription">Tự động cập nhật các gói đăng ký</string>
<string name="summary_pref_auto_update_subscription">Tự động cập nhật các gói đăng ký của bạn ở trong nền với khoảng thời gian cố định. Tùy thiết bị, tính năng này có thể không luôn hoạt động đúng như mong đợi.</string>
<string name="title_pref_auto_update_interval">Thời gian cập nhật tự động (Phút, giá trị tối thiểu là 15)</string>
<string name="title_pref_auto_update_interval">Khoảng thời gian cập nhật tự động (phút; tối thiểu 15)</string>
<string name="title_core_loglevel">Cấp độ nhật ký</string>
<string name="title_outbound_domain_resolve_method">Outbound domain pre-resolve method</string>
<string name="title_outbound_domain_resolve_method">Phân giải tên miền cho kết nối đi (outbound)</string>
<string name="title_mode">Chế độ kết nối</string>
<string name="title_mode_help">Nhấn vào đây nếu bạn cần trợ giúp!</string>
<string name="title_language">Ngôn ngữ</string>
<string name="title_ui_settings">Cài đặt UI</string>
<string name="title_pref_ui_mode_night">Cài đặt chế độ UI</string>
<string name="title_pref_use_hev_tunnel">Enable Hev TUN Feature</string>
<string name="summary_pref_use_hev_tunnel">When enabled, TUN will use hev-socks5-tunnel; otherwise, it will use xray-core.</string>
<string name="title_pref_hev_tunnel_loglevel">Hev Tun Log Level</string>
<string name="title_pref_hev_tunnel_rw_timeout">Hev Tun read/write timeout (seconds) (tcp,udp default 300,60)</string>
<string name="title_pref_dynamic_color">Bật màu động</string>
<string name="summary_pref_dynamic_color">Chỉ hoạt động trên Android 12+</string>
<string name="title_pref_use_hev_tunnel">Dùng Hev TUN</string>
<string name="summary_pref_use_hev_tunnel">Khi bật, TUN sẽ dùng hev-socks5-tunnel; nếu không, TUN sẽ dùng xray-core.</string>
<string name="title_pref_hev_tunnel_loglevel">Mức nhật ký Hev TUN</string>
<string name="title_pref_hev_tunnel_rw_timeout">Thời gian chờ đọc/ghi của Hev TUN (giây; mặc định TCP/UDP: 300/60)</string>
<string name="title_mode_settings">Cài đặt chế độ</string>
<string name="title_root_mode_enabled">Bật chế độ Root (dành cho người dùng Root)</string>
<string name="summary_root_mode_enabled">Dùng quyền Root cho proxy trong suốt cấp thấp. Chế độ Root xử lý trực tiếp lưu lượng mạng thay vì dùng dịch vụ VPN của Android. Khi chế độ này bật, chế độ thông thường, định tuyến theo ứng dụng và các cài đặt VPN liên quan sẽ không được áp dụng.</string>
<string name="toast_root_required">Tính năng này yêu cầu quyền truy cập Root</string>
<string name="title_root_lan_sharing">Chia sẻ VPN với thiết bị LAN / chia sẻ kết nối (dành cho người dùng Root)</string>
<string name="summary_root_lan_sharing">Định tuyến lưu lượng từ thiết bị dùng điểm phát Wi-Fi và chia sẻ kết nối USB qua VPN.</string>
<string name="title_logcat">Logcat</string>
<string name="title_logcat" translatable="false">Logcat</string>
<string name="logcat_copy">Sao chép</string>
<string name="logcat_clear">Xoá</string>
<string name="logcat_share">Chia sẻ nhật ký</string>
@@ -298,38 +319,39 @@
<string name="title_del_all_config">Xoá tất cả cấu hình</string>
<string name="title_del_duplicate_config">Xoá cấu hình trùng lặp</string>
<string name="title_del_invalid_config">Xoá cấu hình lỗi</string>
<string name="title_export_all">Xuất và Sao chép tất cả cấu hình</string>
<string name="title_sub_setting">Các gói đăng ký</string>
<string name="title_export_all">Xuất cấu hình vào bảng tạm</string>
<string name="title_sub_setting">Gói đăng ký</string>
<string name="sub_setting_remarks">Tên gói đăng ký</string>
<string name="sub_setting_url">URL gói đăng ký</string>
<string name="sub_setting_user_agent">User Agent</string>
<string name="sub_setting_filter">Remarks regular filter</string>
<string name="sub_setting_enable">Sử dụng gói đăng ký này</string>
<string name="sub_setting_url">URL gói đăng ký (không bắt buộc)</string>
<string name="sub_setting_user_agent" translatable="false">User Agent</string>
<string name="sub_setting_request_headers">Tiêu đề yêu cầu (định dạng JSON)</string>
<string name="sub_setting_filter">Bộ lọc biểu thức chính quy cho tên ghi chú</string>
<string name="sub_setting_enable">Bật cập nhật</string>
<string name="sub_auto_update">Bật tự động cập nhật</string>
<string name="sub_allow_insecure_url">Allow insecure HTTP address</string>
<string name="sub_setting_pre_profile">Previous proxy configuration remarks</string>
<string name="sub_setting_next_profile">Next proxy configuration remarks</string>
<string name="sub_setting_pre_profile_tip">The configuration remarks exists and is unique</string>
<string name="sub_allow_insecure_url">Cho phép địa chỉ HTTP không an toàn</string>
<string name="sub_setting_pre_profile">Proxy đầu vào</string>
<string name="sub_setting_next_profile">Proxy đầu ra</string>
<string name="sub_setting_pre_profile_tip">Tên ghi chú của cấu hình phải tồn tại và là duy nhất</string>
<string name="sub_setting_entry_proxy_tip">Proxy đã chọn được thêm trước mỗi cấu hình trong gói đăng ký, làm mắt xích đầu vào của chuỗi proxy cho cấu hình đó.</string>
<string name="sub_setting_exit_proxy_tip">Proxy đã chọn được thêm sau mỗi cấu hình trong gói đăng ký, làm mắt xích đầu ra của chuỗi proxy cho cấu hình đó.</string>
<string name="toast_invalid_update_interval">Khoảng thời gian cập nhật không hợp lệ. Giá trị tối thiểu là 15 phút.</string>
<string name="title_sub_update">Cập nhật các gói đăng ký</string>
<string name="title_ping_all_server">Ping tất cả máy chủ</string>
<string name="title_real_ping_all_server">Kiểm tra HTTP tất cả máy chủ</string>
<string name="title_user_asset_setting">Asset files</string>
<string name="title_sort_by_test_results">Sắp xếp lại theo lần kiểm tra cuối cùng</string>
<string name="title_filter_config">Lọc cấu hình theo các gói đăng ký</string>
<string name="filter_config_all">All</string>
<string name="title_sub_update">Cập nhật gói đăng ký</string>
<string name="title_ping_all_server">Kiểm tra độ trễ TCP (TCPing)</string>
<string name="title_real_ping_all_server">Kiểm tra độ trễ thực</string>
<string name="title_user_asset_setting">Tệp tài nguyên</string>
<string name="title_sort_by_test_results">Sắp xếp theo kết quả kiểm tra</string>
<string name="title_filter_config">Lọc cấu hình</string>
<string name="filter_config_all">Tất cả</string>
<string name="summary_scan_qrcode">Chạm vào màn hình để mở camera và quét</string>
<string name="title_del_duplicate_config_count">Xoá %d cấu hình trùng lặp</string>
<string name="summary_scan_qrcode">Click screen open the camera scan</string>
<string name="title_del_config_count">Delete %d configurations</string>
<string name="title_import_config_count">Import %d configurations</string>
<string name="title_export_config_count">Export %d configurations</string>
<string name="title_update_config_count">Update %d configurations</string>
<string name="title_update_subscription_result">Updated %1$d configs (%2$d success, %3$d failed, %4$d skipped)</string>
<string name="title_update_subscription_no_subscription">No subscriptions</string>
<string name="toast_server_not_found_in_group">Selected server not found in current group</string>
<string name="toast_fragment_not_available">Unable to locate current view</string>
<string name="title_locate_selected_config">Locate the selected config</string>
<string name="title_del_config_count">Xóa %d cấu hình</string>
<string name="title_import_config_count">Nhập %d cấu hình</string>
<string name="title_export_config_count">Xuất %d cấu hình</string>
<string name="title_update_config_count">Cập nhật %d cấu hình</string>
<string name="title_update_subscription_result">Đã cập nhật %1$d cấu hình (%2$d thành công, %3$d thất bại, %4$d bỏ qua)</string>
<string name="title_update_subscription_no_subscription">Không có đăng ký</string>
<string name="toast_server_not_found_in_group">Không tìm thấy máy chủ đã chọn trong nhóm hiện tại</string>
<string name="title_locate_selected_config">Tìm cấu hình đã chọn</string>
<string name="tasker_start_service">Khởi động v2rayNG</string>
<string name="tasker_setting_confirm">Xác nhận</string>
@@ -337,47 +359,50 @@
<!-- RoutingSettingActivity -->
<string name="routing_settings_domain_strategy">Chiến lược tên miền (DomainStrategy)</string>
<string name="routing_settings_title">Cài đặt định tuyến</string>
<string name="routing_settings_tips">Phân cách bằng dấu phẩy (,). Chọn một trong: domain, ip hoặc process</string>
<string name="routing_settings_tips">Quy tắc chỉ được áp dụng khi tất cả điều kiện đối sánh đã đặt đều được thỏa mãn cùng lúc (AND). Các quy tắc được kiểm tra từ trên xuống; quy tắc khớp đầu tiên sẽ được áp dụng.</string>
<string name="routing_settings_comma_tip">Phân cách nhiều mục bằng dấu phẩy (,).</string>
<string name="routing_settings_save">Lưu lại</string>
<string name="routing_settings_delete">Xoá</string>
<string name="routing_settings_rule_title">Routing Rule Settings</string>
<string name="routing_settings_add_rule">Add rule</string>
<string name="routing_settings_rule_title">Cài đặt quy tắc định tuyến</string>
<string name="routing_settings_add_rule">Thêm quy tắc</string>
<string name="routing_settings_import_predefined_rulesets">Nhập các bộ quy tắc được xác định trước</string>
<string name="routing_settings_import_rulesets_tip">Existing rulesets will be deleted, are you sure to continue?</string>
<string name="routing_settings_import_rulesets_from_clipboard">Import ruleset from clipboard</string>
<string name="routing_settings_import_rulesets_from_qrcode">Nhập bộ quy tắc từ QRcode</string>
<string name="routing_settings_export_rulesets_to_clipboard">Export ruleset to clipboard</string>
<string name="routing_settings_locked">Locked, keep this rule when import presets</string>
<string name="routing_settings_domain">domain</string>
<string name="routing_settings_ip">ip</string>
<string name="routing_settings_process">process (Package Name — only supported when using Xray TUN, routeOnly enabled, and Android 10+)</string>
<string name="routing_settings_port">port</string>
<string name="routing_settings_protocol">protocol</string>
<string name="routing_settings_protocol_tip">[http,tls,bittorrent]</string>
<string name="routing_settings_network">network</string>
<string name="routing_settings_outbound_tag">outboundTag</string>
<string name="routing_settings_import_rulesets_tip">Các bộ quy tắc hiện có sẽ bị xóa. Bạn có chắc muốn tiếp tục không?</string>
<string name="routing_settings_import_rulesets_from_clipboard">Nhập bộ quy tắc từ bảng tạm</string>
<string name="routing_settings_import_rulesets_from_qrcode">Nhập bộ quy tắc từ mã QR</string>
<string name="routing_settings_export_rulesets_to_clipboard">Xuất bộ quy tắc vào bảng tạm</string>
<string name="routing_settings_locked">Đã khóa; giữ quy tắc này khi nhập cài đặt sẵn</string>
<string name="routing_settings_domain" translatable="false">domain</string>
<string name="routing_settings_ip" translatable="false">ip</string>
<string name="routing_settings_process">process (tên gói — chỉ được hỗ trợ khi dùng Xray TUN, bật routeOnly và chạy Android 10+)</string>
<string name="routing_settings_process_select">Chọn tên gói</string>
<string name="routing_settings_port" translatable="false">port</string>
<string name="routing_settings_protocol" translatable="false">protocol</string>
<string name="routing_settings_protocol_tip" translatable="false">[http,tls,bittorrent]</string>
<string name="routing_settings_network" translatable="false">network</string>
<string name="routing_settings_outbound_tag_hint">proxy / direct / block / &lt;%1$s&gt;</string>
<string name="routing_settings_outbound_tag" translatable="false">outboundTag</string>
<string name="connection_test_pending">Kiểm tra kết nối</string>
<string name="connection_test_testing">Đang kiểm tra kết nối mạng...</string>
<string name="connection_test_testing_count">Testing %d configurations…</string>
<string name="connection_test_available">Kiểm tra thành công: thời gian truy cập Google là %d ms</string>
<string name="connection_test_error">Lỗi kết nối mạng, hãy thử đổi cấu hình hoặc kiểm tra lại! Mã lỗi: %s</string>
<string name="connection_test_fail">Không có kết nối mạng!</string>
<string name="connection_test_testing">Đang kiểm tra kết nối mạng…</string>
<string name="connection_test_testing_count">Đang kiểm tra %d cấu hình…</string>
<string name="connection_test_available">Kết nối thành công sau %1$s</string>
<string name="server_test_delay_value">%1$d mili giây</string>
<string name="connection_test_error">Kiểm tra kết nối thất bại: %s</string>
<string name="connection_test_fail">Không thể truy cập Internet</string>
<string name="connection_test_error_status_code">Mã lỗi: #%d</string>
<string name="connection_connected">Đã kết nối, nhấn để kiểm tra kết nối mạng!</string>
<string name="connection_connected">Đã kết nối.\nNhấn để kiểm tra kết nối.</string>
<string name="connection_not_connected">Chưa kết nối</string>
<string name="connection_runing_task_left">Number of running test tasks: %s</string>
<string name="connection_running_task_left">Số lượt kiểm tra đang chạy: %s</string>
<string name="import_subscription_success">Nhập gói đăng ký thành công!</string>
<string name="import_subscription_failure">Nhập gói đăng ký không thành công!</string>
<string name="title_fragment_settings">Fragment Settings</string>
<string name="title_pref_fragment_packets">Fragment Packets</string>
<string name="title_pref_fragment_length">Fragment Length (min-max)</string>
<string name="title_pref_fragment_interval">Fragment Interval (min-max)</string>
<string name="title_pref_fragment_enabled">Enable Fragment</string>
<string name="title_pref_fragment_maxsplit">Fragment Max Split</string>
<string name="title_observatory_settings">Cài đặt giám sát kết nối</string>
<string name="title_fragment_settings">Cài đặt phân mảnh (Fragment)</string>
<string name="title_pref_fragment_packets">Gói tin cần phân mảnh</string>
<string name="title_pref_fragment_length">Độ dài phân mảnh (tối thiểu-tối đa)</string>
<string name="title_pref_fragment_interval">Khoảng phân mảnh (tối thiểu-tối đa)</string>
<string name="title_pref_fragment_enabled">Bật phân mảnh</string>
<string name="title_pref_fragment_maxsplit">Số lần chia nhỏ tối đa</string>
<string name="title_observatory_settings">Cài đặt giám sát kết nối (Observatory)</string>
<string name="title_pref_observatory_least_ping_interval">Khoảng thời gian leastPing</string>
<string name="title_pref_observatory_least_load_interval">Khoảng thời gian leastLoad</string>
<string name="title_pref_observatory_least_load_method">Phương thức HTTP leastLoad</string>
@@ -386,82 +411,133 @@
<string name="toast_invalid_observatory_duration">Khoảng thời gian không hợp lệ. Dùng giá trị như 3m hoặc 30s.</string>
<string name="toast_invalid_observatory_sampling">Lấy mẫu không hợp lệ. Dùng một số dương.</string>
<string name="update_check_for_update">Check for update</string>
<string name="update_already_latest_version">Already on the latest version</string>
<string name="update_new_version_found">New version found: %s</string>
<string name="update_now">Update now</string>
<string name="update_check_pre_release">Check Pre-release</string>
<string name="update_checking_for_update">Checking for update…</string>
<string name="update_check_for_update">Kiểm tra bản cập nhật</string>
<string name="update_already_latest_version">Đã dùng phiên bản mới nhất</string>
<string name="update_new_version_found">Đã tìm thấy phiên bản mới: %s</string>
<string name="update_now">Cập nhật ngay</string>
<string name="update_check_pre_release">Kiểm tra bản phát hành thử</string>
<string name="update_checking_for_update">Đang kiểm tra bản cập nhật…</string>
<string name="title_policy_group_type">Policy group type</string>
<string name="title_policy_group_subscription_id">From subscription group</string>
<string name="title_policy_group_subscription_filter">Remarks regular filter</string>
<string name="title_policy_group_test_outbounds">Kiểm tra outbound</string>
<string name="title_policy_group_fallback">Outbound dự phòng (tùy chọn)</string>
<string name="server_proxy_chain_members">Proxy chain members</string>
<string name="server_proxy_chain_pick_members">Tap here to pick member</string>
<string name="server_proxy_chain_member_unselected">Select a member</string>
<string name="server_proxy_chain_members_unselected">Please select member for each chain row</string>
<string name="server_proxy_chain_members_insufficient">Insufficient members</string>
<string name="server_proxy_chain_members_invalid">Invalid chain members: %1$s</string>
<string name="title_policy_group_type">Loại nhóm chính sách</string>
<string name="title_policy_group_subscription_id">Từ nhóm đăng ký</string>
<string name="title_policy_group_subscription_filter">Bộ lọc biểu thức chính quy cho tên ghi chú</string>
<string name="title_policy_group_test_outbounds">Kiểm tra các kết nối đi (outbounds)</string>
<string name="title_policy_group_fallback">Kết nối dự phòng (outbound, tùy chọn)</string>
<string name="server_proxy_chain_members">Thành viên chuỗi proxy</string>
<string name="server_proxy_chain_pick_members">Chạm vào đây để chọn thành viên</string>
<string name="server_proxy_chain_member_unselected">Chọn một thành viên</string>
<string name="server_proxy_chain_members_unselected">Vui lòng chọn thành viên cho từng hàng trong chuỗi</string>
<string name="server_proxy_chain_members_insufficient">Không đủ thành viên</string>
<string name="server_proxy_chain_members_invalid">Thành viên chuỗi không hợp lệ: %1$s</string>
<!-- BackupActivity -->
<string name="title_configuration_backup_restore">Backup &amp; Restore</string>
<string name="title_configuration_backup_restore">Sao lưu &amp; khôi phục</string>
<string name="title_configuration_backup">Sao lưu cấu hình</string>
<string name="title_configuration_restore">Khôi phục cấu hình</string>
<string name="title_configuration_share">Chia sẻ cấu hình</string>
<string name="title_webdav_config_setting">WebDAV Settings</string>
<string name="title_webdav_config_setting_unknown">Please configure WebDAV first.</string>
<string name="title_webdav_url">WebDAV server URL</string>
<string name="title_webdav_user">Username</string>
<string name="title_webdav_pass">Password</string>
<string name="title_webdav_remote_path">Remote directory (optional)</string>
<string name="title_webdav_config_setting">Cài đặt WebDAV</string>
<string name="title_webdav_config_setting_unknown">Vui lòng cấu hình WebDAV trước.</string>
<string name="title_webdav_url">URL máy chủ WebDAV</string>
<string name="title_webdav_user">Tên người dùng</string>
<string name="title_webdav_pass">Mật khẩu</string>
<string name="title_webdav_remote_path">Thư mục từ xa (không bắt buộc)</string>
<string name="share_method_qrcode">Xuất ra mã QR (Chụp màn hình để lưu)</string>
<string name="share_method_clipboard">Sao chép vào Clipboard</string>
<string name="share_method_full_content">Sao chép thành cấu hình tùy chỉnh</string>
<string name="share_method_qrcode">Mã QR</string>
<string name="share_method_clipboard">Sao chép liên kết cấu hình</string>
<string name="share_method_full_content">Sao chép toàn bộ cấu hình</string>
<string name="action_edit">Chỉnh sửa</string>
<string name="action_delete">Xoá</string>
<string name="action_close">Đóng</string>
<string-array name="share_sub_method">
<item>Xuất gói ra mã QR (Chụp màn hình để lưu)</item>
<item>Xuất gói vào Clipboard</item>
</string-array>
<string name="share_subscription_qrcode">Xuất gói ra mã QR (Chụp màn hình để lưu)</string>
<string name="share_subscription_clipboard">Xuất gói vào bảng tạm</string>
<string-array name="mode_entries">
<item>Chế độ VPN</item>
<item>Chế độ Proxy</item>
</string-array>
<string name="menu_item_add_asset">Thêm vào</string>
<string name="menu_item_add_url">Thêm liên kết</string>
<string-array name="browser_dialer_mode">
<item>Tắt</item>
<item>OkHttp</item>
<item>WebView</item>
</string-array>
<string-array name="ui_mode_night">
<item>Theo hệ thống</item>
<item>Sáng</item>
<item>Tối</item>
</string-array>
<string name="routing_preset_china_whitelist">Danh sách trắng Trung Quốc</string>
<string name="routing_preset_china_blacklist">Danh sách đen Trung Quốc</string>
<string name="routing_preset_global">Toàn cầu</string>
<string name="routing_preset_iran_whitelist">Danh sách trắng Iran</string>
<string name="routing_preset_russia_whitelist">Danh sách trắng Nga</string>
<string-array name="vpn_bypass_lan">
<item>Follow config</item>
<item>Bypass</item>
<item>Not Bypass</item>
<item>Theo cấu hình</item>
<item>Bỏ qua</item>
<item>Không bỏ qua</item>
</string-array>
<string-array name="outbound_domain_resolve_method">
<item>Do not resolve</item>
<item>Resolve and add to DNS Hosts</item>
<item>Resolve and replace domain</item>
</string-array>
<string-array name="policy_group_type">
<item>Least Ping</item>
<item>Least Load</item>
<item>Random</item>
<item>Round Robin</item>
<item>Không phân giải</item>
<item>Phân giải và thêm vào DNS Hosts</item>
<item>Phân giải và thay thế tên miền</item>
</string-array>
<string-array name="config_backup_options">
<item>Local</item>
<item>WebDAV</item>
<string-array name="policy_group_type">
<item>Ping thấp nhất (leastPing)</item>
<item>Tải thấp nhất (leastLoad)</item>
<item>Ngẫu nhiên (random)</item>
<item>Luân phiên (roundRobin)</item>
</string-array>
<string name="backup_location_local">Cục bộ</string>
<string name="backup_location_webdav" translatable="false">WebDAV</string>
<string name="acc_refresh">Làm mới nhật ký</string>
<string name="toast_permission_denied_for">Chưa cấp quyền: %1$s</string>
<string name="acc_add_subscription">Thêm gói đăng ký</string>
<string name="toast_malformed_json_detail">Cấu hình không hợp lệ: %1$s</string>
<string name="acc_add_asset">Thêm nguồn tệp tài nguyên</string>
<string name="acc_download_file">Tải xuống tệp tài nguyên</string>
<string name="acc_qr_code">Mã QR</string>
<string name="acc_copy_log">Sao chép nhật ký</string>
<string name="acc_clear_log">Xóa nhật ký</string>
<string name="acc_add_rule">Thêm quy tắc định tuyến</string>
<string name="acc_start">Khởi động dịch vụ</string>
<string name="acc_stop">Dừng dịch vụ</string>
<string name="acc_back">Quay lại</string>
<string name="acc_search">Tìm kiếm</string>
<string name="acc_add">Thêm cấu hình</string>
<string name="acc_more">Tùy chọn khác</string>
<string name="acc_share_subscription">Chia sẻ liên kết đăng ký</string>
<string name="acc_share_log">Chia sẻ nhật ký</string>
<string name="acc_remove">Xóa thành viên khỏi chuỗi proxy</string>
<string name="acc_add_member">Thêm thành viên vào chuỗi proxy</string>
<string name="acc_start_scanner">Khởi động trình quét mã QR</string>
<string name="acc_stop_scanner">Dừng trình quét mã QR</string>
<string name="acc_turn_torch_on">Bật đèn pin</string>
<string name="acc_turn_torch_off">Tắt đèn pin</string>
<string name="acc_select_image">Chọn ảnh để quét</string>
<string name="acc_locked">Giữ quy tắc khi nhập cài đặt sẵn</string>
<string name="acc_open_menu">Mở trình đơn điều hướng</string>
<string name="acc_edit">Chỉnh sửa</string>
<string name="acc_delete">Xóa</string>
<string name="acc_save">Lưu</string>
<string name="acc_update_subscriptions">Cập nhật các gói đăng ký</string>
<string name="acc_per_app_proxy_information">Thông tin proxy theo ứng dụng</string>
<string name="permission_camera">Máy ảnh</string>
<string name="permission_notification">Thông báo</string>
<string name="permission_local_network">Mạng cục bộ</string>
<string name="subscription_update_updating">Đang cập nhật gói đăng ký: %1$s</string>
<string name="subscription_update_progress">Đang kiểm tra %2$s: %1$s</string>
<string name="tasker_blurb_start">Khởi động %1$s</string>
<string name="tasker_blurb_stop">Dừng %1$s</string>
<string name="connection_test_empty_message">không có thông tin chi tiết</string>
<string name="value_unknown">không xác định</string>
</resources>
+186 -131
View File
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" translatable="false">v2rayNG</string>
<string name="app_widget_name">开关</string>
<string name="app_tile_name">开关</string>
<string name="app_tile_first_use">初次使用此功能请先用 APP 添加配置</string>
@@ -7,6 +8,8 @@
<string name="navigation_drawer_close">关闭导航栏</string>
<string name="migration_success">数据迁移成功!</string>
<string name="action_stop_service">停止服务</string>
<string name="action_ok">确定</string>
<string name="action_cancel">取消</string>
<string name="migration_fail">数据迁移失败啦!</string>
<string name="pull_down_to_refresh">请下拉刷新!</string>
@@ -37,7 +40,7 @@
<string name="menu_item_import_config_manually_socks">添加 [SOCKS]</string>
<string name="menu_item_import_config_manually_http">添加 [HTTP]</string>
<string name="menu_item_import_config_manually_trojan">添加 [Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">添加 [Wireguard]</string>
<string name="menu_item_import_config_manually_wireguard">添加 [WireGuard]</string>
<string name="menu_item_import_config_manually_hysteria2">添加 [Hysteria2]</string>
<string name="confirm_delete_visible_profiles">确定要删除当前显示的所有配置吗?</string>
<string name="confirm_delete_duplicate_profiles">确定要删除当前显示的所有重复配置吗?</string>
@@ -75,11 +78,11 @@
<string name="server_lab_path_quic">QUIC 加密密钥</string>
<string name="server_lab_path_kcp">kcp seed</string>
<string name="server_lab_path_grpc">gRPC serviceName</string>
<string name="server_lab_stream_security">传输层安全 (TLS)</string>
<string name="server_lab_stream_security" translatable="false">TLS</string>
<string name="server_lab_stream_fingerprint">Fingerprint</string>
<string name="server_lab_stream_alpn">Alpn</string>
<string name="server_lab_stream_alpn" translatable="false">ALPN</string>
<string name="server_lab_allow_insecure">跳过证书验证 (allowInsecure)</string>
<string name="server_lab_sni">SNI</string>
<string name="server_lab_sni" translatable="false">SNI</string>
<string name="server_lab_address3">服务器地址</string>
<string name="server_lab_port3">服务器端口</string>
<string name="server_lab_id3">密码</string>
@@ -89,16 +92,16 @@
<string name="server_lab_encryption">加密方式 (encryption)</string>
<string name="server_lab_flow">流控 (flow)</string>
<string name="server_lab_public_key">PublicKey</string>
<string name="server_lab_preshared_key">PreSharedKey (optional)</string>
<string name="server_lab_preshared_key">PreSharedKey(可选)</string>
<string name="server_lab_short_id">ShortId</string>
<string name="server_lab_spider_x">SpiderX</string>
<string name="server_lab_mldsa65_verify">Mldsa65Verify</string>
<string name="server_lab_spider_x" translatable="false">SpiderX</string>
<string name="server_lab_mldsa65_verify" translatable="false">mldsa65Verify</string>
<string name="server_lab_secret_key">SecretKey</string>
<string name="server_lab_reserved">Reserved (可选,逗号隔开)</string>
<string name="server_lab_local_address">本地地址 (可选 IPv4/IPv6,逗号隔开)</string>
<string name="server_lab_local_mtu">Mtu (可选, 默认 1420)</string>
<string name="server_lab_kcp_mtu">mKCP MTU (可选, 默认 1350)</string>
<string name="server_lab_kcp_tti">mKCP TTI (可选, 默认 50)</string>
<string name="server_lab_local_mtu">MTU(可选,默认 1420)</string>
<string name="server_lab_kcp_mtu">mKCP MTU(可选,核心默认 1350)</string>
<string name="server_lab_kcp_tti">mKCP TTI(可选,核心默认 50)</string>
<string name="toast_success">成功</string>
<string name="toast_failure">失败</string>
<string name="toast_none_data">没有数据</string>
@@ -112,8 +115,8 @@
<string name="toast_none_data_clipboard">剪贴板中没有数据</string>
<string name="toast_invalid_url">无效的网址</string>
<string name="toast_insecure_url_protocol">请不要使用不安全的 HTTP 协议订阅地址</string>
<string name="server_lab_need_inbound">确保 inbounds port 和设置中的一致</string>
<string name="toast_malformed_josn">配置格式错误</string>
<string name="server_lab_need_inbound">确保入站端口与设置一致</string>
<string name="toast_malformed_json">配置格式无效。</string>
<string name="server_lab_request_host6">Host (SNI) (可选)</string>
<string name="toast_action_not_allowed">禁止此项操作</string>
<string name="server_obfs_password">混淆密码</string>
@@ -124,25 +127,27 @@
<string name="server_lab_xhttp_mode">XHTTP 模式</string>
<string name="server_lab_xhttp_extra">XHTTP Extra 原始 JSON,格式: { XHTTPObject }</string>
<string name="server_lab_final_mask">FinalMask 原始 JSON 格式: { FinalMaskObject }</string>
<string name="server_lab_ech_config_list">EchConfigList</string>
<string name="server_lab_verify_peer_cert_by_name">Verify Peer Cert By Name</string>
<string name="server_lab_ech_config_list" translatable="false">echConfigList</string>
<string name="server_lab_verify_peer_cert_by_name">按名称验证对端证书</string>
<string name="server_lab_pinned_ca256">证书指纹 (SHA-256)</string>
<string name="server_lab_browser_dialer">启用浏览器转发</string>
<string name="server_lab_browser_dialer_tip">仅支持 xhttp (packet-up) 和 ws。与优选域名冲突,utls, alpn, ech 等 TLS 设置将被忽略</string>
<string name="toast_allow_insecure_deprecated">当前节点使用未加密连接,您的通信可能会被威权政府掌控的网络中间设施直接查看\n为了安全,此类节点无法通过 26.2.6+ 版本的 Xray 核心连接\n如果是自建节点请启用 TLS 等安全加密,或固定证书 pinnedCA256\n如果机场节点请联系服务商完成技术升级,如服务商拒绝配合,建议更换更重视用户安全的服务商\n更多的信息,请访问 https://github.com/2dust/v2rayN/discussions/9460</string>
<string name="pinned_ca256_action_fetch">获取并填充指纹证书</string>
<string name="toast_fetch_cert_sha256_success">获取指纹证书完成</string>
<string name="server_lab_browser_dialer">启用 Browser Dialer</string>
<string name="server_lab_browser_dialer_tip">仅支持 xhttp(packet-up)和 ws 出站;TLS 相关设置可能会被忽略或产生冲突</string>
<string name="toast_allow_insecure_deprecated">当前节点使用未加密连接,您的通信可能被威权政府控制的网络中间设施直接查看。\n出于安全考虑,此类节点无法使用 26.2.6+ 版本的 Xray 核心连接。\n如为自建节点,请启用 TLS 等安全加密,或固定证书 pinnedCA256。\n如节点由服务商提供,请联系服务商完成技术升级。若服务商拒绝配合,建议改用更重视用户安全的服务商。\n更多信息请访问 https://github.com/2dust/v2rayN/discussions/9460</string>
<string name="pinned_ca256_action_fetch">获取证书指纹</string>
<string name="toast_fetch_cert_sha256_success">证书指纹获取成功</string>
<string name="toast_fetch_cert_sha256_failed">获取证书指纹失败</string>
<!-- UserAssetActivity -->
<string name="toast_asset_copy_failed">失败, 请使用文件管理器</string>
<string name="toast_asset_copy_failed">文件复制失败,请使用文件管理器</string>
<string name="menu_item_add_asset">添加资源</string>
<string name="menu_item_add_file">添加文件</string>
<string name="menu_item_scan_qrcode">扫描 QRcode</string>
<string name="title_url">URL</string>
<string name="menu_item_add_url">添加 URL</string>
<string name="menu_item_scan_qrcode">扫描二维码</string>
<string name="title_url" translatable="false">URL</string>
<string name="menu_item_download_file">下载文件</string>
<string name="title_user_asset_add_url">添加资产网址</string>
<string name="msg_file_not_found">文件未找到</string>
<string name="msg_remark_is_duplicate">备注已经存在</string>
<string name="title_user_asset_add_url">添加资源 URL</string>
<string name="msg_file_not_found">未找到文件</string>
<string name="msg_remark_is_duplicate">名称已存在</string>
<string name="asset_geo_files_sources">Geo 文件来源 (可选)</string>
<!-- PerAppProxyActivity -->
@@ -158,17 +163,19 @@
<string name="menu_item_import_proxy_app">从剪贴板导入</string>
<string name="per_app_proxy_settings">分应用设置</string>
<string name="per_app_proxy_settings_enable">启用分应用</string>
<string name="app_picker_unknown_app">未知应用(无法识别 UID)</string>
<!-- Preferences -->
<string name="title_settings">设置</string>
<string name="title_advanced">进阶设置</string>
<string name="title_core_settings">核心设置</string>
<string name="title_vpn_settings">VPN 设置</string>
<string name="title_pref_per_app_proxy">分应用</string>
<string name="summary_pref_per_app_proxy">常规: 勾选的 App 被代理, 未勾选的直连;\n绕行模式: 勾选的 App 直连, 未勾选的被代理.\n不明白者在菜单中选择自动选中需代理应用</string>
<string name="title_pref_per_app_proxy">分应用代理</string>
<string name="summary_pref_per_app_proxy">常规:勾选的应用使用代理,未勾选的应用直连;\n绕行模式:勾选的应用直连,未勾选的应用使用代理。\n菜单中可自动选择需要使用代理的应用。</string>
<string name="title_pref_is_booted">开机时自动连接</string>
<string name="summary_pref_is_booted">开机时自动连接选择的服务器,可能会不成功</string>
<string name="subscription_updater_job_tips">任务将在后台运行,在通知中会显示进度信息</string>
<string name="title_pref_auto_test_after_update_subscription">更新订阅后自动测试</string>
<string name="summary_pref_auto_test_after_update_subscription">自动测试需要比较长的时间,开启后任务将在后台运行;不开启则在当前页面运行</string>
@@ -177,31 +184,31 @@
<string name="title_pref_auto_sort_after_test">测试后自动排序</string>
<string name="summary_pref_auto_sort_after_test">测试结果可能不准确</string>
<string name="title_mux_settings">Mux 多路复用 设置</string>
<string name="title_mux_settings">Mux 多路复用设置</string>
<string name="title_pref_mux_enabled">启用 Mux 多路复用</string>
<string name="summary_pref_mux_enabled">减低延时,但可能会断流,建议不要启用。\nTCP,UDP 及 QUIC 流量处理方式下方可选。</string>
<string name="title_pref_mux_concurency">TCP 复用子链接数(可填 -1 至 1024)</string>
<string name="title_pref_mux_xudp_concurency">XUDP 复用子链接数(可填 -1 至 1024)</string>
<string name="summary_pref_mux_enabled">速度更快,但可能导致连接不稳定。\n可在下方自定义 TCP、UDP 和 QUIC 的处理方式。</string>
<string name="title_pref_mux_concurrency">TCP 复用子连接数(可填 -1 至 1024)</string>
<string name="title_pref_mux_xudp_concurrency">XUDP 复用子连接数(可填 -1 至 1024)</string>
<string name="title_pref_mux_xudp_quic">QUIC 流量处理方式</string>
<string-array name="mux_xudp_quic_entries">
<item>不代理</item>
<item>多路复用</item>
<item>原生</item>
<item>拒绝</item>
<item>允许</item>
<item>跳过</item>
</string-array>
<string name="title_pref_speed_enabled">启用速度显示</string>
<string name="summary_pref_speed_enabled">在通知中显示当前速度\n小图标显示流量的路由情况</string>
<string name="summary_pref_speed_enabled">在通知中显示当前速度。\n图标指示代理流量或直连流量哪一方占主导。</string>
<string name="title_pref_sniffing_enabled">启用流量探测</string>
<string name="summary_pref_sniffing_enabled">从流量中探测域名 (默认启用)</string>
<string name="title_pref_sniffing_enabled">启用流量探测 (Sniffing)</string>
<string name="summary_pref_sniffing_enabled">从流量中探测目标域名(默认启用)。</string>
<string name="title_pref_route_only_enabled">启用 routeOnly</string>
<string name="summary_pref_route_only_enabled">将嗅探得到的域名仅用于路由,代理目标地址仍为 IP</string>
<string name="title_pref_local_dns_enabled">启用本地 DNS</string>
<string name="summary_pref_local_dns_enabled">DNS 请求导入 core 由 DNS 模块处理(推荐启用 如果需要路由绕过局域网及大陆地址)</string>
<string name="summary_pref_local_dns_enabled">DNS 由核心的 DNS 模块处理(需要绕过局域网和中国大陆地址的路由时建议启用)。</string>
<string name="title_pref_fake_dns_enabled">启用虚拟 DNS</string>
<string name="summary_pref_fake_dns_enabled">本地返回虚构解析结果 (减低延时 但个别应用可能无法使用)</string>
<string name="title_pref_fake_dns_enabled">启用伪造 DNS (FakeDNS)</string>
<string name="summary_pref_fake_dns_enabled">FakeDNS 在解析域名时返回虚构的 IP 地址(速度更快,但可能不适用于某些应用)。</string>
<string name="title_pref_ipv6_enabled">启用 IPv6</string>
<string name="summary_pref_ipv6_enabled">为 VPN 接口添加 IPv6 地址和路由</string>
@@ -209,27 +216,29 @@
<string name="title_pref_prefer_ipv6">IPv6 优先</string>
<string name="summary_pref_prefer_ipv6">解析域名时优先使用 IPv6 地址</string>
<string name="title_pref_remote_dns">远程 DNS (udp/tcp/https/quic)(可选)</string>
<string name="summary_pref_remote_dns">DNS</string>
<string name="title_pref_remote_dns">远程 DNS(UDP/TCP/HTTPS/QUIC,可选)</string>
<string name="summary_pref_remote_dns" translatable="false">DNS</string>
<string name="title_pref_vpn_dns">VPN DNS (仅支持 IPv4/v6)</string>
<string name="title_pref_vpn_dns">VPN DNS(仅支持 IPv4/IPv6)</string>
<string name="title_pref_vpn_bypass_lan">VPN 是否绕过局域网</string>
<string name="title_pref_vpn_interface_address">VPN 接口地址</string>
<string name="title_pref_vpn_mtu">VPN MTU (默认 1500)</string>
<string name="title_pref_domestic_dns">境内 DNS (可选)</string>
<string name="summary_pref_domestic_dns">DNS</string>
<string name="title_pref_dns_hosts">DNS hosts (格式: 域名: 地址,…)</string>
<string name="title_pref_domestic_dns">直连 DNS(可选)</string>
<string name="summary_pref_domestic_dns" translatable="false">DNS</string>
<string name="title_pref_dns_hosts">DNS 主机映射(格式:domain:address,…)</string>
<string name="summary_pref_dns_hosts">domain: address,…</string>
<string name="title_pref_delay_test_url">真连接延迟测试网址 </string>
<string name="summary_pref_delay_test_url">Url</string>
<string name="title_pref_real_ping_concurrency">真连接延迟测试并发数量</string>
<string name="title_pref_delay_test_url">真实延迟测试 URL</string>
<string name="summary_pref_delay_test_url" translatable="false">URL</string>
<string name="title_pref_real_ping_concurrency">真连接延迟并发测试数</string>
<string name="title_pref_ip_api_url">当前连接信息测试网址</string>
<string name="summary_pref_ip_api_url">URL</string>
<string name="summary_pref_ip_api_url" translatable="false">URL</string>
<string name="title_pref_proxy_sharing_enabled">允许来自局域网的连接</string>
<string name="summary_pref_proxy_sharing_enabled">其他设备可以使用 socks/http 协议通过您的 IP 地址连接到代理, 仅在受信任的网络中启用以避免未经授权的连接</string>
@@ -238,42 +247,42 @@
<string name="title_pref_socks_port">本地代理端口</string>
<string name="title_pref_enable_local_proxy">启用本地代理</string>
<string name="summary_pref_enable_local_proxy">不开启时没有 socks 代理,无法通过代理更新订阅等</string>
<string name="title_pref_socks_enable_udp">SOCKS5 UDP</string>
<string name="summary_pref_socks_enable_udp">使用 UDP 时,socks5 认证并不完全安全</string>
<string name="summary_pref_socks_port">本地代理端口</string>
<string name="title_pref_dynamic_socks_port">启用动态本地代理端口</string>
<string name="summary_pref_dynamic_socks_port">每次生成 inbound 时随机生成一个本地代理端口</string>
<string name="title_pref_socks_username">本地代理用户名 (可选)</string>
<string name="summary_pref_socks_username">用户名</string>
<string name="title_pref_socks_password">本地代理密码 (可选)</string>
<string name="summary_pref_socks_password">密码</string>
<string name="title_pref_socks_enable_udp" translatable="false">SOCKS5 UDP</string>
<string name="summary_pref_socks_enable_udp">使用 UDP 时,SOCKS5 认证并不完全安全。</string>
<string name="summary_pref_socks_port">本地代理端口</string>
<string name="title_pref_dynamic_socks_port">启用动态本地代理端口</string>
<string name="summary_pref_dynamic_socks_port">为每个 inbound 使用随机的本地代理端口</string>
<string name="title_pref_socks_username">本地代理用户名(可选)</string>
<string name="summary_pref_socks_username">用户名</string>
<string name="title_pref_socks_password">本地代理密码(可选)</string>
<string name="summary_pref_socks_password">密码</string>
<string name="title_pref_local_dns_port">本地 DNS 端口</string>
<string name="title_pref_local_dns_port">本地 DNS 端口</string>
<string name="summary_pref_local_dns_port">本地 DNS 端口</string>
<string name="title_pref_confirm_remove">删除配置确认</string>
<string name="summary_pref_confirm_remove">删除配置是否需要用户二次确认</string>
<string name="title_pref_append_http_proxy">追加 HTTP 代理至 VPN</string>
<string name="summary_pref_append_http_proxy">浏览器 / 一些支持的应用 将直接使用 HTTP 代理, 而不经过虚拟网卡设备 (Android 10+)</string>
<string name="title_pref_append_http_proxy">将 HTTP 代理添加到 VPN</string>
<string name="summary_pref_append_http_proxy">浏览器和部分受支持的应用将直接使用 HTTP 代理,而不经过虚拟网卡(Android 10+)。</string>
<string name="title_pref_double_column_display">启用双列显示</string>
<string name="summary_pref_double_column_display">配置列表以双列显示,允许在屏幕上显示更多内容。</string>
<string name="title_pref_group_all_display">启用显示所有组</string>
<string name="summary_pref_group_all_display">添加一个额外的“所有选项卡”页面</string>
<string name="title_pref_group_all_display">显示“全部”组标签页</string>
<string name="summary_pref_group_all_display">在一个标签页中汇总所有订阅组的配置。</string>
<!-- AboutActivity -->
<string name="title_pref_feedback">反馈</string>
<string name="summary_pref_feedback">反馈改进或漏洞至 GitHub</string>
<string name="summary_pref_tg_group">加入 Telegram Group</string>
<string name="toast_tg_app_not_found">未找到 Telegram app</string>
<string name="summary_pref_feedback">前往 GitHub 提出改进建议或报告问题</string>
<string name="summary_pref_tg_group">加入 Telegram 群组</string>
<string name="toast_tg_app_not_found">未找到 Telegram 应用</string>
<string name="title_privacy_policy">隐私权政策</string>
<string name="title_qr_code">二维码</string>
<string name="title_about">关于</string>
<string name="title_source_code">源代码</string>
<string name="title_oss_license">Open Source licenses</string>
<string name="title_oss_license">开源许可证</string>
<string name="title_tg_channel">Telegram 频道</string>
<string name="title_pref_promotion">推广</string>
@@ -283,25 +292,26 @@
<string name="title_pref_auto_update_interval">自动更新间隔(分钟,最小值 15)</string>
<string name="title_core_loglevel">日志级别</string>
<string name="title_outbound_domain_resolve_method">Outbound 域名预解析方式</string>
<string name="title_outbound_domain_resolve_method">出站域名预解析方式 (outbound)</string>
<string name="title_mode">模式</string>
<string name="title_mode_help">点此查看更多帮助</string>
<string name="title_language">语言</string>
<string name="title_ui_settings">用户界面设置</string>
<string name="title_pref_ui_mode_night">深色模式</string>
<string name="title_pref_dynamic_color">开启莫奈取色</string>
<string name="summary_pref_dynamic_color">仅在 Android 12+ 设备上工作</string>
<string name="title_pref_use_hev_tunnel">启用 Hev TUN 功能</string>
<string name="summary_pref_use_hev_tunnel">选择启用后 TUN 将使用 hev-socks5-tunnel 否则使用 xray-core</string>
<string name="title_pref_hev_tunnel_loglevel">HevTun 日志级别</string>
<string name="title_pref_hev_tunnel_rw_timeout">HevTun 读写超时(秒) (tcp,udp 默认 300,60)</string>
<string name="title_pref_hev_tunnel_loglevel">Hev TUN 日志级别</string>
<string name="title_pref_hev_tunnel_rw_timeout">Hev TUN 读写超时(秒;TCP/UDP 默认值:300/60)</string>
<string name="title_mode_settings">模式设置</string>
<string name="title_root_mode_enabled">启用 Root 模式 (仅限 Root 用户)</string>
<string name="summary_root_mode_enabled">通过 Root 权限启用底层透明代理。此模式将不再通过 Android 常规系统 VPN 建立连接,而是直接接管系统底层所有网络流量。开启后,原有的常规模式、应用分流及相关 VPN 设置将直接失效。</string>
<string name="summary_root_mode_enabled">使用 Root 权限实现底层透明代理。Root 模式不使用 Android 的 VPN 服务,而是直接处理网络流量。启用期间,常规模式、应用分流及相关 VPN 设置不会生效。</string>
<string name="toast_root_required">此功能需要 Root 权限</string>
<string name="title_root_lan_sharing">局域网 / 热点网络共享 (仅限 Root 用户)</string>
<string name="summary_root_lan_sharing">允许通过 Wi-Fi 热点和 USB 共享网络连接的设备走 VPN 代理流量</string>
<string name="title_root_lan_sharing">与局域网 / 热点设备共享 VPN (仅限 Root 用户)</string>
<string name="summary_root_lan_sharing">将 Wi-Fi 热点和 USB 网络共享设备的流量通过 VPN 转发。</string>
<string name="title_logcat">Logcat</string>
<string name="title_logcat" translatable="false">Logcat</string>
<string name="logcat_copy">复制</string>
<string name="logcat_clear">清除</string>
<string name="logcat_share">分享日志</string>
@@ -309,11 +319,11 @@
<string name="title_del_all_config">删除配置</string>
<string name="title_del_duplicate_config">删除重复配置</string>
<string name="title_del_invalid_config">删除无效配置</string>
<string name="title_export_all">导出配置至剪贴板</string>
<string name="title_sub_setting">订阅分组设置</string>
<string name="title_export_all">将配置导出至剪贴板</string>
<string name="title_sub_setting">订阅分组</string>
<string name="sub_setting_remarks">备注</string>
<string name="sub_setting_url">可选地址 (url)</string>
<string name="sub_setting_user_agent">User Agent</string>
<string name="sub_setting_url">URL(可选)</string>
<string name="sub_setting_user_agent" translatable="false">User Agent</string>
<string name="sub_setting_request_headers">请求头(JSON 格式)</string>
<string name="sub_setting_filter">别名正则过滤</string>
<string name="sub_setting_enable">启用更新</string>
@@ -322,17 +332,18 @@
<string name="sub_setting_pre_profile">前置代理配置别名</string>
<string name="sub_setting_next_profile">落地代理配置別名</string>
<string name="sub_setting_pre_profile_tip">请确保配置别名存在并唯一</string>
<string name="sub_setting_entry_proxy_tip">所选代理会添加到该订阅中每个配置的前面,作为该配置代理链的入口节点。</string>
<string name="sub_setting_exit_proxy_tip">所选代理会添加到该订阅中每个配置的后面,作为该配置代理链的出口节点。</string>
<string name="toast_invalid_update_interval">更新间隔无效,最小值为 15 分钟。</string>
<string name="title_sub_update">更新订阅</string>
<string name="title_ping_all_server">测试配置 Tcping</string>
<string name="title_real_ping_all_server">测试配置真连接</string>
<string name="title_ping_all_server">测试 TCP 延迟(TCPing)</string>
<string name="title_real_ping_all_server">测试实际延迟</string>
<string name="title_user_asset_setting">资源文件</string>
<string name="title_sort_by_test_results">按测试结果排序</string>
<string name="title_filter_config">过滤配置</string>
<string name="filter_config_all">所有</string>
<string name="title_del_duplicate_config_count">删除 %d 个重复配置</string>
<string name="summary_scan_qrcode">点击屏幕打开相机扫描</string>
<string name="title_del_duplicate_config_count">删除 %d 个重复配置</string>
<string name="title_del_config_count">删除 %d 个配置</string>
<string name="title_import_config_count">导入 %d 个配置</string>
<string name="title_export_config_count">导出 %d 个配置</string>
@@ -340,7 +351,6 @@
<string name="title_update_subscription_result">更新了 %1$d 个配置(%2$d 个成功,%3$d 个失败,%4$d 个跳过)</string>
<string name="title_update_subscription_no_subscription">无订阅</string>
<string name="toast_server_not_found_in_group">当前分组中未找到选中的服务器</string>
<string name="toast_fragment_not_available">无法定位当前视图</string>
<string name="title_locate_selected_config">定位所选配置</string>
<string name="tasker_start_service">启动服务</string>
@@ -349,7 +359,8 @@
<!-- RoutingSettingActivity -->
<string name="routing_settings_domain_strategy">域名策略</string>
<string name="routing_settings_title">路由设置</string>
<string name="routing_settings_tips">用逗号(,)分隔,选择填写 domain、ip 或 process 中的一项</string>
<string name="routing_settings_tips">一条规则仅在所有已设置的匹配条件同时满足时生效(AND)。规则按从上到下的顺序检查,并应用首条匹配的规则。</string>
<string name="routing_settings_comma_tip">多个条目请用逗号(,)分隔。</string>
<string name="routing_settings_save">保存</string>
<string name="routing_settings_delete">清空</string>
<string name="routing_settings_rule_title">路由规则设置</string>
@@ -357,41 +368,41 @@
<string name="routing_settings_import_predefined_rulesets">导入预定义规则集</string>
<string name="routing_settings_import_rulesets_tip">将删除现有的规则集,是否确定继续?</string>
<string name="routing_settings_import_rulesets_from_clipboard">从剪贴板导入规则集</string>
<string name="routing_settings_import_rulesets_from_qrcode">从 QRcode 导入规则集</string>
<string name="routing_settings_import_rulesets_from_qrcode">从二维码导入规则集</string>
<string name="routing_settings_export_rulesets_to_clipboard">导出规则集至剪贴板</string>
<string name="routing_settings_locked">锁定中,导入预设时不删除此规则</string>
<string name="routing_settings_domain">domain</string>
<string name="routing_settings_ip">ip</string>
<string name="routing_settings_process">process (包名 — 仅在使用 Xray 的 TUN、开启 routeOnly 且 Android 10+ 时可用)</string>
<string name="routing_settings_domain" translatable="false">domain</string>
<string name="routing_settings_ip" translatable="false">ip</string>
<string name="routing_settings_process">process (包名 — 仅在使用 Xray TUN、开启 routeOnly 且 Android 10+ 时可用)</string>
<string name="routing_settings_process_select">选择包名</string>
<string name="routing_settings_port">port</string>
<string name="routing_settings_protocol">protocol</string>
<string name="routing_settings_protocol_tip">[http,tls,bittorrent]</string>
<string name="routing_settings_network">network</string>
<string name="routing_settings_outbound_tag">outboundTag</string>
<string name="routing_settings_port" translatable="false">port</string>
<string name="routing_settings_protocol" translatable="false">protocol</string>
<string name="routing_settings_protocol_tip" translatable="false">[http,tls,bittorrent]</string>
<string name="routing_settings_network" translatable="false">network</string>
<string name="routing_settings_outbound_tag_hint">proxy / direct / block / &lt;%1$s&gt;</string>
<string name="routing_settings_outbound_tag" translatable="false">outboundTag</string>
<string name="connection_test_pending">"检查网络连接"</string>
<string name="connection_test_testing">"测试中…"</string>
<string name="connection_test_testing_count">测试 %d 个配置中…</string>
<string name="connection_test_available">"连接成功:延时 %d 毫秒"</string>
<string name="connection_test_error">"失败:%s"</string>
<string name="connection_test_fail">"无互联网连接"</string>
<string name="connection_test_error_status_code">"状态码无效(#%d)"</string>
<string name="connection_connected">"已连接,点击测试连接"</string>
<string name="connection_test_available">"连接成功:延时 %1$s"</string>
<string name="server_test_delay_value">%1$d 毫秒</string>
<string name="connection_test_error">连接测试失败:%s</string>
<string name="connection_test_fail">无法访问互联网</string>
<string name="connection_test_error_status_code">错误码:#%d</string>
<string name="connection_connected">"已连接。点击检查连接。"</string>
<string name="connection_not_connected">"未连接"</string>
<string name="connection_runing_task_left">运行中的测试任务数:%s</string>
<string name="connection_running_task_left">正在运行的测试:%s</string>
<string name="import_subscription_success">订阅导入成功</string>
<string name="import_subscription_failure">导入订阅失败</string>
<string name="menu_item_add_asset">添加</string>
<string name="menu_item_add_url">添加链接</string>
<string name="title_fragment_settings">分片(Fragment)设置</string>
<string name="title_pref_fragment_packets">分片方式</string>
<string name="title_pref_fragment_length">分片包长(最小 - 最大)</string>
<string name="title_pref_fragment_interval">分片间隔(最小 - 最大)</string>
<string name="title_pref_fragment_enabled">启用分片(Fragment)</string>
<string name="title_pref_fragment_maxsplit">分片最大分割数</string>
<string name="title_observatory_settings">连接观测设置</string>
<string name="title_observatory_settings">连接观测设置 (Observatory)</string>
<string name="title_pref_observatory_least_ping_interval">leastPing 探测间隔</string>
<string name="title_pref_observatory_least_load_interval">leastLoad 探测间隔</string>
<string name="title_pref_observatory_least_load_method">leastLoad HTTP 方法</string>
@@ -402,16 +413,17 @@
<string name="update_check_for_update">检查更新</string>
<string name="update_already_latest_version">目前已是最新版本</string>
<string name="update_new_version_found">发现新版本: %s</string>
<string name="update_new_version_found">发现新版本:%s</string>
<string name="update_now">立即更新</string>
<string name="update_check_pre_release">检查 Pre-release</string>
<string name="update_check_pre_release">检查预发布版本</string>
<string name="update_checking_for_update">正在检查更新中…</string>
<string name="title_policy_group_type">策略组类型</string>
<string name="title_policy_group_subscription_id">来自订阅分组</string>
<string name="title_policy_group_subscription_filter">别名正则过滤</string>
<string name="title_policy_group_test_outbounds">测试出站</string>
<string name="title_policy_group_fallback">备用出站(可选)</string>
<string name="title_policy_group_subscription_filter">备注正则筛选</string>
<string name="title_policy_group_test_outbounds">测试出站 (outbounds)</string>
<string name="title_policy_group_fallback">备用出站 (outbound,可选)</string>
<string name="server_proxy_chain_members">代理链成员</string>
<string name="server_proxy_chain_pick_members">点此选择成员</string>
<string name="server_proxy_chain_member_unselected">请选择成员</string>
@@ -426,41 +438,43 @@
<string name="title_configuration_share">分享配置</string>
<string name="title_webdav_config_setting">WebDAV 设置</string>
<string name="title_webdav_config_setting_unknown">请先设置 WebDAV</string>
<string name="title_webdav_url">WebDAV 服务器地址</string>WebDAV server address
<string name="title_webdav_url">WebDAV 服务器地址</string>
<string name="title_webdav_user">用户名</string>
<string name="title_webdav_pass">密码</string>
<string name="title_webdav_remote_path">远程文件夹名(可选)</string>
<string name="share_method_qrcode">二维码</string>
<string name="share_method_clipboard">导出至剪贴板</string>
<string name="share_method_full_content">导出完整配置至剪贴板</string>
<string name="share_method_clipboard">复制配置链接</string>
<string name="share_method_full_content">复制完整配置</string>
<string name="action_edit">编辑</string>
<string name="action_delete">删除</string>
<string name="action_close">关闭</string>
<string-array name="share_sub_method">
<item>二维码</item>
<item>导出至剪贴板</item>
</string-array>
<string name="share_subscription_qrcode">二维码</string>
<string name="share_subscription_clipboard">导出至剪贴板</string>
<string-array name="mode_entries">
<item>VPN</item>
<item>仅代理</item>
</string-array>
<string-array name="browser_dialer_mode">
<item>禁用</item>
<item>OkHttp</item>
<item>WebView</item>
</string-array>
<string-array name="ui_mode_night">
<item>跟随系统</item>
<item>浅色</item>
<item>深色</item>
</string-array>
<string-array name="preset_rulesets">
<item>绕过大陆 (Whitelist)</item>
<item>黑名单 (Blacklist)</item>
<item>全局 (Global)</item>
<item>伊朗 (Iran)</item>
<item>俄罗斯白名单 (Russia Whitelist)</item>
</string-array>
<string name="routing_preset_china_whitelist">绕过大陆 (Whitelist)</string>
<string name="routing_preset_china_blacklist">黑名单 (Blacklist)</string>
<string name="routing_preset_global">全局 (Global)</string>
<string name="routing_preset_iran_whitelist">伊朗 (Iran)</string>
<string name="routing_preset_russia_whitelist">俄罗斯白名单 (Russia Whitelist)</string>
<string-array name="vpn_bypass_lan">
<item>跟随配置</item>
@@ -473,16 +487,57 @@
<item>解析后添加至 DNS Hosts</item>
<item>解析后替换原域名</item>
</string-array>
<string-array name="policy_group_type">
<item>最低延迟</item>
<item>最稳定</item>
<item>随机选择</item>
<item>轮询</item>
<item>最低延迟 (leastPing)</item>
<item>最低负载 (leastLoad)</item>
<item>随机选择 (random)</item>
<item>轮询 (roundRobin)</item>
</string-array>
<string-array name="config_backup_options">
<item>本地</item>
<item>WebDAV</item>
</string-array>
<string name="backup_location_local">本地</string>
<string name="backup_location_webdav" translatable="false">WebDAV</string>
<string name="acc_refresh">刷新日志</string>
<string name="toast_permission_denied_for">%1$s权限被拒绝</string>
<string name="acc_add_subscription">添加订阅</string>
<string name="toast_malformed_json_detail">配置格式无效:%1$s</string>
<string name="acc_add_asset">添加资源来源</string>
<string name="acc_download_file">下载资源文件</string>
<string name="acc_qr_code">二维码</string>
<string name="acc_copy_log">复制日志</string>
<string name="acc_clear_log">清除日志</string>
<string name="acc_add_rule">添加路由规则</string>
<string name="acc_start">启动服务</string>
<string name="acc_stop">停止服务</string>
<string name="acc_back">返回</string>
<string name="acc_search">搜索</string>
<string name="acc_add">添加配置</string>
<string name="acc_more">更多选项</string>
<string name="acc_share_subscription">分享订阅链接</string>
<string name="acc_share_log">分享日志</string>
<string name="acc_remove">移除代理链成员</string>
<string name="acc_add_member">添加代理链成员</string>
<string name="acc_start_scanner">启动二维码扫描器</string>
<string name="acc_stop_scanner">停止二维码扫描器</string>
<string name="acc_turn_torch_on">打开手电筒</string>
<string name="acc_turn_torch_off">关闭手电筒</string>
<string name="acc_select_image">选择要扫描的图片</string>
<string name="acc_locked">导入预设时保留此规则</string>
<string name="acc_open_menu">打开导航菜单</string>
<string name="acc_edit">编辑</string>
<string name="acc_delete">删除</string>
<string name="acc_save">保存</string>
<string name="acc_update_subscriptions">更新订阅</string>
<string name="acc_per_app_proxy_information">分应用代理信息</string>
<string name="permission_camera">相机</string>
<string name="permission_notification">通知</string>
<string name="permission_local_network">局域网</string>
<string name="subscription_update_updating">正在更新订阅:%1$s</string>
<string name="subscription_update_progress">正在测试%2$s:%1$s</string>
<string name="tasker_blurb_start">启动 %1$s</string>
<string name="tasker_blurb_stop">停止 %1$s</string>
<string name="connection_test_empty_message">无详细信息</string>
<string name="value_unknown">未知</string>
</resources>
+244 -187
View File
@@ -1,14 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" translatable="false">v2rayNG</string>
<string name="app_widget_name">開關</string>
<string name="app_tile_name">開關</string>
<string name="app_tile_first_use">首次使用此功能,請使用此應用程式新增伺服器</string>
<string name="navigation_drawer_open">開啟導覽匣</string>
<string name="navigation_drawer_close">關閉導覽匣</string>
<string name="migration_success">資料遷移成功!</string>
<string name="action_stop_service">Stop service</string>
<string name="action_stop_service">停止服務</string>
<string name="action_ok">確定</string>
<string name="action_cancel">取消</string>
<string name="migration_fail">資料遷移失敗!</string>
<string name="pull_down_to_refresh">請下拉刷新!</string>
<string name="pull_down_to_refresh">請下拉重新整理!</string>
<!-- Notifications -->
<string name="notification_action_stop_v2ray">停止</string>
@@ -20,24 +23,24 @@
<string name="toast_services_success">啟動服務成功</string>
<string name="toast_services_failure">啟動服務失敗</string>
<!-- ServerActivity -->
<!--ServerActivity-->
<string name="title_server">設定檔</string>
<string name="menu_item_add_config">新增設定</string>
<string name="menu_item_save_config">儲存設定</string>
<string name="menu_item_edit_config">Edit configuration</string>
<string name="menu_item_edit_config">編輯設定檔</string>
<string name="menu_item_del_config">刪除設定</string>
<string name="menu_item_import_config_qrcode">從 QR Code 匯入設定</string>
<string name="menu_item_import_config_clipboard">從剪貼簿匯入設定</string>
<string name="menu_item_import_config_local">從本地匯入</string>
<string name="menu_item_import_config_local">從本機匯入</string>
<string name="menu_item_import_config_policy_group">新增 [策略組]</string>
<string name="menu_item_import_config_proxy_chain">新增 [鍊式代理]</string>
<string name="menu_item_import_config_proxy_chain">新增 [代理鏈]</string>
<string name="menu_item_import_config_manually_vmess">新增 [VMess]</string>
<string name="menu_item_import_config_manually_vless">新增 [VLESS]</string>
<string name="menu_item_import_config_manually_ss">新增 [Shadowsocks]</string>
<string name="menu_item_import_config_manually_socks">新增 [SOCKS]</string>
<string name="menu_item_import_config_manually_http">新增 [HTTP]</string>
<string name="menu_item_import_config_manually_trojan">新增 [Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">新增 [Wireguard]</string>
<string name="menu_item_import_config_manually_wireguard">新增 [WireGuard]</string>
<string name="menu_item_import_config_manually_hysteria2">新增 [Hysteria2]</string>
<string name="confirm_delete_visible_profiles">確定要刪除目前顯示的所有設定檔嗎?</string>
<string name="confirm_delete_duplicate_profiles">確定要刪除目前顯示的所有重複設定檔嗎?</string>
@@ -75,11 +78,11 @@
<string name="server_lab_path_quic">QUIC 加密金鑰</string>
<string name="server_lab_path_kcp">kcp seed</string>
<string name="server_lab_path_grpc">gRPC serviceName</string>
<string name="server_lab_stream_security">傳輸層安全 (TLS)</string>
<string name="server_lab_stream_security" translatable="false">TLS</string>
<string name="server_lab_stream_fingerprint">Fingerprint</string>
<string name="server_lab_stream_alpn">Alpn</string>
<string name="server_lab_stream_alpn" translatable="false">ALPN</string>
<string name="server_lab_allow_insecure">跳過憑證驗證 (allowInsecure)</string>
<string name="server_lab_sni">SNI</string>
<string name="server_lab_sni" translatable="false">SNI</string>
<string name="server_lab_address3">伺服器位址</string>
<string name="server_lab_port3">伺服器埠</string>
<string name="server_lab_id3">密碼</string>
@@ -87,18 +90,18 @@
<string name="server_lab_id4">密碼 (可選)</string>
<string name="server_lab_security4">使用者名稱 (可選)</string>
<string name="server_lab_encryption">加密 (encryption)</string>
<string name="server_lab_flow">流程 (flow)</string>
<string name="server_lab_flow">流量控制 (flow)</string>
<string name="server_lab_public_key">PublicKey</string>
<string name="server_lab_preshared_key">PreSharedKey (optional)</string>
<string name="server_lab_preshared_key">PreSharedKey(可選)</string>
<string name="server_lab_short_id">ShortId</string>
<string name="server_lab_spider_x">SpiderX</string>
<string name="server_lab_mldsa65_verify">Mldsa65Verify</string>
<string name="server_lab_spider_x" translatable="false">SpiderX</string>
<string name="server_lab_mldsa65_verify" translatable="false">mldsa65Verify</string>
<string name="server_lab_secret_key">SecretKey</string>
<string name="server_lab_reserved">Reserved (可選,逗號隔開)</string>
<string name="server_lab_local_address">本機位址 (可選 IPv4/IPv6,逗號隔開)</string>
<string name="server_lab_local_mtu">MTU (可選, 預設 1420)</string>
<string name="server_lab_kcp_mtu">mKCP MTU (可選, 預設 1350)</string>
<string name="server_lab_kcp_tti">mKCP TTI (可選, 預設 50)</string>
<string name="server_lab_local_mtu">MTU(可選,預設 1420)</string>
<string name="server_lab_kcp_mtu">mKCP MTU(可選,核心預設 1350)</string>
<string name="server_lab_kcp_tti">mKCP TTI(可選,核心預設 50)</string>
<string name="toast_success">成功</string>
<string name="toast_failure">失敗</string>
<string name="toast_none_data">無資料</string>
@@ -112,96 +115,100 @@
<string name="toast_none_data_clipboard">剪貼簿內無資料</string>
<string name="toast_invalid_url">URL 無效</string>
<string name="toast_insecure_url_protocol">請不要使用不安全的 HTTP 協定訂閱位址</string>
<string name="server_lab_need_inbound">​​確保 inbounds port 和設定中的一致</string>
<string name="toast_malformed_josn">設定格式不正確</string>
<string name="server_lab_need_inbound">請確保入站連接埠與設定一致</string>
<string name="toast_malformed_json">設定檔格式不正確。</string>
<string name="server_lab_request_host6">Host (SNI) (可選)</string>
<string name="toast_action_not_allowed">禁止此項操作</string>
<string name="server_obfs_password">混淆密碼</string>
<string name="server_lab_port_hop">跳躍連接埠 (會覆蓋伺服器連接埠)</string>
<string name="server_lab_port_hop_interval">連接埠跳躍間隔 (秒)</string>
<string name="server_lab_bandwidth_down">頻寬下行 (支持的單位 k/m/g/t)</string>
<string name="server_lab_bandwidth_up">頻寬上行 (支持的單位 k/m/g/t)</string>
<string name="server_lab_bandwidth_down">下載頻寬(支援的單位:k/m/g/t)</string>
<string name="server_lab_bandwidth_up">上傳頻寬(支援的單位:k/m/g/t)</string>
<string name="server_lab_xhttp_mode">XHTTP 模式</string>
<string name="server_lab_xhttp_extra">XHTTP Extra 原始 JSON,格式: { XHTTPObject }</string>
<string name="server_lab_final_mask">FinalMask 原始 JSON 格式: { FinalMaskObject }</string>
<string name="server_lab_ech_config_list">EchConfigList</string>
<string name="server_lab_verify_peer_cert_by_name">Verify Peer Cert By Name</string>
<string name="server_lab_pinned_ca256">證書指紋 (SHA-256)</string>
<string name="toast_allow_insecure_deprecated">目前節點使用未加密連線,您的通訊可能會被威權政府掌控的網路中間設施直接查看\n為了安全,此類節點無法通過 26.2.6+ 版本的 Xray 核心連線\n如果是自建節點請啟用 TLS 等安全加密,或固定憑證 pinnedCA256\n如果機場節點請聯繫服務商完成技術升級,如服務商拒絕配合,建議更換更重視用戶安全的服務商\n更多的資訊,請訪問 https://github.com/2dust/v2rayN/discussions/9460</string>
<string name="pinned_ca256_action_fetch">獲取並填充指紋證書</string>
<string name="toast_fetch_cert_sha256_success">獲取指紋證書完成</string>
<string name="toast_fetch_cert_sha256_failed">獲取證書指紋失敗</string>
<string name="server_lab_final_mask">finalMask 原始 JSON,格式:{ FinalMaskObject }</string>
<string name="server_lab_ech_config_list" translatable="false">echConfigList</string>
<string name="server_lab_verify_peer_cert_by_name">依名稱驗證對端憑證</string>
<string name="server_lab_pinned_ca256">憑證指紋 (SHA-256)</string>
<string name="server_lab_browser_dialer">啟用 Browser Dialer</string>
<string name="server_lab_browser_dialer_tip">僅支援 xhttp (packet-up) 和 ws 出站;與 TLS 相關的設定可能會被忽略或發生衝突</string>
<string name="toast_allow_insecure_deprecated">目前節點使用未加密連線,您的通訊可能會被威權政府掌控的網路中間設施直接查看\n為了安全,此類節點無法使用 26.2.6+ 版本的 Xray 核心連線\n如果是自建節點,請啟用 TLS 等安全加密,或固定憑證 pinnedCA256\n如果是服務供應商的節點,請聯絡供應商完成技術升級。若供應商拒絕配合,建議改用更重視使用者安全的供應商\n如需更多資訊,請造訪 https://github.com/2dust/v2rayN/discussions/9460</string>
<string name="pinned_ca256_action_fetch">取得憑證指紋</string>
<string name="toast_fetch_cert_sha256_success">已成功取得憑證指紋</string>
<string name="toast_fetch_cert_sha256_failed">無法取得憑證指紋</string>
<!-- UserAssetActivity -->
<string name="toast_asset_copy_failed">失敗,請使用檔案總管</string>
<string name="toast_asset_copy_failed">檔案複製失敗,請使用檔案總管</string>
<string name="menu_item_add_asset">新增資源</string>
<string name="menu_item_add_file">新增檔案</string>
<string name="menu_item_scan_qrcode">掃描二維碼</string>
<string name="title_url">URL</string>
<string name="menu_item_add_url">新增 URL</string>
<string name="menu_item_scan_qrcode">掃描 QR Code</string>
<string name="title_url" translatable="false">URL</string>
<string name="menu_item_download_file">下載檔案</string>
<string name="title_user_asset_add_url">新增資產網址</string>
<string name="msg_file_not_found">文件未找到</string>
<string name="msg_remark_is_duplicate">備註已經存在</string>
<string name="title_user_asset_add_url">新增資源 URL</string>
<string name="msg_file_not_found">找不到檔案</string>
<string name="msg_remark_is_duplicate">名稱已存在</string>
<string name="asset_geo_files_sources">Geo 檔案來源 (可選)</string>
<!-- PerAppProxyActivity -->
<string name="msg_dialog_progress">載入</string>
<string name="menu_item_search">搜尋</string>
<string name="menu_item_select_all">全選</string>
<string name="menu_item_invert_selection">反選</string>
<string name="menu_item_invert_selection">反向選取</string>
<string name="msg_enter_keywords">輸入關鍵字</string>
<string name="switch_bypass_apps_mode">略過模式</string>
<string name="menu_item_select_proxy_app">自動選中需代理的應用</string>
<string name="menu_item_select_proxy_app">自動選取需要使用代理的應用程式</string>
<string name="msg_downloading_content">正在下載內容</string>
<string name="menu_item_export_proxy_app">匯出至剪貼簿</string>
<string name="menu_item_import_proxy_app">從剪貼簿匯入</string>
<string name="per_app_proxy_settings">分應用設置</string>
<string name="per_app_proxy_settings_enable">根據應用分流</string>
<string name="per_app_proxy_settings">個別應用程式設定</string>
<string name="per_app_proxy_settings_enable">啟用個別應用程式代理</string>
<string name="app_picker_unknown_app">未知應用程式(無法識別 UID)</string>
<!-- Preferences -->
<string name="title_settings">設定</string>
<string name="title_advanced">進階</string>
<string name="title_core_settings">核心設定</string>
<string name="title_vpn_settings">VPN 設定</string>
<string name="title_pref_per_app_proxy">Proxy 個別應用程式</string>
<string name="summary_pref_per_app_proxy">常規:勾選的 App 啟用 Proxy,未勾選的直接連線;\n繞行模式:勾選的 App 直接連線,未勾選的啟用 Proxy。\n可在選單中選擇自動選中需 Proxy 應用</string>
<string name="title_pref_per_app_proxy">個別應用程式代理</string>
<string name="summary_pref_per_app_proxy">一般:已勾選的應用程式使用代理,未勾選的應用程式直接連線;\n繞行模式:已勾選的應用程式直接連線,未勾選的應用程式使用代理。\n選單中可自動選取需要使用代理的應用程式。</string>
<string name="title_pref_is_booted">開機時自動連線</string>
<string name="summary_pref_is_booted">開機時自動連線選擇的伺服器,可能會不成功</string>
<string name="subscription_updater_job_tips">任務將在背景運行,在通知中會顯示進度資訊</string>
<string name="subscription_updater_job_tips">任務將在背景執行,通知中會顯示進度資訊。</string>
<string name="title_pref_auto_test_after_update_subscription">更新訂閱後自動測試</string>
<string name="summary_pref_auto_test_after_update_subscription">自動測試需要較長的時間,開啟後任務將在後台運行;不開啟則在目前頁面運行</string>
<string name="title_pref_auto_remove_invalid_after_test">測試後自動刪除無效配置</string>
<string name="summary_pref_auto_remove_invalid_after_test">測試結果可能不準確且已刪除的配置無法復原</string>
<string name="summary_pref_auto_test_after_update_subscription">自動測試需要較長時間。啟用後,任務會在背景執行;否則會在目前頁面執行。</string>
<string name="title_pref_auto_remove_invalid_after_test">測試後自動刪除無效設定</string>
<string name="summary_pref_auto_remove_invalid_after_test">測試結果可能不準確,且已刪除的設定無法復原</string>
<string name="title_pref_auto_sort_after_test">測試後自動排序</string>
<string name="summary_pref_auto_sort_after_test">測試結果可能不準確</string>
<string name="title_mux_settings">Mux 設定</string>
<string name="title_pref_mux_enabled">啟用 Mux 多路復用</string>
<string name="summary_pref_mux_enabled">減低延時 但可能會斷流\nTCP,UDP 及 QUIC 流量處理方式下方可選</string>
<string name="title_pref_mux_concurency">TCP 復用子鏈接數(可填 -1 至 1024)</string>
<string name="title_pref_mux_xudp_concurency">XUDP 復用子鏈接數(可填 -1 至 1024)</string>
<string name="summary_pref_mux_enabled">速度更快,但可能導致連線不穩定。\n可在下方自訂 TCP、UDP 和 QUIC 的處理方式。</string>
<string name="title_pref_mux_concurrency">TCP 多工子連線數(可填 -1 至 1024)</string>
<string name="title_pref_mux_xudp_concurrency">XUDP 多工子連線數(可填 -1 至 1024)</string>
<string name="title_pref_mux_xudp_quic">QUIC 流量處理方式</string>
<string-array name="mux_xudp_quic_entries">
<item>不代理</item>
<item>多路復用</item>
<item>原生</item>
<item>拒絕</item>
<item>允許</item>
<item>略過</item>
</string-array>
<string name="title_pref_speed_enabled">啟用速度顯示</string>
<string name="summary_pref_speed_enabled">在通知中顯示當前速度\n小圖示顯示流量的轉送狀況</string>
<string name="summary_pref_speed_enabled">在通知中顯示目前速度。\n圖示會指出代理流量或直接連線流量何者較多。</string>
<string name="title_pref_sniffing_enabled">啟用流量監聽</string>
<string name="summary_pref_sniffing_enabled">從流量中監聽網域 (預設啟用)</string>
<string name="title_pref_sniffing_enabled">啟用流量探測 (Sniffing)</string>
<string name="summary_pref_sniffing_enabled">從流量中探測目標網域(預設啟用)。</string>
<string name="title_pref_route_only_enabled">啟用 routeOnly</string>
<string name="summary_pref_route_only_enabled">將嗅探得到的網域只用於路由,代理目標位址仍為 IP</string>
<string name="title_pref_local_dns_enabled">啟用本機 DNS</string>
<string name="summary_pref_local_dns_enabled">DNS 請求匯入 core 由 DNS 模組處理 (建議啟用,如果需要轉送略過區域網路及中國大陸)</string>
<string name="summary_pref_local_dns_enabled">DNS 由核心的 DNS 模組處理(若需要路由略過區域網路和中國大陸位址,建議啟用)。</string>
<string name="title_pref_fake_dns_enabled">啟用假 DNS</string>
<string name="summary_pref_fake_dns_enabled">本機退回假解析結果 (減低延時,但個別應用可能無法使用)</string>
<string name="title_pref_fake_dns_enabled">啟用偽造 DNS (FakeDNS)</string>
<string name="summary_pref_fake_dns_enabled">FakeDNS 解析網域時會傳回虛構的 IP 位址(速度較快,但可能不適用於部分應用程式)。</string>
<string name="title_pref_ipv6_enabled">啟用 IPv6</string>
<string name="summary_pref_ipv6_enabled">為 VPN 介面新增 IPv6 位址和路由</string>
@@ -209,256 +216,265 @@
<string name="title_pref_prefer_ipv6">IPv6 偏好</string>
<string name="summary_pref_prefer_ipv6">解析網域名稱時優先使用 IPv6 位址</string>
<string name="title_pref_remote_dns">遠端 DNS (udp/tcp/https/quic)(可選)</string>
<string name="summary_pref_remote_dns">DNS</string>
<string name="title_pref_remote_dns">遠端 DNS(UDP/TCP/HTTPS/QUIC,可選)</string>
<string name="summary_pref_remote_dns" translatable="false">DNS</string>
<string name="title_pref_vpn_dns">VPN DNS (僅支援 IPv4/v6)</string>
<string name="title_pref_vpn_bypass_lan">VPN 是否繞過區域網</string>
<string name="title_pref_vpn_dns">VPN DNS(僅支援 IPv4/IPv6)</string>
<string name="title_pref_vpn_bypass_lan">VPN 是否繞過區域網路</string>
<string name="title_pref_vpn_interface_address">VPN 介面位址</string>
<string name="title_pref_vpn_mtu">VPN MTU (預設 1500)</string>
<string name="summary_pref_domestic_dns">DNS</string>
<string name="title_pref_domestic_dns">境内 DNS (可选)</string>
<string name="title_pref_dns_hosts">DNS hosts (格式: 網域:位址,…)</string>
<string name="title_pref_domestic_dns">直接連線 DNS(可選)</string>
<string name="summary_pref_domestic_dns" translatable="false">DNS</string>
<string name="title_pref_dns_hosts">DNS 主機對應(格式:domain:address,…)</string>
<string name="summary_pref_dns_hosts">domain:address,…</string>
<string name="title_pref_delay_test_url">真連線延遲測試網址 </string>
<string name="summary_pref_delay_test_url">Url</string>
<string name="title_pref_real_ping_concurrency">真連線延遲測試並發數量</string>
<string name="title_pref_delay_test_url">真實延遲測試 URL</string>
<string name="summary_pref_delay_test_url" translatable="false">URL</string>
<string name="title_pref_real_ping_concurrency">同時執行的真實延遲測試數</string>
<string name="title_pref_ip_api_url">目前連線資訊測試網址</string>
<string name="summary_pref_ip_api_url">URL</string>
<string name="title_pref_ip_api_url">目前連線資訊測試 URL</string>
<string name="summary_pref_ip_api_url" translatable="false">URL</string>
<string name="title_pref_proxy_sharing_enabled">允許來自區域網路的連線</string>
<string name="summary_pref_proxy_sharing_enabled">其他裝置可以使用 socks/http 協定透過您的 IP 位址連線到 Proxy,僅在受信任的網路中啟用以避免未經授權的連線</string>
<string name="toast_warning_pref_proxysharing_short">允許來自區域網路的連線,請確保處於受信網路</string>
<string name="summary_pref_proxy_sharing_enabled">其他裝置可以透過您的 IP 位址連線到本機代理。請只在受信任的網路中啟用,以避免未經授權的連線。</string>
<string name="toast_warning_pref_proxysharing_short">已允許來自區域網路的連線。請確認目前使用的是受信任的網路。</string>
<string name="title_pref_socks_port">本地代理埠</string>
<string name="title_pref_enable_local_proxy">啟用本地代理</string>
<string name="summary_pref_enable_local_proxy">未開啟時沒有 socks 代理,無法透過代理更新訂閱等</string>
<string name="title_pref_socks_enable_udp">SOCKS5 UDP</string>
<string name="summary_pref_socks_enable_udp">使用 UDP 時,socks5 認證並不完全安全</string>
<string name="summary_pref_socks_port">本地代理埠</string>
<string name="title_pref_dynamic_socks_port">啟用動態本地代理埠</string>
<string name="summary_pref_dynamic_socks_port">每次產生 inbound 時隨機產生一個本地代理埠</string>
<string name="title_pref_socks_username">本地代理使用者名稱 (選擇)</string>
<string name="title_pref_socks_port">本機代理埠</string>
<string name="title_pref_enable_local_proxy">啟用本機代理</string>
<string name="summary_pref_enable_local_proxy">停用時不會提供 SOCKS 代理,因此訂閱更新等操作無法使用代理。</string>
<string name="title_pref_socks_enable_udp" translatable="false">SOCKS5 UDP</string>
<string name="summary_pref_socks_enable_udp">使用 UDP 時,SOCKS5 驗證並不完全安全。</string>
<string name="summary_pref_socks_port">本機代理埠</string>
<string name="title_pref_dynamic_socks_port">啟用動態本機代理埠</string>
<string name="summary_pref_dynamic_socks_port">為每個輸入連線(inbound)使用隨機的本機代理埠</string>
<string name="title_pref_socks_username">本機代理使用者名稱(可選)</string>
<string name="summary_pref_socks_username">使用者名稱</string>
<string name="title_pref_socks_password">本地代理密碼 (選擇)</string>
<string name="title_pref_socks_password">本機代理密碼(可選)</string>
<string name="summary_pref_socks_password">密碼</string>
<string name="title_pref_local_dns_port">本機 DNS 埠</string>
<string name="summary_pref_local_dns_port">本機 DNS 埠</string>
<string name="title_pref_confirm_remove">刪除設定檔確認</string>
<string name="summary_pref_confirm_remove">刪除設定檔是否需要用戶二次確認</string>
<string name="summary_pref_confirm_remove">刪除設定檔時是否要求使用者再次確認</string>
<string name="title_pref_append_http_proxy">追加 HTTP 代理至 VPN</string>
<string name="summary_pref_append_http_proxy">瀏覽器 / 一些支援的應用 將直接使用 HTTP 代理, 而不經過虛擬網卡設備 (Android 10+)</string>
<string name="title_pref_append_http_proxy">將 HTTP 代理加入 VPN</string>
<string name="summary_pref_append_http_proxy">瀏覽器和部分支援的應用程式會直接使用 HTTP 代理,而不經過虛擬網路介面(Android 10+)。</string>
<string name="title_pref_double_column_display">啟用雙列顯示</string>
<string name="summary_pref_double_column_display">設定檔清單以雙列顯示,允許在螢幕上顯示更多內容。</string>
<string name="title_pref_group_all_display">啟用顯示所有群組</string>
<string name="summary_pref_group_all_display">新增一個額外的「所有選項卡」頁面</string>
<string name="title_pref_group_all_display">顯示「全部」群組分頁</string>
<string name="summary_pref_group_all_display">在一個分頁中彙整所有訂閱群組的設定檔。</string>
<!-- AboutActivity -->
<string name="title_pref_feedback">意見回饋</string>
<string name="summary_pref_feedback">前往 GitHub 回報錯誤</string>
<string name="summary_pref_feedback">前往 GitHub 提出改進建議或回報錯誤</string>
<string name="summary_pref_tg_group">加入 Telegram 群組</string>
<string name="toast_tg_app_not_found">未找到 Telegram 應用程式</string>
<string name="toast_tg_app_not_found">找不到 Telegram 應用程式</string>
<string name="title_privacy_policy">隱私權政策</string>
<string name="title_qr_code">QR 碼</string>
<string name="title_qr_code">QR Code</string>
<string name="title_about">關於</string>
<string name="title_source_code">原始碼</string>
<string name="title_oss_license">Open Source licenses</string>
<string name="title_oss_license">開放原始碼授權</string>
<string name="title_tg_channel">Telegram 頻道</string>
<string name="title_pref_promotion">推廣</string>
<string name="title_pref_auto_update_subscription">自動更新訂閱</string>
<string name="summary_pref_auto_update_subscription">在後台以一定時間間隔自動更新您的訂閱。受設備影響,此功能不一定總是有效</string>
<string name="summary_pref_auto_update_subscription">在背景依指定間隔自動更新訂閱。此功能可能因裝置而無法穩定運作。</string>
<string name="title_pref_auto_update_interval">自動更新間隔(分鐘,最小值 15)</string>
<string name="title_core_loglevel">記錄層級</string>
<string name="title_outbound_domain_resolve_method">出口網域預解析方式</string>
<string name="title_outbound_domain_resolve_method">出站網域預解析方式 (outbound)</string>
<string name="title_mode">模式</string>
<string name="title_mode_help">輕觸以檢視說明</string>
<string name="title_language">語言</string>
<string name="title_ui_settings">介面顯示設定</string>
<string name="title_pref_ui_mode_night">深色模式</string>
<string name="title_pref_dynamic_color">開啟莫奈取色</string>
<string name="summary_pref_dynamic_color">僅在 Android 12+ 裝置上工作</string>
<string name="title_pref_use_hev_tunnel">啟用 Hev TUN 功能</string>
<string name="summary_pref_use_hev_tunnel">選擇啟用後 TUN 將使用 hev-socks5-tunnel 否則使用 xray-core</string>
<string name="title_pref_hev_tunnel_loglevel">HevTun 日誌級別</string>
<string name="title_pref_hev_tunnel_rw_timeout">HevTun 讀寫逾時(秒) (tcp,udp 預設 300,60)</string>
<string name="summary_pref_use_hev_tunnel">啟用後,TUN 會使用 hev-socks5-tunnel;否則使用 xray-core。</string>
<string name="title_pref_hev_tunnel_loglevel">Hev TUN 日誌層級</string>
<string name="title_pref_hev_tunnel_rw_timeout">Hev TUN 讀寫逾時(秒;TCP/UDP 預設 300/60)</string>
<string name="title_mode_settings">模式設定</string>
<string name="title_root_mode_enabled">啟用 Root 模式 (僅限 Root 使用者)</string>
<string name="summary_root_mode_enabled">透過 Root 權限啟用底層透明代理。此模式將不再透過 Android 常規系統 VPN 建立連線,而是直接接管系統底層所有網路流量。開啟後,原有的常规模式、應用分流及相關 VPN 設定將直接失效。</string>
<string name="summary_root_mode_enabled">使用 Root 權限實作底層透明代理。Root 模式不使用 Android 的 VPN 服務,而是直接處理網路流量。啟用期間,一般模式、個別應用程式路由及相關 VPN 設定不會生效。</string>
<string name="toast_root_required">此功能需要 Root 權限</string>
<string name="title_root_lan_sharing">區域網路 / 熱點網路共享 (僅限 Root 使用者)</string>
<string name="summary_root_lan_sharing">允許透過 Wi-Fi 熱點和 USB 共享網路連線的裝置走 VPN 代理流量</string>
<string name="title_root_lan_sharing">與區域網路 / 熱點裝置共用 VPN (僅限 Root 使用者)</string>
<string name="summary_root_lan_sharing">將 Wi-Fi 熱點和 USB 網路共享裝置的流量透過 VPN 轉送。</string>
<string name="title_logcat">Logcat</string>
<string name="title_logcat" translatable="false">Logcat</string>
<string name="logcat_copy">複製</string>
<string name="logcat_clear">清除</string>
<string name="logcat_share">分享日誌</string>
<string name="title_service_restart">重啟服務</string>
<string name="title_del_all_config">刪除設定</string>
<string name="title_service_restart">重新啟動服務</string>
<string name="title_del_all_config">刪除所有設定</string>
<string name="title_del_duplicate_config">刪除重複設定</string>
<string name="title_del_invalid_config">刪除無效設定</string>
<string name="title_export_all">匯出設定至剪貼簿</string>
<string name="title_sub_setting">訂閱分組設定</string>
<string name="title_export_all">將設定匯出至剪貼簿</string>
<string name="title_sub_setting">訂閱分組</string>
<string name="sub_setting_remarks">備註</string>
<string name="sub_setting_url">可選位址(url)</string>
<string name="sub_setting_user_agent">User Agent</string>
<string name="sub_setting_request_headers">請求頭(JSON 格式)</string>
<string name="sub_setting_filter">別名正規過濾</string>
<string name="sub_setting_url">URL(可選)</string>
<string name="sub_setting_user_agent" translatable="false">User Agent</string>
<string name="sub_setting_request_headers">請求標頭(JSON 格式)</string>
<string name="sub_setting_filter">備註篩選條件(正規表示式)</string>
<string name="sub_setting_enable">啟用更新</string>
<string name="sub_auto_update">啟用自動更新</string>
<string name="sub_allow_insecure_url">允許不安全的 HTTP 位址</string>
<string name="sub_setting_pre_profile">前置代理設定檔别名</string>
<string name="sub_setting_next_profile">落地代理設定檔別名</string>
<string name="sub_setting_pre_profile_tip">请确保設定檔别名存在并唯一</string>
<string name="sub_setting_pre_profile_tip">請確保設定檔別名存在且唯一</string>
<string name="sub_setting_entry_proxy_tip">所選代理會加在此訂閱中每個設定檔之前,作為該設定檔代理鏈的入口節點。</string>
<string name="sub_setting_exit_proxy_tip">所選代理會加在此訂閱中每個設定檔之後,作為該設定檔代理鏈的出口節點。</string>
<string name="toast_invalid_update_interval">更新間隔無效,最小值為 15 分鐘。</string>
<string name="title_sub_update">更新訂閱</string>
<string name="title_ping_all_server">偵測設定 Tcping</string>
<string name="title_real_ping_all_server">偵測設定真延遲</string>
<string name="title_ping_all_server">測試 TCP 延遲(TCPing)</string>
<string name="title_real_ping_all_server">測試實際延遲</string>
<string name="title_user_asset_setting">資源檔案</string>
<string name="title_sort_by_test_results">依偵測結果排序</string>
<string name="title_filter_config">過濾設定</string>
<string name="title_sort_by_test_results">依測試結果排序</string>
<string name="title_filter_config">篩選設定</string>
<string name="filter_config_all">所有</string>
<string name="summary_scan_qrcode">點擊熒幕打開相機掃描</string>
<string name="title_del_duplicate_config_count">刪除 %d 個重複配置</string>
<string name="title_del_config_count">刪除 %d 個配置</string>
<string name="title_import_config_count">匯入 %d 個配置</string>
<string name="title_export_config_count">匯出 %d 個配置</string>
<string name="title_update_config_count">更新 %d 個配置</string>
<string name="title_update_subscription_result">更新了 %1$d 個配置(%2$d 個成功,%3$d 個失敗,%4$d 個跳過)</string>
<string name="summary_scan_qrcode">點一下螢幕以開啟相機並掃描</string>
<string name="title_del_duplicate_config_count">刪除 %d 個重複設定</string>
<string name="title_del_config_count">刪除 %d 個設定</string>
<string name="title_import_config_count">匯入 %d 個設定</string>
<string name="title_export_config_count">匯出 %d 個設定</string>
<string name="title_update_config_count">更新 %d 個設定</string>
<string name="title_update_subscription_result">更新了 %1$d 個設定(%2$d 個成功,%3$d 個失敗,%4$d 個跳過)</string>
<string name="title_update_subscription_no_subscription">無訂閱</string>
<string name="toast_server_not_found_in_group">當前分組中未找到選中的伺服器</string>
<string name="toast_fragment_not_available">無法定位當前視圖</string>
<string name="title_locate_selected_config">定位所選配置</string>
<string name="toast_server_not_found_in_group">目前群組中找不到所選伺服器</string>
<string name="title_locate_selected_config">尋找所選設定檔</string>
<string name="tasker_start_service">啟動服務</string>
<string name="tasker_setting_confirm">確定</string>
<!-- RoutingSettingActivity -->
<string name="routing_settings_domain_strategy">網域策略</string>
<string name="routing_settings_title">轉送設定</string>
<string name="routing_settings_tips">用逗號(,)分隔,選擇填寫 domain、ip 或 process 中的一項</string>
<string name="routing_settings_title">路由設定</string>
<string name="routing_settings_tips">一條規則只有在所有已設定的比對條件同時符合時才會生效(AND)。規則會由上而下檢查,並套用第一條符合的規則。</string>
<string name="routing_settings_comma_tip">多個項目請用逗號(,)分隔。</string>
<string name="routing_settings_save">儲存</string>
<string name="routing_settings_delete">清除</string>
<string name="routing_settings_rule_title">路由規則設定</string>
<string name="routing_settings_add_rule">新增規則</string>
<string name="routing_settings_import_predefined_rulesets">匯入預先定義的規則集</string>
<string name="routing_settings_import_rulesets_tip">將刪除現有的規則集,是否確定繼續? </string>
<string name="routing_settings_import_rulesets_tip">將刪除現有的規則集。確定要繼續嗎?</string>
<string name="routing_settings_import_rulesets_from_clipboard">從剪貼簿匯入規則集</string>
<string name="routing_settings_import_rulesets_from_qrcode">從二維碼匯入規則集</string>
<string name="routing_settings_import_rulesets_from_qrcode">從 QR Code 匯入規則集</string>
<string name="routing_settings_export_rulesets_to_clipboard">匯出規則集至剪貼簿</string>
<string name="routing_settings_locked">鎖定中,匯入預設時不刪除此規則</string>
<string name="routing_settings_domain">domain</string>
<string name="routing_settings_ip">ip</string>
<string name="routing_settings_process">process (套件名稱 — 僅在使用 Xray 的 TUN、開啟 routeOnly 且 Android 10+ 時可用)</string>
<string name="routing_settings_process_select">選擇包名</string>
<string name="routing_settings_port">port</string>
<string name="routing_settings_protocol">protocol</string>
<string name="routing_settings_protocol_tip">[http,tls,bittorrent]</string>
<string name="routing_settings_network">network</string>
<string name="routing_settings_outbound_tag">outboundTag</string>
<string name="routing_settings_domain" translatable="false">domain</string>
<string name="routing_settings_ip" translatable="false">ip</string>
<string name="routing_settings_process">process (套件名稱 — 僅在使用 Xray TUN、開啟 routeOnly 且 Android 10+ 時可用)</string>
<string name="routing_settings_process_select">選取套件名稱</string>
<string name="routing_settings_port" translatable="false">port</string>
<string name="routing_settings_protocol" translatable="false">protocol</string>
<string name="routing_settings_protocol_tip" translatable="false">[http,tls,bittorrent]</string>
<string name="routing_settings_network" translatable="false">network</string>
<string name="routing_settings_outbound_tag_hint">proxy / direct / block / &lt;%1$s&gt;</string>
<string name="routing_settings_outbound_tag" translatable="false">outboundTag</string>
<string name="connection_test_pending">"測試連線能力"</string>
<string name="connection_test_testing">"測試中……"</string>
<string name="connection_test_testing_count">測試 %d 個配置中…</string>
<string name="connection_test_available">"成功:%d ms延遲"</string>
<string name="connection_test_error">"測試網際網路連線失敗:%s"</string>
<string name="connection_test_testing_count">正在測試 %d 個設定…</string>
<string name="connection_test_available">"連線成功:延遲 %1$s"</string>
<string name="server_test_delay_value">%1$d 毫秒</string>
<string name="connection_test_error">連線測試失敗:%s</string>
<string name="connection_test_fail">"無法使用網際網路"</string>
<string name="connection_test_error_status_code">"錯誤碼:(#%d)"</string>
<string name="connection_connected">"已連線,輕觸以檢查連線能力"</string>
<string name="connection_test_error_status_code">錯誤碼:#%d</string>
<string name="connection_connected">"已連線。輕觸以檢查連線。"</string>
<string name="connection_not_connected">"未連線"</string>
<string name="connection_runing_task_left">運行中的測試任務數:%s</string>
<string name="connection_running_task_left">正在執行的測試:%s</string>
<string name="import_subscription_success">匯入訂閱成功</string>
<string name="import_subscription_failure">匯入訂閱失敗</string>
<string name="menu_item_add_asset">新增資源</string>
<string name="menu_item_add_url">新增連結</string>
<string name="title_fragment_settings">分片(Fragment) 設定</string>
<string name="title_pref_fragment_packets">分片方式</string>
<string name="title_pref_fragment_length">分片包長(最小-最大)</string>
<string name="title_pref_fragment_interval">分片間隔(最小-最大)</string>
<string name="title_pref_fragment_enabled">啟用分片(Fragment)</string>
<string name="title_pref_fragment_maxsplit">分片最大分割數</string>
<string name="title_observatory_settings">連線觀測設定</string>
<string name="title_fragment_settings">Fragment 設定</string>
<string name="title_pref_fragment_packets">要分割的封包</string>
<string name="title_pref_fragment_length">分段長度(最小值-最大值)</string>
<string name="title_pref_fragment_interval">分段間隔(最小值-最大值)</string>
<string name="title_pref_fragment_enabled">啟用 Fragment</string>
<string name="title_pref_fragment_maxsplit">Fragment 最大分段數</string>
<string name="title_observatory_settings">連線觀測設定 (Observatory)</string>
<string name="title_pref_observatory_least_ping_interval">leastPing 探測間隔</string>
<string name="title_pref_observatory_least_load_interval">leastLoad 探測間隔</string>
<string name="title_pref_observatory_least_load_method">leastLoad HTTP 方法</string>
<string name="title_pref_observatory_least_load_sampling">leastLoad 取樣數量</string>
<string name="title_pref_observatory_least_load_timeout">leastLoad 探測逾時</string>
<string name="toast_invalid_observatory_duration">時間格式無效。請使用類似 3m 或 30s 的值。</string>
<string name="toast_invalid_observatory_duration">期間無效。請使用 3m 或 30s 之類的值。</string>
<string name="toast_invalid_observatory_sampling">取樣數量無效。請使用正數。</string>
<string name="update_check_for_update">檢查更新</string>
<string name="update_already_latest_version">当前已是最新版本</string>
<string name="update_new_version_found">發現新版本: %s</string>
<string name="update_already_latest_version">目前已是最新版本</string>
<string name="update_new_version_found">發現新版本:%s</string>
<string name="update_now">立即更新</string>
<string name="update_check_pre_release">檢查 Pre-release</string>
<string name="update_check_pre_release">檢查預發行版本</string>
<string name="update_checking_for_update">正在檢查更新中…</string>
<string name="title_policy_group_type">策略群組類型</string>
<string name="title_policy_group_subscription_id">來自訂閱分組</string>
<string name="title_policy_group_subscription_filter">別名正規過濾</string>
<string name="title_policy_group_test_outbounds">測試出口</string>
<string name="title_policy_group_fallback">備用出口(選填)</string>
<string name="title_policy_group_subscription_id">來自訂閱群組</string>
<string name="title_policy_group_subscription_filter">備註正規表示式篩選</string>
<string name="title_policy_group_test_outbounds">測試出站 (outbounds)</string>
<string name="title_policy_group_fallback">備用出站 (outbound,選填)</string>
<string name="server_proxy_chain_members">代理鏈成員</string>
<string name="server_proxy_chain_pick_members">點此選擇成員</string>
<string name="server_proxy_chain_member_unselected">請選擇成員</string>
<string name="server_proxy_chain_members_unselected">請為鏈路中的每一列選擇成員</string>
<string name="server_proxy_chain_members_unselected">請為代理鏈中的每一列選擇成員</string>
<string name="server_proxy_chain_members_insufficient">成員數量不足</string>
<string name="server_proxy_chain_members_invalid">無效的鏈路成員: %1$s</string>
<string name="server_proxy_chain_members_invalid">無效的代理鏈成員:%1$s</string>
<!-- BackupActivity -->
<string name="title_configuration_backup_restore">備份與恢復</string>
<string name="title_configuration_backup_restore">備份與還原</string>
<string name="title_configuration_backup">備份設定</string>
<string name="title_configuration_restore">還原設定</string>
<string name="title_configuration_share">分享設定</string>
<string name="title_webdav_config_setting">WebDAV 設定</string>
<string name="title_webdav_config_setting_unknown">請先設定 WebDAV</string>
<string name="title_webdav_url">WebDAV 伺服器位址</string>
<string name="title_webdav_url">WebDAV 伺服器 URL</string>
<string name="title_webdav_user">使用者名稱</string>
<string name="title_webdav_pass">密碼</string>
<string name="title_webdav_remote_path">遠端目錄(可選)</string>
<string name="share_method_qrcode">二維碼</string>
<string name="share_method_clipboard">匯出至剪貼簿</string>
<string name="share_method_full_content">匯出完整設定至剪貼簿</string>
<string name="share_method_qrcode">QR Code</string>
<string name="share_method_clipboard">複製設定連結</string>
<string name="share_method_full_content">複製完整設定</string>
<string name="action_edit">編輯</string>
<string name="action_delete">刪除</string>
<string name="action_close">關閉</string>
<string-array name="share_sub_method">
<item>二維碼</item>
<item>匯出至剪貼簿</item>
</string-array>
<string name="share_subscription_qrcode">QR Code</string>
<string name="share_subscription_clipboard">匯出至剪貼簿</string>
<string-array name="mode_entries">
<item>VPN</item>
<item>僅代理</item>
</string-array>
<string-array name="browser_dialer_mode">
<item>停用</item>
<item>OkHttp</item>
<item>WebView</item>
</string-array>
<string-array name="ui_mode_night">
<item>跟隨系統</item>
<item>淺色</item>
<item>深色</item>
</string-array>
<string-array name="preset_rulesets">
<item>繞過大陸 (Whitelist)</item>
<item>黑名單 (Blacklist)</item>
<item>全域 (Global)</item>
<item>伊朗 (Iran)</item>
<item>俄羅斯白名單 (Russia Whitelist)</item>
</string-array>
<string name="routing_preset_china_whitelist">中國大陸白名單</string>
<string name="routing_preset_china_blacklist">中國大陸黑名單</string>
<string name="routing_preset_global">全域</string>
<string name="routing_preset_iran_whitelist">伊朗白名單</string>
<string name="routing_preset_russia_whitelist">俄羅斯白名單</string>
<string-array name="vpn_bypass_lan">
<item>跟隨設定檔</item>
@@ -471,16 +487,57 @@
<item>解析後加入 DNS Hosts</item>
<item>解析後替換原網域名稱</item>
</string-array>
<string-array name="policy_group_type">
<item>最低延遲</item>
<item>最少卡頓</item>
<item>隨機選擇</item>
<item>輪詢</item>
<item>最低延遲 (leastPing)</item>
<item>最低負載 (leastLoad)</item>
<item>隨機選擇 (random)</item>
<item>輪詢 (roundRobin)</item>
</string-array>
<string-array name="config_backup_options">
<item>本地</item>
<item>WebDAV</item>
</string-array>
<string name="backup_location_local">本機</string>
<string name="backup_location_webdav" translatable="false">WebDAV</string>
<string name="acc_refresh">重新整理日誌</string>
<string name="toast_permission_denied_for">未授予 %1$s 權限</string>
<string name="acc_add_subscription">新增訂閱</string>
<string name="toast_malformed_json_detail">設定檔格式不正確:%1$s</string>
<string name="acc_add_asset">新增資源來源</string>
<string name="acc_download_file">下載資源檔案</string>
<string name="acc_qr_code">QR Code</string>
<string name="acc_copy_log">複製日誌</string>
<string name="acc_clear_log">清除日誌</string>
<string name="acc_add_rule">新增路由規則</string>
<string name="acc_start">啟動服務</string>
<string name="acc_stop">停止服務</string>
<string name="acc_back">返回</string>
<string name="acc_search">搜尋</string>
<string name="acc_add">新增設定</string>
<string name="acc_more">更多選項</string>
<string name="acc_share_subscription">分享訂閱連結</string>
<string name="acc_share_log">分享日誌</string>
<string name="acc_remove">移除代理鏈成員</string>
<string name="acc_add_member">新增代理鏈成員</string>
<string name="acc_start_scanner">啟動 QR Code 掃描器</string>
<string name="acc_stop_scanner">停止 QR Code 掃描器</string>
<string name="acc_turn_torch_on">開啟手電筒</string>
<string name="acc_turn_torch_off">關閉手電筒</string>
<string name="acc_select_image">選取要掃描的圖片</string>
<string name="acc_locked">匯入預設時保留此規則</string>
<string name="acc_open_menu">開啟導覽選單</string>
<string name="acc_edit">編輯</string>
<string name="acc_delete">刪除</string>
<string name="acc_save">儲存</string>
<string name="acc_update_subscriptions">更新訂閱</string>
<string name="acc_per_app_proxy_information">個別應用程式代理資訊</string>
<string name="permission_camera">相機</string>
<string name="permission_notification">通知</string>
<string name="permission_local_network">區域網路</string>
<string name="subscription_update_updating">正在更新訂閱:%1$s</string>
<string name="subscription_update_progress">正在測試 %2$s:%1$s</string>
<string name="tasker_blurb_start">啟動 %1$s</string>
<string name="tasker_blurb_stop">停止 %1$s</string>
<string name="connection_test_empty_message">沒有詳細資訊</string>
<string name="value_unknown">未知</string>
</resources>
+1 -1
View File
@@ -205,7 +205,7 @@
<item>6</item>
</string-array>
<string-array name="vpn_interface_address">
<string-array name="vpn_interface_address" translatable="false">
<item>10.10.14.x</item>
<item>10.1.0.x</item>
<item>10.0.0.x</item>
+187 -145
View File
@@ -3,23 +3,25 @@
<string name="app_name" translatable="false">v2rayNG</string>
<string name="app_widget_name">Switch</string>
<string name="app_tile_name">Switch</string>
<string name="app_tile_first_use">First use of this feature, please use the app to add server</string>
<string name="app_tile_first_use">Add a profile in the app before using this feature.</string>
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>
<string name="migration_success">Data migration success!</string>
<string name="migration_success">Data migration succeeded!</string>
<string name="action_stop_service">Stop service</string>
<string name="action_ok">OK</string>
<string name="action_cancel">Cancel</string>
<string name="migration_fail">Data migration failed!</string>
<string name="pull_down_to_refresh">Please pull down to refresh!</string>
<!-- Notifications -->
<string name="notification_action_stop_v2ray">Stop</string>
<string name="toast_permission_denied">Unable to obtain the permission</string>
<string name="toast_permission_denied_notification">Unable to obtain the notification permission</string>
<string name="notification_action_more">Click for more</string>
<string name="toast_services_start">Start Services</string>
<string name="toast_services_stop">Stop Services</string>
<string name="toast_services_success">Start Services Success</string>
<string name="toast_services_failure">Start Services Failure</string>
<string name="toast_permission_denied">Permission denied</string>
<string name="toast_permission_denied_notification">Notification permission denied</string>
<string name="notification_action_more">Tap for more</string>
<string name="toast_services_start">Starting service</string>
<string name="toast_services_stop">Stopping service</string>
<string name="toast_services_success">Service started successfully</string>
<string name="toast_services_failure">Failed to start service</string>
<!--ServerActivity-->
<string name="title_server">Config</string>
@@ -27,9 +29,9 @@
<string name="menu_item_save_config">Save config</string>
<string name="menu_item_edit_config">Edit config</string>
<string name="menu_item_del_config">Delete config</string>
<string name="menu_item_import_config_qrcode">Import from QRcode</string>
<string name="menu_item_import_config_qrcode">Import from QR code</string>
<string name="menu_item_import_config_clipboard">Import from Clipboard</string>
<string name="menu_item_import_config_local">Import from locally</string>
<string name="menu_item_import_config_local">Import from a local file</string>
<string name="menu_item_import_config_policy_group">Add [Policy group]</string>
<string name="menu_item_import_config_proxy_chain">Add [Proxy chain]</string>
<string name="menu_item_import_config_manually_vmess">Add [VMess]</string>
@@ -38,7 +40,7 @@
<string name="menu_item_import_config_manually_socks">Add [SOCKS]</string>
<string name="menu_item_import_config_manually_http">Add [HTTP]</string>
<string name="menu_item_import_config_manually_trojan">Add [Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">Add [Wireguard]</string>
<string name="menu_item_import_config_manually_wireguard">Add [WireGuard]</string>
<string name="menu_item_import_config_manually_hysteria2">Add [Hysteria2]</string>
<string name="confirm_delete_visible_profiles">Are you sure you want to delete all profiles currently shown?</string>
<string name="confirm_delete_duplicate_profiles">Are you sure you want to delete all duplicate profiles currently shown?</string>
@@ -76,62 +78,62 @@
<string name="server_lab_path_quic">QUIC key</string>
<string name="server_lab_path_kcp">kcp seed</string>
<string name="server_lab_path_grpc">gRPC serviceName</string>
<string name="server_lab_stream_security">TLS</string>
<string name="server_lab_stream_security" translatable="false">TLS</string>
<string name="server_lab_stream_fingerprint">Fingerprint</string>
<string name="server_lab_stream_alpn">Alpn</string>
<string name="server_lab_stream_alpn" translatable="false">ALPN</string>
<string name="server_lab_allow_insecure">allowInsecure</string>
<string name="server_lab_sni">SNI</string>
<string name="server_lab_sni" translatable="false">SNI</string>
<string name="server_lab_address3">address</string>
<string name="server_lab_port3">port</string>
<string name="server_lab_id3">password</string>
<string name="server_lab_security3">security</string>
<string name="server_lab_id4">Password(Optional)</string>
<string name="server_lab_security4">User(Optional)</string>
<string name="server_lab_id4">Password (optional)</string>
<string name="server_lab_security4">User (optional)</string>
<string name="server_lab_encryption">encryption</string>
<string name="server_lab_flow">flow</string>
<string name="server_lab_public_key">PublicKey</string>
<string name="server_lab_preshared_key">PreSharedKey(optional)</string>
<string name="server_lab_preshared_key">PreSharedKey (optional)</string>
<string name="server_lab_short_id">ShortId</string>
<string name="server_lab_spider_x">SpiderX</string>
<string name="server_lab_mldsa65_verify">Mldsa65Verify</string>
<string name="server_lab_spider_x" translatable="false">SpiderX</string>
<string name="server_lab_mldsa65_verify" translatable="false">mldsa65Verify</string>
<string name="server_lab_secret_key">SecretKey</string>
<string name="server_lab_reserved">Reserved(Optional, separated by commas)</string>
<string name="server_lab_reserved">Reserved (optional, separated by commas)</string>
<string name="server_lab_local_address">Local address (optional IPv4/IPv6, separated by commas)</string>
<string name="server_lab_local_mtu">Mtu(optional, default 1420)</string>
<string name="server_lab_kcp_mtu">mKCP MTU (Optional, core default 1350)</string>
<string name="server_lab_kcp_tti">mKCP TTI (Optional, core default 50)</string>
<string name="server_lab_local_mtu">MTU (optional, default 1420)</string>
<string name="server_lab_kcp_mtu">mKCP MTU (optional, core default 1350)</string>
<string name="server_lab_kcp_tti">mKCP TTI (optional, core default 50)</string>
<string name="toast_success">Success</string>
<string name="toast_failure">Failure</string>
<string name="toast_none_data">There is nothing</string>
<string name="toast_none_data">No data available</string>
<string name="toast_incorrect_protocol">Incorrect protocol</string>
<string name="toast_decoding_failed">Decoding failed</string>
<string name="title_file_chooser">Select a config</string>
<string name="toast_require_file_manager">Please install a File Manager.</string>
<string name="toast_require_file_manager">Please install a file manager.</string>
<string name="server_customize_config">Customize config</string>
<string name="toast_config_file_invalid">Invalid config</string>
<string name="server_lab_content">Content</string>
<string name="toast_none_data_clipboard">There is no data in the clipboard</string>
<string name="toast_invalid_url">Invalid URL</string>
<string name="toast_insecure_url_protocol">Please do not use the insecure HTTP protocol subscription address</string>
<string name="server_lab_need_inbound">Ensure inbounds port is consistent with the settings</string>
<string name="toast_malformed_josn">Config malformed</string>
<string name="server_lab_request_host6">Host(SNI)(Optional)</string>
<string name="toast_insecure_url_protocol">Do not use an insecure HTTP subscription URL</string>
<string name="server_lab_need_inbound">Make sure the inbound port matches the settings</string>
<string name="toast_malformed_json">Invalid configuration.</string>
<string name="server_lab_request_host6">Host (SNI) (optional)</string>
<string name="toast_action_not_allowed">Action not allowed</string>
<string name="server_obfs_password">Obfs password</string>
<string name="server_lab_port_hop">Port Hopping(will override the port)</string>
<string name="server_lab_port_hop_interval">Port Hopping Interval</string>
<string name="server_lab_bandwidth_down">Bandwidth down (Supported units: k/m/g/t)</string>
<string name="server_lab_bandwidth_up">Bandwidth up (Supported units: k/m/g/t)</string>
<string name="server_lab_port_hop">Port hopping (overrides the port)</string>
<string name="server_lab_port_hop_interval">Port hopping interval (seconds)</string>
<string name="server_lab_bandwidth_down">Download bandwidth (supported units: k/m/g/t)</string>
<string name="server_lab_bandwidth_up">Upload bandwidth (supported units: k/m/g/t)</string>
<string name="server_lab_xhttp_mode">XHTTP Mode</string>
<string name="server_lab_xhttp_extra">XHTTP Extra raw JSON, format: { XHTTPObject }</string>
<string name="server_lab_final_mask">finalMask raw JSON, format: { FinalMaskObject }</string>
<string name="server_lab_ech_config_list">EchConfigList</string>
<string name="server_lab_verify_peer_cert_by_name">Verify Peer Cert By Name</string>
<string name="server_lab_ech_config_list" translatable="false">echConfigList</string>
<string name="server_lab_verify_peer_cert_by_name">Verify peer certificate by name</string>
<string name="server_lab_pinned_ca256">Certificate fingerprint (SHA-256)</string>
<string name="server_lab_browser_dialer">Enable Browser Dialer</string>
<string name="server_lab_browser_dialer_tip">Only supports xhttp (packet-up) and ws outbound; TLS-related settings may be ignored or conflict</string>
<string name="toast_allow_insecure_deprecated">Current node uses an unencrypted connection. Your communication may be directly viewed by network intermediate facilities controlled by authoritarian governments.\nFor security reasons, such nodes cannot be connected via Xray core version 26.2.6+.\nIf it is a self-built node, please enable security encryption such as TLS, or pin the certificate pinnedCA256.\nIf it is a provider node, please contact the service provider to complete the technical upgrade. If the service provider refuses to cooperate, it is recommended to switch to a provider that pays more attention to user security.\nFor more information, please visit https://github.com/2dust/v2rayN/discussions/9460</string>
<string name="pinned_ca256_action_fetch">Fetch and fill certificate fingerprint</string>
<string name="pinned_ca256_action_fetch">Fetch certificate fingerprint</string>
<string name="toast_fetch_cert_sha256_success">Certificate fingerprint fetched successfully</string>
<string name="toast_fetch_cert_sha256_failed">Failed to fetch certificate fingerprint</string>
@@ -140,13 +142,13 @@
<string name="menu_item_add_asset">Add asset</string>
<string name="menu_item_add_file">Add files</string>
<string name="menu_item_add_url">Add URL</string>
<string name="menu_item_scan_qrcode">Scan QRcode</string>
<string name="title_url">URL</string>
<string name="menu_item_scan_qrcode">Scan QR code</string>
<string name="title_url" translatable="false">URL</string>
<string name="menu_item_download_file">Download files</string>
<string name="title_user_asset_add_url">Add asset URL</string>
<string name="msg_file_not_found">File not found</string>
<string name="msg_remark_is_duplicate">The remarks already exists</string>
<string name="asset_geo_files_sources">Geo files source (optional)</string>
<string name="msg_remark_is_duplicate">This name already exists</string>
<string name="asset_geo_files_sources">Geo file source (optional)</string>
<!-- PerAppProxyActivity -->
<string name="msg_dialog_progress">Loading</string>
@@ -155,13 +157,13 @@
<string name="menu_item_invert_selection">Invert selection</string>
<string name="msg_enter_keywords">Enter keywords</string>
<string name="switch_bypass_apps_mode">Bypass Mode</string>
<string name="menu_item_select_proxy_app">Auto select proxy app</string>
<string name="menu_item_select_proxy_app">Auto-select apps to be proxied</string>
<string name="msg_downloading_content">Downloading content</string>
<string name="menu_item_export_proxy_app">Export to Clipboard</string>
<string name="menu_item_import_proxy_app">Import from Clipboard</string>
<string name="per_app_proxy_settings">Per-app settings</string>
<string name="per_app_proxy_settings_enable">Enable per-app</string>
<string name="app_picker_unknown_app">Unknown app (unidentified UID)</string>
<string name="app_picker_unknown_app">Unknown app (UID not recognized)</string>
<!-- Preferences -->
<string name="title_settings">Settings</string>
@@ -169,7 +171,7 @@
<string name="title_core_settings">Core Settings</string>
<string name="title_vpn_settings">VPN Settings</string>
<string name="title_pref_per_app_proxy">Per-app proxy</string>
<string name="summary_pref_per_app_proxy">General: Checked apps use proxy, unchecked apps connect directly; \nBypass mode: checked apps connect directly, unchecked apps use proxy. \nThe option to automatically select proxy applications is in the menu</string>
<string name="summary_pref_per_app_proxy">General: checked apps use the proxy, and unchecked apps connect directly;\nBypass mode: checked apps connect directly, and unchecked apps use the proxy.\nThe option to automatically select apps that should use the proxy is in the menu.</string>
<string name="title_pref_is_booted">Auto connect at startup</string>
<string name="summary_pref_is_booted">Automatically connects to the selected server at startup, which may be unsuccessful</string>
@@ -185,8 +187,8 @@
<string name="title_mux_settings">Mux Settings</string>
<string name="title_pref_mux_enabled">Enable Mux</string>
<string name="summary_pref_mux_enabled">Faster, but it may cause unstable connectivity\nCustomize how to handle TCP, UDP and QUIC below</string>
<string name="title_pref_mux_concurency">TCP connections(range -1 to 1024)</string>
<string name="title_pref_mux_xudp_concurency">XUDP connections(range -1 to 1024)</string>
<string name="title_pref_mux_concurrency">TCP connections (range -1 to 1024)</string>
<string name="title_pref_mux_xudp_concurrency">XUDP connections (range -1 to 1024)</string>
<string name="title_pref_mux_xudp_quic">Handling of QUIC in mux tunnel</string>
<string-array name="mux_xudp_quic_entries">
<item>reject</item>
@@ -195,19 +197,18 @@
</string-array>
<string name="title_pref_speed_enabled">Enable speed display</string>
<string name="summary_pref_speed_enabled">Display current speed in the notification.\nNotification icon would change based on
usage.</string>
<string name="summary_pref_speed_enabled">Show current speeds in the notification.\nThe icon indicates whether proxy or direct traffic is dominant.</string>
<string name="title_pref_sniffing_enabled">Enable Sniffing</string>
<string name="summary_pref_sniffing_enabled">Try sniff domain from the packet (default on)</string>
<string name="summary_pref_sniffing_enabled">Detect destination domains from traffic (enabled by default).</string>
<string name="title_pref_route_only_enabled">Enable routeOnly</string>
<string name="summary_pref_route_only_enabled">Use the sniffed domain name for routing only, and keep the target address as the IP address.</string>
<string name="title_pref_local_dns_enabled">Enable local DNS</string>
<string name="summary_pref_local_dns_enabled">DNS processed by core‘s DNS module (Recommended if you need routing bypassing LAN and mainland addresses)</string>
<string name="title_pref_fake_dns_enabled">Enable fake DNS</string>
<string name="summary_pref_fake_dns_enabled">Local DNS returns fake IP addresses (faster, but it may not work for some apps)</string>
<string name="title_pref_fake_dns_enabled">Enable FakeDNS</string>
<string name="summary_pref_fake_dns_enabled">FakeDNS returns synthetic IP addresses for domain lookups (faster, but may not work with some apps).</string>
<string name="title_pref_ipv6_enabled">Enable IPv6</string>
<string name="summary_pref_ipv6_enabled">Add IPv6 address and routes to the VPN interface</string>
@@ -215,29 +216,29 @@
<string name="title_pref_prefer_ipv6">Prefer IPv6</string>
<string name="summary_pref_prefer_ipv6">Prefer IPv6 addresses when resolving domain names</string>
<string name="title_pref_remote_dns">Remote DNS (udp/tcp/https/quic)(Optional)</string>
<string name="summary_pref_remote_dns">DNS</string>
<string name="title_pref_remote_dns">Remote DNS (UDP/TCP/HTTPS/QUIC, optional)</string>
<string name="summary_pref_remote_dns" translatable="false">DNS</string>
<string name="title_pref_vpn_dns">VPN DNS (only IPv4/v6)</string>
<string name="title_pref_vpn_bypass_lan">Does VPN bypass LAN</string>
<string name="title_pref_vpn_dns">VPN DNS (IPv4/IPv6 only)</string>
<string name="title_pref_vpn_bypass_lan">Bypass LAN in VPN mode</string>
<string name="title_pref_vpn_interface_address">VPN Interface Address</string>
<string name="title_pref_vpn_mtu">VPN MTU (default 1500)</string>
<string name="title_pref_domestic_dns">Domestic DNS (Optional)</string>
<string name="summary_pref_domestic_dns">DNS</string>
<string name="title_pref_domestic_dns">Direct DNS (optional)</string>
<string name="summary_pref_domestic_dns" translatable="false">DNS</string>
<string name="title_pref_dns_hosts">DNS hosts (Format: domain:address,…)</string>
<string name="title_pref_dns_hosts">DNS host mappings (format: domain:address,…)</string>
<string name="summary_pref_dns_hosts">domain:address,…</string>
<string name="title_pref_delay_test_url">True delay test url </string>
<string name="summary_pref_delay_test_url">Url</string>
<string name="title_pref_real_ping_concurrency">True delay test concurrency</string>
<string name="title_pref_delay_test_url">Real delay test URL</string>
<string name="summary_pref_delay_test_url" translatable="false">URL</string>
<string name="title_pref_real_ping_concurrency">Concurrent real-delay tests</string>
<string name="title_pref_ip_api_url">Current connection info test url</string>
<string name="summary_pref_ip_api_url">Url</string>
<string name="title_pref_ip_api_url">Current connection info test URL</string>
<string name="summary_pref_ip_api_url" translatable="false">URL</string>
<string name="title_pref_proxy_sharing_enabled">Allow connections from the LAN</string>
<string name="summary_pref_proxy_sharing_enabled">Other devices can connect to proxy by your IP address through local proxy. Only enable in trusted networks to avoid unauthorized connections</string>
@@ -246,11 +247,11 @@
<string name="title_pref_socks_port">Local proxy port</string>
<string name="title_pref_enable_local_proxy">Enable local proxy</string>
<string name="summary_pref_enable_local_proxy">When disabled, no SOCKS proxy is available, so subscription updates and similar actions cannot use the proxy</string>
<string name="title_pref_socks_enable_udp">SOCKS5 UDP</string>
<string name="title_pref_socks_enable_udp" translatable="false">SOCKS5 UDP</string>
<string name="summary_pref_socks_enable_udp">SOCKS5 authentication is not fully secure when using UDP.</string>
<string name="summary_pref_socks_port">Local proxy port</string>
<string name="title_pref_dynamic_socks_port">Enable dynamic local proxy port</string>
<string name="summary_pref_dynamic_socks_port">Generate a random local proxy port each time the inbound is created</string>
<string name="summary_pref_dynamic_socks_port">Use a random local proxy port for each inbound</string>
<string name="title_pref_socks_username">Local proxy username (optional)</string>
<string name="summary_pref_socks_username">Username</string>
<string name="title_pref_socks_password">Local proxy password (optional)</string>
@@ -263,81 +264,85 @@
<string name="summary_pref_confirm_remove">Whether deleting a config requires a second confirmation by the user</string>
<string name="title_pref_append_http_proxy">Append HTTP Proxy to VPN</string>
<string name="summary_pref_append_http_proxy">HTTP proxy will be used directly from (browser/ some supported apps), without going through the virtual NIC device (Android 10+)</string>
<string name="title_pref_append_http_proxy">Add HTTP proxy to VPN</string>
<string name="summary_pref_append_http_proxy">Allow browsers and supported apps to use the HTTP proxy directly instead of the virtual network interface (Android 10+).</string>
<string name="title_pref_double_column_display">Enable double column display</string>
<string name="summary_pref_double_column_display">The profile list is displayed in double columns, allowing more content to be displayed on the screen.</string>
<string name="title_pref_double_column_display">Use two-column layout</string>
<string name="summary_pref_double_column_display">Display the profile list in two columns to fit more content on screen.</string>
<string name="title_pref_group_all_display">Enable show all groups</string>
<string name="summary_pref_group_all_display">Add an extra "All Tabs" page</string>
<string name="title_pref_group_all_display">Show an "All" group tab</string>
<string name="summary_pref_group_all_display">Combine profiles from every subscription group in one tab.</string>
<!-- AboutActivity -->
<string name="title_pref_feedback">Feedback</string>
<string name="summary_pref_feedback">Feedback enhancements or bugs to GitHub</string>
<string name="summary_pref_tg_group">Join Telegram Group</string>
<string name="summary_pref_feedback">Suggest improvements or report bugs on GitHub</string>
<string name="summary_pref_tg_group">Join the Telegram group</string>
<string name="toast_tg_app_not_found">Telegram app not found</string>
<string name="title_privacy_policy">Privacy policy</string>
<string name="title_qr_code">QR code</string>
<string name="title_about">About</string>
<string name="title_source_code">Source code</string>
<string name="title_oss_license">Open Source licenses</string>
<string name="title_oss_license">Open-source licenses</string>
<string name="title_tg_channel">Telegram channel</string>
<string name="title_pref_promotion">Promotion</string>
<string name="title_pref_auto_update_subscription">Automatic update subscriptions</string>
<string name="title_pref_auto_update_subscription">Automatically update subscriptions</string>
<string name="summary_pref_auto_update_subscription">Update your subscriptions automatically at set intervals in the background. Depending on the device, this feature may not always work</string>
<string name="title_pref_auto_update_interval">Auto Update Interval (Minutes, Min value 15)</string>
<string name="title_pref_auto_update_interval">Automatic update interval (minutes; minimum 15)</string>
<string name="title_core_loglevel">Log Level</string>
<string name="title_outbound_domain_resolve_method">Outbound domain pre-resolve method</string>
<string name="title_outbound_domain_resolve_method">Outbound domain resolution</string>
<string name="title_mode">Mode</string>
<string name="title_mode_help">Click me for more help</string>
<string name="title_language">Language</string>
<string name="title_ui_settings">UI settings</string>
<string name="title_pref_ui_mode_night">UI mode settings</string>
<string name="title_pref_use_hev_tunnel">Enable Hev TUN Feature</string>
<string name="title_pref_dynamic_color">Enable dynamic color</string>
<string name="summary_pref_dynamic_color">Only works on Android 12+ devices</string>
<string name="title_pref_use_hev_tunnel">Use Hev TUN</string>
<string name="summary_pref_use_hev_tunnel">When enabled, TUN will use hev-socks5-tunnel; otherwise, it will use xray-core.</string>
<string name="title_pref_hev_tunnel_loglevel">Hev Tun Log Level</string>
<string name="title_pref_hev_tunnel_rw_timeout">Hev Tun read/write timeout (seconds) (tcp,udp default 300,60)</string>
<string name="title_pref_hev_tunnel_loglevel">Hev TUN log level</string>
<string name="title_pref_hev_tunnel_rw_timeout">Hev TUN read/write timeout (seconds; TCP/UDP defaults: 300/60)</string>
<string name="title_mode_settings">Mode Settings</string>
<string name="title_root_mode_enabled">Root mode enabled (Root Users)</string>
<string name="summary_root_mode_enabled">Enable low-level transparent proxying via root privileges. This mode bypasses the standard Android system VPN to directly take over all underlying network traffic. Once enabled, the original regular mode, per-app routing, and related VPN settings will become completely invalid.</string>
<string name="title_root_mode_enabled">Enable root mode (root users)</string>
<string name="summary_root_mode_enabled">Use root access for low-level transparent proxying. Root mode handles network traffic directly instead of using the Android VPN service. Standard mode, per-app routing, and VPN-related settings do not apply while root mode is enabled.</string>
<string name="toast_root_required">Root access is required for this feature</string>
<string name="title_root_lan_sharing">LAN / tethering sharing (Root Users)</string>
<string name="summary_root_lan_sharing">Route Wi-Fi hotspot and USB-tethered devices through the VPN</string>
<string name="title_root_lan_sharing">Share VPN with LAN / tethered devices (root users)</string>
<string name="summary_root_lan_sharing">Route traffic from Wi-Fi hotspot and USB-tethered devices through the VPN.</string>
<string name="title_logcat">Logcat</string>
<string name="title_logcat" translatable="false">Logcat</string>
<string name="logcat_copy">Copy</string>
<string name="logcat_clear">Clear</string>
<string name="logcat_share">Share log</string>
<string name="title_service_restart">Service restart</string>
<string name="title_del_all_config">Delete config</string>
<string name="title_del_duplicate_config">Delete duplicate config</string>
<string name="title_del_invalid_config">Delete invalid config</string>
<string name="title_service_restart">Restart service</string>
<string name="title_del_all_config">Delete configs</string>
<string name="title_del_duplicate_config">Delete duplicate configs</string>
<string name="title_del_invalid_config">Delete invalid configs</string>
<string name="title_export_all">Export configs to clipboard</string>
<string name="title_sub_setting">Subscription group setting</string>
<string name="sub_setting_remarks">remarks</string>
<string name="title_sub_setting">Subscriptions</string>
<string name="sub_setting_remarks">Remarks</string>
<string name="sub_setting_url">Optional URL</string>
<string name="sub_setting_user_agent">User Agent</string>
<string name="sub_setting_user_agent" translatable="false">User Agent</string>
<string name="sub_setting_request_headers">Request Headers (JSON format)</string>
<string name="sub_setting_filter">Remarks regular filter</string>
<string name="sub_setting_filter">Remarks filter (regular expression)</string>
<string name="sub_setting_enable">Enable update</string>
<string name="sub_auto_update">Enable automatic update</string>
<string name="sub_allow_insecure_url">Allow insecure HTTP address</string>
<string name="sub_setting_pre_profile">Previous proxy config remarks</string>
<string name="sub_setting_next_profile">Next proxy config remarks</string>
<string name="sub_setting_pre_profile_tip">The config remarks exist and are unique</string>
<string name="sub_setting_pre_profile">Entry proxy</string>
<string name="sub_setting_next_profile">Exit proxy</string>
<string name="sub_setting_pre_profile_tip">Make sure the config remarks exist and are unique</string>
<string name="sub_setting_entry_proxy_tip">The selected proxy is added before every profile in this subscription as the entry link in the proxy chain for that profile.</string>
<string name="sub_setting_exit_proxy_tip">The selected proxy is added after every profile in this subscription as the exit link in the proxy chain for that profile.</string>
<string name="toast_invalid_update_interval">Invalid update interval. Minimum is 15 minutes.</string>
<string name="title_sub_update">Update subscription</string>
<string name="title_ping_all_server">Tcping config</string>
<string name="title_real_ping_all_server">Real delay config</string>
<string name="title_ping_all_server">Test TCP delays (TCPing)</string>
<string name="title_real_ping_all_server">Test real delays</string>
<string name="title_user_asset_setting">Asset files</string>
<string name="title_sort_by_test_results">Sorting by test results</string>
<string name="title_filter_config">Filter config</string>
<string name="title_sort_by_test_results">Sort by test results</string>
<string name="title_filter_config">Filter configs</string>
<string name="filter_config_all">All</string>
<string name="summary_scan_qrcode">Click screen open the camera scan</string>
<string name="summary_scan_qrcode">Tap the screen to open the camera and scan</string>
<string name="title_del_duplicate_config_count">Delete %d duplicate configs</string>
<string name="title_del_config_count">Delete %d configs</string>
<string name="title_import_config_count">Import %d configs</string>
@@ -346,8 +351,7 @@
<string name="title_update_subscription_result">Updated %1$d configs (%2$d success, %3$d failed, %4$d skipped)</string>
<string name="title_update_subscription_no_subscription">No subscriptions</string>
<string name="toast_server_not_found_in_group">Selected server not found in current group</string>
<string name="toast_fragment_not_available">Unable to locate current view</string>
<string name="title_locate_selected_config">Locate the selected config</string>
<string name="title_locate_selected_config">Find selected configuration</string>
<string name="tasker_start_service">Start Service</string>
<string name="tasker_setting_confirm">Confirm</string>
@@ -355,40 +359,42 @@
<!-- RoutingSettingActivity -->
<string name="routing_settings_domain_strategy">Domain strategy</string>
<string name="routing_settings_title">Routing Settings</string>
<string name="routing_settings_tips">Separated by commas(,), \nchoose domain or ip or process</string>
<string name="routing_settings_tips">A rule applies only when every configured matching condition is satisfied (AND). Rules are checked from top to bottom; the first matching rule is applied.</string>
<string name="routing_settings_comma_tip">Separate multiple entries with commas (,).</string>
<string name="routing_settings_save">Save</string>
<string name="routing_settings_delete">Clear</string>
<string name="routing_settings_rule_title">Routing Rule Settings</string>
<string name="routing_settings_add_rule">Add rule</string>
<string name="routing_settings_import_predefined_rulesets">Import predefined rulesets</string>
<string name="routing_settings_import_rulesets_tip">Existing rulesets will be deleted, are you sure to continue?</string>
<string name="routing_settings_import_rulesets_tip">Existing rulesets will be deleted. Continue?</string>
<string name="routing_settings_import_rulesets_from_clipboard">Import ruleset from clipboard</string>
<string name="routing_settings_import_rulesets_from_qrcode">Import ruleset from QRcode</string>
<string name="routing_settings_import_rulesets_from_qrcode">Import ruleset from QR code</string>
<string name="routing_settings_export_rulesets_to_clipboard">Export ruleset to clipboard</string>
<string name="routing_settings_locked">Locked, keep this rule when import presets</string>
<string name="routing_settings_domain">domain</string>
<string name="routing_settings_ip">ip</string>
<string name="routing_settings_locked">Locked; keep this rule when importing presets</string>
<string name="routing_settings_domain" translatable="false">domain</string>
<string name="routing_settings_ip" translatable="false">ip</string>
<string name="routing_settings_process">process (Package Name — only supported when using Xray TUN, routeOnly enabled, and Android 10+)</string>
<string name="routing_settings_process_select">Select package name</string>
<string name="routing_settings_port">port</string>
<string name="routing_settings_protocol">protocol</string>
<string name="routing_settings_protocol_tip">[http,tls,bittorrent]</string>
<string name="routing_settings_network">network</string>
<string name="routing_settings_outbound_tag_hint" translatable="false">proxy / direct / block / &lt;remarks&gt;</string>
<string name="routing_settings_outbound_tag">outboundTag</string>
<string name="routing_settings_port" translatable="false">port</string>
<string name="routing_settings_protocol" translatable="false">protocol</string>
<string name="routing_settings_protocol_tip" translatable="false">[http,tls,bittorrent]</string>
<string name="routing_settings_network" translatable="false">network</string>
<string name="routing_settings_outbound_tag_hint">proxy / direct / block / &lt;%1$s&gt;</string>
<string name="routing_settings_outbound_tag" translatable="false">outboundTag</string>
<string name="connection_test_pending">Check Connectivity</string>
<string name="connection_test_pending">Check connectivity</string>
<string name="connection_test_testing">Testing…</string>
<string name="connection_test_testing_count">Testing %d configs…</string>
<string name="connection_test_available">Success: Connection took %dms</string>
<string name="connection_test_error">Fail to detect internet connection: %s</string>
<string name="connection_test_fail">Internet Unavailable</string>
<string name="connection_test_available">Connection succeeded in %1$s</string>
<string name="server_test_delay_value">%1$d ms</string>
<string name="connection_test_error">Connection test failed: %s</string>
<string name="connection_test_fail">Internet unavailable</string>
<string name="connection_test_error_status_code">Error code: #%d</string>
<string name="connection_connected">Connected, tap to check connection</string>
<string name="connection_connected">Connected. Tap to check connection.</string>
<string name="connection_not_connected">Not connected</string>
<string name="connection_runing_task_left">Number of running test tasks: %s</string>
<string name="connection_running_task_left">Tests running: %s</string>
<string name="import_subscription_success">Subscription imported Successfully</string>
<string name="import_subscription_success">Subscription imported successfully</string>
<string name="import_subscription_failure">Import subscription failed</string>
<string name="title_fragment_settings">Fragment Settings</string>
<string name="title_pref_fragment_packets">Fragment Packets</string>
@@ -399,7 +405,7 @@
<string name="title_observatory_settings">Observatory Settings</string>
<string name="title_pref_observatory_least_ping_interval">leastPing Interval</string>
<string name="title_pref_observatory_least_load_interval">leastLoad Interval</string>
<string name="title_pref_observatory_least_load_method">leastLoad Mode</string>
<string name="title_pref_observatory_least_load_method">leastLoad HTTP method</string>
<string name="title_pref_observatory_least_load_sampling">leastLoad Sampling</string>
<string name="title_pref_observatory_least_load_timeout">leastLoad Timeout</string>
<string name="toast_invalid_observatory_duration">Invalid duration. Use a value like 3m or 30s.</string>
@@ -409,19 +415,19 @@
<string name="update_already_latest_version">Already on the latest version</string>
<string name="update_new_version_found">New version found: %s</string>
<string name="update_now">Update now</string>
<string name="update_check_pre_release">Check Pre-release</string>
<string name="update_check_pre_release">Check pre-release versions</string>
<string name="update_checking_for_update">Checking for update…</string>
<string name="title_policy_group_type">Policy group type</string>
<string name="title_policy_group_subscription_id">From subscription group</string>
<string name="title_policy_group_subscription_filter">Remarks regular filter</string>
<string name="title_policy_group_subscription_filter">Remarks regex filter</string>
<string name="title_policy_group_test_outbounds">Test outbounds</string>
<string name="title_policy_group_fallback">Fallback outbound (optional)</string>
<string name="server_proxy_chain_members">Proxy chain members</string>
<string name="server_proxy_chain_pick_members">Tap here to pick member</string>
<string name="server_proxy_chain_pick_members">Tap here to pick a member</string>
<string name="server_proxy_chain_member_unselected">Select a member</string>
<string name="server_proxy_chain_members_unselected">Please select member for each chain row</string>
<string name="server_proxy_chain_members_unselected">Please select a member for each chain row</string>
<string name="server_proxy_chain_members_insufficient">Insufficient members</string>
<string name="server_proxy_chain_members_invalid">Invalid chain members: %1$s</string>
@@ -437,17 +443,15 @@
<string name="title_webdav_pass">Password</string>
<string name="title_webdav_remote_path">Remote directory (optional)</string>
<string name="share_method_qrcode">QRcode</string>
<string name="share_method_clipboard">Export to clipboard</string>
<string name="share_method_full_content">Export full config to clipboard</string>
<string name="share_method_qrcode">QR code</string>
<string name="share_method_clipboard">Copy profile link</string>
<string name="share_method_full_content">Copy full configuration</string>
<string name="action_edit">Edit</string>
<string name="action_delete">Delete</string>
<string name="action_close">Close</string>
<string-array name="share_sub_method">
<item>QRcode</item>
<item>Export to clipboard</item>
</string-array>
<string name="share_subscription_qrcode">QR code</string>
<string name="share_subscription_clipboard">Export to clipboard</string>
<string-array name="mode_entries">
<item>VPN</item>
@@ -466,13 +470,11 @@
<item>Dark</item>
</string-array>
<string-array name="preset_rulesets">
<item>China Whitelist</item>
<item>China Blacklist</item>
<item>Global</item>
<item>Iran Whitelist</item>
<item>Russia Whitelist</item>
</string-array>
<string name="routing_preset_china_whitelist">China Whitelist</string>
<string name="routing_preset_china_blacklist">China Blacklist</string>
<string name="routing_preset_global">Global</string>
<string name="routing_preset_iran_whitelist">Iran Whitelist</string>
<string name="routing_preset_russia_whitelist">Russia Whitelist</string>
<string-array name="vpn_bypass_lan">
<item>Follow config</item>
@@ -493,9 +495,49 @@
<item>Round Robin</item>
</string-array>
<string-array name="config_backup_options">
<item>Local</item>
<item>WebDAV</item>
</string-array>
<string name="backup_location_local">Local</string>
<string name="backup_location_webdav" translatable="false">WebDAV</string>
<string name="acc_refresh">Refresh log</string>
<string name="toast_permission_denied_for">%1$s permission denied</string>
<string name="acc_add_subscription">Add subscription</string>
<string name="toast_malformed_json_detail">Invalid configuration: %1$s</string>
<string name="acc_add_asset">Add asset source</string>
<string name="acc_download_file">Download asset files</string>
<string name="acc_qr_code">QR code</string>
<string name="acc_copy_log">Copy log</string>
<string name="acc_clear_log">Clear log</string>
<string name="acc_add_rule">Add routing rule</string>
<string name="acc_start">Start service</string>
<string name="acc_stop">Stop service</string>
<string name="acc_back">Back</string>
<string name="acc_search">Search</string>
<string name="acc_add">Add configuration</string>
<string name="acc_more">More options</string>
<string name="acc_share_subscription">Share subscription link</string>
<string name="acc_share_log">Share log</string>
<string name="acc_remove">Remove proxy chain member</string>
<string name="acc_add_member">Add proxy chain member</string>
<string name="acc_start_scanner">Start QR scanner</string>
<string name="acc_stop_scanner">Stop QR scanner</string>
<string name="acc_turn_torch_on">Turn flashlight on</string>
<string name="acc_turn_torch_off">Turn flashlight off</string>
<string name="acc_select_image">Select image to scan</string>
<string name="acc_locked">This rule is kept when importing presets</string>
<string name="acc_open_menu">Open navigation menu</string>
<string name="acc_edit">Edit</string>
<string name="acc_delete">Delete</string>
<string name="acc_save">Save</string>
<string name="acc_update_subscriptions">Update subscriptions</string>
<string name="acc_per_app_proxy_information">Per-app proxy information</string>
<string name="permission_camera">Camera</string>
<string name="permission_notification">Notification</string>
<string name="permission_local_network">Local network</string>
<string name="subscription_update_updating">Updating subscription: %1$s</string>
<string name="subscription_update_progress">Testing %2$s: %1$s</string>
<string name="tasker_blurb_start">Start %1$s</string>
<string name="tasker_blurb_stop">Stop %1$s</string>
<string name="connection_test_empty_message">no details available</string>
<string name="value_unknown">unknown</string>
</resources>
+1 -1
View File
@@ -2,7 +2,7 @@
<color name="window_background_light">#FFFFFFFF</color>
<color name="window_background_dark">#FF1C1B1F</color>
<style name="AppThemeBase" parent="@android:style/Theme.Material.Light.NoActionBar">
<style name="AppThemeBase" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:windowLightStatusBar">true</item>
@@ -0,0 +1,48 @@
package com.v2ray.ang.ui
import com.google.zxing.BarcodeFormat
import com.google.zxing.BinaryBitmap
import com.google.zxing.DecodeHintType
import com.google.zxing.MultiFormatReader
import com.google.zxing.common.HybridBinarizer
import com.google.zxing.qrcode.QRCodeWriter
import org.junit.Assert.assertEquals
import org.junit.Test
import java.nio.ByteBuffer
class ScannerActivityTest {
@Test
fun paddedCameraRowsDecodeQrCode() {
val payload = "vless://00000000-0000-4000-8000-000000006007@example.com:443" +
"?encryption=none&security=tls&type=tcp#issue-6007-gallery"
val width = 320
val height = 320
val rowStride = width + 32
val qrCode = QRCodeWriter().encode(payload, BarcodeFormat.QR_CODE, width, height)
val paddedYPlane = ByteArray(rowStride * height)
for (y in 0 until height) {
for (x in 0 until width) {
paddedYPlane[y * rowStride + x] = if (qrCode[x, y]) 0 else 0xFF.toByte()
}
for (x in width until rowStride) {
paddedYPlane[y * rowStride + x] = (x + y).toByte()
}
}
val source = createYPlaneLuminanceSource(
buffer = ByteBuffer.wrap(paddedYPlane),
width = width,
height = height,
rowStride = rowStride,
)
val hints = mapOf(
DecodeHintType.POSSIBLE_FORMATS to listOf(BarcodeFormat.QR_CODE),
DecodeHintType.TRY_HARDER to true,
)
val result = MultiFormatReader().decode(BinaryBitmap(HybridBinarizer(source)), hints)
assertEquals(payload, result.text)
}
}
+4
View File
@@ -8,6 +8,7 @@ junit = "4.13.2"
junitVersion = "1.3.0"
espressoCore = "3.7.0"
activity = "1.13.0"
appcompat = "1.7.1"
mmkvStatic = "1.3.16"
gson = "2.14.0"
okhttp = "5.4.0"
@@ -19,6 +20,7 @@ mockitoMockitoInline = "5.2.0"
camerax = "1.6.1"
composeBom = "2026.06.01"
reorderable = "3.1.0"
coil = "2.7.0"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
desugar-jdk-libs = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugarJdkLibs" }
@@ -47,6 +49,7 @@ camerax-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref =
camerax-compose = { module = "androidx.camera:camera-compose", version.ref = "camerax" }
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activity" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
androidx-compose-foundation = { group = "androidx.compose.foundation", name = "foundation" }
androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" }
@@ -54,6 +57,7 @@ androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" }
androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycleViewmodelKtx" }
coil-compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
android-library = { id = "com.android.library", version.ref = "agp" }