6

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.

Hossam Ghareeb
  • 7,063
  • 3
  • 53
  • 64
  • You're unfortunately going to have a lot of trouble getting this to work for interfaces, as well as getting RTL UI to behave correctly, not to mention formatters and localised format strings not doing the correct thing. The general expectation is that apps follow the system language and do not implement an in-app language switcher... it would save you a lot of trouble in the long run. :( – wakachamo May 03 '16 at 17:15

2 Answers2

2

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)
}
}
Hossam Ghareeb
  • 7,063
  • 3
  • 53
  • 64
2

change the bundle which is used to init the storyboard:

        let path = Bundle.main.path(forResource: "ar", ofType: "lproj")
        let bundle = Bundle(path: path!)
        let delegate : AppDelegate = UIApplication.shared.delegate as! AppDelegate
        let storyboard = UIStoryboard(name: "Main", bundle: bundle)
        delegate.window?.rootViewController = (storyboard.instantiateInitialViewController())

although this change the storyboard based on language but do not load images! :(

Navid
  • 901
  • 9
  • 20