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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions Localize_Swift.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "";
Expand Down Expand Up @@ -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";
Expand All @@ -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;
};
Expand All @@ -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;
};
Expand All @@ -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;
};
Expand All @@ -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;
};
Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.changeSemantics = true
```

To update the UI in the view controller where a language change can take place, observe LCLLanguageChangeNotification:
Expand Down
81 changes: 55 additions & 26 deletions Sources/Localize.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//

import Foundation
import UIKit

/// Internal current language key
let LCLCurrentLanguageKey = "LCLCurrentLanguageKey"
Expand All @@ -23,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()
}
Expand Down Expand Up @@ -61,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.
Expand All @@ -87,6 +88,16 @@ public extension String {
// MARK: Language Setting Functions

open class Localize: NSObject {
// Set appearnce language direction responsnding
public static var changeSemantics = false {
didSet{
if #available(iOS 9.0, *) {
setCurrentSemantics(currentLanguage)
} else {
// Fallback on earlier versions
}
}
}

/**
List available languages
Expand All @@ -101,35 +112,53 @@ 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



/// 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
}
}
}
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)


@available(iOS 9.0, *)
open class func setCurrentSemantics(_ language: String) {
if changeSemantics {
let direction = Locale.characterDirection(forLanguage: language)
switch direction {
case .rightToLeft:
UIView.appearance().semanticContentAttribute = .forceRightToLeft
case .leftToRight:
UIView.appearance().semanticContentAttribute = .forceLeftToRight
default:
break
}
}
}

/**
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
Expand All @@ -148,7 +177,7 @@ open class Localize: NSObject {
Resets the current language to the default
*/
open class func resetCurrentLanguageToDefault() {
setCurrentLanguage(self.defaultLanguage())
currentLanguage = self.defaultLanguage
}

/**
Expand All @@ -157,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
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/String+LocalizedBundleTableName.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
2 changes: 1 addition & 1 deletion examples/LanguageSwitch/Sample/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
20 changes: 10 additions & 10 deletions examples/LanguageSwitch/SampleTests/SampleTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,60 +18,60 @@ 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")
}

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")
}

func testTableNameFail() {
let testString = "Change";
Localize.setCurrentLanguage("xxx")
Localize.currentLanguage = "xxx"
let translatedString = testString.localized(using: "ButtonTitles")
XCTAssertEqual(translatedString, "Change")
}
Expand Down