I\'m finally getting round to wrestling with Auto Layout and can\'t seem to figure out how to get right-to-left (RTL) support to work the way I\'d expect/want...
I h
@Aviel answer as a swift 4 UILabel extension
extension UILabel {
func decideTextDirection () {
let tagScheme = [NSLinguisticTagScheme.language]
let tagger = NSLinguisticTagger(tagSchemes: tagScheme, options: 0)
tagger.string = self.text
let lang = tagger.tag(at: 0, scheme: NSLinguisticTagScheme.language,
tokenRange: nil, sentenceRange: nil)
if lang?.rawValue.range(of: "he") != nil || lang?.rawValue.range(of: "ar") != nil {
self.textAlignment = NSTextAlignment.right
} else {
self.textAlignment = NSTextAlignment.left
}
}
}
usage
label.text = "كتابة باللغة العربية" // Assign text
label.decideTextDirection() // Decide direction
Here is my version. It's simpler and also handles multiple languages in the source document.
The Main point is to use the dominantLanguage:
let lang = tagger.dominantLanguage
Code Snippet:
extension UILabel {
func determineTextDirection () {
guard self.text != nil else {return}
let tagger = NSLinguisticTagger(tagSchemes: [.language], options: 0)
tagger.string = self.text
let lang = tagger.dominantLanguage
let rtl = lang == "he" || lang == "ar"
self.textAlignment = rtl ? .right : .left
}
}
Usage:
titleLabel.text = "UILabel היפוך שפה עבור"
titleLabel.determineTextDirection()
Finally: Note that if the App is localized and you may rely on the phones language - the solution your after is: "Natural Text Alignment for RTL": i.e:
titleLabel.textAlignment = .natural
Use the NSLinguisticTagger when your app shows multiple lines with different languages. or when you allow free search in any language, regardless of the local.
You want NSTextAlignmentNatural
. That infers the text alignment from the loaded application language (not from the script).
For iOS 9 and later (using Xcode 7), you can set this in the storyboard (choose the --- alignment option). If you need to target earlier releases, you'll need to create an outlet to the label and set the alignment in awakeFromNib
.
- (void)awakeFromNib {
[[self label] setTextAlignment:NSTextAlignmentNatural];
}
You can use MyLinearLayout to easy support RTL and LRT.
For me those solutions didn't help, and I ended up doing something pretty ugly but it's the only one that did the trick for me. I added it as an NSString
category:
NSString+Extras.h:
#import <Foundation/Foundation.h>
@interface NSString (Extras)
- (NSTextAlignment)naturalTextAligment;
@end
NSString+Extras.m:
#import "NSString+Extras.h"
@implementation NSString (Extras)
- (NSTextAlignment)naturalTextAligment {
NSArray *tagschemes = [NSArray arrayWithObjects:NSLinguisticTagSchemeLanguage, nil];
NSLinguisticTagger *tagger = [[NSLinguisticTagger alloc] initWithTagSchemes:tagschemes options:0];
[tagger setString:self];
NSString *language = [tagger tagAtIndex:0 scheme:NSLinguisticTagSchemeLanguage tokenRange:NULL sentenceRange:NULL];
if ([language rangeOfString:@"he"].location != NSNotFound || [language rangeOfString:@"ar"].location != NSNotFound) {
return NSTextAlignmentRight;
} else {
return NSTextAlignmentLeft;
}
}
@end
To detect the language I used this SO answer.
@Aviel answer as a swift UILabel extension
//MARK: UILabel extension
extension UILabel {
func decideTextDirection () {
let tagScheme = [NSLinguisticTagSchemeLanguage]
let tagger = NSLinguisticTagger(tagSchemes: tagScheme, options: 0)
tagger.string = self.text
let lang = tagger.tagAtIndex(0, scheme: NSLinguisticTagSchemeLanguage,
tokenRange: nil, sentenceRange: nil)
if lang?.rangeOfString("he") != nil || lang?.rangeOfString("ar") != nil {
self.textAlignment = NSTextAlignment.Right
} else {
self.textAlignment = NSTextAlignment.Left
}
}
}
How to use it ?
label.text = "كتابة باللغة العربية" // Assign text
label.decideTextDirection() // Decide direction