diff --git a/Documentation/GenerationLibrary/enums/Generation.md b/Documentation/GenerationLibrary/enums/Generation.md index 1287720..efc7c7e 100644 --- a/Documentation/GenerationLibrary/enums/Generation.md +++ b/Documentation/GenerationLibrary/enums/Generation.md @@ -44,6 +44,16 @@ Generate the variables for the translations. - defaultLanguage: The default language. - Returns: The syntax. +### `parseValue(defaultTranslation:translations:language:arguments:)` + +Parse the content of a switch case. +- Parameters: + - defaultTranslation: The translation without any conditions (always required). + - translations: All the available translations for an entry. + - language: The language. + - arguments: The arguments of the entry. +- Returns: The syntax. + ### `generateLanguageFunction(dictionary:defaultLanguage:)` Generate the function for getting the translated string for a specified language code. diff --git a/README.md b/README.md index ae93f45..4305dbd 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,12 @@ house: en: House de: Haus fr: Maison + +houses(count): + en(count == "1"): There is one house. + en: There are (count) houses. + de(count == "1"): Es gibt ein Haus. + de: Es gibt (count) Häuser. ``` Then, access the localized strings safely in your code: @@ -35,6 +41,7 @@ Then, access the localized strings safely in your code: // Use the system language print(Loc.hello(name: "Peter")) print(Loc.house) +print(Loc.houses(count: "1")) // Access the translation for a specific language print(Localized.hello(name: "Peter").en) @@ -70,11 +77,13 @@ export: de: Exportiere das Dokument send(message, name): + en(name == ""): Send (message). en: Send (message) to (name). de: Sende (message) to (name). ``` -As you can see, you can add parameters using brackets after the key. +As you can see, you can add parameters using brackets after the key, +and conditions using brackets after the language (e.g. for pluralization). The line `default: en` sets English as the fallback language. diff --git a/Sources/GenerationLibrary/Generation.swift b/Sources/GenerationLibrary/Generation.swift index d0f7777..5594330 100644 --- a/Sources/GenerationLibrary/Generation.swift +++ b/Sources/GenerationLibrary/Generation.swift @@ -151,13 +151,18 @@ public enum Generation { guard let valueForLanguage = entry.value[language] ?? entry.value[defaultLanguage] else { throw GenerationError.missingTranslationInDefaultLanguage(key: key.0) } + let value = parseValue( + defaultTranslation: valueForLanguage, + translations: entry.value, + language: language, + arguments: key.1 + ) if key.1.isEmpty { variable += indent("\ncase .\(entry.key):", by: indentTwo) - variable += indent("\n\"\(valueForLanguage)\"", by: indentThree) + variable += value } else { - let translation = parse(translation: valueForLanguage, arguments: key.1) variable += indent("\ncase let .\(entry.key):", by: indentTwo) - variable += indent("\n\"\(translation)\"", by: indentThree) + variable += value } } variable += indent("\n }\n}", by: indentOne) @@ -169,6 +174,42 @@ public enum Generation { return result } + /// Parse the content of a switch case. + /// - Parameters: + /// - defaultTranslation: The translation without any conditions (always required). + /// - translations: All the available translations for an entry. + /// - language: The language. + /// - arguments: The arguments of the entry. + /// - Returns: The syntax. + static func parseValue( + defaultTranslation: String, + translations: [String: String], + language: String, + arguments: [String] = [] + ) -> String { + var value = "\n" + let conditionTranslations = translations.filter { $0.key.hasPrefix(language + "(") } + let lastTranslation = parse(translation: defaultTranslation, arguments: arguments) + if conditionTranslations.isEmpty { + return indent("\n\"\(lastTranslation)\"", by: indentThree) + } + for translation in conditionTranslations { + var condition = translation.key.split(separator: "(")[1] + condition.removeLast() + value.append(indent(""" + if \(condition) { + \"\(parse(translation: translation.value, arguments: arguments))\" + } else + """, by: indentThree)) + } + value.append(""" + { + \"\(lastTranslation)\" + } + """) + return value + } + /// Generate the function for getting the translated string for a specified language code. /// - Parameters: /// - dictionary: The parsed YML. @@ -199,7 +240,7 @@ public enum Generation { static func getLanguages(dictionary: [String: [String: String]]) -> [String] { var languages: Set = [] for key in dictionary { - languages = languages.union(key.value.map { $0.key }) + languages = languages.union(key.value.compactMap { $0.key.components(separatedBy: "(").first }) } return .init(languages) } diff --git a/Tests/PluginTests/Localized.yml b/Tests/PluginTests/Localized.yml index 0a489b4..4eafe72 100644 --- a/Tests/PluginTests/Localized.yml +++ b/Tests/PluginTests/Localized.yml @@ -10,6 +10,16 @@ house: de: Haus fr: Maison +houses(count): + en(count == "1"): There is one house. + en(count == "0"): There is no house. + en: There are (count) houses. + de(count == "1"): Es gibt ein Haus. + de(count == "0"): Es gibt kein Haus. + de: Es gibt (count) Häuser. + # There is no French translation for this phrase. + # The default language, in this case English, will be used. + helloPair(name1, name2): en: Hello, (name1) and (name2)! de: Hallo, (name1) und (name2)! diff --git a/Tests/PluginTests/Tests.swift b/Tests/PluginTests/Tests.swift index 9eafff2..920be26 100644 --- a/Tests/PluginTests/Tests.swift +++ b/Tests/PluginTests/Tests.swift @@ -20,6 +20,9 @@ enum Tests { print("DE_CH: \(Localized.house.string(for: "de_CH"))") print("SYSTEM: \(Localized.house.string)") print("EN: \(Localized.helloPair(name1: "Max", name2: "Ruedi").en)") + print(Loc.houses(count: "0")) + print(Loc.houses(count: "1")) + print(Loc.houses(count: "2")) } } diff --git a/Tests/Tests.swift b/Tests/Tests.swift deleted file mode 100644 index d0e6a37..0000000 --- a/Tests/Tests.swift +++ /dev/null @@ -1,43 +0,0 @@ -// -// Tests.swift -// Localized -// -// Created by david-swift on 27.02.2024. -// - -import Foundation -import Localized - -#localized(default: "en", yml: """ -hello(name): - en: Hello, (name)! - de: Hallo, (name)! - fr: Salut, (name)! - -house: - en: House - de: Haus - fr: Maison - -helloPair(name1, name2): - en: Hello, (name1) and (name2)! - de: Hallo, (name1) und (name2)! - fr: Salut, (name1) et (name2)! -""") - -/// Test cases for the `localized` macro. -@main -enum Tests { - - /// Test the `localized` macro. - static func main() { - print("EN: \(Localized.hello(name: "Peter").en)") - print("DE: \(Localized.hello(name: "Ruedi").de)") - print("SYSTEM: \(Loc.hello(name: "Sams"))") - print("FR: \(Localized.house.fr)") - print("DE_CH: \(Localized.house.string(for: "de_CH"))") - print("SYSTEM: \(Localized.house.string)") - print("EN: \(Localized.helloPair(name1: "Max", name2: "Ruedi").en)") - } - -}