Make your iOS app compatible with Right to Left languages in SwiftUI and UIKit!
When you test your app, you may miss one of the important parts of the localisation: Right to Left(RTL) languages! There are a couple of languages that the direction of the text is from right to left such as Persian, Arabic, Hebrew, and more. Here we’re going to review some of the important points that by considering them you can easily have the RTL language support in your app and make your app usage even wider.
First of all, we need to know how to test the app in right to left(RTL) conditions. Before going to that matter, let’s create a sample iOS app to use as a sandbox.
The whole sample project is also available at the following Github repository:
https://github.com/novinfard/iOSRTLSample
Create a sample Sandbox for testing
Follow these steps:
File > New > Project > iOS tab > App > Interface: StoryBoard
After creating a new project, go to main.storyboard
add a label and with 16 point margin from the top, left, and right in constraints:
In the label attributes, change the number of lines to 0
, have natural as text alignment, and add the following text as a sample:
این یک متن تست است. در این متن به بررسی عملکرد زبان های راست به چپ میپردازیم.
Add an imageView below the text with 16 points margin from left and top, and 100 points for width and height constraints:
In the image attributes, use one of the system icons like pencil.circle.fill
.
In addition, add a new SwiftUI view to the project with ContentView
name with the following code:
The preview of this view would be as the below picture:
Now we’re ready to test the app in RTL.
Display and also Test the app in RTL
There are a couple of different ways to see your app (or part of your app) in right to left semantic.
Launch Argument
One of the solutions is to set it as a launch argument. For doing so, choose the current scheme from the top bar of Xcode and press “Edit Scheme ...” :
After opening the scheme window, go to the options tab, and in the “App Language” section, choose Right-to-Left Pseudolanguage
instead of System Language
:
If you run the application now, you would see the layout has been changed to a right-to-left layout:
Open the preview of the SwiftUI view and you will see a similar result:
We will come back to this layout automatic changing in the next section, but let’s now see what are the other options for testing in RTL.
Force all or some of the views in the application to RTL mode
For the testing purposes or in some scenarios based on the design requirement, you can force all the views in the application to use the right-to-left direction. To do so in UIKit you need to add this somewhere in AppDelegate
:
If we want to force some specific views to change to the right-to-left direction in UIKit, just change semanticContentAttribute
of that view in the app.
For having a similar approach and force all SwiftUI views to use right-to-left direction we can use the environment key named layoutDirection
at topmost view of the application, somewhere in SceneDelegate
for instance:
If we want to force some specific views to change to the right-to-left direction in SwiftUI, we can change layoutDirection
environment key on that view (including all sub-views of that view)
After exploring the different ways to update the app and view’s logic in the right-to-left direction, now let’s analyse the changes applied in iOS by this update.
SwiftUI Previews for RTL direction
We can easily display the SwiftUI previews in right-to-left and left-to-right by the following code using layoutDirection
environment value:
We used the previewLayout
to just have more space for previewing, so you can remove it if you want to see it fully. The result would be as follows with a neat preview in both language directions:
Automatic changes by iOS for Right-to-Left languages
The first important thing to note is that when we set the labels to have natural
alignment, the OS itself changes the alignment based on the language. In our example, we can see this clearly:
The second thing to notice is the update on auto-layout constraints. It changed the leading constraint to trailing one automatically (and of course visually):
Rotate images based on language direction
The next thing you may want in right to left languages is to rotate the images themselves in these languages. To achieve this, we can use imageFlippedForRightToLeftLayoutDirection
attribute of UIImage
in UIKit.
To see it in action, in our example app, connect the imageView to ViewController
class add the following code:
Now if we compare the result, we can see the image flipped horizontally:
For having the same result in the SwiftUI view, we can use rotationEffect
modifier with 90-degree value:
The result is similar to UIKit one:
A point to consider here is that the general signs or trademarks should not be flipped based on language direction.
Detect the language direction in the app
In the previous example, we changed the rotation of the image, but we need to do this operation only when the direction is right-to-left. In this case and similar scenarios, we need to detect the language direction.
Since iOS 10, the view has the property effectiveUserInterfaceLayoutDirection
that indicates the language direction. So by using it, we can update our UIKit example as follows:
In SwiftUI, we can define the layoutDirection
environment value and read it for checking the language direction:
Now we can see the language direction-based image rotation in the SwiftUI previews:
Avoid the anti-pattern in the design to support Right-to-Left
One of the simple, but important point to keep an eye on that in the design to make the application compatible with RTL languages is to avoid using element alignment as much as possible and keep the element natural alignment and behaviour.
For instance, let’s say we want to add the date in our blog view, in the right bottom corner of it. One way to do so is to having the equal leading and trailing constraint for the label and set the label alignment to right. So we’ll have the view setup as follows:
With the above layout setup, If we run the application in an RTL environment, the result would be the below picture:
As you might realise, it’s not a desirable layout. Because we want the date to be shown in the left bottom corner when the user uses a Right-to-Left language.
To fix this, we can have only a trailing constraint for the label, and keep the label alignment natural
:
Now if we run the application again, we would see that the date label in the correct position for RTL direction:
With this small adjustment, now the layout is correct to Right-to-Left languages as well.
The same technique applies to SwiftUI. For instance, In the same scenario as above, we should try to use “Horizontal Stack” with “Label” and “Spacer” instead of set strict alignment for the label:
If we preview the above view in both direction environments, we will see the correct layouts:
Beyond the layout
There are some consideration in right-to-left languages which are not related to layouts.
One of these considerations is about the numbers. The numbers in Persian and Arabic are different from English counterparts. Thus, the users can write with these localise versions of numbers both in normal keyboard mode and number pad:
So what if the user enters the number in localised keyboard for the verification code or as a mobile number? In order to avoid further issues in the system and the client or server-side logic, we should detect these cases in our app and update the numbers with the English equivalent. To achieve this, we can use number formatter in Swift. By the use of the following small helper we can convert numbers in any languages to English for integer types:
To see how it works, we can update our SwiftUI app as below:
We can see the converted number in the preview:
Conclusion
In this article, we covered how can support the right-to-left languages in our apps using UIKit or SwiftUI. we first made a sandbox to be able to test the right-to-left languages there. Then we talked about different ways we can display and test our app or some parts of it in RTL languages. In the following section, we analysed how iOS works in RTL and we made sure that we understand its automatic right-to-left behaviour. Then we reviewed how can detect the language direction in our code and use that to rotate the image for different language directions. Finally, we covered some cases where we need to consider the right-to-left languages beyond the layouts.
Further Reading
Apple’s Human Interface Guideline for Right-to-Left languages
https://developer.apple.com/design/human-interface-guidelines/right-to-left/overview/introduction/
Supporting Right-to-Left Languages by Apple
https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPInternational/SupportingRight-To-LeftLanguages/SupportingRight-To-LeftLanguages.html