Files
ggbond268--mactools/Tests/App/PluginRuntimeLocalizationTests.swift
wehub-resource-sync 1d1286fadb
Build / Build and test (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:18:38 +08:00

230 lines
8.4 KiB
Swift

import XCTest
@testable import MacToolsPluginKit
@testable import MacTools
@MainActor
final class PluginRuntimeLocalizationTests: XCTestCase {
private let preferenceKey = PluginRuntimeLocalization.preferenceUserDefaultsKey
private var originalPreference: String?
override func setUp() {
super.setUp()
originalPreference = UserDefaults.standard.string(forKey: preferenceKey)
PluginRuntimeLocalization.source.setPreference(originalPreference)
}
override func tearDown() {
if let originalPreference {
UserDefaults.standard.set(originalPreference, forKey: preferenceKey)
} else {
UserDefaults.standard.removeObject(forKey: preferenceKey)
}
PluginRuntimeLocalization.source.setPreference(originalPreference)
originalPreference = nil
super.tearDown()
}
func testFixedPreferenceOverridesProcessPreferredLanguages() {
setRuntimePreference("ar")
XCTAssertEqual(PluginRuntimeLocalization.preferredLanguages, ["ar"])
XCTAssertEqual(PluginRuntimeLocalization.locale.language.languageCode?.identifier, "ar")
}
func testFixedPreferenceThenSystemUsesTheSystemLanguageSnapshot() {
let source = makeLocaleSource(
systemLanguages: ["en-GB"],
currentLocale: Locale(identifier: "en_DE@calendar=gregorian")
)
source.setPreference("fr")
XCTAssertEqual(source.preferredLanguages, ["fr"])
XCTAssertEqual(source.locale.language.languageCode?.identifier, "fr")
XCTAssertEqual(source.locale.region?.identifier, "DE")
source.setPreference("system")
XCTAssertEqual(source.preferredLanguages, ["en-GB"])
XCTAssertEqual(source.locale.language.languageCode?.identifier, "en")
XCTAssertEqual(source.locale.region?.identifier, "DE")
}
func testFixedLanguageKeepsTheCurrentLocaleFormatSettings() {
let source = makeLocaleSource(
systemLanguages: ["en"],
currentLocale: Locale(identifier: "en_DE@calendar=japanese")
)
source.setPreference("ja")
XCTAssertEqual(source.locale.language.languageCode?.identifier, "ja")
XCTAssertEqual(source.locale.region?.identifier, "DE")
XCTAssertEqual(source.locale.calendar.identifier, .japanese)
}
func testChineseRegionUsesSimplifiedChineseResourceFallback() {
XCTAssertEqual(
PluginRuntimeLocalization.candidateLanguageIdentifiers(for: "zh-Hans-CN"),
["zh-Hans-CN", "zh-Hans", "zh"]
)
}
func testStringLookupChangesLanguageWithoutRecreatingBundle() throws {
let bundleURL = try makeLocalizedTestBundle()
defer { try? FileManager.default.removeItem(at: bundleURL.deletingLastPathComponent()) }
let bundle = try XCTUnwrap(Bundle(url: bundleURL))
setRuntimePreference("en")
XCTAssertEqual(
PluginRuntimeLocalization.string(
"menu.title",
defaultValue: "Fallback",
table: "Settings",
bundle: bundle
),
"Menu Bar Icon"
)
setRuntimePreference("zh-Hans")
XCTAssertEqual(
PluginRuntimeLocalization.string(
"menu.title",
defaultValue: "Fallback",
table: "Settings",
bundle: bundle
),
"菜单栏图标"
)
}
func testPrimaryPanelButtonTitleProviderIsReadOnEveryAccess() {
var title = "English"
let descriptor = PluginPrimaryPanelDescriptor(
controlStyle: .button,
menuActionBehavior: .keepPresented,
buttonTitleProvider: { title }
)
XCTAssertEqual(descriptor.buttonTitle, "English")
title = "中文"
XCTAssertEqual(descriptor.buttonTitle, "中文")
}
func testMissingSelectedLanguageStringFallsBackToBaseLanguage() throws {
let bundleURL = try makeLocalizedTestBundle()
defer { try? FileManager.default.removeItem(at: bundleURL.deletingLastPathComponent()) }
let bundle = try XCTUnwrap(Bundle(url: bundleURL))
setRuntimePreference("zh-Hans")
XCTAssertEqual(
PluginRuntimeLocalization.string(
"fallback.title",
defaultValue: "Fallback",
table: "Settings",
bundle: bundle
),
"Base Language"
)
}
func testMissingAllTranslationsFallsBackToTheCallerDefault() throws {
let bundleURL = try makeLocalizedTestBundle()
defer { try? FileManager.default.removeItem(at: bundleURL.deletingLastPathComponent()) }
let bundle = try XCTUnwrap(Bundle(url: bundleURL))
setRuntimePreference("fr")
XCTAssertEqual(
PluginRuntimeLocalization.string(
"missing.title",
defaultValue: "Caller Default",
table: "Settings",
bundle: bundle
),
"Caller Default"
)
}
func testAppearanceLabelsFollowTheRuntimeLanguage() {
setRuntimePreference("en")
XCTAssertEqual(
AppAppearancePreference.allCases.map(\.title),
["Automatic", "Dark", "Light"]
)
setRuntimePreference("zh-Hans")
XCTAssertEqual(
AppAppearancePreference.allCases.map(\.title),
["自动", "深色", "浅色"]
)
}
func testWindowAndMenuBarTitlesFollowTwoRuntimeSwitches() {
setRuntimePreference("en")
XCTAssertEqual(AppWindowRouter.settingsWindowTitle, "Settings")
XCTAssertEqual(MenuBarPanelTab.components.accessibilityTitle, "Components Panel")
XCTAssertEqual(MenuBarPanelTab.features.accessibilityTitle, "Features Panel")
setRuntimePreference("zh-Hans")
XCTAssertEqual(AppWindowRouter.settingsWindowTitle, "设置")
XCTAssertEqual(MenuBarPanelTab.components.accessibilityTitle, "组件面板")
XCTAssertEqual(MenuBarPanelTab.features.accessibilityTitle, "功能面板")
setRuntimePreference("en")
XCTAssertEqual(AppWindowRouter.settingsWindowTitle, "Settings")
XCTAssertEqual(MenuBarPanelTab.components.accessibilityTitle, "Components Panel")
}
private func makeLocalizedTestBundle() throws -> URL {
let directory = FileManager.default.temporaryDirectory
.appendingPathComponent(UUID().uuidString, isDirectory: true)
let bundleURL = directory.appendingPathComponent("Test.bundle", isDirectory: true)
try FileManager.default.createDirectory(at: bundleURL, withIntermediateDirectories: true)
for (language, value) in [("en", "Menu Bar Icon"), ("zh-Hans", "菜单栏图标")] {
let lprojURL = bundleURL.appendingPathComponent("\(language).lproj", isDirectory: true)
try FileManager.default.createDirectory(at: lprojURL, withIntermediateDirectories: true)
try "\"menu.title\" = \"\(value)\";\n".write(
to: lprojURL.appendingPathComponent("Settings.strings"),
atomically: true,
encoding: .utf8
)
}
let englishStrings = bundleURL
.appendingPathComponent("en.lproj", isDirectory: true)
.appendingPathComponent("Settings.strings")
let existingStrings = try String(contentsOf: englishStrings, encoding: .utf8)
try (existingStrings + "\"fallback.title\" = \"Base Language\";\n").write(
to: englishStrings,
atomically: true,
encoding: .utf8
)
return bundleURL
}
private func setRuntimePreference(_ preference: String?) {
if let preference {
UserDefaults.standard.set(preference, forKey: preferenceKey)
} else {
UserDefaults.standard.removeObject(forKey: preferenceKey)
}
PluginRuntimeLocalization.source.setPreference(preference)
}
private func makeLocaleSource(
systemLanguages: [String],
currentLocale: Locale
) -> PluginRuntimeLocaleSource {
let suiteName = "PluginRuntimeLocalizationTests.\(UUID().uuidString)"
let defaults = UserDefaults(suiteName: suiteName)!
defaults.removePersistentDomain(forName: suiteName)
return PluginRuntimeLocaleSource(
userDefaults: defaults,
systemPreferredLanguages: { systemLanguages },
currentLocale: { currentLocale }
)
}
}