Supporting Right-to-Left Languages

For the most part iOS supports Right-to-Left (RTL) languages such as Arabic with minimal developer effort. Standard UIKit controls take care of switching text alignment and direction automatically as long as you follow some simple guidelines.

Handling exceptions to this natural layout has not been so easy. For example, having right-aligned text switch to the left with a right-to-left language. After a quick recap on natural text alignment I look at how to fix this with the new semantic content API added in iOS 9.

Natural Text Alignment - A Recap

There are two simple guidelines you need to follow to have UIKit automatically adjust layout for right-to-left languages:

  • Use leading/trailing auto layout constraints, not left/right constraints
  • Use NSTextAlignmentNatural (.Natural) not NSTextAlignmentLeft (.Left)

To test RTL text support I have three UILabel objects with horizontal Auto Layout constraints from the leading edge of the label to the leading margin. I will not bother to describe the vertical constraints.

Leading constraints

If we inspect the leading constraint of the first label the menu for each of the items should have Respect language direction ticked:

This can be confusing but is just choosing between having a constraint using leading rather than left edges. For comparison, here is how we would create this constraint in code:

NSLayoutConstraint(item: yesterdayLabel,
              attribute: .Leading,
              relatedBy: .Equal,
                 toItem: view,
              attribute: .LeadingMargin,
             multiplier: 1.0,
               constant: 0.0).active = true

If you untick Respect language direction the constraint switches to using the left edge and left margin:

In code this constraint would now be like this:

NSLayoutConstraint(item: yesterdayLabel,
              attribute: .Left,
              relatedBy: .Equal,
                 toItem: view,
              attribute: .LeftMargin,
             multiplier: 1.0,
               constant: 0.0).active = true

Remember that to support right-to-left languages use leading/trailing not left/right constraints.

Natural Text Alignment

The second point we need to check is the text alignment. If we inspect the UILabel you should see we are using the alignment labelled ---:

Xcode does not make it obvious but this is the natural alignment which means the label will use the default alignment for the application language. If you wanted to set it in code:

yesterdayLabel.textAlignment = .Natural

Interface Builder defaults mean there is nothing extra to do for basic right-to-left text support.

Simulating Right-To-Left Languages

If you are yet to localize your App with a right-to-left language you can preview the layout by changing the Xcode scheme. From the scheme editor (?<) change the Application Language to “Right to Left Pseudolanguage” and launch the app. The interface will switch to right-to-left:

Trying that with our three labels gives us a user interface with the labels flipped to the right:

When You Do No Want Natural Alignment

There can be times when you want to override the natural direction. Suppose I have a label containing some cherry symbols with a green background that I want to fill the horizontal width of the view.

In this scenario I want my cherry label to be right-aligned for left-to-right layouts and left-aligned for right-to-left layouts. To see how to handle that let’s first force the label to be right-aligned for left-to-right layouts. Assume I have a property in my view controller for the cherry label:

var cherryLabel = UILabel()

The code to setup the label, right align it and add it to the superview:

cherryLabel.text = "??????"
cherryLabel.backgroundColor = .greenColor()
cherryLabel.textAlignment = .Right
view.addSubview(cherryLabel)

I want this label width to fill the width of the superview so I will add both leading and trailing constraints and also position it below the top layout guide:

let margins = view.layoutMarginsGuide
cherryLabel.translatesAutoresizingMaskIntoConstraints = false
cherryLabel.leadingAnchor.constraintEqualToAnchor(margins.leadingAnchor).active = true
cherryLabel.trailingAnchor.constraintEqualToAnchor(margins.trailingAnchor).active = true
cherryLabel.topAnchor.constraintEqualToAnchor(topLayoutGuide.bottomAnchor, constant: 20.0).active = true

At this point everything works for left-to-right languages. The trouble comes if we switch to a right-to-left language as our cherries are still on the right side of the view. The automatic flipping of the text alignment only works when we use a natural alignment:

Translation by Google Translate - may not be accurate

To fix the problem we need to detect when we are using a right-to-left layout and then left align our cherries. Before iOS 9 this meant checking the application language against the known list of RTL languages. With iOS 9 there is a better way.

Testing for Layout direction

The iOS 9 way to find the layout direction is to use the UIView class function userInterfaceLayoutDirectionForSemanticContentAttribute. This function takes the semanticContentAttribute property of the view as an argument and returns the layout direction of the user interface.

The default value of semanticContentAttribute for a view is Unspecifiedwhich means that the view should flip between left-to-right and right-to-left layouts. You generally only need to change the default if you have views containing playback or direction controls which you do not want flipped.

With that in mind here are the extra steps to detect when the view is using a right-to-left layout and switch our label to left alignment:

let attribute = view.semanticContentAttribute
let layoutDirection = UIView.userInterfaceLayoutDirectionForSemanticContentAttribute(attribute)
if layoutDirection == .RightToLeft {
  cherryLabel.textAlignment = .Left
}

The cherries now switch to the left when running in Arabic:

Sample Code

You can find the RTLViewController code from this post in the  AutoLayout Xcode project in my GitHub Code Examples repository.

Further Reading

This post has only looked at one aspect of supporting right-to-left user interfaces. I may cover some of the other challenges in future posts but in the meantime I highly recommend taking a look at the WWDC session and Apple Internationalization Guide for further details.

Summary

Getting the Layout Direction

In iOS apps, you get the layout direction of an instance of UIView by calling the userInterfaceLayoutDirectionForSemanticContentAttribute: method. For example:

if ([UIView userInterfaceLayoutDirectionForSemanticContentAttribute:view.semanticContentAttribute] == UIUserInterfaceLayoutDirectionRightToLeft) {
    …
}

In Mac apps, you get the layout direction of an instance of NSView by examining the view’s userInterfaceLayoutDirection property. For example:

if (view.userInterfaceLayoutDirection == NSUserInterfaceLayoutDirectionRightToLeft) {
    …
}

参考链接:https://useyourloaf.com/blog/natural-text-alignment-for-rtl-languages/

https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPInternational/SupportingRight-To-LeftLanguages/SupportingRight-To-LeftLanguages.html

时间: 2024-12-14 02:34:20

Supporting Right-to-Left Languages的相关文章

API翻译 --- Supporting Different Devices 支持不同的设备

DEPENDENCIES AND PREREQUISITES  依赖和先决条件 Android 1.6 or higher YOU SHOULD ALSO READ Application Resources  应用资源 Designing for Multiple Screens 设计多屏幕 Android devices come in many shapes and sizes all around the world. With a wide range of device types,

Supporting Python 3(支持python3)——使用现代的风格改善你的代码

使用现代的风格来改善你的代码 一旦你已经添加了Python 3的支持,你将改成使用Python的新的函数来改进的代码.Once you have added Python 3 support you have a chance to use the newer features of Python to improve your code. Many of the things mentioned in this chapter are in fact possible to do even b

Supporting Python 3(支持python3)——欢迎来到Python 3

欢迎来到Python 3 On Christmas Day 1999 I sat down to write my first piece of software in Python. My experience seems to be typical for Python users. I was initially surprised that indentation was significant, it felt scary to not define variables and I w

CodeForces 277A Learning Languages 并查集

The "BerCorp" company has got n employees. These employees can use m approved official languages for the formal correspondence. The languages are numbered with integers from 1 to m. For each employee we have the list of languages, which he knows

PatentTips - Supporting heterogeneous virtualization

BACKGROUND A virtual machine (VM) architecture logically partitions a physical machine, such that the underlying hardware of the machine is time-shared and appears as one or more independently operation virtual machines. A computer platform in a virt

Supporting Connected Routes to Subnet Zero

Supporting Connected Routes to Subnet Zero IOS allows the network engineer to tell a router to either allow addresses in the zero subnet or not. The motivation has to do with some older IP routing protocols that did not support the use of the zero su

VS2015 Offline Help Content is now available in 10 more languages!

https://blogs.msdn.microsoft.com/devcontentloc/2015/10/21/vs2015-offline-help-content-is-now-available-in-10-more-languages/ The Cloud and Enterprise International team has published Offline Help Content of Visual Studio 2015 for 10 languages. Now yo

[Cycle.js] Hyperscript as our alternative to template languages

Usually we use template languages like Handlebars, JSX, and Jade to create. One simple way we can create our own template language is to write a function that returns these objects for us. This lessons shows how we can use these functions as a DSL to

C. Learning Languages 求联通块的个数

C. Learning Languages 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <string> 7 #include <vector> 8 #include <stack> 9 #include <queue&