设置iOS语言而不重新启动

时间:2015-10-27 13:18:57

标签: ios swift localization

我知道有不少帖子表示不应该这样做,或者不可能。我修改了一些想法,现在我问这个问题,因为我想绝对确定没有其他选择。

选项1:

最受欢迎的解决方案是在this帖子中更改AppleLanguages。我不介意要求重启,所以这对我来说是一个可以接受的解决方案,除了你不能以编程方式重启你的应用程序(无法找到方法,或者被Apple拒绝)。要求用户手动重启应用程序并不理想。

选项2:

下一个解决方案是获取相应的捆绑包并对每个localizedStringForKeyUILabel等执行UIButton查找。这可能有点单调乏味但对我来说没问题因为我已经将localizationProperties(类似于this)添加到这些视图中,所以我可以拥有一个集中的字符串文件。

AppDelegate.swift:

static var userLanguage: String?
    {
        set
        {
            let defaults = NSUserDefaults.standardUserDefaults();
            defaults.setObject(newValue, forKey: LanguageKey);
            defaults.synchronize();

            let storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle());
            instance.window?.rootViewController = storyboard.instantiateInitialViewController();
        }

        get
        {
            let defaults = NSUserDefaults.standardUserDefaults();
            return defaults.stringForKey(LanguageKey);
        }
    }

Localization.swift:

private var bundle: NSBundle
{
    get
    {
        let bundle: NSBundle;
        #if TARGET_INTERFACE_BUILDER
            bundle = NSBundle(forClass: self.dynamicType);
        #else
            bundle = NSBundle.mainBundle();
        #endif

        let lang: String;
        if(AppDelegate.userLanguage == nil || AppDelegate.userLanguage == "en")
        {
            lang = "Base";
        }
        else
        {
            lang = AppDelegate.userLanguage!;
        }

        let path = bundle.pathForResource(lang, ofType: "lproj");
        if(path != nil)
        {
            let toreturn = NSBundle(path: path!);
            if(toreturn != nil)
            {
                return toreturn!;
            }
        }

        return bundle;
    }
}

extension UILabel
{
    @IBInspectable var localizedText: String?
    {
        get { return "" }

        set
        {
            if(newValue != nil)
            {
                text = bundle.localizedStringForKey(newValue!, value:"", table: nil);
            }
        }
    }
}

选项2的问题在于,这仅为这些字段设置语言。布局方向将保持不变,并且不会使用特定于语言的布局等文件。

通过扩展UIApplication,我可以指定一个自定义userInterfaceLayoutDirection,它可以在LTR和RTL之间成功交换所有布局。

DemoApplication.swift:

class DemoApplication: UIApplication
{
    override internal var userInterfaceLayoutDirection: UIUserInterfaceLayoutDirection
    {
        get
        {
            if(AppDelegate.userLanguage == "ar")
            {
                return UIUserInterfaceLayoutDirection.RightToLeft;
            }

            return UIUserInterfaceLayoutDirection.LeftToRight;
        }
    }
}

现在,当我设置AppDelegate.userLanguage时,应用程序将重置为初始视图控制器,显示新语言,翻转LTR和RTL之间的布局。这解决了语言特定文件的问题,我也注意到文本在其自己的边界内保持左右对齐。

由于我无法找到原生iOS类的源代码,因此我无法查看启动时设置的语言特定变量,因此我认为它与NSBundle.mainBundle相关联。我尝试使用方法swizzling覆盖它。

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

        // make sure this isn't a subclass
        if (self !== NSBundle.self)
        {
            return;
        }

        dispatch_once(&Static.token)
        {
            do
            {
                try jr_swizzleClassMethod("mainBundle", withClassMethod: "mainBundleExt");
            }
            catch
            {
                print("\(error)");
            }
        }

        super.initialize();
    }

    public class func mainBundleExt() -> NSBundle
    {
        let bundle = self.mainBundleExt();  // Due to swizzling, this is the "super" method

        let lang: String;
        if(AppDelegate.userLanguage == nil || AppDelegate.userLanguage == "en")
        {
            lang = "Base";
        }
        else
        {
            lang = AppDelegate.userLanguage!;
        }

        let path = bundle.pathForResource(lang, ofType: "lproj");
        if(path != nil)
        {
            let toreturn = NSBundle(path: path!);
            if(toreturn != nil)
            {
                return toreturn!;
            }
        }
    }
}

但这不起作用,似乎仍然使用默认的mainBundle

所以我的问题是:mainBundle如何分配值?启动时设置了哪些其他语言特定变量,例如userInterfaceLayoutDirection。 我假设有2或3个这些变量。最后,这可能是有效还是我只是在浪费时间?

感谢。

2 个答案:

答案 0 :(得分:0)

我以前有这个问题,并且我已经使用过一个图书馆。它帮助我即时更改语言。 尝试使用此: https://github.com/Decybel07/L10n-swift

L10n.shared.language = "en"
L10n.shared.language = "en-GB"

在运行时,您可以随时通过设置language属性来切换语言

答案 1 :(得分:0)

使用此行代码,它将更改布局而无需关闭应用程序。从右到左

rm -f $dummyfile

从左向右翻转

UIView.appearance().semanticContentAttribute = .forceRightToLeft

,如果您想更改文本字段布局或更改文本,请使用此代码,因为我遇到了这个问题。 textfield的文本未更改布局。检查此代码以更改文本字段文本的布局

UIView.appearance().semanticContentAttribute = .forceLeftToRight