mirror of
https://github.com/xweiba/location-spoofer.git
synced 2026-09-21 22:30:46 +08:00
fix(i18n): 完善国际化并迁移 WLOC 脚本
This commit is contained in:
@@ -13,8 +13,8 @@ enum CertificateAuthorityStoreError: LocalizedError {
|
||||
|
||||
var errorDescription: String? {
|
||||
switch self {
|
||||
case .invalidAuthority: return "本地 CA 证书或私钥无效"
|
||||
case let .keychain(status): return "无法写入设备钥匙串(\(status))"
|
||||
case .invalidAuthority: return String(localized: "本地 CA 证书或私钥无效")
|
||||
case let .keychain(status): return String(localized: "无法写入设备钥匙串(\(status))")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,8 @@ enum CoreBridgeError: LocalizedError {
|
||||
|
||||
var errorDescription: String? {
|
||||
switch self {
|
||||
case .generationFailed: return "无法生成本地证书"
|
||||
case .serverStartFailed: return "无法启动本地证书服务"
|
||||
case .generationFailed: return String(localized: "无法生成本地证书")
|
||||
case .serverStartFailed: return String(localized: "无法启动本地证书服务")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+28
-3
@@ -38,10 +38,35 @@ struct RuntimeLogEntry: Codable, Identifiable, Equatable {
|
||||
var renderedText: String {
|
||||
let formatter = ISO8601DateFormatter()
|
||||
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
|
||||
let suffix = details.isEmpty
|
||||
let localizedDetails = details.map {
|
||||
(localizedDiagnosticText($0.key), localizedDiagnosticValue($0.value))
|
||||
}
|
||||
let suffix = localizedDetails.isEmpty
|
||||
? ""
|
||||
: " " + details.sorted(by: { $0.key < $1.key }).map { "\($0.key)=\($0.value)" }.joined(separator: " ")
|
||||
return "\(formatter.string(from: timestamp)) [\(source)] [\(level.rawValue.uppercased())] [\(category)] \(message)\(suffix)"
|
||||
: " " + localizedDetails.sorted(by: { $0.0 < $1.0 }).map { "\($0.0)=\($0.1)" }.joined(separator: " ")
|
||||
return "\(formatter.string(from: timestamp)) [\(source)] [\(level.rawValue.uppercased())] [\(localizedCategory)] \(localizedMessage)\(suffix)"
|
||||
}
|
||||
|
||||
var localizedCategory: String { localizedDiagnosticText(category) }
|
||||
var localizedMessage: String { localizedDiagnosticText(message) }
|
||||
|
||||
var localizedDetailsText: String {
|
||||
details.map { (localizedDiagnosticText($0.key), localizedDiagnosticValue($0.value)) }
|
||||
.sorted(by: { $0.0 < $1.0 })
|
||||
.map { "\($0.0): \($0.1)" }
|
||||
.joined(separator: "\n")
|
||||
}
|
||||
|
||||
private func localizedDiagnosticText(_ text: String) -> String {
|
||||
String(localized: String.LocalizationValue(text))
|
||||
}
|
||||
|
||||
private func localizedDiagnosticValue(_ value: String) -> String {
|
||||
switch value {
|
||||
case "true": return String(localized: "是")
|
||||
case "false": return String(localized: "否")
|
||||
default: return localizedDiagnosticText(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -170,7 +170,10 @@ final class ThirdPartyProxyManager: ObservableObject {
|
||||
URLQueryItem(name: "lon", value: String(format: "%.8f", locale: Locale(identifier: "en_US_POSIX"), longitude)),
|
||||
URLQueryItem(name: "lat", value: String(format: "%.8f", locale: Locale(identifier: "en_US_POSIX"), latitude)),
|
||||
URLQueryItem(name: "acc", value: String(accuracy)),
|
||||
URLQueryItem(name: "randomRadius", value: String(randomRadius))
|
||||
URLQueryItem(
|
||||
name: "randomRadius",
|
||||
value: String(format: "%g", locale: Locale(identifier: "en_US_POSIX"), randomRadius)
|
||||
)
|
||||
]
|
||||
}
|
||||
guard let url = components.url else { throw ThirdPartyProxyError.invalidResponse }
|
||||
@@ -203,6 +206,9 @@ final class ThirdPartyProxyManager: ObservableObject {
|
||||
}
|
||||
|
||||
enum ThirdPartyProxyClient: String, CaseIterable, Identifiable {
|
||||
/// Bump when a hosted module or script changes to invalidate proxy-client caches.
|
||||
static let moduleSubscriptionVersion = "1.0.7"
|
||||
|
||||
case shadowrocket
|
||||
case surge
|
||||
case quantumultX
|
||||
@@ -239,21 +245,14 @@ enum ThirdPartyProxyClient: String, CaseIterable, Identifiable {
|
||||
|
||||
@MainActor
|
||||
var subscriptionURL: URL {
|
||||
// Third-party modules are served directly from the upstream Yu9191/wloc
|
||||
// repository (mirror via gh-proxy when enabled). We no longer maintain
|
||||
// project-owned module copies, so the URL tracks upstream releases.
|
||||
let fileName: String
|
||||
switch self {
|
||||
case .surge, .egern: fileName = "wloc.sgmodule"
|
||||
case .quantumultX: fileName = "wloc.conf"
|
||||
case .loon: fileName = "wloc.lpx"
|
||||
case .stash: fileName = "wloc.stoverride"
|
||||
case .shadowrocket: fileName = "wloc.module"
|
||||
}
|
||||
let base = ThirdPartyModuleSourceStore.shared.useMirror
|
||||
? "https://gh-proxy.org/https://raw.githubusercontent.com/Yu9191/wloc/refs/heads/main/modules/\(fileName)"
|
||||
: "https://raw.githubusercontent.com/Yu9191/wloc/refs/heads/main/modules/\(fileName)"
|
||||
return URL(string: base)!
|
||||
let directory = ThirdPartyModuleSourceStore.shared.useMirror
|
||||
? "Resources/ThirdPartyProxyModules"
|
||||
: "ThirdParty/WlocScripts/modules/direct"
|
||||
let prefix = ThirdPartyModuleSourceStore.shared.useMirror
|
||||
? "https://gh-proxy.org/https://raw.githubusercontent.com/xweiba/location-spoofer/main/"
|
||||
: "https://raw.githubusercontent.com/xweiba/location-spoofer/main/"
|
||||
let base = "\(prefix)\(directory)/\(moduleFileName)"
|
||||
return URL(string: "\(base)?v=\(Self.moduleSubscriptionVersion)")!
|
||||
}
|
||||
|
||||
var launchURL: URL? {
|
||||
|
||||
Reference in New Issue
Block a user