Created
April 21, 2020 03:50
-
-
Save DisappearPing/43bbbbd601b3599ecec110d0a4529011 to your computer and use it in GitHub Desktop.
In-app change language to lokalize temp gist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Bundle-AppLocale.swift | |
// Radiant Tap Essentials | |
// | |
// Copyright © 2016 Aleksandar Vacić, Radiant Tap | |
// MIT License · http://choosealicense.com/licenses/mit/ | |
// | |
import Foundation | |
import Lokalise | |
/* | |
Credits: | |
https://www.factorialcomplexity.com/blog/2015/01/28/how-to-change-localization-internally-in-your-ios-application.html | |
*/ | |
class MyLocale { | |
enum Language: String { | |
case bySystem = "bySystem" | |
case en = "en" | |
case tw = "zh-Hant" | |
case cn = "zh-Hans" | |
case ja = "ja" | |
case ms = "ms" | |
func getName() -> String { | |
switch self { | |
case .bySystem: | |
return NSLocalizedString("MyLocale_bySystem", comment: "") | |
case .tw: | |
return "繁體中文" | |
case .ja: | |
return "日本語" | |
case .cn: | |
return "简体中文" | |
case .en: | |
return "English" | |
case .ms: | |
return "Bahasa Melayu" | |
} | |
} | |
} | |
static var mDeviceLocaldID: String = "" | |
static var mCurrentLocaleID: String? = nil | |
static var mLocale: Locale = Locale.current | |
static var mUserDefault = UserDefaults.standard | |
static func initialize(locale: Locale, userDefault: UserDefaults) { | |
print("mLocale = \(mLocale)") | |
print("mUserDefault = \(mUserDefault)") | |
mLocale = locale | |
mUserDefault = userDefault | |
mDeviceLocaldID = mLocale.identifier | |
print("mDeviceLocaldID = \(mDeviceLocaldID)") | |
// NSLocale.swizzle(selector: #selector(getter: NSLocale.current)) | |
mCurrentLocaleID = mUserDefault.object(forKey: "savedLocaleID") as? String | |
if mCurrentLocaleID == nil { | |
mCurrentLocaleID = Language.bySystem.rawValue | |
// Bundle.clearInAppOverrides() | |
} else { | |
// Bundle.enforceLanguage(code: currentLocale.identifier) | |
let lokalizedLocal = self.identifyIDToLokalizeSupportID(currentLocale.identifier) | |
Lokalise.shared.setLocalizationLocale(lokalizedLocal, makeDefault: false) { (error) in | |
print("Lokalise = \(error?.localizedDescription)") | |
} | |
} | |
} | |
@objc static var currentLocale: Locale { | |
if let id = mCurrentLocaleID, mCurrentLocaleID != Language.bySystem.rawValue { | |
return Locale(identifier: id) | |
} | |
return Locale(identifier: mDeviceLocaldID) | |
} | |
static func getCurrentLanguage() -> Language { | |
var id: String | |
id = mCurrentLocaleID! | |
if id == Language.bySystem.rawValue { | |
return .bySystem | |
} else if id.contains("Hant") || id.contains("zh_TW") || id.contains("zh_HK") { | |
return .tw | |
} else if id.hasPrefix("zh") { | |
return .cn | |
} else if id.hasPrefix("ja") { | |
return .ja | |
} else if id.contains("ms") { | |
return .ms | |
} else { | |
return .en | |
} | |
} | |
static func getCurrentLanguageName() -> String { | |
return getCurrentLanguage().getName() | |
} | |
static func setCurrentLocale(lang: Language){ | |
let id = lang.rawValue | |
mCurrentLocaleID = id | |
let userDefault = UserDefaults.standard | |
userDefault.set(id, forKey: "savedLocaleID") | |
print("mCurrentLocaleID = \(mCurrentLocaleID)") | |
print("currentLocale.identifier = \(currentLocale.identifier)") | |
print("Locale.current = \(Locale.current)") | |
print("Locale.current.languageCode = \(Locale.current.languageCode)") | |
// if currentLocale.identifier.contains("TW") { | |
// Lokalise.shared.setLocalizationLocale(Locale(identifier: "zh-Hant"), makeDefault: false) { (error) in | |
// print("Lokalise = \(error?.localizedDescription)") | |
// } | |
// } else { | |
let lokalizedLocal = self.identifyIDToLokalizeSupportID(currentLocale.identifier) | |
Lokalise.shared.setLocalizationLocale(lokalizedLocal, makeDefault: false) { (error) in | |
print("Lokalise = \(error?.localizedDescription)") | |
} | |
// } | |
// Bundle.enforceLanguage(code: currentLocale.identifier) | |
AppDelegate.getDelegate()?.setupCategoryActions() | |
MyApi.shared.updatePushToken() | |
EventTracker.languageSetting(eventProperties: nil, userProperties: ["language": MyLocale.currentLocale.identifier]).fire() | |
} | |
static func identifyIDToLokalizeSupportID(_ id: String) -> Locale { | |
if id.contains("Hant") || id.contains("zh_TW") || id.contains("zh_HK") { | |
return Locale(identifier: Language.tw.rawValue) | |
} else if id.hasPrefix("zh") { | |
return Locale(identifier: Language.cn.rawValue) | |
} else if id.hasPrefix("ja") { | |
return Locale(identifier: Language.ja.rawValue) | |
} else if id.contains("ms") { | |
return Locale(identifier: Language.ms.rawValue) | |
} else { | |
return Locale(identifier: Language.en.rawValue) | |
} | |
} | |
} | |
/// Custom subclass to enable on-the-fly Bundle.main language change | |
public final class LocalizedBundle: Bundle { | |
/// Overrides system method and enforces usage of particular .lproj translation bundle | |
override public func localizedString(forKey key: String, value: String?, table tableName: String?) -> String { | |
if let bundle = Bundle.main.localizedBundle { | |
return bundle.localizedString(forKey: key, value: value, table: tableName) | |
} | |
return super.localizedString(forKey: key, value: value, table: tableName) | |
} | |
} | |
public extension Bundle { | |
private struct AssociatedKeys { | |
static var b = "LocalizedMainBundle" | |
} | |
fileprivate var localizedBundle: Bundle? { | |
get { | |
// warning: Make sure this object you are fetching really exists | |
return objc_getAssociatedObject(self, &AssociatedKeys.b) as? Bundle | |
} | |
} | |
static func mapIDToLproj(id: String) -> String { | |
if id.contains("Hant") || id.contains("zh_TW") || id.contains("zh_HK") { | |
return "zh-Hant" | |
} else if id.hasPrefix("zh") { | |
return "zh-Hans" | |
} else if id.hasPrefix("ja") { | |
return "ja" | |
} else if id.contains("ms") { | |
return "ms" | |
} else { | |
return "Base" | |
} | |
} | |
/// Loads the translations for the given language code. | |
/// | |
/// - Parameter code: two-letter ISO 639-1 language code | |
public static func enforceLanguage(code: String) { | |
let lproj = mapIDToLproj(id: code) | |
guard let path = Bundle.main.path(forResource: lproj, ofType: "lproj") else { return } | |
guard let bundle = Bundle(path: path) else { return } | |
// prepare translated bundle for chosen language and | |
// save it as property of the Bundle.main | |
objc_setAssociatedObject(Bundle.main, &AssociatedKeys.b, bundle, .OBJC_ASSOCIATION_RETAIN) | |
// now override class of the main bundle (only once during the app lifetime) | |
// this way, `localizedString(forKey:value:table)` method in our subclass above will actually be called | |
DispatchQueue.once(token: AssociatedKeys.b) { | |
object_setClass(Bundle.main, LocalizedBundle.self) | |
} | |
} | |
/// Removes the custom bundle | |
public static func clearInAppOverrides() { | |
objc_setAssociatedObject(Bundle.main, &AssociatedKeys.b, nil, .OBJC_ASSOCIATION_RETAIN) | |
} | |
} | |
extension NSLocale { | |
static func swizzle(selector: Selector) { | |
let originalSelector = selector | |
let swizzledSelector = #selector(getter: MyLocale.currentLocale) | |
let originalMethod = class_getClassMethod(self, originalSelector) | |
let swizzledMethod = class_getClassMethod(self, swizzledSelector) | |
method_exchangeImplementations(originalMethod!, swizzledMethod!) | |
} | |
} | |
public extension DispatchQueue { | |
private static var _onceTracker = [String]() | |
/** | |
Executes a block of code, associated with a unique token, only once. The code is thread safe and will | |
only execute the code once even in the presence of multithreaded calls. | |
- parameter token: A unique reverse DNS style name such as com.vectorform.<name> or a GUID | |
- parameter block: Block to execute once | |
*/ | |
public class func once(token: String, block:() -> Void) { | |
objc_sync_enter(self); defer { objc_sync_exit(self) } | |
if _onceTracker.contains(token) { | |
return | |
} | |
_onceTracker.append(token) | |
block() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment