Make your iOS app compatible with Right to Left languages in SwiftUI and UIKit!

Soheil Novinfard
8 min readJun 29, 2021

--

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:

Sample label 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:

Sample Image 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:

Sample SwiftUI view with a text and an image

The preview of this view would be as the below picture:

Preview of Sample SwiftUI view with a text and an image

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 ...” :

Edit the current scheme to set the launch argument

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 :

Choose Right to Left launch argument in Edit Scheme window

If you run the application now, you would see the layout has been changed to a right-to-left layout:

The sample app running in RTL mode — UIKit

Open the preview of the SwiftUI view and you will see a similar result:

The sample SwiftUI View previewing in RTL mode

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:

Force all UIKit views to use right-to-left direction in layouts

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:

Change all SwiftUI views to use right-to-left direction in layouts

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:

Preview the SwiftUI view in both RTL and LTR language direction

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:

The result of previewing the SwiftUI view in both RTL and LTR language direction

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:

Automatic label alignment update based on language direction

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):

Automatic auto-layout update based on language direction

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:

Force the image to rotate in UIKit

Now if we compare the result, we can see the image flipped horizontally:

The result of forcing the image to rotate in UIKit

For having the same result in the SwiftUI view, we can use rotationEffect modifier with 90-degree value:

Force the image to rotate in SwiftUI

The result is similar to UIKit one:

The result of forcing the image to rotate in SwiftUI

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:

Detect RTL in the UIKit views

In SwiftUI, we can define the layoutDirection environment value and read it for checking the language direction:

Detect RTL in the SwiftUI views

Now we can see the language direction-based image rotation in the SwiftUI previews:

The result of detecting RTL in the SwiftUI views

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:

An example of an incorrect pattern for the RTL compatible layout in UIKit

With the above layout setup, If we run the application in an RTL environment, the result would be the below picture:

The result of an incorrect pattern for the RTL compatible layout in UIKit

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 :

An example of the correct pattern for the RTL compatible layout in UIKit

Now if we run the application again, we would see that the date label in the correct position for RTL direction:

The result of a correct pattern for the RTL compatible layout in UIKit

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:

An example of the correct pattern for the RTL compatible layout in SwiftUI

If we preview the above view in both direction environments, we will see the correct layouts:

The result of a correct pattern for the RTL compatible layout in SwiftUI

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:

Number pad of Persian language in iOS

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:

Convert numbers from any language to English numbers for Integer types

To see how it works, we can update our SwiftUI app as below:

An example of a Persian number and its converted English equivalent

We can see the converted number in the preview:

The preview of an example of Persian number and its converted English equivalent

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

--

--

Soheil Novinfard

Accomplished software engineer with +11 years of experience in collaborating with the product and design teams, helping the travellers at @Skyscanner