From 3b9e06c2fc684247f3da6d11914a6c4863bffb9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cihat=20G=C3=BCnd=C3=BCz?= Date: Mon, 12 Oct 2026 09:08:43 +0200 Subject: [PATCH] Add plural labels for subjects and sections Lists and headers need the plural, which a translator cannot derive from the singular label. Education gets 'Subjects', Music and Magazines and Newspapers get 'Sections', each translated in the same terms as the singular next to it. --- Package.swift | 5 +- .../Localizable.xcstrings | 251 ++++++++++++++++++ Sources/TranslateKitEducation/TK+Label.swift | 10 + .../Localizable.xcstrings | 251 ++++++++++++++++++ .../TK+Label.swift | 10 + .../TranslateKitMusic/Localizable.xcstrings | 251 ++++++++++++++++++ Sources/TranslateKitMusic/TK+Label.swift | 10 + .../TranslateKitTests/PluralLabelTests.swift | 21 ++ 8 files changed, 808 insertions(+), 1 deletion(-) create mode 100644 Tests/TranslateKitTests/PluralLabelTests.swift diff --git a/Package.swift b/Package.swift index 5d485e3..ffd311b 100644 --- a/Package.swift +++ b/Package.swift @@ -171,7 +171,10 @@ let package = Package( ), .testTarget( name: "TranslateKitTests", - dependencies: ["TranslateKit", "TranslateKitBusiness", "TranslateKitFinance", "TranslateKitGraphicsAndDesign"] + dependencies: [ + "TranslateKit", "TranslateKitBusiness", "TranslateKitEducation", "TranslateKitFinance", "TranslateKitGraphicsAndDesign", + "TranslateKitMagazinesAndNewspapers", "TranslateKitMusic", + ] ), ] ) diff --git a/Sources/TranslateKitEducation/Localizable.xcstrings b/Sources/TranslateKitEducation/Localizable.xcstrings index 64778cd..29d30ba 100644 --- a/Sources/TranslateKitEducation/Localizable.xcstrings +++ b/Sources/TranslateKitEducation/Localizable.xcstrings @@ -15313,6 +15313,257 @@ } } }, + "TK.Label.subjects" : { + "comment" : "Use when referring to multiple topics or disciplines of study", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "المواضيع" + } + }, + "bg" : { + "stringUnit" : { + "state" : "translated", + "value" : "Предмети" + } + }, + "ca" : { + "stringUnit" : { + "state" : "translated", + "value" : "Assignatures" + } + }, + "cs" : { + "stringUnit" : { + "state" : "translated", + "value" : "Předměty" + } + }, + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Emner" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fächer" + } + }, + "el" : { + "stringUnit" : { + "state" : "translated", + "value" : "Μαθήματα" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Subjects" + } + }, + "en-AU" : { + "stringUnit" : { + "state" : "translated", + "value" : "Subjects" + } + }, + "en-GB" : { + "stringUnit" : { + "state" : "translated", + "value" : "Subjects" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Asignaturas" + } + }, + "es-419" : { + "stringUnit" : { + "state" : "translated", + "value" : "Asignaturas" + } + }, + "fi" : { + "stringUnit" : { + "state" : "translated", + "value" : "Oppiaineet" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Matières" + } + }, + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Matières" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "נושאים" + } + }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "विषय" + } + }, + "hr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Predmeti" + } + }, + "hu" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tárgyak" + } + }, + "id" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mata Pelajaran" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Materie" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "科目" + } + }, + "kk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Тақырыптар" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "과목" + } + }, + "ms" : { + "stringUnit" : { + "state" : "translated", + "value" : "Subjek" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Emner" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onderwerpen" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Przedmioty" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Disciplinas" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Disciplinas" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Subiecte" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Предметы" + } + }, + "sk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Predmety" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ämnen" + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "วิชา" + } + }, + "tr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Konular" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Предмети" + } + }, + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "Môn học" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "科目" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "科目" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "科目" + } + } + } + }, "TK.Label.teacher" : { "comment" : "Use to refer to a person providing instruction", "localizations" : { diff --git a/Sources/TranslateKitEducation/TK+Label.swift b/Sources/TranslateKitEducation/TK+Label.swift index 7dec87b..6d2fd73 100644 --- a/Sources/TranslateKitEducation/TK+Label.swift +++ b/Sources/TranslateKitEducation/TK+Label.swift @@ -92,6 +92,16 @@ extension TK.Label { String(localized: "TK.Label.student", defaultValue: "Student", bundle: .module, comment: "Use to refer to a person engaged in learning") } + /// "Subjects" - Use when referring to multiple topics or disciplines of study + public static var subjects: String { + String( + localized: "TK.Label.subjects", + defaultValue: "Subjects", + bundle: .module, + comment: "Use when referring to multiple topics or disciplines of study" + ) + } + /// "Teacher" - Use to refer to a person providing instruction public static var teacher: String { String(localized: "TK.Label.teacher", defaultValue: "Teacher", bundle: .module, comment: "Use to refer to a person providing instruction") diff --git a/Sources/TranslateKitMagazinesAndNewspapers/Localizable.xcstrings b/Sources/TranslateKitMagazinesAndNewspapers/Localizable.xcstrings index 5d45d2f..a760a3b 100644 --- a/Sources/TranslateKitMagazinesAndNewspapers/Localizable.xcstrings +++ b/Sources/TranslateKitMagazinesAndNewspapers/Localizable.xcstrings @@ -13306,6 +13306,257 @@ } } }, + "TK.Label.sections" : { + "comment" : "Use for multiple categories or parts within a publication", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "أقسام" + } + }, + "bg" : { + "stringUnit" : { + "state" : "translated", + "value" : "Секции" + } + }, + "ca" : { + "stringUnit" : { + "state" : "translated", + "value" : "Seccions" + } + }, + "cs" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sekce" + } + }, + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sektioner" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bereiche" + } + }, + "el" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ενότητες" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sections" + } + }, + "en-AU" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sections" + } + }, + "en-GB" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sections" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Secciones" + } + }, + "es-419" : { + "stringUnit" : { + "state" : "translated", + "value" : "Secciones" + } + }, + "fi" : { + "stringUnit" : { + "state" : "translated", + "value" : "Osat" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sections" + } + }, + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sections" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "מדורים" + } + }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "अनुभाग" + } + }, + "hr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Odjeljci" + } + }, + "hu" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rovatok" + } + }, + "id" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bagian" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sezioni" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "セクション" + } + }, + "kk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Бөлімдер" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "섹션" + } + }, + "ms" : { + "stringUnit" : { + "state" : "translated", + "value" : "Seksyen" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Seksjoner" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Secties" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sekcje" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Seções" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Secções" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Secțiuni" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Разделы" + } + }, + "sk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sekcie" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Avsnitt" + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "หมวดหมู่" + } + }, + "tr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bölümler" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Розділи" + } + }, + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "Phần" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "部分" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "區段" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "版面" + } + } + } + }, "TK.Label.subscriptions" : { "comment" : "Use for managing or subscribing to content or services", "localizations" : { diff --git a/Sources/TranslateKitMagazinesAndNewspapers/TK+Label.swift b/Sources/TranslateKitMagazinesAndNewspapers/TK+Label.swift index 9fdb9dd..a1a9a12 100644 --- a/Sources/TranslateKitMagazinesAndNewspapers/TK+Label.swift +++ b/Sources/TranslateKitMagazinesAndNewspapers/TK+Label.swift @@ -252,6 +252,16 @@ extension TK.Label { ) } + /// "Sections" - Use for multiple categories or parts within a publication + public static var sections: String { + String( + localized: "TK.Label.sections", + defaultValue: "Sections", + bundle: .module, + comment: "Use for multiple categories or parts within a publication" + ) + } + /// "Subscriptions" - Use for managing or subscribing to content or services public static var subscriptions: String { String( diff --git a/Sources/TranslateKitMusic/Localizable.xcstrings b/Sources/TranslateKitMusic/Localizable.xcstrings index ec8f730..5ef39e3 100644 --- a/Sources/TranslateKitMusic/Localizable.xcstrings +++ b/Sources/TranslateKitMusic/Localizable.xcstrings @@ -16333,6 +16333,257 @@ } } }, + "TK.Label.sections" : { + "comment" : "Use for multiple categories or parts within a publication", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "أقسام" + } + }, + "bg" : { + "stringUnit" : { + "state" : "translated", + "value" : "Раздели" + } + }, + "ca" : { + "stringUnit" : { + "state" : "translated", + "value" : "Seccions" + } + }, + "cs" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sekce" + } + }, + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Afsnit" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Abschnitte" + } + }, + "el" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ενότητες" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sections" + } + }, + "en-AU" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sections" + } + }, + "en-GB" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sections" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Secciones" + } + }, + "es-419" : { + "stringUnit" : { + "state" : "translated", + "value" : "Secciones" + } + }, + "fi" : { + "stringUnit" : { + "state" : "translated", + "value" : "Osiot" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sections" + } + }, + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sections" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "מדורים" + } + }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "खंड" + } + }, + "hr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Odjeljci" + } + }, + "hu" : { + "stringUnit" : { + "state" : "translated", + "value" : "Szakaszok" + } + }, + "id" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bagian" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sezioni" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "セクション" + } + }, + "kk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Бөлімдер" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "섹션" + } + }, + "ms" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bahagian" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Seksjoner" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Secties" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sekcje" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Seções" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Secções" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Secțiuni" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Разделы" + } + }, + "sk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sekcie" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Avsnitt" + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "หมวดหมู่" + } + }, + "tr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bölümler" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Розділи" + } + }, + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mục" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "版块" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "部分" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "部分" + } + } + } + }, "TK.Label.subscriptions" : { "comment" : "Use for managing or subscribing to content or services", "extractionState" : "extracted_with_value", diff --git a/Sources/TranslateKitMusic/TK+Label.swift b/Sources/TranslateKitMusic/TK+Label.swift index 9fdb9dd..a1a9a12 100644 --- a/Sources/TranslateKitMusic/TK+Label.swift +++ b/Sources/TranslateKitMusic/TK+Label.swift @@ -252,6 +252,16 @@ extension TK.Label { ) } + /// "Sections" - Use for multiple categories or parts within a publication + public static var sections: String { + String( + localized: "TK.Label.sections", + defaultValue: "Sections", + bundle: .module, + comment: "Use for multiple categories or parts within a publication" + ) + } + /// "Subscriptions" - Use for managing or subscribing to content or services public static var subscriptions: String { String( diff --git a/Tests/TranslateKitTests/PluralLabelTests.swift b/Tests/TranslateKitTests/PluralLabelTests.swift new file mode 100644 index 0000000..2b2dbcf --- /dev/null +++ b/Tests/TranslateKitTests/PluralLabelTests.swift @@ -0,0 +1,21 @@ +import Testing + +import TranslateKitEducation + +@Suite("Plural labels") +struct PluralLabelTests { + @Test func pluralLabelsUseTheirEnglishSource() { + #expect(TK.Label.subjects == "Subjects") + } + + @Test(arguments: [ + ("TK.Label.subjects", "TranslateKitEducation"), + ("TK.Label.sections", "TranslateKitMusic"), + ("TK.Label.sections", "TranslateKitMagazinesAndNewspapers"), + ]) + func pluralLabelIsTranslatedIntoEveryLanguage(key: String, target: String) throws { + let bundle = try CompiledCatalog.bundle(for: target) + #expect(try CompiledCatalog.languages(in: bundle).count >= 40) + #expect(try CompiledCatalog.languagesMissing(key, inTarget: target) == []) + } +}