如何在应用程序中设置本地化方向?(RTL如果用户选择阿拉伯语,LTR被选中语言为英语)

Kan*_*IOS 19 xcode localization localizable.strings ios swift

我的应用程序必须支持阿拉伯语(从右到左的方向)和英语(从左到右的方向)语言,我需要设置UI并根据我的应用程序中的用户选择语言.

我将使用NSLayoutConstraint实现UI,以便它可以根据前导和尾随约束自动更新UI.

现在我的问题是我如何实现这一目标?由于我的设备语言是英语,我的应用程序用户选择阿拉伯语(仅限我的应用程序),所以我的流程,用户界面,动画等应该是从右到左.

这是ui Direction的示例快照 在此输入图像描述 在此输入图像描述

谢谢

has*_*san 33

最重要的是,您可以在应用内部更改语言.但是,需要额外的工作.我列出了每个iOS版本的限制背景,然后提供解决方案.因为在解释解决方案时,您需要了解其背后的原因.

更新(iOS 9+)

解决方案键: semanticContentAttribute

有人说这种方式不是官方的,可能会导致效率问题.

现在可以在不关闭应用程序的情况下强制UI方向:

UIView.appearance().semanticContentAttribute = .forceRightToLeft
Run Code Online (Sandbox Code Playgroud)

请注意,iOS 9中的栏不能强制转换为RTL(导航和TabBar).虽然它被迫使用iOS 10.

在iOS 10中唯一不能强制RTL的是默认的后退按钮.

更改应用程序语言以及强制布局不会自动强制系统使用与该语言关联的本地化字符串文件.

在iOS 9下面

简短回答:

更改应用程序语言不会根据所选语言强制布局方向,而无需重新启动应用程序.

Apple的指导方针:

Apple没有提供,因为他们不喜欢允许用户从应用程序内部更改语言.Apple推动开发人员使用设备语言.而不是从应用程序内部改变它.

Workarwound:

一些支持阿拉伯语言的应用程序会在用户可以更改语言的设置页面中向用户注释,如果没有重新启动应用程序,布局将无法生效.存储示例应用的链接

将应用程序语言更改为阿拉伯语的示例代码:

[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:@"ar", @"en", nil] forKey:@"AppleLanguages"];
Run Code Online (Sandbox Code Playgroud)

没有重启就不会生效


如何在不重启应用的情况下更改应用语言

解决方案是提供自己的本地化解决方案:

  1. 使用Base Internationalization但不要本地化故事板.
  2. 创建一个字符串文件并将其本地化为所有语言,并以(英语)为基础.
  3. 将更改语言功能置于ViewController其他任何内容ViewController之前,甚至在主要功能之前.或者unwindSegue在更改语言后使用an 返回到根视图控制器.
  4. 在viewDidLoad方法中为所有视图控制器设置视图的字符串.

如果您不支持iOS 9以下,请不要满足第5点和第6点

  1. 在viewDidLoad方法中为所有视图控制器设置视图的约束.

  2. 根据所选语言而不是前导/尾随设置约束使用右/左.


语言类示例(Swift): 在您的单元类中初始化此类的对象.

class LanguageDetails: NSObject {

    var language: String!
    var bundle: Bundle!
    let LANGUAGE_KEY: String = "LANGUAGE_KEY"

    override init() {
        super.init()

        // user preferred languages. this is the default app language(device language - first launch app language)!
        language = Bundle.main.preferredLocalizations[0]

        // the language stored in UserDefaults have the priority over the device language.
        language = Common.valueForKey(key: LANGUAGE_KEY, default_value: language as AnyObject) as! String

        // init the bundle object that contains the localization files based on language
        bundle = Bundle(path: Bundle.main.path(forResource: language == "ar" ? language : "Base", ofType: "lproj")!)

        // bars direction
        if isArabic() {
            UIView.appearance().semanticContentAttribute = .forceRightToLeft
        } else {
            UIView.appearance().semanticContentAttribute = .forceLeftToRight
        }
    }

    // check if current language is arabic
    func isArabic () -> Bool {
        return language == "ar"
    }

    // returns app language direction.
    func rtl () -> Bool {
        return Locale.characterDirection(forLanguage: language) == Locale.LanguageDirection.rightToLeft
    }

    // switches language. if its ar change it to en and vise-versa
    func changeLanguage()
    {
        var changeTo: String
        // check current language to switch to the other.
        if language == "ar" {
            changeTo = "en"
        } else {
            changeTo = "ar"
        }

        // change language
        changeLanguageTo(lang: changeTo)

        Log.info("Language changed to: \(language)")
    }

    // change language to a specfic one.
    func changeLanguageTo(lang: String) {
        language = lang

        // set language to user defaults
        Common.setValue(value: language as AnyObject, key: LANGUAGE_KEY)

        // set prefered languages for the app.
        UserDefaults.standard.set([lang], forKey: "AppleLanguages")
        UserDefaults.standard.synchronize()

        // re-set the bundle object based on the new langauge
        bundle = Bundle(path: Bundle.main.path(forResource: language == "ar" ? language : "Base", ofType: "lproj")!)

        // app direction
        if isArabic() {
            UIView.appearance().semanticContentAttribute = .forceRightToLeft
        } else {
            UIView.appearance().semanticContentAttribute = .forceLeftToRight
        }

        Log.info("Language changed to: \(language)")
    }

    // get local string
    func getLocale() -> NSLocale {
        if rtl() {
            return NSLocale(localeIdentifier: "ar_JO")
        } else {
            return NSLocale(localeIdentifier: "en_US")
        }
    }

    // get localized string based on app langauge.
    func LocalString(key: String) -> String {
        let localizedString: String? = NSLocalizedString(key, bundle: bundle, value: key, comment: "")
//        Log.ver("Localized string '\(localizedString ?? "not found")' for key '\(key)'")
        return localizedString ?? key
    }

    // get localized string for specific language
    func LocalString(key: String, lan: String) -> String {
        let bundl:Bundle! = Bundle(path: Bundle.main.path(forResource: lan == "ar" ? lan : "Base", ofType: "lproj")!)
        return NSLocalizedString(key, bundle: bundl, value: key, comment: "")
    }
}
Run Code Online (Sandbox Code Playgroud)

语言类示例(Objective-c): Swift示例提供完整的解决方案.对不起,你需要自己转换它.

@implementation LanguageDetails

@synthesize language;
@synthesize bundle;

#define LANGUAGE_KEY @"LANGUAGE_KEY"

// language var is also the strings file name ar or en

- (id)init
{
    if (self = [super init]) {

        language = [[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0];

        if (![language isEqualToString:@"ar"])
            language = @"en";

        language = [Common valueForKey:LANGUAGE_KEY defaultValue:language];

        bundle = [NSBundle mainBundle];
    }
    return  self;
}

- (BOOL)rtl {
    return [NSLocale characterDirectionForLanguage:language] == NSLocaleLanguageDirectionRightToLeft;
}

- (void)changeLanguage
{
    if ([language isEqualToString:@"ar"])
        language = @"en";
    else
        language = @"ar";

    [Common setValue:language forKey:LANGUAGE_KEY];
}

- (void)changeLanguageTo:(NSString *)lang
{
    language = lang;

    [Common setValue:language forKey:LANGUAGE_KEY];
}

- (NSString *) LocalString:(NSString *)key {
    return NSLocalizedStringFromTableInBundle(key, language, bundle, nil);
}

@end
Run Code Online (Sandbox Code Playgroud)


MAh*_*ngh 5

使用方向布局边距(iOS 11.0+)

在此输入图像描述

并将视图设置为

右到左

 UIView.appearance().semanticContentAttribute = .forceRightToLeft
Run Code Online (Sandbox Code Playgroud)

左到右

 UIView.appearance().semanticContentAttribute = .forceLeftToRight
Run Code Online (Sandbox Code Playgroud)