iOS 9 Swift Programming Cookbook (2015)
Chapter 3. The User Interface
3.9 Supporting Right-to-Left Languages
Problem
You are internationalizing your app and, as part of this process, need to support right-to-left languages such as Persian or Arabic.
Solution
Use a combination of the followings:
§ Use IB’s view properties to arrange your items with proper semantic properties.
§ Ensure that you create your constraints correctly, preferrably using IB.
§ Use UIView’s userInterfaceLayoutDirectionForSemanticContentAttribute(_:) class method to find the direction of the user interface based on the semantic attributes that are part of the UISemanticContentAttribute enum.
§ If arranging your items in code, use the semanticContentAttribute property of your views to set their semantic properly.
Discussion
Let’s create an app that has a text view on top and four buttons arranged like the arrow keys on the keyboard: up, left, down, right. When each one of these buttons is pressed, we will display the corresponding word in the text field. The text field will be read-only, and when displaying right-to-left languages, it will of course show the text on the right- hand side. Make sure that your UI looks (for now) something like Figure 3-21. There are one text field and four buttons.
Figure 3-21. Initial layout
Now select the left, down, and right buttons on the UI (exclude the up button for now) and stack them up together. In the new stack that was created, set the spacing to 20 (see Figure 3-22). Set the horizontal stack view’s spacing so that the buttons will be horizontally stacked with the proper distance from each other.
Figure 3-22. Horizontal spacing between buttons
Then select the newly created stack and the up button on IB and stack those up together. This will create a vertical stack view for you. Set the spacing for this new stack view to 10. Place the main stack view at the center of the screen. Use IB’s “Resolve Auto Layout Issues” feature to add all missing constraints for all the components. Also make sure that you disable editing of the text field. Then hook up the text field to your code as an outlet and hook up the four buttons’ touch events to your view controller as well. Now your UI should look like Figure 3-23) on IB.
Figure 3-23. Your UI should look like this at the moment
Now choose the main stack view in your UI. In IB, under attributes inspector, in the Semantic section, choose Playback. This will ensure that the views inside this stack view will not be mirrored right to left when the language changes to a right-to-left language (see Figure 3-24).
Figure 3-24. Choosing the Playback view semantic
Now from Xcode, create a new Strings file, name it Localizable.strings, and place your string keys in there:
"up" = "Up";
"down" = "Down";
"right" = "Right";
"left" = "Left";
Under your main projects’s info page in Xcode, choose Localizations and add Arabic as a localization. Then move over to your newly created strings file and enable the Arabic language on it (see Figure 3-25).
Figure 3-25. Localize the strings file so that you have both English and Arabic in the list
You will now have two strings files. Go into the Arabic one and localize the file:
"up" = "Up in Arabic";
"down" = "Down in Arabic";
"right" = "Right in Arabic";
"left" = "Left in Arabic";
NOTE
I don’t speak Arabic and I’m not going to start now!
In your code now, we have to set the text field’s text direction based on the orientation that we get from UIView. That orientation itself depends on the semantics that we set on our text field before:
class ViewController: UIViewController {
@IBOutlet var txtField: UITextField!
@IBAction func up() {
txtField.text = NSLocalizedString("up", comment: "")
}
@IBAction func left() {
txtField.text = NSLocalizedString("left", comment: "")
}
@IBAction func down() {
txtField.text = NSLocalizedString("down", comment: "")
}
@IBAction func right() {
txtField.text = NSLocalizedString("right", comment: "")
}
override func viewDidAppear(animated: Bool) {
let direction = UIView
.userInterfaceLayoutDirectionForSemanticContentAttribute(
txtField.semanticContentAttribute)
switch direction{
case .LeftToRight:
txtField.textAlignment = .Left
case .RightToLeft:
txtField.textAlignment = .Right
}
}
}
Now run the app on an English device and you will see English content in the text field aligned from left to right. Run it on an Arabic localized device and you’ll see the text aligned on the right hand side.
See Also