Hello, and welcome to Localization Best Practices on tvOS.
My name is Joaquim Lobo Silva, and over the next few minutes, I'm going to walk you through some of the steps you'll want to take to build a great localized application experience on tvOS.
Apple TV is available in multiple languages and regions.
And new in tvOS 11, is the addition of Arabic and Hebrew and selectable system languages.
Adding international support to your app, is an incredible opportunity to reach new markets and enable more users to use and enjoy your content.
And we have a wide variety of APIs and tools to help you do just that.
Let's dive right in.
I'm going to divide this topic into three different sections.
First, I'll talk about best practices on how to handle text that is displayed to your user.
Then, I'll cover some considerations regarding layout and images.
And finally, the steps needed to export your localizable content, as well as test your app, to make sure it all works.
So, let's get started with text.
Any text that will be presented to your user, should be displayed in their preferred language.
If you have text in Storyboard elements, there's nothing else you need to do.
These are marked "localizable" by default.
If you have strings and code that you're planning on presenting, these should be wrapped with a call to "NSLocalizedString."
This will essentially mark your string as "localizable," so that it is included in the file that you will send out for translation.
In both of these cases, comments on the strings themselves, are extremely useful, and should be included as part of every localizable string in your app.
Comments can be the defining factor between great translated content and text that feels unnatural or unclear.
Here's an example of a localized string in code.
As you can see, this is simply the English word "subscribe" with a comment describing where it will appear in my UI, as well as what it does within the context of my app.
Comments are just as easy to add to Storyboard elements as well.
For every element, you can simply add a comment in the Comment for Localizer text field, in the Identity Inspector.
Do note that when it comes to displaying text in your app, localized strings are not the only way to accomplish this.
In fact, it's very likely that you have a number of use cases that are covered by our formatted classes.
These help you format and display things like numbers, currencies, dates, units such as length and mass, and much more, without having to write out localized strings for these.
Here's an example of date formatted usage.
I simply create the object, and in this case, I only care about showing time, so I set the Time Style to a length value of my preference, and finally get a formatted string out of the object.
This string is guaranteed to not only be in the user's preferred language, but it also takes care of a number of other formatting contexts, such as whether the user prefers 12 or 24-hour time.
For much more information on how to make the most out of formatters, as well as some guidance on their international prowess, I highly recommend you check out these two talks from 2016.
Let's talk about remote content.
Any text that you're fetching from a server, should also match your app's running language.
I'm referring to, for example, media content and descriptions that are shown in your app.
For this to happen, you'll need to inform your server what language the content should actually be in.
We have APIs that let you know what language you're app is currently running in, and these do a lot of the heavy lifting in terms of choosing the best language out of the ones that you support, while respecting the user's preferences.
Things like regional variance and any appropriate regional fallbacks, are also considered.
Just to give a few small examples, I have here a table where the first column shows a language that the user might have picked for their system language.
The second column shows potential languages that your application supports, and the third column would be the end result, given the circumstances.
For the first example, the user has picked Spanish as their language, with their region set to Mexico, hence the "es-MX" identifier.
The app supports both Spanish for Spain, as well as Latin American Spanish and the list of localizations, that's "es-EX" and "es-419" respectively.
And the runtime will go ahead and pick the Latin American Spanish variant for your app.
Similarly, for the second example, the user has picked Chinese with the region set to China, and Bundle will go ahead and pick "Simplified Chinese" out of the languages that your app supports.
To get the language that your app is running in, all you have to do is get the first object of preferred localizations from your app's bundle.
This will return a language identifier that you can send to your server.
Alternatively, if your server supports a different set of languages relative to your app, you can also get the best possible language match out of those, using Bundle's Preferred Localizations from Available.
So, that's an overview of how to handle text in your app.
Text can be marked as localizable through using Storyboards, as well as calling NSLocalizedString and code.
We have a number of formatters that help display and contextualize information, like dates and numbers.
For remote content, you can rely on the Bundle API to help inform your server what language your content should be displayed in.
With that, let's talk a little about layout and images.
When it comes to layout, there are typically two different aspects to adapt for.
The first one is potential differences in word length.
For example, here's the word "backup" in English, and here's that same word in Finnish.
Translations being significantly longer or shorter, can impact the way your layout behaves at runtime, and you should design for this accordingly.
The other aspect is script directionality.
English uses the Latin alphabet, which is read and parsed from left to right.
Some languages like Arabic, have their scripts read from right to left.
As a result, there are a number of design considerations regarding flow and ordering of information.
For example, in a right to left language, the first item in a list is expected to be in the far right, as opposed to the far left.
If your app uses UIKit to display user interface elements, there are a few technologies that you can use to easily adapt for these two different aspects.
It's highly recommended that you start off with exploring UIStackView.
UIStackView is a streamlined interface for laying out a series of views, either horizontally or vertically.
And these can be nested to create complex layouts as shown here.
In this example, you can see that I have some numbered views, and the general flow of information here is left to right, as expected for a language like English.
The thing about UIStackView is that under the hood, it relies on something called Auto Layout.
Auto Layout is a set of APIs that help determine layout relationships between views, such that if the size of a view changes, other views can adapt accordingly to prevent overlap or truncation.
In addition to this, Auto Layout also relies on the concept of leading and trailing constraints.
These are essentially left and right position constraints, but that evaluate to right and left when running in a right to left language.
So, for the stack views above, the layout would automatically change to right to left, when running in, for example, Arabic or Hebrew.
And this can be accomplished without having to write a single line of extra code for different layout environments.
For apps using TVMLKit, the standard templates provided do all the heavy lifting for the two aspects I mentioned.
In particular for right to left languages, once again, with the addition of Arabic and Hebrew and selectable system languages, we have some new APIs that leverage the same concept of leading and trailing for TVMLKit elements that have a specific position or alignment.
Similarly, for margins and padding, we have new media queries to help specify custom values for a specific layout direction.
To explore these new features in depth, please be sure to check out Advances in TVMLKit.
Let's move on to images.
And for this, I'm going to briefly cover an approach to keep in mind for different layout directions.
Typically, images in your app will fall into one of three separate buckets.
The first one, likely to be most of your images, is universal.
These are images that do not need specific adaptation for a layout direction.
The second category, is images that do have some direction associated to them.
This can be a number of things such as navigation arrows, disclosure indicators, or in this case, a simplified representation of text.
The only step required for these images to adapt for the opposite layout direction, is to graphically mirror them.
And now, we have the correct result.
Lastly, the third category is similar to the second, but these are relatively complex such that simply flipping them would actually produce an incorrect result.
In this example, I've a bulleted list with checkmarks, but checkmarks as a symbol should not be mirrored.
So, in this case, what I really need is two separate images, one for each layout direction.
Xcode makes it very easy to handle all of these cases, right from within your Asset Catalog.
For each asset, you can specify whether or not an image has a fixed direction or if it should adapt either through mirroring or through specifying different images.
Then, it's simply a matter of using images regularly either in code or in Interface Builder, as usual.
For much more information on how to use asset catalogs for different layout directions, please check out this talk from 2016.
So, that's layout and images.
We've seen how both UIKit and TVMLKit have very high-level approaches for adaptive layouts, as well as some of the new APIs introduced in tvOS 11 for right to left support.
And also, the concept of image directionality and how this is part of image assets.
Last but not least, let's cover how you can actually add a language to your app, from start to finish.
Adding a language to your project is done in the Project Editor.
Select your project file from within Xcode, and in the Project Settings, you can add supported languages in the Localization section.
Xcode will manage and keep track of any applicable file management, such as extracting text from Storyboards, as well as strings you've marked as localizable in code.
When you're ready to send your app's content out for translation, this is as simple as selecting your project file in Xcode, and choosing Export for Localization in the Editor menu.
Xcode will generate a translation interchange file, or XLIFF, for you to send out for translation.
Once you have this file back, reimporting this content into your Xcode project is just a matter of selecting Import Localizations from that same menu.
Xcode will update all of the relevant files and resources to make sure that when your app is built, all up to date supported translations are included.
Once this is done, it's a good idea to test your app in the different environments that you're planning on supporting.
Xcode provides a number of different features to help you do this, and you can get a good idea of how your app behaves in these circumstances, even if you don't speak the languages you support.
For Objective-C code, the Static Analyzer supports making sure that any string you provide to a UI element is appropriately marked as "localizable."
Not only that, you can also check if any of your localized strings are missing comments.
For running your app in different languages, there's a convenient set of options for simulating a specific language or region setting.
In addition to this, Xcode also lets you run your app in a simulated environment, or pseudo language, such as right to left, so that you can continue testing your app in your base language, but also see how it would look like in a right to left language.
This can be done in the Options tab of the Scheme Editor for your app.
The Localizing with Xcode 9 session, covers all of these features and much more for getting the most out of the tool set when preparing your app for localization.
And that's an overview of localizing and testing your application, from within Xcode.
We've seen how you can add supported languages to your project, integrate translations, as well as checking your project and app out in different environments.
For more information and resources on localization, please check out the link for the session.
In addition to these resources, if you're interested in a deeper exploration of localization and internationalization topics, the sessions listed are a great place to start.
Thank you for watching.