Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Sources/MacCleanKit/CleanupStrings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public enum CleanupStrings {
case .es: return "\(selectedText) de \(totalText) \(total == 1 ? "elemento seleccionado" : "elementos seleccionados")"
case .ptBR: return "\(selectedText) de \(totalText) \(total == 1 ? "item" : "itens") \(selected == 1 ? "selecionado" : "selecionados")"
case .ja: return "\(selectedText) / \(totalText) 項目を選択済み"
case .ko: return "\(totalText)개 항목 중 \(selectedText)개 선택됨"
case .ru:
return "Выбрано \(selectedText) из \(totalText) \(L10n.russianPlural(total, one: "объекта", few: "объектов", many: "объектов"))"
case .zhHans: return "已选择 \(selectedText) / \(totalText) 项"
Expand All @@ -38,6 +39,7 @@ public enum CleanupStrings {
case .es: return "¿Limpiar \(number) \(count == 1 ? "elemento" : "elementos")?"
case .ptBR: return "Limpar \(number) \(count == 1 ? "item" : "itens")?"
case .ja: return "\(number) 項目をクリーンアップしますか?"
case .ko: return "\(number)개 항목을 정리할까요?"
case .ru:
return "Очистить \(number) \(L10n.russianPlural(count, one: "объект", few: "объекта", many: "объектов"))?"
case .zhHans: return "清理 \(number) 项?"
Expand All @@ -55,6 +57,7 @@ public enum CleanupStrings {
case .es: return "\(number) \(count == 1 ? "elemento" : "elementos")"
case .ptBR: return "\(number) \(count == 1 ? "item" : "itens")"
case .ja: return "\(number) 項目"
case .ko: return "\(number)개 항목"
case .ru:
return "\(number) \(L10n.russianPlural(count, one: "объект", few: "объекта", many: "объектов"))"
case .zhHans: return "\(number) 项"
Expand Down
3 changes: 2 additions & 1 deletion Sources/MacCleanKit/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ public enum MCConstants {
"es.lproj", "es-ES.lproj", "es_ES.lproj", "es-MX.lproj", "es_MX.lproj", "es-419.lproj", "es_419.lproj",
"es-US.lproj", "es_US.lproj", "Spanish.lproj",
"pt.lproj", "pt-BR.lproj", "pt_BR.lproj", "Portuguese.lproj", "Portuguese (Brazil).lproj", "Brazilian Portuguese.lproj",
"ko.lproj", "ko-KR.lproj", "ko_KR.lproj", "Korean.lproj",
"it.lproj", "it-IT.lproj", "it_IT.lproj", "it-CH.lproj", "it_CH.lproj", "Italian.lproj",
"ja.lproj", "ja-JP.lproj", "ja_JP.lproj", "Japanese.lproj",
]
Expand Down Expand Up @@ -238,5 +239,5 @@ public enum MCConstants {
// plugin was tried (commit history) but doesn't work under multi-arch
// `swift build --arch arm64 --arch x86_64` because xcbuild doesn't
// execute plugins.
public static let appVersion = "1.28.4"
public static let appVersion = "1.28.5"
}
710 changes: 709 additions & 1 deletion Sources/MacCleanKit/Localization.swift

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Tests/MacCleanKitTests/BatchCleanupLocalizationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ final class BatchCleanupLocalizationTests: AppLanguageTestCase {
]
// These phrases are written identically in both Chinese scripts.
let sameInTraditional: Set<String> = ["清理已停止", "完成", "清理完成"]
for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .zhHant] {
for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ko, .zhHant] {
AppLanguage.current = language
for key in keys {
let value = L10n.tr(key, "MISSING_CLEANUP_TRANSLATION", "RU")
Expand Down
4 changes: 2 additions & 2 deletions Tests/MacCleanKitTests/CleanupLocalizationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ final class CleanupLocalizationTests: AppLanguageTestCase {
]

func testStaticCleanupCopyIsTranslatedForEveryDictionaryBackedLanguage() {
for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .zhHant] {
for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ko, .zhHant] {
AppLanguage.current = language
for key in staticKeys {
let value = L10n.tr(key, "UNTRANSLATED", "Russian")
Expand All @@ -29,7 +29,7 @@ final class CleanupLocalizationTests: AppLanguageTestCase {
AppLanguage.current = .en
let english = [CleanupStrings.selectionSummary(selected: 2, total: 21),
CleanupStrings.confirmationTitle(count: 2), CleanupStrings.itemCount(2)]
for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ru, .zhHans, .zhHant] {
for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ko, .ru, .zhHans, .zhHant] {
AppLanguage.current = language
let localized = [CleanupStrings.selectionSummary(selected: 2, total: 21),
CleanupStrings.confirmationTitle(count: 2), CleanupStrings.itemCount(2)]
Expand Down
4 changes: 2 additions & 2 deletions Tests/MacCleanKitTests/HealthAlertsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ final class HealthAlertLocalizationTests: AppLanguageTestCase {
let english = allStrings()
AppLanguage.current = .zhHans
let simplified = allStrings()
for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja] {
for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ko] {
AppLanguage.current = language
for (index, translated) in allStrings().enumerated() where index != swapLine {
XCTAssertNotEqual(translated, english[index], "\(language): \(english[index])")
Expand All @@ -97,7 +97,7 @@ final class HealthAlertLocalizationTests: AppLanguageTestCase {
}

func testPlaceholdersAreFilledInEveryLanguage() {
for language in [AppLanguage.en, .de, .fr, .it, .es, .ptBR, .ja, .ru, .zhHans, .zhHant] {
for language in [AppLanguage.en, .de, .fr, .it, .es, .ptBR, .ja, .ko, .ru, .zhHans, .zhHant] {
AppLanguage.current = language
let body = HealthAlertStrings.swapAlertBody(used: 6_800_000_000, threshold: 4_000_000_000)
XCTAssertFalse(body.contains("{"), "\(language): \(body)")
Expand Down
46 changes: 42 additions & 4 deletions Tests/MacCleanKitTests/LocalizationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,49 @@ final class LocalizationTests: AppLanguageTestCase {
}
}

func testKoreanLanguageSelectionAndRegionalIdentifiers() {
XCTAssertTrue(AppLanguage.allCases.contains(.ko))
XCTAssertEqual(AppLanguage.ko.rawValue, "ko")
XCTAssertEqual(AppLanguage.ko.pickerLabel, "한국어")
XCTAssertEqual(AppLanguage.ko.localeIdentifier, "ko")
for identifier in ["ko", "ko-KR", "ko_KR", "KO-kr"] {
XCTAssertEqual(AppLanguage.preferredLanguage(for: identifier), .ko, identifier)
}
}

func testKoreanTranslationOverloadsAndFallbacks() {
AppLanguage.current = .ko
XCTAssertEqual(L10n.tr("设置", "Settings"), "설정")
XCTAssertEqual(L10n.tr("设置", "Settings", "Настройки"), "설정")
XCTAssertEqual(L10n.tr("设置"), "설정")
XCTAssertEqual(MaintenanceTask.freeUpRAM.title, "RAM 확보")
XCTAssertEqual(ScanCategory.userCaches.displayName, "사용자 캐시 파일")
XCTAssertEqual(FileListSort.sizeDescending.label, "큰 파일 먼저")
XCTAssertEqual(L10n.tr("未翻译", "New feature"), "New feature")
XCTAssertEqual(L10n.tr("未翻译", "New feature", "Russian"), "New feature")
XCTAssertEqual(L10n.tr("未翻译"), "未翻译")
for count in [1, 2] {
let english = "\(count) threat\(count == 1 ? "" : "s") found"
XCTAssertEqual(L10n.tr("发现 \(count) 个威胁", english), english)
XCTAssertEqual(L10n.tr("发现 \(count) 个威胁", english, "Russian"), english)
}
}

func testBrazilianPortugueseLanguageResourcesCannotBeOfferedForCleanup() {
for folder in ["pt.lproj", "pt-BR.lproj", "pt_BR.lproj", "Portuguese.lproj", "Portuguese (Brazil).lproj", "Brazilian Portuguese.lproj"] {
XCTAssertTrue(LanguagePreferences.alwaysKept.contains(folder), folder)
}
}

func testKoreanLanguageResourcesCannotBeOfferedForCleanup() {
let original = LanguagePreferences.discoveredLproj
defer { LanguagePreferences.discoveredLproj = original }
let folders: Set<String> = ["ko.lproj", "ko-KR.lproj", "ko_KR.lproj", "Korean.lproj"]
LanguagePreferences.discoveredLproj = folders
XCTAssertTrue(folders.isSubset(of: LanguagePreferences.alwaysKept))
XCTAssertTrue(LanguagePreferences.selectableLanguages().isEmpty)
}

func testGermanLanguageSelectionAndRegionalIdentifiers() {
XCTAssertTrue(AppLanguage.allCases.contains(.de))
XCTAssertEqual(AppLanguage.de.pickerLabel, "Deutsch")
Expand Down Expand Up @@ -264,7 +301,7 @@ final class LocalizationTests: AppLanguageTestCase {
("清除", "Clear", "Очистить"),
("这只会忘掉恢复记录,废纸篓里的文件不会被动。之后就不能一键恢复这些清理了。", "This only forgets the restore list. Nothing in the Trash is touched, but these cleans can no longer be restored in one click.", "Это"),
]
for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja] {
for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ko] {
AppLanguage.current = language
for (zh, en, ru) in strings {
let value = L10n.tr(zh, en, ru)
Expand Down Expand Up @@ -380,6 +417,7 @@ final class LocalizationTests: AppLanguageTestCase {
.es: "Invítame a un café",
.ptBR: "Me pague um café",
.ja: "コーヒーをおごる",
.ko: "커피 한 잔 후원하기",
.zhHant: "請我喝杯咖啡",
.ru: "Угостить кофе",
]
Expand All @@ -401,7 +439,7 @@ final class LocalizationTests: AppLanguageTestCase {
let sameAsSimplified: Set<String> = [
"容器", "卷", "大小", "取消", "永久清理", "清理完成", "未能完成", "已停止",
]
for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ru] {
for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ko, .ru] {
AppLanguage.current = language
for (index, value) in DiskHogsText.all.enumerated() where !sameAsEnglish.contains(english[index]) || language == .ru {
XCTAssertNotEqual(value, english[index], "\(language) is missing: \(english[index])")
Expand Down Expand Up @@ -431,7 +469,7 @@ final class LocalizationTests: AppLanguageTestCase {
("正在查找项目…", "Finding projects…", "Поиск проектов…"),
("正在计算文件夹大小…", "Measuring folders…", "Подсчёт размера папок…"),
]
for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .zhHant, .ru] {
for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ko, .zhHant, .ru] {
AppLanguage.current = language
for s in strings {
let text = L10n.tr(s.zh, s.en, s.ru)
Expand Down Expand Up @@ -475,7 +513,7 @@ final class LocalizationTests: AppLanguageTestCase {
let sameInTraditional: Set<String> = ["未知"]

for (zh, english) in strings {
for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja] {
for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ko] {
AppLanguage.current = language
XCTAssertNotEqual(L10n.tr(zh, english), english, "\(language) is missing \"\(english)\"")
}
Expand Down
4 changes: 2 additions & 2 deletions Tests/MacCleanKitTests/SupportersTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ final class SupporterStringsTests: AppLanguageTestCase {
let english = allStrings()
AppLanguage.current = .zhHans
let simplified = allStrings()
for language in [AppLanguage.de, .fr, .it, .ru, .ja, .ptBR, .es] {
for language in [AppLanguage.de, .fr, .it, .ru, .ko, .ja, .ptBR, .es] {
AppLanguage.current = language
for (index, translated) in allStrings().enumerated() {
XCTAssertNotEqual(translated, english[index], "\(language): \(english[index])")
Expand All @@ -77,7 +77,7 @@ final class SupporterStringsTests: AppLanguageTestCase {
}

func testPlaceholderIsFilledInEveryLanguage() {
for language in [AppLanguage.en, .de, .fr, .it, .ru, .zhHans, .zhHant, .ja, .ptBR, .es] {
for language in [AppLanguage.en, .de, .fr, .it, .ru, .zhHans, .zhHant, .ko, .ja, .ptBR, .es] {
AppLanguage.current = language
let caption = SupporterStrings.caption(for: ["Ada"])
XCTAssertTrue(caption.contains("Ada"), "\(language): \(caption)")
Expand Down
4 changes: 2 additions & 2 deletions Tests/MacCleanTests/BrowserExtensionsLocalizationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ final class BrowserExtensionsLocalizationTests: EnglishAppLanguageTestCase {
AppLanguage.current = .zhHans
let simplified = allStrings()

for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ru] {
for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ko, .ru] {
AppLanguage.current = language
for (index, value) in allStrings().enumerated() {
XCTAssertNotEqual(value, english[index], "\(language) is untranslated: \(english[index])")
Expand All @@ -70,7 +70,7 @@ final class BrowserExtensionsLocalizationTests: EnglishAppLanguageTestCase {
}

func testNoEmDashesOrUnfilledPlaceholders() {
for language in [AppLanguage.en, .de, .fr, .it, .es, .ptBR, .ja, .ru, .zhHans, .zhHant] {
for language in [AppLanguage.en, .de, .fr, .it, .es, .ptBR, .ja, .ko, .ru, .zhHans, .zhHant] {
AppLanguage.current = language
for value in allStrings() {
XCTAssertFalse(value.contains("\u{2014}"), "\(language) has an em dash: \(value)")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ final class LaunchAtLoginErrorLocalizationTests: EnglishAppLanguageTestCase {
(.ptBR, "Não foi possível ativar a abertura ao iniciar sessão: MSG",
"Não foi possível desativar a abertura ao iniciar sessão: MSG"),
(.ja, "ログイン時に起動をオンにできませんでした:MSG", "ログイン時に起動をオフにできませんでした:MSG"),
(.ko, "로그인 시 실행을 켤 수 없음: MSG", "로그인 시 실행을 끌 수 없음: MSG"),
(.ru, "Не удалось включить запуск при входе: MSG", "Не удалось отключить запуск при входе: MSG"),
(.zhHans, "无法开启登录时启动:MSG", "无法关闭登录时启动:MSG"),
(.zhHant, "無法開啟登入時啟動:MSG", "無法關閉登入時啟動:MSG"),
Expand Down
2 changes: 1 addition & 1 deletion Tests/MacCleanTests/MalwareLocalizationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ final class MalwareLocalizationTests: EnglishAppLanguageTestCase {
AppLanguage.current = .zhHans
let simplified = allStrings()

for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ru] {
for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ko, .ru] {
AppLanguage.current = language
for (index, value) in allStrings().enumerated() {
XCTAssertNotEqual(value, english[index], "\(language) is untranslated: \(english[index])")
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.28.4
1.28.5
2 changes: 2 additions & 0 deletions scripts/build-dmg.sh
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ cat > "${APP_BUNDLE}/Contents/Info.plist" << PLIST
<string>es</string>
<string>pt-BR</string>
<string>ja</string>
<string>ko</string>
</array>
<key>CFBundleExecutable</key>
<string>MacClean</string>
Expand Down Expand Up @@ -189,6 +190,7 @@ cat > "${MENU_APP}/Contents/Info.plist" << MENU_PLIST
<string>es</string>
<string>pt-BR</string>
<string>ja</string>
<string>ko</string>
</array>
<key>CFBundleExecutable</key>
<string>MacCleanMenu</string>
Expand Down
Loading