From 7953cd867ac42bcd2db409f7be393b69dfc0e3b4 Mon Sep 17 00:00:00 2001 From: yoloabdo Date: Mon, 12 Mar 2018 08:01:58 +0200 Subject: [PATCH 1/9] adding layoutvar --- Sources/Localize.swift | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Sources/Localize.swift b/Sources/Localize.swift index 278240f..def116c 100644 --- a/Sources/Localize.swift +++ b/Sources/Localize.swift @@ -7,6 +7,7 @@ // import Foundation +import UIKit /// Internal current language key let LCLCurrentLanguageKey = "LCLCurrentLanguageKey" @@ -20,6 +21,9 @@ let LCLBaseBundle = "Base" /// Name for language change notification public let LCLLanguageChangeNotification = "LCLLanguageChangeNotification" +// Set appearnce language direction responsnding + +public var changeSemantics = false // MARK: Localization Syntax /** @@ -122,6 +126,14 @@ open class Localize: NSObject { UserDefaults.standard.set(selectedLanguage, forKey: LCLCurrentLanguageKey) UserDefaults.standard.synchronize() NotificationCenter.default.post(name: Notification.Name(rawValue: LCLLanguageChangeNotification), object: nil) + if changeSemantics, selectedLanguage == "ar"{ + if #available(iOSApplicationExtension 9.0, *) { + UIView.appearance().semanticContentAttribute = .forceRightToLeft + } else { + // TODO: - Fallback on earlier versions + // + } + } } } From 80ad0ccc32ba1b01362c8800c4e59bf3bc9429b8 Mon Sep 17 00:00:00 2001 From: yoloabdo Date: Mon, 12 Mar 2018 08:19:11 +0200 Subject: [PATCH 2/9] moving variable inside the class instead of public --- Sources/Localize.swift | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Sources/Localize.swift b/Sources/Localize.swift index def116c..1448f7b 100644 --- a/Sources/Localize.swift +++ b/Sources/Localize.swift @@ -21,9 +21,6 @@ let LCLBaseBundle = "Base" /// Name for language change notification public let LCLLanguageChangeNotification = "LCLLanguageChangeNotification" -// Set appearnce language direction responsnding - -public var changeSemantics = false // MARK: Localization Syntax /** @@ -91,7 +88,9 @@ public extension String { // MARK: Language Setting Functions open class Localize: NSObject { - + // Set appearnce language direction responsnding + public var changeSemantics = false + /** List available languages - Returns: Array of available languages. From 1ebd9ec0f684d53918453cd0fa0b26a3436fc126 Mon Sep 17 00:00:00 2001 From: yoloabdo Date: Mon, 12 Mar 2018 08:34:05 +0200 Subject: [PATCH 3/9] better handling for other languages other than arabic --- Sources/Localize.swift | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/Sources/Localize.swift b/Sources/Localize.swift index 1448f7b..d15c29a 100644 --- a/Sources/Localize.swift +++ b/Sources/Localize.swift @@ -24,10 +24,10 @@ public let LCLLanguageChangeNotification = "LCLLanguageChangeNotification" // MARK: Localization Syntax /** -Swift 1.x friendly localization syntax, replaces NSLocalizedString -- Parameter string: Key to be localized. -- Returns: The localized string. -*/ + Swift 1.x friendly localization syntax, replaces NSLocalizedString + - Parameter string: Key to be localized. + - Returns: The localized string. + */ public func Localized(_ string: String) -> String { return string.localized() } @@ -62,7 +62,7 @@ public extension String { func localized() -> String { return localized(using: nil, in: .main) } - + /** Swift 2 friendly localization syntax with format arguments, replaces String(format:NSLocalizedString) - Returns: The formatted localized string with arguments. @@ -89,8 +89,8 @@ public extension String { open class Localize: NSObject { // Set appearnce language direction responsnding - public var changeSemantics = false - + public static var changeSemantics = false + /** List available languages - Returns: Array of available languages. @@ -127,10 +127,15 @@ open class Localize: NSObject { NotificationCenter.default.post(name: Notification.Name(rawValue: LCLLanguageChangeNotification), object: nil) if changeSemantics, selectedLanguage == "ar"{ if #available(iOSApplicationExtension 9.0, *) { - UIView.appearance().semanticContentAttribute = .forceRightToLeft - } else { - // TODO: - Fallback on earlier versions - // + if #available(iOS 9.0, *) { + let direction = Locale.characterDirection(forLanguage: selectedLanguage) + switch direction { + case .rightToLeft: + UIView.appearance().semanticContentAttribute = .forceRightToLeft + default: + break + } + } } } } From f98f04727eafb3344f897c106df415c467e69ec7 Mon Sep 17 00:00:00 2001 From: yoloabdo Date: Mon, 12 Mar 2018 08:40:36 +0200 Subject: [PATCH 4/9] update app views if semantics changed --- Sources/Localize.swift | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/Sources/Localize.swift b/Sources/Localize.swift index d15c29a..63d7c55 100644 --- a/Sources/Localize.swift +++ b/Sources/Localize.swift @@ -89,7 +89,11 @@ public extension String { open class Localize: NSObject { // Set appearnce language direction responsnding - public static var changeSemantics = false + public static var changeSemantics = false { + didSet{ + updateAppSemantics(currentLanguage()) + } + } /** List available languages @@ -125,16 +129,20 @@ open class Localize: NSObject { UserDefaults.standard.set(selectedLanguage, forKey: LCLCurrentLanguageKey) UserDefaults.standard.synchronize() NotificationCenter.default.post(name: Notification.Name(rawValue: LCLLanguageChangeNotification), object: nil) - if changeSemantics, selectedLanguage == "ar"{ - if #available(iOSApplicationExtension 9.0, *) { - if #available(iOS 9.0, *) { - let direction = Locale.characterDirection(forLanguage: selectedLanguage) - switch direction { - case .rightToLeft: - UIView.appearance().semanticContentAttribute = .forceRightToLeft - default: - break - } + + } + } + + open class func updateAppSemantics(_ language: String) { + if changeSemantics { + if #available(iOSApplicationExtension 9.0, *) { + if #available(iOS 9.0, *) { + let direction = Locale.characterDirection(forLanguage: language) + switch direction { + case .rightToLeft: + UIView.appearance().semanticContentAttribute = .forceRightToLeft + default: + break } } } From cc18764149253f6518c0e9b8f6d28579a0d52c75 Mon Sep 17 00:00:00 2001 From: yoloabdo Date: Mon, 12 Mar 2018 08:48:31 +0200 Subject: [PATCH 5/9] adding reverse for left to right languages --- Sources/Localize.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Sources/Localize.swift b/Sources/Localize.swift index 63d7c55..8f9e52b 100644 --- a/Sources/Localize.swift +++ b/Sources/Localize.swift @@ -141,6 +141,8 @@ open class Localize: NSObject { switch direction { case .rightToLeft: UIView.appearance().semanticContentAttribute = .forceRightToLeft + case .leftToRight: + UIView.appearance().semanticContentAttribute = .forceLeftToRight default: break } From c67f6601094140cea8ba4060026d2c66d52ed8cb Mon Sep 17 00:00:00 2001 From: yoloabdo Date: Mon, 12 Mar 2018 09:21:43 +0200 Subject: [PATCH 6/9] new functionality now works, also swifting the current language to be a var instead of function --- Sources/Localize.swift | 79 ++++++++++--------- Sources/String+LocalizedBundleTableName.swift | 2 +- 2 files changed, 42 insertions(+), 39 deletions(-) diff --git a/Sources/Localize.swift b/Sources/Localize.swift index 8f9e52b..a7254d2 100644 --- a/Sources/Localize.swift +++ b/Sources/Localize.swift @@ -91,7 +91,11 @@ open class Localize: NSObject { // Set appearnce language direction responsnding public static var changeSemantics = false { didSet{ - updateAppSemantics(currentLanguage()) + if #available(iOS 9.0, *) { + setCurrentSemantics(currentLanguage) + } else { + // Fallback on earlier versions + } } } @@ -108,45 +112,44 @@ open class Localize: NSObject { return availableLanguages } - /** - Current language - - Returns: The current language. String. - */ - open class func currentLanguage() -> String { - if let currentLanguage = UserDefaults.standard.object(forKey: LCLCurrentLanguageKey) as? String { - return currentLanguage - } - return defaultLanguage() - } + - /** - Change the current language - - Parameter language: Desired language. - */ - open class func setCurrentLanguage(_ language: String) { - let selectedLanguage = availableLanguages().contains(language) ? language : defaultLanguage() - if (selectedLanguage != currentLanguage()){ - UserDefaults.standard.set(selectedLanguage, forKey: LCLCurrentLanguageKey) - UserDefaults.standard.synchronize() - NotificationCenter.default.post(name: Notification.Name(rawValue: LCLLanguageChangeNotification), object: nil) - + + /// get and set current language of the app via string, ex: "ar", "en", ... etc + open class var currentLanguage: String { + get { + if let currentLanguage = UserDefaults.standard.object(forKey: LCLCurrentLanguageKey) as? String { + return currentLanguage + } + return defaultLanguage + }set{ + let selectedLanguage = availableLanguages().contains(newValue) ? newValue : defaultLanguage + if (selectedLanguage != currentLanguage){ + UserDefaults.standard.set(selectedLanguage, forKey: LCLCurrentLanguageKey) + UserDefaults.standard.synchronize() + NotificationCenter.default.post(name: Notification.Name(rawValue: LCLLanguageChangeNotification), object: nil) + if #available(iOS 9.0, *) { + setCurrentSemantics(selectedLanguage) + } else { + // Fallback on earlier versions + } + } } } - open class func updateAppSemantics(_ language: String) { + + + @available(iOS 9.0, *) + open class func setCurrentSemantics(_ language: String) { if changeSemantics { - if #available(iOSApplicationExtension 9.0, *) { - if #available(iOS 9.0, *) { - let direction = Locale.characterDirection(forLanguage: language) - switch direction { - case .rightToLeft: - UIView.appearance().semanticContentAttribute = .forceRightToLeft - case .leftToRight: - UIView.appearance().semanticContentAttribute = .forceLeftToRight - default: - break - } - } + let direction = Locale.characterDirection(forLanguage: language) + switch direction { + case .rightToLeft: + UIView.appearance().semanticContentAttribute = .forceRightToLeft + case .leftToRight: + UIView.appearance().semanticContentAttribute = .forceLeftToRight + default: + break } } } @@ -155,7 +158,7 @@ open class Localize: NSObject { Default language - Returns: The app's default language. String. */ - open class func defaultLanguage() -> String { + open class var defaultLanguage: String { var defaultLanguage: String = String() guard let preferredLanguage = Bundle.main.preferredLocalizations.first else { return LCLDefaultLanguage @@ -174,7 +177,7 @@ open class Localize: NSObject { Resets the current language to the default */ open class func resetCurrentLanguageToDefault() { - setCurrentLanguage(self.defaultLanguage()) + currentLanguage = self.defaultLanguage } /** @@ -183,7 +186,7 @@ open class Localize: NSObject { - Returns: The localized string. */ open class func displayNameForLanguage(_ language: String) -> String { - let locale : NSLocale = NSLocale(localeIdentifier: currentLanguage()) + let locale : NSLocale = NSLocale(localeIdentifier: currentLanguage) if let displayName = locale.displayName(forKey: NSLocale.Key.identifier, value: language) { return displayName } diff --git a/Sources/String+LocalizedBundleTableName.swift b/Sources/String+LocalizedBundleTableName.swift index 9cdd2f1..6df4e6d 100644 --- a/Sources/String+LocalizedBundleTableName.swift +++ b/Sources/String+LocalizedBundleTableName.swift @@ -24,7 +24,7 @@ public extension String { */ func localized(using tableName: String?, in bundle: Bundle?) -> String { let bundle: Bundle = bundle ?? .main - if let path = bundle.path(forResource: Localize.currentLanguage(), ofType: "lproj"), + if let path = bundle.path(forResource: Localize.currentLanguage, ofType: "lproj"), let bundle = Bundle(path: path) { return bundle.localizedString(forKey: self, value: nil, table: tableName) } From 02d1a967780739e4f96f67e923fa21fac5c3730b Mon Sep 17 00:00:00 2001 From: yoloabdo Date: Mon, 12 Mar 2018 09:57:50 +0200 Subject: [PATCH 7/9] fix example tests and readme file --- README.md | 7 ++++++- .../Sample/ViewController.swift | 2 +- .../SampleTests/SampleTests.swift | 20 +++++++++---------- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 72721b3..a2720a3 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,12 @@ Localize.availableLanguages() To change the current language: ```swift -Localize.setCurrentLanguage("fr") +Localize.currentLanguage = "fr" +``` + +To change app semantics depending on language, add this to appdelegate on didFinishLaunchingWithOptions: +```swift +Localize.currentLanguage = "fr" ``` To update the UI in the view controller where a language change can take place, observe LCLLanguageChangeNotification: diff --git a/examples/LanguageSwitch/Sample/ViewController.swift b/examples/LanguageSwitch/Sample/ViewController.swift index e765a40..ff7cab9 100644 --- a/examples/LanguageSwitch/Sample/ViewController.swift +++ b/examples/LanguageSwitch/Sample/ViewController.swift @@ -54,7 +54,7 @@ class ViewController: UIViewController { let displayName = Localize.displayNameForLanguage(language) let languageAction = UIAlertAction(title: displayName, style: .default, handler: { (alert: UIAlertAction!) -> Void in - Localize.setCurrentLanguage(language) + Localize.currentLanguage = language }) actionSheet.addAction(languageAction) } diff --git a/examples/LanguageSwitch/SampleTests/SampleTests.swift b/examples/LanguageSwitch/SampleTests/SampleTests.swift index 2a4735a..c770f04 100644 --- a/examples/LanguageSwitch/SampleTests/SampleTests.swift +++ b/examples/LanguageSwitch/SampleTests/SampleTests.swift @@ -18,23 +18,23 @@ class SampleTests: XCTestCase { func testSwift1Syntax() { let testString = "Hello world"; - Localize.setCurrentLanguage("fr") + Localize.currentLanguage = "fr" let translatedString = Localized(testString) XCTAssertEqual(translatedString, "Bonjour le monde") } func testSwift2Syntax() { let testString = "Hello world"; - Localize.setCurrentLanguage("fr") + Localize.currentLanguage = "fr" let translatedString = testString.localized() XCTAssertEqual(translatedString, "Bonjour le monde") } func testMultipleLanguageSwitching() { let testString = "Hello world"; - Localize.setCurrentLanguage("es") + Localize.currentLanguage = "es" XCTAssertEqual(testString.localized(), "Hola mundo") - Localize.setCurrentLanguage("de") + Localize.currentLanguage = "de" XCTAssertEqual(testString.localized(), "Hallo Welt") Localize.resetCurrentLanguageToDefault() XCTAssertEqual(testString.localized(), "Hello world") @@ -42,28 +42,28 @@ class SampleTests: XCTestCase { func testFalseLanguage() { let testString = "Hello world"; - Localize.setCurrentLanguage("xxx") + Localize.currentLanguage = "xxx" XCTAssertEqual(testString.localized(), "Hello world") } func testFalseString() { let testString = "Non translated string"; - Localize.setCurrentLanguage("fr") + Localize.currentLanguage = "fr" XCTAssertEqual(testString.localized(), "Non translated string") } func testTableName() { let testString = "Change"; - Localize.setCurrentLanguage("fr") + Localize.currentLanguage = "fr" let translatedString = testString.localized(using: "ButtonTitles") XCTAssertEqual(translatedString, "Modifier") } func testTableNameMultipleLanguage() { let testString = "Change"; - Localize.setCurrentLanguage("es") + Localize.currentLanguage = "es" XCTAssertEqual(testString.localized(using: "ButtonTitles"), "Cambiar") - Localize.setCurrentLanguage("de") + Localize.currentLanguage = "de" XCTAssertEqual(testString.localized(using: "ButtonTitles"), "Ändern") Localize.resetCurrentLanguageToDefault() XCTAssertEqual(testString.localized(using: "ButtonTitles"), "Change") @@ -71,7 +71,7 @@ class SampleTests: XCTestCase { func testTableNameFail() { let testString = "Change"; - Localize.setCurrentLanguage("xxx") + Localize.currentLanguage = "xxx" let translatedString = testString.localized(using: "ButtonTitles") XCTAssertEqual(translatedString, "Change") } From 95df1e21ea891fa50b7ebade84b7c8fe50830833 Mon Sep 17 00:00:00 2001 From: yoloabdo Date: Mon, 12 Mar 2018 11:25:24 +0200 Subject: [PATCH 8/9] instruction type --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a2720a3..f4c8190 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Localize.currentLanguage = "fr" To change app semantics depending on language, add this to appdelegate on didFinishLaunchingWithOptions: ```swift -Localize.currentLanguage = "fr" +Localize.changeSemantics = true ``` To update the UI in the view controller where a language change can take place, observe LCLLanguageChangeNotification: From e92f63d50a111050148da36e06a2c23fa5336ebe Mon Sep 17 00:00:00 2001 From: yoloabdo Date: Wed, 10 Oct 2018 12:27:08 +0200 Subject: [PATCH 9/9] update to 4.2 --- Localize_Swift.xcodeproj/project.pbxproj | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Localize_Swift.xcodeproj/project.pbxproj b/Localize_Swift.xcodeproj/project.pbxproj index c04e11c..3fcb592 100644 --- a/Localize_Swift.xcodeproj/project.pbxproj +++ b/Localize_Swift.xcodeproj/project.pbxproj @@ -474,7 +474,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -524,7 +524,7 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -551,7 +551,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; }; name = Debug; }; @@ -572,7 +572,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.roymarmelstein.Localize-Swift"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; }; name = Release; }; @@ -583,7 +583,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.roymarmelstein.Localize-SwiftTests"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; }; name = Debug; }; @@ -594,7 +594,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.roymarmelstein.Localize-SwiftTests"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; }; name = Release; };