mirror of
https://github.com/xweiba/location-spoofer.git
synced 2026-09-27 00:51:55 +08:00
fix(i18n): 修复首选语言回退并准备 v1.0.8
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
import Foundation
|
||||
|
||||
/// Chooses the app language from the first preferred language only. iOS normally
|
||||
/// scans the whole preference list, which can select Chinese when Italian is first
|
||||
/// and Chinese is second; this app intentionally falls back to English instead.
|
||||
enum AppLocalization {
|
||||
static func identifier(for preferredLanguages: [String]) -> String {
|
||||
guard let first = preferredLanguages.first,
|
||||
Locale(identifier: first).languageCode == "zh" else {
|
||||
return "en"
|
||||
}
|
||||
return Bundle.preferredLocalizations(
|
||||
from: ["zh-Hans", "zh-Hant"], forPreferences: [first]
|
||||
).first ?? "zh-Hans"
|
||||
}
|
||||
|
||||
static let identifier = identifier(for: Locale.preferredLanguages)
|
||||
static let locale = Locale(identifier: identifier)
|
||||
|
||||
// An explicit .lproj bundle also covers String(localized:) calls made outside
|
||||
// SwiftUI views, where the view's locale environment is not available.
|
||||
private static let localizedBundle: Bundle = {
|
||||
guard let path = Bundle.main.path(forResource: identifier, ofType: "lproj"),
|
||||
let bundle = Bundle(path: path) else {
|
||||
return .main
|
||||
}
|
||||
return bundle
|
||||
}()
|
||||
|
||||
static func string(_ value: String.LocalizationValue) -> String {
|
||||
String(localized: value, bundle: localizedBundle)
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ struct AppRemoteConfiguration: Decodable, Equatable {
|
||||
let communityPromptClients: [String]
|
||||
|
||||
static let fallback = AppRemoteConfiguration(
|
||||
latestVersion: "1.0.7",
|
||||
latestVersion: "1.0.8",
|
||||
minimumSupportedVersion: "1.0.0",
|
||||
communityPromptClients: [
|
||||
ThirdPartyProxyClient.surge.rawValue,
|
||||
|
||||
@@ -13,8 +13,8 @@ enum CertificateAuthorityStoreError: LocalizedError {
|
||||
|
||||
var errorDescription: String? {
|
||||
switch self {
|
||||
case .invalidAuthority: return String(localized: "本地 CA 证书或私钥无效")
|
||||
case let .keychain(status): return String(localized: "无法写入设备钥匙串(\(status))")
|
||||
case .invalidAuthority: return AppLocalization.string("本地 CA 证书或私钥无效")
|
||||
case let .keychain(status): return AppLocalization.string("无法写入设备钥匙串(\(status))")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,8 @@ enum CoreBridgeError: LocalizedError {
|
||||
|
||||
var errorDescription: String? {
|
||||
switch self {
|
||||
case .generationFailed: return String(localized: "无法生成本地证书")
|
||||
case .serverStartFailed: return String(localized: "无法启动本地证书服务")
|
||||
case .generationFailed: return AppLocalization.string("无法生成本地证书")
|
||||
case .serverStartFailed: return AppLocalization.string("无法启动本地证书服务")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ enum ProxyRuntimeMode: String, CaseIterable, Codable, Identifiable {
|
||||
|
||||
var displayName: String {
|
||||
switch self {
|
||||
case .localWiFi: return String(localized: "APP模式")
|
||||
case .thirdParty: return String(localized: "第三方代理模式")
|
||||
case .localWiFi: return AppLocalization.string("APP模式")
|
||||
case .thirdParty: return AppLocalization.string("第三方代理模式")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,13 +58,13 @@ struct RuntimeLogEntry: Codable, Identifiable, Equatable {
|
||||
}
|
||||
|
||||
private func localizedDiagnosticText(_ text: String) -> String {
|
||||
String(localized: String.LocalizationValue(text))
|
||||
AppLocalization.string(String.LocalizationValue(text))
|
||||
}
|
||||
|
||||
private func localizedDiagnosticValue(_ value: String) -> String {
|
||||
switch value {
|
||||
case "true": return String(localized: "是")
|
||||
case "false": return String(localized: "否")
|
||||
case "true": return AppLocalization.string("是")
|
||||
case "false": return AppLocalization.string("否")
|
||||
default: return localizedDiagnosticText(value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,25 +25,25 @@ enum ThirdPartyProxyError: LocalizedError, Equatable {
|
||||
var errorDescription: String? {
|
||||
switch self {
|
||||
case .invalidResponse:
|
||||
return String(localized: "第三方代理返回了无法识别的数据")
|
||||
return AppLocalization.string("第三方代理返回了无法识别的数据")
|
||||
case .moduleNotIntercepted:
|
||||
return String(localized: "请求未被第三方代理模块拦截,请检查模块、MITM 和代理连接")
|
||||
return AppLocalization.string("请求未被第三方代理模块拦截,请检查模块、MITM 和代理连接")
|
||||
case .rejected(let message):
|
||||
return message
|
||||
case .coordinateMismatch:
|
||||
return String(localized: "第三方代理保存的坐标与当前选点不一致")
|
||||
return AppLocalization.string("第三方代理保存的坐标与当前选点不一致")
|
||||
case .network(let message):
|
||||
return String(localized: "第三方代理请求失败:\(message)")
|
||||
return AppLocalization.string("第三方代理请求失败:\(message)")
|
||||
}
|
||||
}
|
||||
|
||||
var recoverySuggestion: String {
|
||||
return String(localized: "检查模块、MITM、证书和代理/VPN连接")
|
||||
return AppLocalization.string("检查模块、MITM、证书和代理/VPN连接")
|
||||
}
|
||||
|
||||
static func recoverySuggestion(for error: Error) -> String {
|
||||
(error as? Self)?.recoverySuggestion
|
||||
?? String(localized: "检查模块、MITM、证书和代理/VPN连接")
|
||||
?? AppLocalization.string("检查模块、MITM、证书和代理/VPN连接")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ final class ThirdPartyProxyManager: ObservableObject {
|
||||
randomRadius: RandomRadiusStore.shared.isEnabled ? RandomRadiusStore.shared.radius : 0
|
||||
))
|
||||
guard response.success else {
|
||||
throw ThirdPartyProxyError.rejected(response.error ?? String(localized: "第三方代理拒绝保存坐标"))
|
||||
throw ThirdPartyProxyError.rejected(response.error ?? AppLocalization.string("第三方代理拒绝保存坐标"))
|
||||
}
|
||||
guard let latitude = response.latitude,
|
||||
let longitude = response.longitude,
|
||||
@@ -126,7 +126,7 @@ final class ThirdPartyProxyManager: ObservableObject {
|
||||
func clear() async throws {
|
||||
let response = try await perform(action: .clear)
|
||||
guard response.success else {
|
||||
throw ThirdPartyProxyError.rejected(response.error ?? String(localized: "第三方代理清除坐标失败"))
|
||||
throw ThirdPartyProxyError.rejected(response.error ?? AppLocalization.string("第三方代理清除坐标失败"))
|
||||
}
|
||||
activeSettings = nil
|
||||
connectionState = .connected(active: false)
|
||||
@@ -142,7 +142,7 @@ final class ThirdPartyProxyManager: ObservableObject {
|
||||
if response.error?.contains("无已保存") == true {
|
||||
return false
|
||||
}
|
||||
throw ThirdPartyProxyError.rejected(response.error ?? String(localized: "第三方代理查询失败"))
|
||||
throw ThirdPartyProxyError.rejected(response.error ?? AppLocalization.string("第三方代理查询失败"))
|
||||
}
|
||||
|
||||
private enum Action {
|
||||
@@ -153,7 +153,7 @@ final class ThirdPartyProxyManager: ObservableObject {
|
||||
|
||||
private func perform(action: Action) async throws -> ThirdPartyProxySettingsResponse {
|
||||
guard !isRequesting else {
|
||||
throw ThirdPartyProxyError.rejected(String(localized: "已有第三方代理请求正在执行"))
|
||||
throw ThirdPartyProxyError.rejected(AppLocalization.string("已有第三方代理请求正在执行"))
|
||||
}
|
||||
isRequesting = true
|
||||
defer { isRequesting = false }
|
||||
@@ -229,7 +229,7 @@ enum ThirdPartyProxyClient: String, CaseIterable, Identifiable {
|
||||
}
|
||||
|
||||
var verificationText: String? {
|
||||
self == .shadowrocket ? nil : String(localized: "配置已提供,尚未验证")
|
||||
self == .shadowrocket ? nil : AppLocalization.string("配置已提供,尚未验证")
|
||||
}
|
||||
|
||||
var moduleFileName: String {
|
||||
|
||||
@@ -29,14 +29,14 @@ enum VerificationResult: Equatable, Identifiable {
|
||||
/// Localized, user-facing title. `id` stays stable for routing/equality.
|
||||
var localizedTitle: String {
|
||||
switch self {
|
||||
case .success: return String(localized: "成功")
|
||||
case .proxyNotRunning: return String(localized: "代理未运行")
|
||||
case .verificationInProgress: return String(localized: "已有验证正在进行")
|
||||
case .verificationSuperseded: return String(localized: "验证已被新位置取代")
|
||||
case .certNotTrusted: return String(localized: "证书未信任")
|
||||
case .wifiProxyNotConfigured: return String(localized: "WiFi代理未配置")
|
||||
case .coordinateWriteFailed: return String(localized: "坐标写入失败")
|
||||
case .patchFailed: return String(localized: "改写验证失败")
|
||||
case .success: return AppLocalization.string("成功")
|
||||
case .proxyNotRunning: return AppLocalization.string("代理未运行")
|
||||
case .verificationInProgress: return AppLocalization.string("已有验证正在进行")
|
||||
case .verificationSuperseded: return AppLocalization.string("验证已被新位置取代")
|
||||
case .certNotTrusted: return AppLocalization.string("证书未信任")
|
||||
case .wifiProxyNotConfigured: return AppLocalization.string("WiFi代理未配置")
|
||||
case .coordinateWriteFailed: return AppLocalization.string("坐标写入失败")
|
||||
case .patchFailed: return AppLocalization.string("改写验证失败")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user