Hossam Ghareeb Hossam Ghareeb - 7 months ago 89
Swift Question

Localization on the fly with localized Storyboards

I'm working on an app that has a toggle button to switch between English and Arabic language and should be on the fly. I'm using the method in https://github.com/maximbilan/ios_language_manager and it works fine in all cases except if the storyboard is localized by interface not strings:

enter image description here

Now when I reload the root view controller like this:

func reloadRootVC(){

let delegate : AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

let storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())

delegate.window?.rootViewController = (storyboard.instantiateInitialViewController())
}


it reload the root with localized strings and in RTL but with the english storyboard not the arabic one.

Tried force loading the arabic one like this:

let storyboard = UIStoryboard(name: "Main", bundle: NSBundle(path: NSBundle.mainBundle().pathForResource(LanguageManager.currentLanguageCode(), ofType: "lproj")!))


but unfortunately it loads the storyboard but with no images. It can't read any resource image.

Answer

I ended up by moving the arabic storyboard outside and name it Main-AR, then adding an extension in UIStoryboard to swizzle and initializer of storyboard to add -AR to the end of the storyboard name if i'm on arabic mode.

extension UIStoryboard {
public override class func initialize() {
    struct Static {
        static var token: dispatch_once_t = 0
    }

    // make sure this isn't a subclass
    if self !== UIStoryboard.self {
        return
    }

    dispatch_once(&Static.token) {
        let originalSelector = #selector(UIStoryboard.init(name:bundle:))
        let swizzledSelector = #selector(UIStoryboard.initWithLoc(_:bundle:))

        let originalMethod = class_getClassMethod(self, originalSelector)
        let swizzledMethod = class_getClassMethod(self, swizzledSelector)

        class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))

        method_exchangeImplementations(originalMethod, swizzledMethod)

    }
}

// MARK: - Method Swizzling

class func initWithLoc(name: String, bundle storyboardBundleOrNil: NSBundle?) -> UIStoryboard{
    var newName = name
    if LanguageManager.isCurrentLanguageRTL(){
        newName += "-AR"
        if #available(iOS 9.0, *) {
            UIView.appearance().semanticContentAttribute = .ForceRightToLeft
        } else {
            // Fallback on earlier versions

        }
    }
    else{
        if #available(iOS 9.0, *) {
            UIView.appearance().semanticContentAttribute = .ForceLeftToRight
        } else {
            // Fallback on earlier versions
        }
    }
    return initWithLoc(newName, bundle: storyboardBundleOrNil)
}
}