Search code examples
iosiphoneuser-interfaceswift4arabic

iOS: how to change Programmatically UI from LTR to RTL and viceversa


I need to change language from English to arabic. All UI's in app developed programatically, I didn't used storyboard/xib for UI. I used localization string for converting language, but I am looking for UI view from LTR to RTL and vice versa.

what is the best way for language change and give me some ideas or samples


Solution

  • You can check the current language by this:

    open class func isCurrentLanguageRTL(language:String) -> Bool {
            return Locale.characterDirection(forLanguage: language) == .rightToLeft
        }
    

    Use this objective C code(Category) you can change your UI RTL:

    #import <Foundation/Foundation.h>
    
    
    @interface NSBundle (Language)
    
    + (void)setLanguage:(NSString *)language;
    
    @end
    

    Implement file :

    #import "NSBundle+Language.h"
    #import <UIKit/UIKit.h>
    #import <objc/runtime.h>
    
    static const char kBundleKey = 0;
    
    @interface BundleEx : NSBundle
    
    @end
    
    @implementation BundleEx
    
    - (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName
    {
        NSBundle *bundle = objc_getAssociatedObject(self, &kBundleKey);
        if (bundle) {
            return [bundle localizedStringForKey:key value:value table:tableName];
        }
        else {
            return [super localizedStringForKey:key value:value table:tableName];
        }
    }
    
    @end
    
    
    @implementation NSBundle (Language)
    
    + (void)setLanguage:(NSString *)language
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            object_setClass([NSBundle mainBundle], [BundleEx class]);
        });
        if ([self isCurrentLanguageRTL:language]) {
            if ([[[UIView alloc] init] respondsToSelector:@selector(setSemanticContentAttribute:)]) {
                [[UIView appearance] setSemanticContentAttribute:UISemanticContentAttributeForceRightToLeft];
                [[UITableView appearance] setSemanticContentAttribute:UISemanticContentAttributeForceRightToLeft];
                [[UINavigationBar appearance] setSemanticContentAttribute:UISemanticContentAttributeForceRightToLeft];
            }
        }else {
            if ([[[UIView alloc] init] respondsToSelector:@selector(setSemanticContentAttribute:)]) {
                [[UIView appearance] setSemanticContentAttribute:UISemanticContentAttributeForceLeftToRight];
                [[UITableView appearance] setSemanticContentAttribute:UISemanticContentAttributeForceLeftToRight];
                [[UINavigationBar appearance] setSemanticContentAttribute:UISemanticContentAttributeForceLeftToRight];
            }
        }
        [[NSUserDefaults standardUserDefaults] setBool:[self isCurrentLanguageRTL:language] forKey:@"AppleTextDirection"];
        [[NSUserDefaults standardUserDefaults] setBool:[self isCurrentLanguageRTL:language] forKey:@"NSForceRightToLeftWritingDirection"];
        [[NSUserDefaults standardUserDefaults] synchronize];
    
        id value = language ? [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language ofType:@"lproj"]] : nil;
        objc_setAssociatedObject([NSBundle mainBundle], &kBundleKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    + (BOOL)isCurrentLanguageRTL:(NSString *)code
    {
        return ([NSLocale characterDirectionForLanguage:code] == NSLocaleLanguageDirectionRightToLeft);
    }
    @end
    

    How to use:

    Any type of language(like RTL, LTR) only call this bundle function in your code:

    Bundle.setLanguage(<#Your Language code#>)
    

    Note: You should add the #import "NSBundle+Language.h" in your bridging Header file.

    If you use the left menu than in case of RTL you have to open the menu from right just checking the above swift function like:

    <#YourClass#>.isCurrentLanguageRTL(<#Your Language Code#>) {
      //open your side menu from right
    }