From 9b24d42399ec2e3a02c3be46d95de3b290dfb668 Mon Sep 17 00:00:00 2001 From: Tomasz Szulc Date: Fri, 31 Jul 2015 23:31:32 +0200 Subject: [PATCH] Implementing new Swifternalization class - WIP --- Swifternalization.xcodeproj/project.pbxproj | 162 +++--------- Swifternalization/Expression.swift | 128 +++------- Swifternalization/ExpressionType.swift | 9 - Swifternalization/KeyValueType.swift | 33 --- Swifternalization/LengthVariation.swift | 2 +- Swifternalization/LengthVariationType.swift | 12 - .../LoadedTranslationsProcessor.swift | 20 +- .../LocalizableFilesLoader.swift | 112 -------- Swifternalization/SharedExpression.swift | 2 +- .../SharedExpressionsConfigurator.swift | 140 ---------- .../SharedExpressionsProcessor.swift | 2 +- Swifternalization/SimpleExpression.swift | 31 --- Swifternalization/Swifternalization.swift | 241 +++--------------- Swifternalization/TranslatablePair.swift | 69 ----- ...ithExpressions.swift => Translation.swift} | 11 +- Swifternalization/TranslationType.swift | 17 -- SwifternalizationTests/ExpressionTests.swift | 53 ---- .../LoadedTranslationsProcessorTests.swift | 8 +- .../LocalizableFilesLoaderTests.swift | 36 --- .../SharedBaseExpressionTests.swift | 8 +- .../SharedPolishExpressionTests.swift | 4 +- .../SwifternalizationTests.swift | 30 +-- .../TranslatablePairTests.swift | 16 +- 23 files changed, 162 insertions(+), 984 deletions(-) delete mode 100644 Swifternalization/ExpressionType.swift delete mode 100644 Swifternalization/KeyValueType.swift delete mode 100644 Swifternalization/LengthVariationType.swift delete mode 100644 Swifternalization/LocalizableFilesLoader.swift delete mode 100644 Swifternalization/SharedExpressionsConfigurator.swift delete mode 100644 Swifternalization/SimpleExpression.swift delete mode 100644 Swifternalization/TranslatablePair.swift rename Swifternalization/{TranslationWithExpressions.swift => Translation.swift} (64%) delete mode 100644 Swifternalization/TranslationType.swift delete mode 100644 SwifternalizationTests/ExpressionTests.swift delete mode 100644 SwifternalizationTests/LocalizableFilesLoaderTests.swift diff --git a/Swifternalization.xcodeproj/project.pbxproj b/Swifternalization.xcodeproj/project.pbxproj index fcdcd18..ede3edb 100644 --- a/Swifternalization.xcodeproj/project.pbxproj +++ b/Swifternalization.xcodeproj/project.pbxproj @@ -11,36 +11,28 @@ 6D4C4EAF1B6AA48F00B7839A /* LoadedTranslation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4C4EAE1B6AA48F00B7839A /* LoadedTranslation.swift */; }; 6D4C4EB01B6AA54800B7839A /* LoadedTranslation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4C4EAE1B6AA48F00B7839A /* LoadedTranslation.swift */; }; 6D4C4EB31B6AAE3200B7839A /* LoadedTranslationsProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4C4EB21B6AAE3200B7839A /* LoadedTranslationsProcessor.swift */; }; - 6D4C4EB51B6AB38400B7839A /* TranslationType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4C4EB41B6AB38400B7839A /* TranslationType.swift */; }; - 6D4C4EB61B6AB43F00B7839A /* TranslationType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4C4EB41B6AB38400B7839A /* TranslationType.swift */; }; 6D4C4EB81B6AB6DE00B7839A /* LoadedTranslationType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4C4EB71B6AB6DE00B7839A /* LoadedTranslationType.swift */; }; 6D4C4EB91B6AB6EF00B7839A /* LoadedTranslationType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4C4EB71B6AB6DE00B7839A /* LoadedTranslationType.swift */; }; - 6D4C4EBD1B6ABE0700B7839A /* TranslationWithExpressions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4C4EBC1B6ABE0700B7839A /* TranslationWithExpressions.swift */; }; - 6D4C4EC41B6ACF2C00B7839A /* TranslationWithExpressions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4C4EBC1B6ABE0700B7839A /* TranslationWithExpressions.swift */; }; + 6D4C4EBD1B6ABE0700B7839A /* Translation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4C4EBC1B6ABE0700B7839A /* Translation.swift */; }; + 6D4C4EC41B6ACF2C00B7839A /* Translation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4C4EBC1B6ABE0700B7839A /* Translation.swift */; }; 6D4C4EC51B6AD01300B7839A /* LoadedTranslationsProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4C4EB21B6AAE3200B7839A /* LoadedTranslationsProcessor.swift */; }; - 6D4C4EC61B6AD01D00B7839A /* SimpleExpression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D5BA6081B655F1D000D7E49 /* SimpleExpression.swift */; }; + 6D4C4EC61B6AD01D00B7839A /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D5BA6081B655F1D000D7E49 /* Expression.swift */; }; 6D50044E1B3EF91600A54B36 /* Swifternalization.h in Headers */ = {isa = PBXBuildFile; fileRef = 6D50044D1B3EF91600A54B36 /* Swifternalization.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6D5004541B3EF91600A54B36 /* Swifternalization.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D5004481B3EF91600A54B36 /* Swifternalization.framework */; }; 6D50045B1B3EF91600A54B36 /* SwifternalizationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D50045A1B3EF91600A54B36 /* SwifternalizationTests.swift */; }; 6D5004661B3EF92600A54B36 /* Swifternalization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D5004641B3EF92600A54B36 /* Swifternalization.swift */; }; - 6D5004671B3EF92600A54B36 /* TranslatablePair.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D5004651B3EF92600A54B36 /* TranslatablePair.swift */; }; 6D5004921B3EFF6D00A54B36 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6D5004941B3EFF6D00A54B36 /* Localizable.strings */; }; 6D5004961B3EFFC100A54B36 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 6D5004591B3EF91600A54B36 /* Info.plist */; }; 6D5BA5F01B651796000D7E49 /* TranslationsLoaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D5BA5EF1B651796000D7E49 /* TranslationsLoaderTests.swift */; }; 6D5BA5F11B6517A6000D7E49 /* TranslationsLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DB3CC731B5EBDA600A1220F /* TranslationsLoader.swift */; }; 6D5BA5F31B651809000D7E49 /* LengthVariation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DB3CC6A1B5EBDA600A1220F /* LengthVariation.swift */; }; - 6D5BA5F41B65180F000D7E49 /* LengthVariationType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DB3CC6B1B5EBDA600A1220F /* LengthVariationType.swift */; }; 6D5BA5FB1B65253B000D7E49 /* SharedExpressionsProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D5BA5FA1B65253B000D7E49 /* SharedExpressionsProcessor.swift */; }; 6D5BA6001B6526F0000D7E49 /* SharedExpression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D5BA5FF1B6526F0000D7E49 /* SharedExpression.swift */; }; 6D5BA6011B65271A000D7E49 /* SharedExpression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D5BA5FF1B6526F0000D7E49 /* SharedExpression.swift */; }; 6D5BA6041B6537D5000D7E49 /* SharedExpressionsProcessorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D5BA6031B6537D5000D7E49 /* SharedExpressionsProcessorTests.swift */; }; 6D5BA6051B653935000D7E49 /* SharedExpressionsProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D5BA5FA1B65253B000D7E49 /* SharedExpressionsProcessor.swift */; }; - 6D5BA6091B655F1D000D7E49 /* SimpleExpression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D5BA6081B655F1D000D7E49 /* SimpleExpression.swift */; }; - 6D6282921B3F04C800E65FCD /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6282911B3F04C800E65FCD /* Expression.swift */; }; + 6D5BA6091B655F1D000D7E49 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D5BA6081B655F1D000D7E49 /* Expression.swift */; }; 6D6282941B3F052B00E65FCD /* TranslatablePairTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6282931B3F052B00E65FCD /* TranslatablePairTests.swift */; }; - 6D6282951B3F05DE00E65FCD /* TranslatablePair.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D5004651B3EF92600A54B36 /* TranslatablePair.swift */; }; - 6D6282961B3F063A00E65FCD /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6282911B3F04C800E65FCD /* Expression.swift */; }; - 6D6282981B3F13C300E65FCD /* ExpressionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6282971B3F13C300E65FCD /* ExpressionTests.swift */; }; 6D62829A1B3F17CA00E65FCD /* Regex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6282991B3F17CA00E65FCD /* Regex.swift */; }; 6D62829B1B3F17FE00E65FCD /* Regex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6282991B3F17CA00E65FCD /* Regex.swift */; }; 6D62829D1B3F19CC00E65FCD /* RegexTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D62829C1B3F19CC00E65FCD /* RegexTests.swift */; }; @@ -76,28 +68,19 @@ 6D6283501B3F62B100E65FCD /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D62834F1B3F62B100E65FCD /* LaunchScreen.xib */; }; 6D62F9FC1B6B808400596A7C /* ExpressionJSONs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D62F9FB1B6B808400596A7C /* ExpressionJSONs.swift */; }; 6D62F9FE1B6B824300596A7C /* TranslationJSONs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D62F9FD1B6B824300596A7C /* TranslationJSONs.swift */; }; - 6D6464821B40106C00C46C6D /* LocalizableFilesLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6464811B40106C00C46C6D /* LocalizableFilesLoader.swift */; }; - 6D6464841B40146100C46C6D /* KeyValueType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6464831B40146100C46C6D /* KeyValueType.swift */; }; - 6D6464851B40146600C46C6D /* KeyValueType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6464831B40146100C46C6D /* KeyValueType.swift */; }; 6D75E6D41B6B6CFE00B370DC /* LoadedTranslationsProcessorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D75E6D31B6B6CFE00B370DC /* LoadedTranslationsProcessorTests.swift */; }; 6DB3CC751B5EBDA600A1220F /* CountryCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DB3CC651B5EBDA600A1220F /* CountryCode.swift */; }; - 6DB3CC761B5EBDA600A1220F /* ExpressionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DB3CC661B5EBDA600A1220F /* ExpressionType.swift */; }; 6DB3CC771B5EBDA600A1220F /* SharedExpressionLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DB3CC671B5EBDA600A1220F /* SharedExpressionLoader.swift */; }; 6DB3CC791B5EBDA600A1220F /* JSONFileLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DB3CC691B5EBDA600A1220F /* JSONFileLoader.swift */; }; 6DB3CC7A1B5EBDA600A1220F /* LengthVariation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DB3CC6A1B5EBDA600A1220F /* LengthVariation.swift */; }; - 6DB3CC7B1B5EBDA600A1220F /* LengthVariationType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DB3CC6B1B5EBDA600A1220F /* LengthVariationType.swift */; }; 6DB3CC831B5EBDA600A1220F /* TranslationsLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DB3CC731B5EBDA600A1220F /* TranslationsLoader.swift */; }; 6DB3CC861B5EBF4800A1220F /* CountryCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DB3CC651B5EBDA600A1220F /* CountryCode.swift */; }; 6DB3CC901B5EC29600A1220F /* ExpressionPatternType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DB3CC8F1B5EC29600A1220F /* ExpressionPatternType.swift */; }; 6DB3CC911B5EC29E00A1220F /* ExpressionPatternType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DB3CC8F1B5EC29600A1220F /* ExpressionPatternType.swift */; }; - 6DBB6C511B401B7C002F39A3 /* LocalizableFilesLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6464811B40106C00C46C6D /* LocalizableFilesLoader.swift */; }; 6DBB6C521B401B8A002F39A3 /* Swifternalization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D5004641B3EF92600A54B36 /* Swifternalization.swift */; }; 6DBB6C591B4026B8002F39A3 /* Expressions.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6DBB6C5B1B4026B8002F39A3 /* Expressions.strings */; }; - 6DBB6C651B403367002F39A3 /* SharedExpressionsConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DBB6C641B403367002F39A3 /* SharedExpressionsConfigurator.swift */; }; - 6DBB6C661B40369A002F39A3 /* SharedExpressionsConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DBB6C641B403367002F39A3 /* SharedExpressionsConfigurator.swift */; }; 6DBB6C691B4040F0002F39A3 /* InternalPattern.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DBB6C681B4040F0002F39A3 /* InternalPattern.swift */; }; 6DBB6C6A1B40412D002F39A3 /* InternalPattern.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DBB6C681B4040F0002F39A3 /* InternalPattern.swift */; }; - 6DBB6C6C1B40431D002F39A3 /* LocalizableFilesLoaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DBB6C6B1B40431D002F39A3 /* LocalizableFilesLoaderTests.swift */; }; 6DBB6C871B40718F002F39A3 /* Expressions.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6DBB6C891B40718F002F39A3 /* Expressions.strings */; }; 6DBB6C8F1B40768A002F39A3 /* SharedBaseExpression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DBB6C8C1B40768A002F39A3 /* SharedBaseExpression.swift */; }; 6DBB6C911B40768A002F39A3 /* SharedPolishExpression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DBB6C8E1B40768A002F39A3 /* SharedPolishExpression.swift */; }; @@ -112,7 +95,6 @@ 6DD3B9421B5ED3F000C79EAC /* JSONFileLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DB3CC691B5EBDA600A1220F /* JSONFileLoader.swift */; }; 6DD3B9441B5ED55500C79EAC /* SharedExpressionsLoaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DD3B9431B5ED55500C79EAC /* SharedExpressionsLoaderTests.swift */; }; 6DD3B9451B5ED58A00C79EAC /* SharedExpressionLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DB3CC671B5EBDA600A1220F /* SharedExpressionLoader.swift */; }; - 6DD3B9491B5ED61800C79EAC /* ExpressionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DB3CC661B5EBDA600A1220F /* ExpressionType.swift */; }; 6DD3B94B1B5ED65A00C79EAC /* NSBundle+TestExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DD3B94A1B5ED65A00C79EAC /* NSBundle+TestExtension.swift */; }; /* End PBXBuildFile section */ @@ -130,9 +112,8 @@ 6D140F431B56D03D00359143 /* RandomNumbers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RandomNumbers.swift; sourceTree = ""; }; 6D4C4EAE1B6AA48F00B7839A /* LoadedTranslation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadedTranslation.swift; sourceTree = ""; }; 6D4C4EB21B6AAE3200B7839A /* LoadedTranslationsProcessor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadedTranslationsProcessor.swift; sourceTree = ""; }; - 6D4C4EB41B6AB38400B7839A /* TranslationType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TranslationType.swift; sourceTree = ""; }; 6D4C4EB71B6AB6DE00B7839A /* LoadedTranslationType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadedTranslationType.swift; sourceTree = ""; }; - 6D4C4EBC1B6ABE0700B7839A /* TranslationWithExpressions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TranslationWithExpressions.swift; sourceTree = ""; }; + 6D4C4EBC1B6ABE0700B7839A /* Translation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Translation.swift; sourceTree = ""; }; 6D5004481B3EF91600A54B36 /* Swifternalization.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Swifternalization.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 6D50044C1B3EF91600A54B36 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 6D50044D1B3EF91600A54B36 /* Swifternalization.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Swifternalization.h; sourceTree = ""; }; @@ -140,16 +121,13 @@ 6D5004591B3EF91600A54B36 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 6D50045A1B3EF91600A54B36 /* SwifternalizationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwifternalizationTests.swift; sourceTree = ""; }; 6D5004641B3EF92600A54B36 /* Swifternalization.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Swifternalization.swift; sourceTree = ""; }; - 6D5004651B3EF92600A54B36 /* TranslatablePair.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TranslatablePair.swift; sourceTree = ""; }; 6D5004931B3EFF6D00A54B36 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = ""; }; 6D5BA5EF1B651796000D7E49 /* TranslationsLoaderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TranslationsLoaderTests.swift; sourceTree = ""; }; 6D5BA5FA1B65253B000D7E49 /* SharedExpressionsProcessor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SharedExpressionsProcessor.swift; sourceTree = ""; }; 6D5BA5FF1B6526F0000D7E49 /* SharedExpression.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SharedExpression.swift; path = ../SharedExpression.swift; sourceTree = ""; }; 6D5BA6031B6537D5000D7E49 /* SharedExpressionsProcessorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SharedExpressionsProcessorTests.swift; sourceTree = ""; }; - 6D5BA6081B655F1D000D7E49 /* SimpleExpression.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SimpleExpression.swift; sourceTree = ""; }; - 6D6282911B3F04C800E65FCD /* Expression.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Expression.swift; sourceTree = ""; }; + 6D5BA6081B655F1D000D7E49 /* Expression.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Expression.swift; sourceTree = ""; }; 6D6282931B3F052B00E65FCD /* TranslatablePairTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TranslatablePairTests.swift; sourceTree = ""; }; - 6D6282971B3F13C300E65FCD /* ExpressionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExpressionTests.swift; sourceTree = ""; }; 6D6282991B3F17CA00E65FCD /* Regex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Regex.swift; sourceTree = ""; }; 6D62829C1B3F19CC00E65FCD /* RegexTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RegexTests.swift; sourceTree = ""; }; 6D62829E1B3F1FA000E65FCD /* InequalityExpressionParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InequalityExpressionParser.swift; sourceTree = ""; }; @@ -178,21 +156,15 @@ 6D62834F1B3F62B100E65FCD /* LaunchScreen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LaunchScreen.xib; sourceTree = ""; }; 6D62F9FB1B6B808400596A7C /* ExpressionJSONs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExpressionJSONs.swift; sourceTree = ""; }; 6D62F9FD1B6B824300596A7C /* TranslationJSONs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TranslationJSONs.swift; sourceTree = ""; }; - 6D6464811B40106C00C46C6D /* LocalizableFilesLoader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocalizableFilesLoader.swift; sourceTree = ""; }; - 6D6464831B40146100C46C6D /* KeyValueType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyValueType.swift; sourceTree = ""; }; 6D75E6D31B6B6CFE00B370DC /* LoadedTranslationsProcessorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadedTranslationsProcessorTests.swift; sourceTree = ""; }; 6DB3CC651B5EBDA600A1220F /* CountryCode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CountryCode.swift; sourceTree = ""; }; - 6DB3CC661B5EBDA600A1220F /* ExpressionType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExpressionType.swift; sourceTree = ""; }; 6DB3CC671B5EBDA600A1220F /* SharedExpressionLoader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SharedExpressionLoader.swift; sourceTree = ""; }; 6DB3CC691B5EBDA600A1220F /* JSONFileLoader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSONFileLoader.swift; sourceTree = ""; }; 6DB3CC6A1B5EBDA600A1220F /* LengthVariation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LengthVariation.swift; sourceTree = ""; }; - 6DB3CC6B1B5EBDA600A1220F /* LengthVariationType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LengthVariationType.swift; sourceTree = ""; }; 6DB3CC731B5EBDA600A1220F /* TranslationsLoader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TranslationsLoader.swift; sourceTree = ""; }; 6DB3CC8F1B5EC29600A1220F /* ExpressionPatternType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExpressionPatternType.swift; sourceTree = ""; }; 6DBB6C5A1B4026B8002F39A3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Expressions.strings; sourceTree = ""; }; - 6DBB6C641B403367002F39A3 /* SharedExpressionsConfigurator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SharedExpressionsConfigurator.swift; sourceTree = ""; }; 6DBB6C681B4040F0002F39A3 /* InternalPattern.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InternalPattern.swift; sourceTree = ""; }; - 6DBB6C6B1B40431D002F39A3 /* LocalizableFilesLoaderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocalizableFilesLoaderTests.swift; sourceTree = ""; }; 6DBB6C881B40718F002F39A3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Expressions.strings; sourceTree = ""; }; 6DBB6C8A1B407190002F39A3 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Expressions.strings; sourceTree = ""; }; 6DBB6C8C1B40768A002F39A3 /* SharedBaseExpression.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SharedBaseExpression.swift; sourceTree = ""; }; @@ -244,27 +216,6 @@ name = Helpers; sourceTree = ""; }; - 6D4C4EB11B6AAB5100B7839A /* Next */ = { - isa = PBXGroup; - children = ( - 6DB3CC651B5EBDA600A1220F /* CountryCode.swift */, - 6DB3CC661B5EBDA600A1220F /* ExpressionType.swift */, - 6DB3CC691B5EBDA600A1220F /* JSONFileLoader.swift */, - 6DB3CC6A1B5EBDA600A1220F /* LengthVariation.swift */, - 6DB3CC6B1B5EBDA600A1220F /* LengthVariationType.swift */, - 6D4C4EAE1B6AA48F00B7839A /* LoadedTranslation.swift */, - 6D4C4EB71B6AB6DE00B7839A /* LoadedTranslationType.swift */, - 6D4C4EB21B6AAE3200B7839A /* LoadedTranslationsProcessor.swift */, - 6D5BA6081B655F1D000D7E49 /* SimpleExpression.swift */, - 6DB3CC671B5EBDA600A1220F /* SharedExpressionLoader.swift */, - 6D5BA5FA1B65253B000D7E49 /* SharedExpressionsProcessor.swift */, - 6DB3CC731B5EBDA600A1220F /* TranslationsLoader.swift */, - 6D4C4EB41B6AB38400B7839A /* TranslationType.swift */, - 6D4C4EBC1B6ABE0700B7839A /* TranslationWithExpressions.swift */, - ); - name = Next; - sourceTree = ""; - }; 6D50043E1B3EF91600A54B36 = { isa = PBXGroup; children = ( @@ -288,19 +239,16 @@ 6D50044A1B3EF91600A54B36 /* Swifternalization */ = { isa = PBXGroup; children = ( - 6D4C4EB11B6AAB5100B7839A /* Next */, - 6DB3CC8E1B5EC27600A1220F /* Enums */, - 6DB3CC8D1B5EC1FF00A1220F /* Matchers and Parsers */, - 6DB3CC8A1B5EC19400A1220F /* Protocols */, - 6D6282911B3F04C800E65FCD /* Expression.swift */, - 6D6464811B40106C00C46C6D /* LocalizableFilesLoader.swift */, + 6DB3CC651B5EBDA600A1220F /* CountryCode.swift */, + 6D5BA6081B655F1D000D7E49 /* Expression.swift */, + 6DB3CC6A1B5EBDA600A1220F /* LengthVariation.swift */, 6D6282991B3F17CA00E65FCD /* Regex.swift */, - 6DBB6C8B1B40767B002F39A3 /* Shared Expressions */, 6D5004641B3EF92600A54B36 /* Swifternalization.swift */, - 6DBB6C641B403367002F39A3 /* SharedExpressionsConfigurator.swift */, - 6D5004651B3EF92600A54B36 /* TranslatablePair.swift */, + 6D4C4EBC1B6ABE0700B7839A /* Translation.swift */, + 6DFC3A071B6C1FDF000296D1 /* Loaders and Processors */, + 6DB3CC8D1B5EC1FF00A1220F /* Matchers and Parsers */, + 6DBB6C8B1B40767B002F39A3 /* Shared Expressions */, 6D50044B1B3EF91600A54B36 /* Supporting Files */, - 6D50044D1B3EF91600A54B36 /* Swifternalization.h */, ); path = Swifternalization; sourceTree = ""; @@ -308,6 +256,7 @@ 6D50044B1B3EF91600A54B36 /* Supporting Files */ = { isa = PBXGroup; children = ( + 6D50044D1B3EF91600A54B36 /* Swifternalization.h */, 6D50044C1B3EF91600A54B36 /* Info.plist */, ); name = "Supporting Files"; @@ -316,21 +265,23 @@ 6D5004571B3EF91600A54B36 /* SwifternalizationTests */ = { isa = PBXGroup; children = ( - 6D75E6D21B6B6CBC00B370DC /* Next */, - 6D140F451B56D04300359143 /* Helpers */, - 6D6282971B3F13C300E65FCD /* ExpressionTests.swift */, 6D6282BE1B3F42CA00E65FCD /* InequalityExpressionMatcherTests.swift */, 6D6282A81B3F25DC00E65FCD /* InequalityExpressionParserTests.swift */, 6D6282C01B3F43C600E65FCD /* InequalityExtendedExpressionMatcherTests.swift */, 6D6282C21B3F45A600E65FCD /* InequalityExtendedExpressionParserTests.swift */, - 6DBB6C6B1B40431D002F39A3 /* LocalizableFilesLoaderTests.swift */, + 6DD3B9401B5ED38B00C79EAC /* JSONFileLoaderTests.swift */, + 6D75E6D31B6B6CFE00B370DC /* LoadedTranslationsProcessorTests.swift */, 6D62829C1B3F19CC00E65FCD /* RegexTests.swift */, 6D6282CA1B3F508C00E65FCD /* RegexExpressionParserTests.swift */, 6D6282CC1B3F52AD00E65FCD /* RegexExpressionMatcherTests.swift */, 6DBB6C951B4076E8002F39A3 /* SharedBaseExpressionTests.swift */, + 6DD3B9431B5ED55500C79EAC /* SharedExpressionsLoaderTests.swift */, + 6D5BA6031B6537D5000D7E49 /* SharedExpressionsProcessorTests.swift */, 6DBB6C971B4077FA002F39A3 /* SharedPolishExpressionTests.swift */, 6D50045A1B3EF91600A54B36 /* SwifternalizationTests.swift */, + 6D5BA5EF1B651796000D7E49 /* TranslationsLoaderTests.swift */, 6D6282931B3F052B00E65FCD /* TranslatablePairTests.swift */, + 6D140F451B56D04300359143 /* Helpers */, 6D5004581B3EF91600A54B36 /* Supporting Files */, 6D5004941B3EFF6D00A54B36 /* Localizable.strings */, 6DBB6C5B1B4026B8002F39A3 /* Expressions.strings */, @@ -378,51 +329,24 @@ name = Resources; sourceTree = ""; }; - 6D75E6D21B6B6CBC00B370DC /* Next */ = { - isa = PBXGroup; - children = ( - 6DD3B9401B5ED38B00C79EAC /* JSONFileLoaderTests.swift */, - 6D75E6D31B6B6CFE00B370DC /* LoadedTranslationsProcessorTests.swift */, - 6DD3B9431B5ED55500C79EAC /* SharedExpressionsLoaderTests.swift */, - 6D5BA6031B6537D5000D7E49 /* SharedExpressionsProcessorTests.swift */, - 6D5BA5EF1B651796000D7E49 /* TranslationsLoaderTests.swift */, - ); - name = Next; - sourceTree = ""; - }; - 6DB3CC8A1B5EC19400A1220F /* Protocols */ = { - isa = PBXGroup; - children = ( - 6D6464831B40146100C46C6D /* KeyValueType.swift */, - ); - name = Protocols; - sourceTree = ""; - }; 6DB3CC8D1B5EC1FF00A1220F /* Matchers and Parsers */ = { isa = PBXGroup; children = ( 6D6282A21B3F247000E65FCD /* ExpressionMatcher.swift */, 6D6282A41B3F24A800E65FCD /* ExpressionParser.swift */, + 6DB3CC8F1B5EC29600A1220F /* ExpressionPatternType.swift */, 6D6282AB1B3F327800E65FCD /* InequalityExpressionMatcher.swift */, 6D62829E1B3F1FA000E65FCD /* InequalityExpressionParser.swift */, 6D6282B91B3F40AF00E65FCD /* InequalityExtendedExpressionMatcher.swift */, 6D6282B01B3F3C1E00E65FCD /* InequalityExtendedExpressionParser.swift */, + 6D6282B41B3F3C4100E65FCD /* InequalitySign.swift */, + 6DBB6C681B4040F0002F39A3 /* InternalPattern.swift */, 6D6282C61B3F4F2100E65FCD /* RegexExpressionMatcher.swift */, 6D6282C41B3F4ED100E65FCD /* RegexExpressionParser.swift */, ); name = "Matchers and Parsers"; sourceTree = ""; }; - 6DB3CC8E1B5EC27600A1220F /* Enums */ = { - isa = PBXGroup; - children = ( - 6DB3CC8F1B5EC29600A1220F /* ExpressionPatternType.swift */, - 6D6282B41B3F3C4100E65FCD /* InequalitySign.swift */, - 6DBB6C681B4040F0002F39A3 /* InternalPattern.swift */, - ); - name = Enums; - sourceTree = ""; - }; 6DBB6C8B1B40767B002F39A3 /* Shared Expressions */ = { isa = PBXGroup; children = ( @@ -443,6 +367,20 @@ name = "Localizable Files"; sourceTree = ""; }; + 6DFC3A071B6C1FDF000296D1 /* Loaders and Processors */ = { + isa = PBXGroup; + children = ( + 6DB3CC691B5EBDA600A1220F /* JSONFileLoader.swift */, + 6D4C4EAE1B6AA48F00B7839A /* LoadedTranslation.swift */, + 6D4C4EB71B6AB6DE00B7839A /* LoadedTranslationType.swift */, + 6D4C4EB21B6AAE3200B7839A /* LoadedTranslationsProcessor.swift */, + 6DB3CC671B5EBDA600A1220F /* SharedExpressionLoader.swift */, + 6D5BA5FA1B65253B000D7E49 /* SharedExpressionsProcessor.swift */, + 6DB3CC731B5EBDA600A1220F /* TranslationsLoader.swift */, + ); + name = "Loaders and Processors"; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -593,19 +531,14 @@ buildActionMask = 2147483647; files = ( 6D5BA5FB1B65253B000D7E49 /* SharedExpressionsProcessor.swift in Sources */, - 6D4C4EB51B6AB38400B7839A /* TranslationType.swift in Sources */, - 6DB3CC7B1B5EBDA600A1220F /* LengthVariationType.swift in Sources */, 6D6282A31B3F247000E65FCD /* ExpressionMatcher.swift in Sources */, 6D5004661B3EF92600A54B36 /* Swifternalization.swift in Sources */, 6D62829A1B3F17CA00E65FCD /* Regex.swift in Sources */, - 6D5004671B3EF92600A54B36 /* TranslatablePair.swift in Sources */, 6D6282B51B3F3C4100E65FCD /* InequalitySign.swift in Sources */, 6DBB6C8F1B40768A002F39A3 /* SharedBaseExpression.swift in Sources */, - 6D4C4EBD1B6ABE0700B7839A /* TranslationWithExpressions.swift in Sources */, + 6D4C4EBD1B6ABE0700B7839A /* Translation.swift in Sources */, 6DB3CC901B5EC29600A1220F /* ExpressionPatternType.swift in Sources */, 6DB3CC7A1B5EBDA600A1220F /* LengthVariation.swift in Sources */, - 6D6464841B40146100C46C6D /* KeyValueType.swift in Sources */, - 6DB3CC761B5EBDA600A1220F /* ExpressionType.swift in Sources */, 6DB3CC751B5EBDA600A1220F /* CountryCode.swift in Sources */, 6D4C4EB31B6AAE3200B7839A /* LoadedTranslationsProcessor.swift in Sources */, 6D4C4EAF1B6AA48F00B7839A /* LoadedTranslation.swift in Sources */, @@ -615,14 +548,11 @@ 6D4C4EB81B6AB6DE00B7839A /* LoadedTranslationType.swift in Sources */, 6DB3CC771B5EBDA600A1220F /* SharedExpressionLoader.swift in Sources */, 6DBB6C691B4040F0002F39A3 /* InternalPattern.swift in Sources */, - 6D5BA6091B655F1D000D7E49 /* SimpleExpression.swift in Sources */, + 6D5BA6091B655F1D000D7E49 /* Expression.swift in Sources */, 6DBB6C911B40768A002F39A3 /* SharedPolishExpression.swift in Sources */, - 6DBB6C651B403367002F39A3 /* SharedExpressionsConfigurator.swift in Sources */, 6D6282C51B3F4ED100E65FCD /* RegexExpressionParser.swift in Sources */, - 6D6282921B3F04C800E65FCD /* Expression.swift in Sources */, 6D6282C71B3F4F2100E65FCD /* RegexExpressionMatcher.swift in Sources */, 6DB3CC791B5EBDA600A1220F /* JSONFileLoader.swift in Sources */, - 6D6464821B40106C00C46C6D /* LocalizableFilesLoader.swift in Sources */, 6D6282B11B3F3C1E00E65FCD /* InequalityExtendedExpressionParser.swift in Sources */, 6D6282BA1B3F40AF00E65FCD /* InequalityExtendedExpressionMatcher.swift in Sources */, 6DB3CC831B5EBDA600A1220F /* TranslationsLoader.swift in Sources */, @@ -639,8 +569,6 @@ 6DD3B9441B5ED55500C79EAC /* SharedExpressionsLoaderTests.swift in Sources */, 6D6282C11B3F43C600E65FCD /* InequalityExtendedExpressionMatcherTests.swift in Sources */, 6DD3B9451B5ED58A00C79EAC /* SharedExpressionLoader.swift in Sources */, - 6D6282981B3F13C300E65FCD /* ExpressionTests.swift in Sources */, - 6DBB6C661B40369A002F39A3 /* SharedExpressionsConfigurator.swift in Sources */, 6D75E6D41B6B6CFE00B370DC /* LoadedTranslationsProcessorTests.swift in Sources */, 6D50045B1B3EF91600A54B36 /* SwifternalizationTests.swift in Sources */, 6D6282A61B3F25B900E65FCD /* InequalityExpressionParser.swift in Sources */, @@ -649,9 +577,7 @@ 6DB3CC861B5EBF4800A1220F /* CountryCode.swift in Sources */, 6D5BA6051B653935000D7E49 /* SharedExpressionsProcessor.swift in Sources */, 6D6282A71B3F25BE00E65FCD /* ExpressionMatcher.swift in Sources */, - 6D4C4EB61B6AB43F00B7839A /* TranslationType.swift in Sources */, 6DD3B94B1B5ED65A00C79EAC /* NSBundle+TestExtension.swift in Sources */, - 6D6464851B40146600C46C6D /* KeyValueType.swift in Sources */, 6D6282C81B3F4F6400E65FCD /* RegexExpressionMatcher.swift in Sources */, 6DD3B9421B5ED3F000C79EAC /* JSONFileLoader.swift in Sources */, 6D5BA6011B65271A000D7E49 /* SharedExpression.swift in Sources */, @@ -666,18 +592,14 @@ 6DBB6C941B40769F002F39A3 /* SharedPolishExpression.swift in Sources */, 6DBB6C521B401B8A002F39A3 /* Swifternalization.swift in Sources */, 6D5BA5F01B651796000D7E49 /* TranslationsLoaderTests.swift in Sources */, - 6D5BA5F41B65180F000D7E49 /* LengthVariationType.swift in Sources */, - 6D4C4EC41B6ACF2C00B7839A /* TranslationWithExpressions.swift in Sources */, - 6D6282951B3F05DE00E65FCD /* TranslatablePair.swift in Sources */, + 6D4C4EC41B6ACF2C00B7839A /* Translation.swift in Sources */, 6D6282BF1B3F42CA00E65FCD /* InequalityExpressionMatcherTests.swift in Sources */, - 6D6282961B3F063A00E65FCD /* Expression.swift in Sources */, 6DBB6C921B40769F002F39A3 /* SharedBaseExpression.swift in Sources */, 6D5BA6041B6537D5000D7E49 /* SharedExpressionsProcessorTests.swift in Sources */, 6D6282B31B3F3C2800E65FCD /* InequalityExtendedExpressionParser.swift in Sources */, 6D140F441B56D03D00359143 /* RandomNumbers.swift in Sources */, 6D6282AD1B3F327C00E65FCD /* InequalityExpressionMatcher.swift in Sources */, - 6D4C4EC61B6AD01D00B7839A /* SimpleExpression.swift in Sources */, - 6DD3B9491B5ED61800C79EAC /* ExpressionType.swift in Sources */, + 6D4C4EC61B6AD01D00B7839A /* Expression.swift in Sources */, 6D62829D1B3F19CC00E65FCD /* RegexTests.swift in Sources */, 6D6282CB1B3F508C00E65FCD /* RegexExpressionParserTests.swift in Sources */, 6D6282C31B3F45A600E65FCD /* InequalityExtendedExpressionParserTests.swift in Sources */, @@ -685,9 +607,7 @@ 6D6282AA1B3F269900E65FCD /* ExpressionParser.swift in Sources */, 6D5BA5F11B6517A6000D7E49 /* TranslationsLoader.swift in Sources */, 6D6282BB1B3F41DB00E65FCD /* InequalityExtendedExpressionMatcher.swift in Sources */, - 6DBB6C511B401B7C002F39A3 /* LocalizableFilesLoader.swift in Sources */, 6D62F9FE1B6B824300596A7C /* TranslationJSONs.swift in Sources */, - 6DBB6C6C1B40431D002F39A3 /* LocalizableFilesLoaderTests.swift in Sources */, 6DBB6C961B4076E8002F39A3 /* SharedBaseExpressionTests.swift in Sources */, 6D62829B1B3F17FE00E65FCD /* Regex.swift in Sources */, 6D6282CD1B3F52AD00E65FCD /* RegexExpressionMatcherTests.swift in Sources */, diff --git a/Swifternalization/Expression.swift b/Swifternalization/Expression.swift index 3dd58ed..a82af1d 100644 --- a/Swifternalization/Expression.swift +++ b/Swifternalization/Expression.swift @@ -2,128 +2,74 @@ // Expression.swift // Swifternalization // -// Created by Tomasz Szulc on 27/06/15. +// Created by Tomasz Szulc on 26/07/15. // Copyright (c) 2015 Tomasz Szulc. All rights reserved. // import Foundation /// String that contains expression pattern, e.g. `ie:x<5`, `exp:^1$`. -internal typealias ExpressionPattern = String +typealias ExpressionPattern = String /** -Class represents single expression that is added in curly -brackets inside key in Localizable.strings file or as a value in -Expressions.strings file. - -It is able to validate passed string using internal expression matcher. +Represents simple epxressions. */ -class Expression { - /// Pattern of expression passed during initialization. - let pattern: ExpressionPattern - - /// Type of expression computed based on `pattern`. - private var type: ExpressionPatternType! - - /// Matcher created based on `pattern`. - private var matcher: ExpressionMatcher! - - /** - Return `ExpressionPattern` object if passed `str` parameter contains - some pattern. The pattern may not be one of the supported one. - If the syntax of the passed string is correct it is treated as pattern. +struct Expression { + /// Pattern of expression. + let pattern: String - :param: str string which may or may not contain a pattern. - :returns: `ExpressionPattern` object or nil when pattern is not found. - */ - class func parseExpressionPattern(str: String) -> ExpressionPattern? { - if let pattern = Regex.firstMatchInString(str, pattern: InternalPattern.Expression.rawValue) { - return pattern - } else { -// println("Cannot get expression pattern from string: \(str).") - return nil - } - } + /// A localized value. If `lengthVariations` array is empty or you want to + /// get full localized value use this property. + let localizedValue: String - /** - Tries to parse passed `str` parameter and created `Expression` from it. - If passed string contains expression that is supported and inside logic - compute that this string is some supported pattern an `Expression` object - will be returned. - - :param: str string that may or may not contain expression pattern - :returns: `Expression` object or nil if pattern is not supported. - */ - class func expressionFromString(str: String) -> Expression? { - if let pattern = parseExpressionPattern(str) { - return Expression(pattern: pattern) - } - return nil - } + /// Array of length variations + let lengthVariations: [LengthVariation] - /** - Initializer that takes expression pattern. It may fail when expression - type of passed expression is not supported. - - :param: pattern pattern of expression - :returns: `Expression` object or nil when pattern is not supported. - */ - init?(pattern: ExpressionPattern) { - // pattern is assigned even if init fails because of Swift/compiler bug. + /// Expression matcher that is used in validation + private var expressionMatcher: ExpressionMatcher? = nil + + // Returns expression object + init(pattern: String, localizedValue: String, lengthVariations: [LengthVariation] = [LengthVariation]()) { self.pattern = pattern - - if let type = Expression.getExpressionType(pattern) { - self.type = type - - // build correct expression matcher - buildMatcher() - if matcher == nil { - println("Cannot create expression because expression pattern cannot be parsed: \(pattern)") - return nil + self.localizedValue = localizedValue + self.lengthVariations = lengthVariations + + // Create expression matcher + if let type = getExpressionType(pattern) { + switch (type as ExpressionPatternType) { + case .Inequality: + expressionMatcher = InequalityExpressionParser(pattern).parse() + + case .InequalityExtended: + expressionMatcher = InequalityExtendedExpressionParser(pattern).parse() + + case .Regex: + expressionMatcher = RegexExpressionParser(pattern).parse() } - } else { - println("Cannot create expression with pattern: \(pattern).") - return nil } } /** Method that validates passed string. - + :param: value value that should be matched :returns: `true` if value match expression, otherwise `false`. */ func validate(value: String) -> Bool { - return matcher.validate(value) - } - - - // MARK: Private methods - - /** - Method used to create `ExpressionMatcher` instance that match expression - pattern of this `Expression` object. - */ - private func buildMatcher() { - switch (type as ExpressionPatternType) { - case .Inequality: - matcher = InequalityExpressionParser(pattern).parse() - - case .InequalityExtended: - matcher = InequalityExtendedExpressionParser(pattern).parse() - - case .Regex: - matcher = RegexExpressionParser(pattern).parse() + if let matcher = expressionMatcher { + return matcher.validate(value) + } else { + return pattern == value } } /** - Method used to get `ExpressionPatternType` of passed `ExpressionPattern`. + Method used to get `ExpressionPatternType` of passed `ExpressionPattern`. :param: pattern expression pattern that will be checked. :returns: `ExpressionPatternType` if pattern is supported, otherwise nil. */ - private class func getExpressionType(pattern: ExpressionPattern) -> ExpressionPatternType? { + private func getExpressionType(pattern: ExpressionPattern) -> ExpressionPatternType? { if let result = Regex.firstMatchInString(pattern, pattern: InternalPattern.ExpressionPatternType.rawValue) { return ExpressionPatternType(rawValue: result) } diff --git a/Swifternalization/ExpressionType.swift b/Swifternalization/ExpressionType.swift deleted file mode 100644 index 476c725..0000000 --- a/Swifternalization/ExpressionType.swift +++ /dev/null @@ -1,9 +0,0 @@ -import Foundation - -/** -Represents expressions in the framework. -*/ -protocol ExpressionType { - /// Pattern of expression. - var pattern: String {get} -} diff --git a/Swifternalization/KeyValueType.swift b/Swifternalization/KeyValueType.swift deleted file mode 100644 index 8e1de47..0000000 --- a/Swifternalization/KeyValueType.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// KeyValueType.swift -// Swifternalization -// -// Created by Tomasz Szulc on 28/06/15. -// Copyright (c) 2015 Tomasz Szulc. All rights reserved. -// - -import Foundation - -/// Represents key from .strings file -internal typealias Key = String - -/// Representes value from .strings file -internal typealias Value = String - -/// Represent key-value pair of Key and Value from .strings file. -internal typealias KVDict = Dictionary - -/** -Protocol that defines properties and methods that need to be implemented by -objects that keeps key-value pair things. -*/ -protocol KeyValueType { - /// A key. - var key: Key {get set} - - /// A value. - var value: Value {get set} - - /// Initializer. - init(key: Key, value: Value) -} \ No newline at end of file diff --git a/Swifternalization/LengthVariation.swift b/Swifternalization/LengthVariation.swift index 98f0c58..09dd4b3 100644 --- a/Swifternalization/LengthVariation.swift +++ b/Swifternalization/LengthVariation.swift @@ -3,7 +3,7 @@ import Foundation /** Length variation representation. */ -struct LengthVariation: LengthVariationType { +struct LengthVariation { /// Length - width of a screen. let length: Int diff --git a/Swifternalization/LengthVariationType.swift b/Swifternalization/LengthVariationType.swift deleted file mode 100644 index 14bc186..0000000 --- a/Swifternalization/LengthVariationType.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Foundation - -/** -Represents length variation. -*/ -protocol LengthVariationType { - /// Length of a screen. - var length: Int {get} - - /// Localized value. - var value: String {get} -} diff --git a/Swifternalization/LoadedTranslationsProcessor.swift b/Swifternalization/LoadedTranslationsProcessor.swift index 6ba8b9e..8111d2c 100644 --- a/Swifternalization/LoadedTranslationsProcessor.swift +++ b/Swifternalization/LoadedTranslationsProcessor.swift @@ -27,7 +27,7 @@ class LoadedTranslationsProcessor { expressions as well as built-in ones. Translations are processed in shared expressions processor. */ - class func processTranslations(baseTranslations: [LoadedTranslation], preferedLanguageTranslations: [LoadedTranslation], sharedExpressions: [SharedExpression]) -> [TranslationType] { + class func processTranslations(baseTranslations: [LoadedTranslation], preferedLanguageTranslations: [LoadedTranslation], sharedExpressions: [SharedExpression]) -> [Translation] { // Find those base translations that are not contained in prefered // language translations. @@ -49,7 +49,7 @@ class LoadedTranslationsProcessor { case .Simple: // Simple translation with key and value. let value = $0.content[$0.key] as! String - return TranslationWithExpressions(key: $0.key, expressions: [SimpleExpression(pattern: $0.key, localizedValue: value)]) + return Translation(key: $0.key, expressions: [Expression(pattern: $0.key, localizedValue: value)]) case .WithExpressions: // Translation that contains expression. @@ -57,12 +57,12 @@ class LoadedTranslationsProcessor { // the shared expressions are filtered to get expression that // matches key and if there is a key it is replaced with real // expression pattern. - var expressions = [ExpressionType]() + var expressions = [Expression]() for (key, value) in $0.content as! Dictionary { let pattern = sharedExpressions.filter({$0.identifier == key}).first?.pattern ?? key - expressions.append(SimpleExpression(pattern: pattern, localizedValue: value)) + expressions.append(Expression(pattern: pattern, localizedValue: value)) } - return TranslationWithExpressions(key: $0.key, expressions: expressions) + return Translation(key: $0.key, expressions: expressions) case .WithLengthVariations: // Translation contains length expressions like @100, @200, etc. @@ -70,7 +70,7 @@ class LoadedTranslationsProcessor { for (key, value) in $0.content as! Dictionary { lengthVariations.append(LengthVariation(length: self.parseNumberFromLengthVariation(key), value: value)) } - return TranslationWithExpressions(key: $0.key, expressions: [SimpleExpression(pattern: $0.key, localizedValue: lengthVariations.last!.value, lengthVariations: lengthVariations)]) + return Translation(key: $0.key, expressions: [Expression(pattern: $0.key, localizedValue: lengthVariations.last!.value, lengthVariations: lengthVariations)]) case .WithExpressionsAndLengthVariations: // The most advanced translation type. It contains expressions @@ -79,7 +79,7 @@ class LoadedTranslationsProcessor { // and .WithLengthVariations cases. key is filtered in shared // expressions to get one of shared expressions and then method // builds array of variations. - var expressions = [ExpressionType]() + var expressions = [Expression]() for (key, value) in $0.content { let pattern = sharedExpressions.filter({$0.identifier == key}).first?.pattern ?? key if value is Dictionary { @@ -87,12 +87,12 @@ class LoadedTranslationsProcessor { for (lvKey, lvValue) in value as! Dictionary { lengthVariations.append(LengthVariation(length: self.parseNumberFromLengthVariation(lvKey), value: lvValue)) } - expressions.append(SimpleExpression(pattern: pattern, localizedValue: lengthVariations.last!.value, lengthVariations: lengthVariations)) + expressions.append(Expression(pattern: pattern, localizedValue: lengthVariations.last!.value, lengthVariations: lengthVariations)) } else if value is String { - expressions.append(SimpleExpression(pattern:pattern, localizedValue: value as! String)) + expressions.append(Expression(pattern:pattern, localizedValue: value as! String)) } } - return TranslationWithExpressions(key: $0.key, expressions: expressions) + return Translation(key: $0.key, expressions: expressions) } }) } diff --git a/Swifternalization/LocalizableFilesLoader.swift b/Swifternalization/LocalizableFilesLoader.swift deleted file mode 100644 index f51fc9e..0000000 --- a/Swifternalization/LocalizableFilesLoader.swift +++ /dev/null @@ -1,112 +0,0 @@ -// -// LocalizableFilesLoader.swift -// Swifternalization -// -// Created by Tomasz Szulc on 28/06/15. -// Copyright (c) 2015 Tomasz Szulc. All rights reserved. -// - -import Foundation - - -/** -Type that contains two dictionaries. - -base - for Base localization - -pref - for preferred language localization - -It contains `KVDict` instanes so every one has key and value. -*/ -internal typealias BasePrefDicts = (base: KVDict, pref: KVDict) - -/// Enum that represents file types used by `LocalizableFilesLoader`. -enum StringsFileType: String { - /// Localizable.strings file. - case Localizable = "Localizable" - /// Expressions.strings file. - case Expressions = "Expressions" -} - -/** -Class responsible for loading content from specified file type. -*/ -class LocalizableFilesLoader { - - /// Defines Base language - which is equal "Base". - private let BaseLanguage: Language = "Base" - - /// Bundle where files are located - private let bundle: NSBundle - - /** - Creates `LocalizableFilesLoader` instance. - - :param: bundle A bundle where .strings files are located. - */ - init(_ bundle: NSBundle) { - self.bundle = bundle - } - - /** - Loads content from files of specified `type` and `language`. - Converts them to `BasePrefDicts` instance. - - :param: type A type of files that will be loaded. - :param: language A preferred language - it will be used to find proper - file for specified file type. - - :returns: Returns content of files converted into key-value pairs. - */ - func loadContentFromFilesOfType(type: StringsFileType, language: Language) -> BasePrefDicts { - var basePairs = KVDict() - var preferredPairs = KVDict() - - let getURL = URLforFile(type) - - // Get file url for preferred language .strings file and load if exist. - if let localizableStringsFileURL = getURL(language) { - preferredPairs = parse(localizableStringsFileURL) - } else { - println("\(type.rawValue).strings file not found for \"\(language)\" language") - } - - // Get file url for Base .strings file and load if exist. - if let baseStringsFileURL = getURL(BaseLanguage) { - basePairs = parse(baseStringsFileURL) - } else { - println("\(type.rawValue).strings file not found for Base localization") - } - - return (basePairs, preferredPairs) - } - - // MARK: Private - - /** - Returns URL for file with specified type. - - :param: type A type of file. - :param: language A language of file. (localization). - :returns: `NSURL` to file or nil when file cannot be found. - */ - private func URLforFile(type: StringsFileType)(_ language: Language) -> NSURL? { - return bundle.URLForResource(type.rawValue, withExtension: "strings", subdirectory: language + ".lproj") - } - - /** - Parses files and return key-value pairs. - - :param: fileURL URL to file. - :returns: key-value pairs from .strings files. - */ - private func parse(fileURL: NSURL) -> KVDict { - if let dictionary = NSDictionary(contentsOfURL: fileURL) as? KVDict { - return dictionary - } else { - println("Cannot load Dictionary from content of URL: \(fileURL)") - } - - return KVDict() - } -} diff --git a/Swifternalization/SharedExpression.swift b/Swifternalization/SharedExpression.swift index c660efc..821bf36 100644 --- a/Swifternalization/SharedExpression.swift +++ b/Swifternalization/SharedExpression.swift @@ -23,7 +23,7 @@ protocol SharedExpressionProtocol { /** Represents built-in expression and expressions from Expressions.strings file. */ -struct SharedExpression: ExpressionType { +struct SharedExpression { /// Identifier of expression. let identifier: String diff --git a/Swifternalization/SharedExpressionsConfigurator.swift b/Swifternalization/SharedExpressionsConfigurator.swift deleted file mode 100644 index b6f888f..0000000 --- a/Swifternalization/SharedExpressionsConfigurator.swift +++ /dev/null @@ -1,140 +0,0 @@ -// -// SharedExpressionsConfigurator.swift -// Swifternalization -// -// Created by Tomasz Szulc on 28/06/15. -// Copyright (c) 2015 Tomasz Szulc. All rights reserved. -// - -import Foundation - -/** -Swifternalization contains some built-in country-related shared expressions. -Developer can create its own expressions in Expressions.strings file for -base and preferred language version of the file. - -The class is responsible for proper loading the built-in shared ones and -those loaded from project's files. It handles overriding of built-in and loads -those from Base and preferred language version. - -It always load base expressions, then looking for language specific. -If in Base file are some expressions that overrides built-in, that's fine -the class adds or developer's custom expressions and add only those of built-in -that are not contained in the Base. - -The same is for preferred languages but also here what is important is that -at first preferred language file expressions are loaded, then if something -different is defined in Base it will be also loaded and then the built-in -expression that differs. -*/ -class SharedExpressionsConfigurator { - - /** - Method takes expression for both Base and preferred language localizations - and also internally loads built-in expressions, combine them and returns - tuple with expressions for Base and another array for preferred language - localization. - - :param: dicts A `BasePrefDicts` tuple that contains two dicts of - shared expressions for Base and preferred language localization. - :param: language A preferred user's language. - :returns: Tuple with arrays of shared expressions for Base and preferred - language localizations. - */ - class func configureExpressions(dicts: BasePrefDicts, language: Language) -> (base: [SharedExpression], pref: [SharedExpression]) { - // Convert loaded expressions dicts to SharedExpression arrays - let loadedBaseExpressions = convert(dicts.base) - let loadedPrefExpressions = convert(dicts.pref) - - - // Load country specific expressions from Expressions.strings - var prefBuiltIn = loadBuiltInExpressions(language) - - // Get base built-in expressions - let baseBuiltIn = SharedBaseExpression.allExpressions() - - // Add unique expressions from Base to language specific (preferred) - mergeExpressions(&prefBuiltIn, additional: baseBuiltIn) - - - // Add built-in expressions to Base expressions from Expressions.strings - let resultBaseExpressions = mergeExpressions(loadedBaseExpressions, additional: baseBuiltIn) - - // Add built-in preferred language expressions to those from - // Expressions.strings - var resultPrefExpressions = mergeExpressions(loadedPrefExpressions, additional: prefBuiltIn) - - // Add those from result of base expressions to result of preferred - // language expressions - mergeExpressions(&resultPrefExpressions, additional: resultBaseExpressions) - - - return (resultBaseExpressions, resultPrefExpressions) - } - - - // MARK: Private - - /** - Converts dictionary with expressions to array of `SharedExpression` objects. - - :param: expressionsDict Dictionary with key-value pair of expression - from Expressions.strings. - :returns: Array of `SharedExpression` objects. - */ - private class func convert(expressionsDict: KVDict) -> [SharedExpression] { - var result = [SharedExpression]() - for (key, pattern) in expressionsDict { - result.append(SharedExpression(identifier: key, pattern: pattern)) - } - return result - } - - /** - Method loads built-in framework's built-in expressions for specific language. - - :param: language A preferred user's language. - :returns: Shared expressions for specific language. If there is no - expression for passed language empty array is returned. - */ - private class func loadBuiltInExpressions(language: Language) -> [SharedExpression] { - switch language { - case "pl": return SharedPolishExpression.allExpressions() - default: return [] - } - } - - /** - Method that merges expressions. It takes two arrays, one is `source` and one - is `additional`. If the `source` does not contain some expression from - `additional` array this expression will be added to the `source`. - - :param: source A source array with expressions. - :param: additional Array with additional expressions that may or may not - be added to `source` array. - :returns: Array with expressions that contains all elements from `source` - and elements from `additional` that were not in `source`. - */ - private class func mergeExpressions(var source: [SharedExpression], additional: [SharedExpression]) -> [SharedExpression] { - for additionalExp in additional { - if source.filter({$0.identifier == additionalExp.identifier}).first == nil { - source.append(additionalExp) - } - } - return source - } - - /** - This is just helper method. It does the same like - `mergeExpressions(source:additional:)` but this one takes reference to - `source` array instead of pasing it by value. - - :param: source reference to source array. - :param: additional Array of additional shared expressions. - - :returns: merged array of shared expressions. - */ - private class func mergeExpressions(inout source: [SharedExpression], additional: [SharedExpression]) -> Void { - source = mergeExpressions(source, additional: additional) - } -} \ No newline at end of file diff --git a/Swifternalization/SharedExpressionsProcessor.swift b/Swifternalization/SharedExpressionsProcessor.swift index 11ad957..696fae8 100644 --- a/Swifternalization/SharedExpressionsProcessor.swift +++ b/Swifternalization/SharedExpressionsProcessor.swift @@ -95,7 +95,7 @@ class SharedExpressionsProcessor { :returns: Shared expressions for specific language. If there is no expression for passed language empty array is returned. */ - private class func loadBuiltInExpressions(language: Language) -> [SharedExpression] { + private class func loadBuiltInExpressions(language: CountryCode) -> [SharedExpression] { switch language { case "pl": return SharedPolishExpression.allExpressions() default: return [] diff --git a/Swifternalization/SimpleExpression.swift b/Swifternalization/SimpleExpression.swift deleted file mode 100644 index dada1b8..0000000 --- a/Swifternalization/SimpleExpression.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// SimpleExpression.swift -// Swifternalization -// -// Created by Tomasz Szulc on 26/07/15. -// Copyright (c) 2015 Tomasz Szulc. All rights reserved. -// - -import Foundation - -/** -Represents simple epxressions. -*/ -struct SimpleExpression: ExpressionType { - /// Pattern of expression. - let pattern: String - - /// A localized value. If `lengthVariations` array is empty or you want to - /// get full localized value use this property. - let localizedValue: String - - /// Array of length variations - let lengthVariations: [LengthVariation] - - // Returns expression object - init(pattern: String, localizedValue: String, lengthVariations: [LengthVariation] = [LengthVariation]()) { - self.pattern = pattern - self.localizedValue = localizedValue - self.lengthVariations = lengthVariations - } -} diff --git a/Swifternalization/Swifternalization.swift b/Swifternalization/Swifternalization.swift index 3dac14f..31b552b 100644 --- a/Swifternalization/Swifternalization.swift +++ b/Swifternalization/Swifternalization.swift @@ -11,236 +11,61 @@ import Foundation /// Handy typealias that can be used instead of long `Swifternalization` public typealias I18n = Swifternalization -/** -Defines language selected on the user's device e.g. en, pl, ru. -Language can be also Base. It used used for finding right Localizable.strings -and Expression.strings and to load built-in shared expressions. -*/ -internal typealias Language = String - -/** -This is the main class of Swifternalization library. It exposes methods -that can be used to get localized keys with or without expressions from -Localizable.strings files. - -It also uses Expressions.strings files to manage shared expressions that -can have theirs identifiers placed in many versions of the Localizable.strings -file. - -Internal classes of the Swifternalization contains logic that is responsible -for detecting which value should be used for the given key and value. - -It is able to work with genstrings command-line tool like NSLocalizedString() -macro does. - -It looks for content in the NSBundle you can provide and try to find: - -- Localizable.strings (Base), -- Localizable.strings of preferred language, e.g. Localizable.strings (en) -- Expressions.strings (Base), -- Expressions.strings of preferred language, e.g. Expressions.strings (en) -*/ public class Swifternalization { + static let sharedInstance = Swifternalization() - /// Struct to keep shared instance of `Swifternalization` - private struct Static { - /// Instance of `Swifternalization` that might be nil if not set. - static var instance: Swifternalization? = nil - } - - /// Bundle when Localizable and Expressions .strings files are located. - private let bundle: NSBundle - - /// key-value from base Localizable.strings file - private var basePairs = [TranslatablePair]() - - /// key-value airs from preferred language Localizable.strings file - private var preferredPairs = [TranslatablePair]() - - // MARK: Public methods - /** - Swifternalization takes NSBundle when Localizable.strings file is located. - This method return instance of the class but you don't need it because - shared instance is set automatically. - - It get Localizable.strings file version based on the first language from - the prefferedLocalizations property of NSBundle. If Localizable.strings for - preferred language isn't exist then Base is used instead. + private var translations = [Translation]() - :param: bundle bundle when .strings files are located. - */ - public init(bundle: NSBundle) { - self.bundle = bundle - - /// Set it as shared instance - Swifternalization.setSharedInstance(self) - - /// load all the content - load() - } - - /** - Returns localized string for simple key that does not contain any expression. - - I18n.localizedString("car") - I18n.localizedString("car", defaultValue: "Audi") - I18n.localizedString("car", defaultValue: "Audi", comment: "Comment") - I18n.localizedString("car", comment: "Comment") - - :param: key key placed in Localizable.strings file. - :param: defaultValue default value that will be returned when there is no - translation for passed key. Default is nil. - :param: comment comment used by genstrings tool to generate description of - a key. Default is nil. + // MARK: Public Methods - :returns: Returns translation for passed key if found. If not found and - defaultValue is not nil it return defaultValue, otherwise - returns key. - */ - public class func localizedString(key: String, defaultValue: String? = nil, comment: String? = nil) -> String { - if sharedInstance() == nil { return (defaultValue != nil) ? defaultValue! : key } - - for TranslatablePair in sharedInstance().preferredPairs.filter({$0.key == key}) { - return TranslatablePair.value - } - - for TranslatablePair in sharedInstance().basePairs.filter({$0.key == key}) { - return TranslatablePair.value - } - - return (defaultValue != nil) ? defaultValue! : key + public class func configure(bundle: NSBundle = NSBundle.mainBundle()) { + sharedInstance.load(bundle: bundle) } - /** - Returns localized string for key which contains expression. - - I18n.localizedExpressionString("cars", value: "10") - I18n.localizedExpressionString("cars", value: "10", defaultValue: "Few cars") - I18n.localizedExpressionString("cars", value: "10", defaultValue: "10", comment: "This is a comment") - I18n.localizedExpressionString("cars", value: "10", comment: "This is a comment") - - :param: key key placed in Localizable.strings file. - :param: value value used when validating expressions. - :param: defaultValue default value that will be returned when there is no - translation for passed key. Default is nil. - :param: comment comment used by genstrings tool to generate description - of a key. Default is nil. - - :returns: Returns translation for passed key if found. If not found and - defaultValue is not nil it return defaultValue, otherwise returns key. - */ - public class func localizedExpressionString(key: String, value: String, defaultValue: String? = nil, comment: String? = nil) -> String { - if sharedInstance() == nil { return (defaultValue != nil) ? defaultValue! : key } - - let filter = {(pair: TranslatablePair) -> Bool in - return pair.hasExpression == true && pair.keyWithoutExpression == key - } - - // Filter preferred pairs - for pair in sharedInstance().preferredPairs.filter(filter) { - if pair.validate(value) { - return pair.value - } - } - - // Filter base pairs - for pair in sharedInstance().basePairs.filter(filter) { - if pair.validate(value) { - return pair.value + public class func localizedString(key: String, stringValue: String, fittingWidth: Int? = nil, defaultValue: String? = nil, comment: String? = nil) -> String { + let filteredTranslations = sharedInstance.translations.filter({$0.key == key}) + if let translation = filteredTranslations.first { + if let matchingExpression = translation.validate(stringValue ?? key, length: fittingWidth) { + if fittingWidth == nil { + return matchingExpression.localizedValue + } else if matchingExpression.lengthVariations.count == 0 { + return matchingExpression.localizedValue + } else if matchingExpression.lengthVariations.count > 0 { + /// GET PROPER VARIANT + } } } return (defaultValue != nil) ? defaultValue! : key } - - /** - This method is just extension to method - `localizedExpressionString(_:value:defaultValue:comment:)` that takes - `String` as a `value` parameter. - */ - public class func localizedExpressionString(key: String, value: Int, defaultValue: String? = nil, comment: String? = nil) -> String { - return self.localizedExpressionString(key, value: "\(value)", defaultValue: defaultValue, comment: comment) - } - - // MARK: Private methods - /// Method that set shared instance of Swifternalization - private class func setSharedInstance(instance: Swifternalization) { - Static.instance = instance + public class func localizedString(key: String, intValue: Int, fittingWidth: Int? = nil, defaultValue: String? = nil, comment: String? = nil) -> String { + return localizedString(key, stringValue: "\(intValue)", fittingWidth: fittingWidth, defaultValue: defaultValue, comment: comment) } - /// Method that returns shared instance of Swifternalization - /// :returns: `Swifternalization` shared instance - private class func sharedInstance() -> Swifternalization! { - return Static.instance + public class func localizedString(key: String, fittingWidth: Int? = nil, defaultValue: String? = nil, comment: String? = nil) -> String { + return localizedString(key, stringValue: key, fittingWidth: fittingWidth, defaultValue: defaultValue, comment: comment) } - /** - Method responsible for loading content into Swifternaliztion library. - It takes preferred language of user's device, and tries to find - Localizable.strings (Preferred Language) and Localizable.strings (Base) - to get keys and values of words to translate. - - It also tries to find and load Expressions.strings (Preferred Language) - and Expressions.strings (Base) files when shared expressions might be - and tries to combine them together with built-in shared expression, - and at the end enumeate through key-value pairs for translation and - changes keys that have only expression shortcuts to full expressions. - */ - private func load() { - let language = getPreferredLanguage() - let loader = LocalizableFilesLoader(bundle) - - // Get expressions pairs from Expressions.strings files - let expressionPairsDict = loader.loadContentFromFilesOfType(.Expressions, language: language) + // MARK: Private Methods + + private func load(bundle: NSBundle = NSBundle.mainBundle()) { + let base = "base" + let language = getPreferredLanguage(bundle) - // Get shared expressions for Base and preferred language - // including Framwork's shared expressions - let sharedExpressions = SharedExpressionsConfigurator.configureExpressions(expressionPairsDict, language: language) + let baseExpressions = SharedExpressionsLoader.loadExpressions(JSONFileLoader.loadExpressions(base, bundle: bundle) ?? [:]) + let languageExpressions = SharedExpressionsLoader.loadExpressions(JSONFileLoader.loadExpressions(language, bundle: bundle) ?? [:]) + let expressions = SharedExpressionsProcessor.processSharedExpression(language, preferedLanguageExpressions: languageExpressions, baseLanguageExpressions: baseExpressions) + let baseTranslations = TranslationsLoader.loadTranslations(JSONFileLoader.loadTranslations(base, bundle: bundle) ?? [:]) + let languageTranslations = TranslationsLoader.loadTranslations(JSONFileLoader.loadTranslations(language, bundle: bundle) ?? [:]) - // Get key-value translatable pairs from Localizable.strings files - let translatablePairsDicts = loader.loadContentFromFilesOfType(.Localizable, language: language) - - // Create TranslatablePair objects - basePairs = createTranslablePairs(translatablePairsDicts.base, expressions: sharedExpressions.base) - preferredPairs = createTranslablePairs(translatablePairsDicts.pref, expressions: sharedExpressions.pref) + translations = LoadedTranslationsProcessor.processTranslations(baseTranslations, preferedLanguageTranslations: languageTranslations, sharedExpressions: expressions) } /// Gets preferred language of user's device - private func getPreferredLanguage() -> Language { + private func getPreferredLanguage(bundle: NSBundle) -> CountryCode { // Get preferred language, the one which is set on user's device - return bundle.preferredLocalizations.first as! Language - } - - /** - Enumerate through translatable pairs dict and check if there are some shared - expression identifiers that needs to be replaced with full expressions. - - Next create translatable pairs with susch updated expressions to make it - ready to be used by framework. - */ - private func createTranslablePairs(translatableDict: KVDict, expressions: [SharedExpression]) -> [TranslatablePair] { - var pairs = [TranslatablePair]() - - for (tKey, tValue) in translatableDict { - // Check if there is expression in tKey - if let expressionPattern = Expression.parseExpressionPattern(tKey), - let sharedExpression = expressions.filter({$0.identifier == expressionPattern}).first, - // Create expression with pattern from Expressions.strings and - // it it is correct use it. - let updatedExpression = Expression.expressionFromString("{" + sharedExpression.pattern + "}"), - // Add translable pair with this new updated expression - let keyWithoutExpression = Regex.firstMatchInString(tKey, pattern: InternalPattern.KeyWithoutExpression.rawValue) { - - pairs.append(TranslatablePair(key: keyWithoutExpression + "{" + updatedExpression.pattern + "}", value: tValue)) - continue - } - - pairs.append(TranslatablePair(key: tKey, value: tValue)) - } - - return pairs + return bundle.preferredLocalizations.first as! CountryCode } } - diff --git a/Swifternalization/TranslatablePair.swift b/Swifternalization/TranslatablePair.swift deleted file mode 100644 index e790c29..0000000 --- a/Swifternalization/TranslatablePair.swift +++ /dev/null @@ -1,69 +0,0 @@ -// -// Pairs.swift -// Swifternalization -// -// Created by Tomasz Szulc on 27/06/15. -// Copyright (c) 2015 Tomasz Szulc. All rights reserved. -// - -import Foundation - -/** -Represents key-value pair from Localizable.strings files. -It contains key, value and expression if exists for the key. -It can also validate if text matches expression's requirements. -*/ -struct TranslatablePair: KeyValueType { - /// Key from Localizable.strings. - var key: Key - - /// Value from Localizable.strings. - var value: Value - - /// `Expression` which is parsed from `key`. - var expression: Expression? = nil - - /// Tells if pair has `expression` or not. - var hasExpression: Bool { return expression != nil } - - /** - It returns key without expression pattern. - If pair has `expression` set to nil it will return `key`. - If `expression` exist the `key` will be parsed and returned without - expression pattern. - */ - var keyWithoutExpression: String { - if hasExpression == false { return key } - return Regex.firstMatchInString(key, pattern: InternalPattern.KeyWithoutExpression.rawValue)! - } - - /** - Creates `TranslatablePair`. It automatically tries to parse - expression from key - if there is any. - - :param: key A key from Localizable.strings - :param: value A value from Localizable.strings - */ - init(key: Key, value: Value) { - self.key = key - self.value = value - parseExpression() - } - - /// Method parses expression from the `key` property. - mutating func parseExpression() { - self.expression = Expression.expressionFromString(key) - } - - /** - Validates string and check if matches `expression`'s requirements. - If pair has no expression it return false. - - :param: value A value that will be matched. - :returns: `true` if value matches `expression`, otherwise `false`. - */ - func validate(value: String) -> Bool { - if hasExpression == false { return false } - return expression!.validate(value) - } -} diff --git a/Swifternalization/TranslationWithExpressions.swift b/Swifternalization/Translation.swift similarity index 64% rename from Swifternalization/TranslationWithExpressions.swift rename to Swifternalization/Translation.swift index 6fd0959..7420e6a 100644 --- a/Swifternalization/TranslationWithExpressions.swift +++ b/Swifternalization/Translation.swift @@ -11,16 +11,19 @@ import Foundation /** Represents translation with expressions. */ -struct TranslationWithExpressions: TranslationType { +struct Translation { /// Key that identifies a translation. let key: String /// Expressions that are related to a translation. - let expressions: [ExpressionType] + let expressions: [Expression] - func validate(text: String, length: Int?) { + func validate(text: String, length: Int?) -> Expression? { for expression in expressions { - // Do something + if expression.validate(text) { + return expression + } } + return nil } } diff --git a/Swifternalization/TranslationType.swift b/Swifternalization/TranslationType.swift deleted file mode 100644 index dc9d02a..0000000 --- a/Swifternalization/TranslationType.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// TranslationType.swift -// Swifternalization -// -// Created by Tomasz Szulc on 30/07/15. -// Copyright (c) 2015 Tomasz Szulc. All rights reserved. -// - -import Foundation - -/** -Represents translation. -*/ -protocol TranslationType { - /// Key that identifies translation. - var key: String {get} -} \ No newline at end of file diff --git a/SwifternalizationTests/ExpressionTests.swift b/SwifternalizationTests/ExpressionTests.swift deleted file mode 100644 index 5bc26a3..0000000 --- a/SwifternalizationTests/ExpressionTests.swift +++ /dev/null @@ -1,53 +0,0 @@ -// -// ExpressionTests.swift -// Swifternalization -// -// Created by Tomasz Szulc on 27/06/15. -// Copyright (c) 2015 Tomasz Szulc. All rights reserved. -// - -import UIKit -import XCTest -import Swifternalization - -class ExpressionTests: XCTestCase { - // MARK: - IE - func testIESupported1() { - XCTAssertTrue(Expression.parseExpressionPattern("{ie:x>2}") != nil, "") - } - - func testIESupported2() { - XCTAssertNotNil(Expression.parseExpressionPattern("{ie:x>0.2}"), "") - } - - func testIESupported3() { - XCTAssertTrue(Expression.expressionFromString("abc{ie:x=2}") != nil, "") - } - - // MARK: - IEX - func testIEXSupported1() { - XCTAssertNotNil(Expression.parseExpressionPattern("{iex:0.1 0, "Keys should be greater than 0") - XCTAssertTrue(result.pref.count == 0, "There should be no preferred language dictionary") - } - - func testLoading2() { - let result = loader.loadContentFromFilesOfType(.Expressions, language: language) - XCTAssertTrue(result.base.count > 0, "Keys should be greater than 0") - XCTAssertTrue(result.pref.count == 0, "There should be no preferred language dictionary") - } -} diff --git a/SwifternalizationTests/SharedBaseExpressionTests.swift b/SwifternalizationTests/SharedBaseExpressionTests.swift index 3ba83ff..31d1888 100644 --- a/SwifternalizationTests/SharedBaseExpressionTests.swift +++ b/SwifternalizationTests/SharedBaseExpressionTests.swift @@ -14,7 +14,7 @@ class SharedBaseExpressionTests: XCTestCase { func testOne() { let sharedExp = SharedBaseExpression.allExpressions().filter({$0.identifier == "one"}).first! - let expression = Expression(pattern: sharedExp.pattern)! + let expression = Expression(pattern: sharedExp.pattern, localizedValue: "") XCTAssertTrue(expression.validate("1"), "Should match 1") XCTAssertFalse(expression.validate("2"), "Should not match 2") @@ -22,7 +22,7 @@ class SharedBaseExpressionTests: XCTestCase { func testMoreThanOne() { let sharedExp = SharedBaseExpression.allExpressions().filter({$0.identifier == ">one"}).first! - let expression = Expression(pattern: sharedExp.pattern)! + let expression = Expression(pattern: sharedExp.pattern, localizedValue: "") XCTAssertTrue(expression.validate("2"), "Should match 2") XCTAssertTrue(expression.validate("3"), "Should match 3") @@ -31,7 +31,7 @@ class SharedBaseExpressionTests: XCTestCase { func testTwo() { let sharedExp = SharedBaseExpression.allExpressions().filter({$0.identifier == "two"}).first! - let expression = Expression(pattern: sharedExp.pattern)! + let expression = Expression(pattern: sharedExp.pattern, localizedValue: "") XCTAssertTrue(expression.validate("2"), "Should match 2") XCTAssertFalse(expression.validate("1"), "Should not match 1") @@ -39,7 +39,7 @@ class SharedBaseExpressionTests: XCTestCase { func testOther() { let sharedExp = SharedBaseExpression.allExpressions().filter({$0.identifier == "other"}).first! - let expression = Expression(pattern: sharedExp.pattern)! + let expression = Expression(pattern: sharedExp.pattern, localizedValue: "") XCTAssertTrue(expression.validate("0"), "Should match 0") XCTAssertTrue(expression.validate("2"), "Should match 2") diff --git a/SwifternalizationTests/SharedPolishExpressionTests.swift b/SwifternalizationTests/SharedPolishExpressionTests.swift index 8cbf12f..d2ed5fb 100644 --- a/SwifternalizationTests/SharedPolishExpressionTests.swift +++ b/SwifternalizationTests/SharedPolishExpressionTests.swift @@ -13,7 +13,7 @@ class SharedPolishExpressionTests: XCTestCase { func testFew() { let sharedExp = SharedPolishExpression.allExpressions().filter({$0.identifier == "few"}).first! - let expression = Expression(pattern: sharedExp.pattern)! + let expression = Expression(pattern: sharedExp.pattern, localizedValue: "") XCTAssertTrue(expression.validate("2"), "Should match 2") XCTAssertTrue(expression.validate("24"), "Should match 24") @@ -28,7 +28,7 @@ class SharedPolishExpressionTests: XCTestCase { func testMany() { let sharedExp = SharedPolishExpression.allExpressions().filter({$0.identifier == "many"}).first! - let expression = Expression(pattern: sharedExp.pattern)! + let expression = Expression(pattern: sharedExp.pattern, localizedValue: "") XCTAssertTrue(expression.validate("10"), "Should match 10") XCTAssertTrue(expression.validate("18"), "Should match 18") diff --git a/SwifternalizationTests/SwifternalizationTests.swift b/SwifternalizationTests/SwifternalizationTests.swift index c44e5ce..e466c9b 100644 --- a/SwifternalizationTests/SwifternalizationTests.swift +++ b/SwifternalizationTests/SwifternalizationTests.swift @@ -14,11 +14,7 @@ class SwifternalizationTests: XCTestCase { override func setUp() { super.setUp() - Swifternalization(bundle: NSBundle(forClass: self.dynamicType)) - } - - override func tearDown() { - super.tearDown() + Swifternalization.configure(bundle: NSBundle.testBundle()) } func testShouldReturnKeyWhenNotTranslated() { @@ -36,24 +32,24 @@ class SwifternalizationTests: XCTestCase { // Inequality func testInequality1() { - XCTAssertEqual(Swifternalization.localizedExpressionString("cars", value: "1"), "one car", "") + XCTAssertEqual(Swifternalization.localizedString("cars", intValue: 1), "one car", "") } func testInequality2() { - XCTAssertEqual(Swifternalization.localizedExpressionString("cars", value: "2"), "%d cars", "") + XCTAssertEqual(Swifternalization.localizedString("cars", intValue: 2), "%d cars", "") } func testInequality3() { - XCTAssertEqual(Swifternalization.localizedExpressionString("cars", value: "-3"), "minus %d cars", "") + XCTAssertEqual(Swifternalization.localizedString("cars", intValue: -3), "minus %d cars", "") } // Shared Expression func testSharedExpression1() { - XCTAssertEqual(Swifternalization.localizedExpressionString("things", value: 10), "10 things", "") + XCTAssertEqual(Swifternalization.localizedString("things", intValue: 10), "10 things", "") } func testSharedExpression2() { - XCTAssertEqual(Swifternalization.localizedExpressionString("things", value: 26), ">20 things", "") + XCTAssertEqual(Swifternalization.localizedString("things", intValue: 26), ">20 things", "") } @@ -61,33 +57,33 @@ class SwifternalizationTests: XCTestCase { // Inequality func testPLInequality1() { - XCTAssertEqual(Swifternalization.localizedExpressionString("pl-cars", value: "1"), "jeden samochód", "") + XCTAssertEqual(Swifternalization.localizedString("pl-cars", intValue: 1), "jeden samochód", "") } // Inequality Extended func testPLInequalityExtended2() { - XCTAssertEqual(Swifternalization.localizedExpressionString("pl-cars", value: "2"), "%d samochody", "") + XCTAssertEqual(Swifternalization.localizedString("pl-cars", intValue: 2), "%d samochody", "") } func testPLInequalityExtended3() { - XCTAssertEqual(Swifternalization.localizedExpressionString("pl-cars", value: "-3"), "-2 - -4 samochody", "") + XCTAssertEqual(Swifternalization.localizedString("pl-cars", intValue: -3), "-2 - -4 samochody", "") } // Regex func testPLRegex1() { - XCTAssertEqual(Swifternalization.localizedExpressionString("pl-police-cars", value: "1"), "1 samochód policyjny", "") + XCTAssertEqual(Swifternalization.localizedString("pl-police-cars", intValue: 1), "1 samochód policyjny", "") } func testPLRegex2() { - XCTAssertEqual(Swifternalization.localizedExpressionString("pl-police-cars", value: "2"), "%d samochody policyjne", "") + XCTAssertEqual(Swifternalization.localizedString("pl-police-cars", intValue: 2), "%d samochody policyjne", "") } func testPLRegex3() { - XCTAssertEqual(Swifternalization.localizedExpressionString("pl-police-cars", value: "5"), "%d samochodów policyjnych", "") + XCTAssertEqual(Swifternalization.localizedString("pl-police-cars", intValue: 5), "%d samochodów policyjnych", "") } func testPLRegex4() { - XCTAssertEqual(Swifternalization.localizedExpressionString("pl-police-cars", value: 13), "%d samochodów policyjnych", "") + XCTAssertEqual(Swifternalization.localizedString("pl-police-cars", intValue: 13), "%d samochodów policyjnych", "") } } diff --git a/SwifternalizationTests/TranslatablePairTests.swift b/SwifternalizationTests/TranslatablePairTests.swift index e637761..84c73a2 100644 --- a/SwifternalizationTests/TranslatablePairTests.swift +++ b/SwifternalizationTests/TranslatablePairTests.swift @@ -11,12 +11,12 @@ import XCTest import Swifternalization class TranslatablePairTests: XCTestCase { - - func testShouldNotHaveExpression() { - XCTAssertFalse(TranslatablePair(key: "abc", value: "def").hasExpression, "Shouldn't have expression") - } - - func testShouldHaveExpression() { - XCTAssertTrue(TranslatablePair(key: "abc{ie:x=2}", value: "def").hasExpression, "Should have expression") - } +// +// func testShouldNotHaveExpression() { +// XCTAssertFalse(TranslatablePair(key: "abc", value: "def").hasExpression, "Shouldn't have expression") +// } +// +// func testShouldHaveExpression() { +// XCTAssertTrue(TranslatablePair(key: "abc{ie:x=2}", value: "def").hasExpression, "Should have expression") +// } }