In Interface Builder, use Auto Layout so views adjust to the localized text.
In our previous post (here) we began the internationalization process by localizing the text in our UI files. This, however, is only have the work that needs to be done. You see, not everybody reads left to right, top to bottom. Some read right to left, some read bottom to top, etc. Additionally, a UI naively configured will be ill suited to handle the different sizes of text that translation necessarily requires. In this post we will learn how to handle these differences gracefully.
Our best tool for configuring a dynamic, internationalized UI is auto layout. Correctly using auto layout makes internationalization almost trivial. Here are the key points to remember:
- Don’t use fixed width constraints! Any label that is going to be localized should be able to resize itself to adjust for the difference in text from each localization.
- Utilize intrinsic content sizes. The intrinsic content size of a view is the minimum space needed to display all of the views content without clipping or shrinking its data. For textFields and labels, this means to resize itself automatically to accommodate the text stored therein.
- Use the leading and trailing attributes. If you use the leading and trailing attributes when applying constraints, you allow the UI to be able to change itself from left-to-right to right-to-left. This will provide a more natural UI experiences for localizations where reading is done right-to-left (such as Hebrew or Arabic).
- Pin views to adjacent views. Rather than pining views inside its parent view, pin views to their neighbors. This then allows a domino effect when a view is resized and prevents view overlap.
- Test! Test! Test! Constantly test your UI with different language settings.
Now that we know what we should be doing, lets look at an example of how to do it.
Lets say I had ben tasked with designing a simple user profile view. And lets say that it needs to look like this:
So, how do we handle this situation? It might be tempting to pin everything to the left hand side of the view, wipe our hand and call it good. However, this is certainly not the way to go!
Our first step should probably be to deal with the image view. So, you talk to the designer and they tell you that they want it to be 10 points from the left, and 20 points from top. You ask about the width and height, they tell you they want it to be 100 x 100. Applying these constraints might look something like this:
Note that the top constraint is actually 0, not 20. This is because we are cleverly using the safe zone and not the view edge to work from. “But!” you gasp, “You have violated rule 1 already!” “No, no..” I state, shanking my head from side to side while chuckling. “You see, the image docent need to be able to adjust for different sizes during localization! Thus, it is OK to apply fixed with to this view. Rule 1 applies to views which may change their size during the localization process.”
OK, So we’ve got the view pinned, now lets try dealing with the labels. First, lets apply constraints to the name label. Keeping in mind rule 4, we pin the label to the image view, and align their tops. This way, any movement, vertical or horizontal of the image view will adjust my name label (and any views pinned to it). The only other constraint to the view we need to apply is to prevent it from moving off screen, this is done with a trailing space, >= constraint. This also helps us to conform to rules 1, 2, and 3 by not setting a fixed and pinning its trailing attribute to the next closest view (the >= constraint allows for expansion and movement, and thus allows the view to fit its intrinsic content size). Here are the constraints:
Sweet! Now lets apply the constraints to the handle label. Again, we are going to try to pin to the nearest views. So we pin the top space to the name label and we are going to align their leading attributes. We are using align here instead of pinning to the image view since the name is already pinned to the image view and what we really care about is that their text is left aligned. While pinning to the image view would get the job done, if we ever needed to change the gap, we would need to change each gap individually. This way, we would only need to change one constraint! Finally, we need to set the trailing space constraint as we did above. Here are the constraints:
The views for the occupation label are almost the same as the handle label constraints, only the occupation label is pinned to the handle label, not the name label.
We have now followed the first 4 rules. Lets look at rule 5. How can we test if we haven’t yet localized our text? Xcode has got some nifty tools that allow you to start testing for internationalization conformance of your interface builder files that you can use without even compiling your code! First, open your interface builder and make sure that your assistant editor is open (⌥⌘↩︎) Next select the preview option from the dropdown menu on what file to show:
This preview view is a fantastic too! it allows you to view your view in different devices, orientations, etc. All without compiling and running your code! So neat. Not only that but it also has an option for adjusting the text to view it under different situations. In the bottom right corner of the assistant editor is a button that states the language the text is being displayed in. For me it is English. Click this and a drop down menu appears with different choices:
Each pseudolanguage allows you to test your UI against various challenges language can present to text layout, including accents and longer than expected strings. For instance, choosing double-length, capitalizes all text and doubles the string in the preview:
Excellent! While this doesn’t look like there is a problem, lets try inputing some information and trying again. Below is the preview next to the double length rendering:
The left image is form interface builder, the right is from the assistant editor. While the first two labels look good on the left, all three look like they need adjusting on the right.
Now this is where feedback from the design team is needed. Perhaps they do, in fact want truncation. However, they probably would rather that some word wrapping happened. So we simply go back to our interface builder, and set the number of lines in the label to 0 (zero) Which allows the labels to have as many lines as they need. Looking back at our assistant may, or may not render the correct scene. In my case the handle label wrapped in the assistant editor, but The others still truncated. If you tweet the height of the labels, it causes a UI update and wrapping happens. Build and running also will show the correct rendering…
Now lets check our left to right. To do this we are going to need to use the simulator (or your device) as the preview assistant is still a bit buggy (see above). Run the app on the simulator and hit ⌘⇧H to exit your app. Navigate to the settings app and got to General ->Language & Region -> iPhone Language. Next hit ⌘⇧H to exit settings and navigate back to your app.
At this point the UI should look exactly the same. This is because we haven’t add a translation for Hebrew and so the app uses the base translation (English). Lets fix that by adding a translation real quick. Remember from our last tutorial, we go to our Project file -> Info, then click the plus under Localizations:
This time choose Hebrew form the drop down menu and click OK on the following popups. Now run your app again and you should see something like this:
Notice how the whole UI is backwards, eg right-to-left! Nothing is stuck on the left that should now be on the right (because we used trailing attributes).
Now to change back to English open settings and tap the gear icon, option 4 from the top, and the first option. Alternatively you can go to Hardware->Erase all content and settings.
So far things are looking pretty good with our app. All we have to do now is to keep on testing; making sure to test each translation as it becomes available.
TL;DR
Prepare your app for internationalization by:
- Not using fixed width constraints!
- Utilizing intrinsic content sizes.
- Using the leading and trailing attributes.
- Pinning views to adjacent views.
- Test! Test! Test!
Sources
https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPInternational/InternationalizingYourUserInterface/InternationalizingYourUserInterface.html#//apple_ref/doc/uid/10000171i-CH3-SW3
http://wordgirl.wikia.com/wiki/Huggy_Face