Internationalization Best Practices

Following some simple practices when writing your app can help make it world-ready. Learn about what's new, how to take greater advantage of existing frameworks, and review some common pitfalls and how to avoid them. Hear some ideas for going one step further and optimizing your app for different countries.

Looks like it's your first session this morning.
If you didn't understand what I said at the beginning
of the talk, you're at the right talk.

So let's talk a little bit about internationalization.
So as you might know,
Apple ships its products all over the world.

And two-thirds of Apple's users are outside the U.S.
Which is why it's really important to make sure
that the linguistic experience is right in your apps.

So we have users all over the place from San Francisco
to Milan and Dubai and from New Delhi to Hong Kong.
And of course these users are most likely
to be using your apps and Apple's apps
in their native languages.
They're also likely to be using these apps
in languages you didn't expect
that aren't related to that region.
For example, English, you might be surprised is a fairly
global language.
So today I'd like to talk to you about what's new,
what we've been up to for the last year in the space
of internationalization.
Some fundamentals about getting started with localization
and internationalizing your app.

Then some quick fixes that you can make in your code
to make it a great app for a worldwide audience.
And lastly, some things to keep in mind from a design
and mentality standpoint when you go about making your app.
So let's get started with what's new.
I'm really excited to talk about the multilingual keyboards
that we've added in iOS 10.
Now if you look around you, just to your left or right,
you're probably sitting next to or are a person
who speaks more than one language.
The U.S. is an extremely multilingual place
and California especially so.

And with iOS 10 we embraced this
by offering you multilingual keyboards.
So you can choose from a mix of any of the two languages.

Or any two of the languages here on screen, and you can type them
on the same layout without having to switch the globe key
and you'll get autocorrections and predictions
for both those languages.
Another enhancement we've made is the addition
of Latin American Spanish.

And this comes to iOS, watchOS, and tvOS.
And this is the first time
that your app might encounter a language variant
that is not for specific country.
And I'll talk about how that's important
at the code level in a bit.

Another great enhancement is the new measurement formatter
that is added in foundation.
And this will take care of unit conversions in a language
and region aware manner for you all under the hood,
and it already supports more than 20 different units
like temperature, energy, pressure, you name it.

Now, I won't be going into depth about this here,
but there's a whole session dedicated to this on Friday.
So please check that out.

We've also localized the keyboard number pads this year.
And so when you request the number pad keyboard type,
you're automatically going to get a keyboard
that supports different numbering systems,
such as those used in Arabic and Hindi.
And when you're in this state, you're going to see a 123 key
in the bottom left of the keyboard to let you switch
between these different numbering systems.
Now in some cases, you might want
to specify ASCII capable number pad instead when you're sure
that the input that you have needs
to be restricted to ASCII digits.

Some examples of this are credit card numbers and IP addresses.
They're edge cases, but things that you should be aware of.
One of the huge new features
in macOS Sierra is native right-to-left support
for languages like Arabic and Hebrew.
And macOS has been redesigned
with right-to-left languages in mind.
And of course, macOS joins our existing family of products
like iOS and watchOS
which already support right-to-left
languages natively.
Again, this is a huge topic, and I won't go into this in detail.

And again, there's a dedicated talk,
What's New in International User Interfaces on Friday at 9 a.m.
that you should definitely check out.

So let's get started with some of the fundamentals
that you need to know about internationalization.
Let's take a look at an app that comes with iOS, the Clock app.

It's been re-themed,
but probably still looks familiar to you.
So what are the various aspects that you would need
to internationalize here for this app to work
in different languages and countries?
First of all, you need to localize the strings.

So this is basically any button or tab or view that has a string
in it, you need to make sure that it's translated
into all the different languages you're going to be supporting.

Then there's another category of string that needs
to be localized but it is formatted content
and so you should use formatters to achieve that.

And this will save you a lot of work.
And lastly, you need to internationalize the layout
so that it will work well for right-to-left languages.

And for languages that have longer or shorter translations
than the language you're starting with.
So if we do all this right, then we take this English app
and we translate it into a Chinese app,
and it looks fantastic.
Notice how in Chinese the a.m.

/p.m. marker goes before the numbers instead of after
like it does in English.
It'll also work well
for right-to-left languages like Arabic.
Notice how the layout
of the entire app is flowing from right-to-left.

And in this case, see how Arabic is using the Arabic-Indic
numbers which are different from those used in English.
Again, if you use formatters, you get this for free.

So those are some fundamentals for the development side.
Let's take a look at the fundamentals
from the user side as well.

What does a user do when they get a brand new Apple device
like an iPhone?
Well, every Apple device that you open
up will first ask you to choose a language.
And what's going on under the covers is
that every language has a code associated with it,
and of course, every region has a code associated with it also.
So let's say a user chooses Spanish, United States.
What that becomes at the end
of the day is a language code like es-US.
What you may not know is
that language codes are part of hierarchies.

So for example, Spanish, United States actually inherits
from Latin American Spanish
which then inherits from base Spanish.

This is really important because not every app is going
to be localized into Spanish, United States.
So we want to know, okay, what is the next best language
that the user would prefer
if we don't have their most preferred language available
on the system.

Also, this hierarchy is not just for Spanish but even languages
like English have a hierarchy.
For example, Indian English has spelling systems
that are more close to British English
than to American English, and so it is part of the hierarchy
in which it inherits from British English.

And English and Spanish are far from the only two languages
that have such a hierarchy.
We also have other languages like Chinese, French,
and Portuguese that have similar hierarchies.
So I hope you all are taking notes on this, you know,
on these aspects because no, of course not.

The reason I'm mentioning this at all is because we're going
to help you solve this problem, and you don't need
to know anything about this.

So I'm going to show you how to do
that in the next section with quick fixes.
So what's the first thing we need to do?
We need to localize the strings.
Now there is a little bit of setup.
It's simple.

But there's some setup involved, and I won't be talking
about that in detail because there's a whole --
there's a lot of documentation, and there's another talk
that goes into detail about how to set up your app.
So let's assume that you've got your setup for localization,
so you've got some localized strings in your app.

If you're using storyboards
with Base Internationalization, you're done.
There's nothing you need to do.

You launch your app.
The strings get loaded.
You're golden.

If you are creating or loading strings in code, then you need
to call NSLocalizedString.
NSLocalizedString will use the fantastic logic that I mentioned
with all the fallback,
and it will load the most appropriate string for you.
Now, note that it's important to provide a comment
to your translator because oftentimes words are
distinguished by which context they're in
and the comment helps clarify that.

Let's move on to slightly more complex scenario.
Let's say you're getting strings from a remote service
like a server or another process.

Well, in that case you probably want to let the server
or the other process know,
hey this is the language my app is launched in,
please give me strings that match this.
And in order to do that, you can call preferredLocalizations
on the Bundle that you're launched from
and get the first language and give
that to your remote service.
If you have an even more involved setup
and for some reason you have a list of available languages,
say, on the server that don't match exactly the list
of languages you have on the client.

Let's say you have a larger set on the server,
then you can call the class method preferredLocalizations
and give it the available set that you have.

And again, it will match you to the right language.
So I mentioned this Bundle's language matching logic multiple
times during the last few slides.

So what is all this about?
And what is Bundle doing for you under the hood?
So what Bundle does for you is that it figures out things like,
okay user prefers English U.S. We don't have an English
U.S. localization.
We do have an English.

So okay, in this case it will give you English.
It figures out things like you want Indian English,
but we have British but not Indian, we'll give you that.

And again, with the Spanish Latin America example,
if you say I prefer Mexican Spanish, it will figure
out that oh the best match for you
in the list shown here is Latin American Spanish.
And similarly, for Chinese and many other languages.
This is a lot of complicated locale aware logic
that you do not want to be implementing in your apps.
And definitely if you have code that does something
like take the language identifier and split it
on hyphens or something like that, please go and delete
that code because you should not be doing that.
So now you've localized all your strings and used the right APIs.

You want to double check
that everything you have done is actually localized.
To do that, you can use the new static analyzer in Xcode 8,
which will actually find any issues that you have
with localizability,
where you're feeding non-localized strings
into the UI.
And that's all there is to localized strings, really.
Next let's talk about formatters.

This is a common kind of app that you see these days
with all the delivery services.
And this, however, is not a good thing that you're seeing here.

So it says AM9:41, which to an English user will definitely
look like nonsense.
But believe me, I've seen this in a real app.

And similarly, you might see something that is the opposite
in Chinese where it puts the a.m.
/p.m. marker after the numbers,
which is completely wrong for Chinese.
So how do we avoid bugs like these?
The problem is actually that we're using this method
which is formatter.dateFormat setting a fixed format on it.
It seems like the right thing to do.
It looks pretty nice in code,
but it's actually the wrong approach.
And although it yields the right result when you try it
out for English, so it'll give you 9:41 a.m. you try the same
thing out in Chinese, and it gives you the wrong result.
Why? Because it's applying a fixed format to no matter
which language you're running in.

The correct approach for this is
to just use the predefined short style on the date formatter.
And it's going to give you the right result for English,
for Chinese, and for any other language your app might be
localized in.
And of course, there are more styles.

So we have the short style that I just showed you.
You can also get a slightly longer style,
which has the seconds.

You can have a style which has the time zone
or the full time zone name.
There are variety of different styles for different needs.

And of course, not just for times.
For dates, also, we have the whole range
of styles going from short to long.

Now you might come back to me and say, "okay, sure but none
of those styles is what my designer wants.
They want, you know, just the full year
or just this or just that."
That's fine.
So you can use a format.

The important thing is to use it
with the setLocalizedDate FormatFrom Template method,
which will make sure that it takes your format, interprets it
for the current language in question
and gives you the correct localized format
for that language.

There are also two classes that you might not have used.
They're fairly new, although not new this year, date components,
which will let you format, say,
a duration like 4 hours and 25 minutes.
Or a date interval like the duration of this talk,
9 to 9:40 a.m. So the advantage to these, again,
is that if you use these classes,
all the localization is going to get taken care of for you.
Next let's talk about another kind of data type
that you can format, names.
Now, if this is how you're going to show the user's name
or their friend's name to them when they open your app,
they're going to get a really bad impression of your app.
So let's not do that.
Instead, you should show the names in the way that is correct
for that given language and script.
So how do we do that?
It's actually really simple.

You create a PersonNameComponents object.
Fill it with some name components, and then just
like any other formatter, you just ask for the string
from the components for any given style that you want.
And again, we have a variety of styles going from long,
which is the full name all the way to abbreviated
which you can use for initials.
And of course, it supports multiple languages.
New this year, though, is name parsing support.

So now you can go from a full name to a set of components.
And it's as easy as creating a formatter, giving it a string,
and then looking at the components.

If it returns nil, it means it wasn't able
to successfully construct components out of it.
The really cool thing, though,
is that this is not a static API that's looking
at some set of static rules.
It's actually a statistical model so that even if you pass
in the name in the opposite order,
it knows that in John Appleseed, John is much more likely
to be the given name and Appleseed the family name.

And it's still going to parse it correctly.
And of course, it supports multiple languages as well.
So there are a lot of formatters.

I talked about Date
and PersonNameComponentsFormatters
in detail.

The components and interval formatters for dates, briefly.
And there are some formatters I didn't even mention
which are existing formatters that we have in the system.

And there's the brand new measurement formatter that's new
in this set of releases.
So be sure to use these formatters wherever you can
in your code because they will do the right thing,
and you will also save localized strings.
Which you shouldn't be using for these cases.

So that's all about at this point your whole UI is localized
in terms of strings.
Now let's take a look at what you need to do in terms
of the layout to make sure
that the UI actually works well with those strings.
So the key word here is Auto Layout.

It does what it's intended -- what its name tells you it does,
which is it automatically lays things out.
And so whether you're in a left-to-right app,
if you use Auto Layout you will get automatically a user
interface for a right-to-left language.
And again, Auto Layout is a big topic, and I'm not going to go
into detail into how you should use Auto Layout
because there are sessions for that both this year
and from previous years that go into a fair amount of detail.

What I will tell you is that you should use UIStackView
and NSStackView as much as you can because these are very easy
to use APIs that leverage Auto Layout and make sure
that your views will flip in the right way
for right-to-left languages and adjust appropriately
when they get long and shorter strings.

So we will have sample code for you that shows you how
to implement a version of the Clock app using Stack Views.
Now one thing that you might want to keep in mind
for layout is that sometimes you need to get creative.
Now you see this screen in English.
Are you sure you don't want to use an Apple ID?
And you have two options there, Use Apple ID or Don't Use.
Now in some languages you can imagine the translations might
be longer than can fit in two side-by-side buttons.

So what do you do?
Well, in this case, you see that the whole view switches
to a top-bottom orientation instead
of a left-right orientation.
And these kind of creative UI elements are things
that you should keep in mind for your apps before you ask a --
you ask a translator to shorten a string to the point
where it might not even be intelligible in that language.
The next thing is vertical flexibility.

And a lot of you may not have realized this before
for your apps.
So we have a lot of scripts in the OS for languages
like Vietnamese, Thai, Arabic, and Hindi that go much higher
or lower or both than the basic Latin alphabet that's used
to write English.

And so what happens often is we see this bug,
which is that somebody might set clipsToBounds
to true on the label.

And what that does is it clips the text often on both side
and besides being very ugly and, you know, just looking terrible
in that language, you often lose important semantic information
like a diacritic mark.
In this case the pronunciation of all of the words
on the right is changing when you clip them like this.

So to fix this it's pretty simple.
Don't set clipsToBounds to true if you have a label.
And that should be enough to solve this problem.

More interestingly, though, when you have multi-line labels,
you also need to consider interline spacing.
So let's take a look here which has Hindi on the left
and English on the right.
And here it's English on the left and Hindi
on the right, sorry about that.

But see what happens when we try to squeeze Hindi
into the same amount of vertical space as English?
It looks really cramped.

And any Hindi reader will tell you this is really hard to read,
and it doesn't look nice.
So what you really need to do is
to give each script the room it needs to breathe
and to look good on screen and to be easy to read.
The good news is that this is really easy to do.

Any time you have a multi-line label, again,
a lot of this is done by default but you just need to be sure
when you set a custom font that you do the right thing
that you get a preferred font using the UI font API.
Now, you might say, okay I have a custom font
and I can't use this.

Well, there is a solution for you, and you should check
out the fonts and typography talk on Wednesday that goes
into more detail about how you can make sure
that a custom font will also adhere to dynamic type.
Next, for table views, we do something really neat,
which is that if you have a language with a taller script,
we will actually make the table row height larger than it is
in other languages like English.
Again, this gives the script the room it needs to breathe,
and it just overall looks more natural for those languages.
The way you can take advantage of this code is
by using the standard UITableViewCell styles.

And now you might say, okay, sure but I have a custom cell,
you know, it's not going to work with this.
I mean, I don't just have a label and you know,
it's not as simple as you think it is.
And I'll be like, okay sure.
I agree. But what I found at least
in using UITableViewCell is that it is highly customizable.
It has a bunch of overrides that you can use,
usually to get exactly the appearance you want.

So try that first before you're implementing a completely
custom UITableViewCell.
So that's mostly what I have in terms of small code fixes
that will make your app great for an international audience.
Let's talk about some things that are more abstract
that are more design based.

And also the mentality you need to keep in mind
for making great apps.
First of all, it's the iconography.

Now you know that when you go to the App Store and you're looking
for an app one of the first things you're going
to notice is that icon.

And oftentimes, at least I've done this,
if the icon doesn't look good I don't buy the app
because that's going to go on my Home Screen.

And I don't want to have an app there that doesn't look good.
So icons are really important, and it's also important
that the icon that you choose works well
for different languages and also languages that go
in different layout directions
like left-to-right or right-to-left.

So photos has a great icon here.
This is a great example of an icon that doesn't have any words
or numbers that would tie it to a specific language.

It also doesn't have a directionality
like left-to-right or right-to-left.
So it really works well, you know, in Japanese,
in English, and in Arabic.
Now if you are making a right-to-left localization,
and you want to make sure your UI is really good
for right-to-left languages.
You should take a look at some of the artwork you're using.
And if you are using artwork that has a directionality to it
that would need to change for a right-to-left language,
then you would probably need to flip or create dedicated artwork
for right-to-left languages.

Now here you see an example of artwork
that you can't just flip horizontally.
You need to create dedicated artwork if you're
in a right-to-left language.
But if you do have images that just need to be flipped,
there is actually API for that and you don't need
to create separate artwork.
There's more information about that, again, in the What's New
in International Interfaces session on Friday.

But the key is asset catalogues.
Another thing that you might or might not have thought
about is your app's name.

Now, when looking at various App Stores around the world,
one consistent theme we've seen that doesn't surprise us
in the least is that users are more likely to buy apps
that work for them in their language.
And that applies to the apps' name as well.
Because if they can -- if they can understand easily what your
app does by looking at the one line name and description,
then they're much more likely
to tap inside the app to take a look.

And of course, the world is --
users all over the world are more and more multilingual
or at least they're bilingual.

So your app should not make assumptions
about the UI language and how it relates to the content
that the user will type.

For example, a very common theme you will see all over countries
in Asia like India and Southeast Asia is
that people will run their phones in English,
but they'll have content in their local languages
like Hindi in this case.
So when you have an app and you run in English, don't assume
that the user's going to type English text,
especially make sure to test your app with Chinese
and Japanese keyboards to make sure
that the experience works well.
And here's an example that I wanted to show you of an app
that in our opinion does a really great job
at the things I just talked about.
So this is Evernote.
And first of all, you'll see the app icon.

It doesn't have any words or symbols or anything
that would associate it with a single language.
So that's great.

However, they have also gone
and localized their app name into Chinese.
And this is actually if you're a Chinese speaker,
you'll see that they have a great visual pun in there
because the Chinese word
that they've chosen also contains the character
for elephant, which is their icons, which is kind of cool.
You'll also notice that they have localized screenshots.
And there's a lot of attention to detail in those screenshots.

You'll see, for example, that in the localized screenshot
in which they're creating a note,
you actually have the Chinese keyboard on screen.

So the user is seeing
in the screenshots exactly the experience that they're going
to get when they download this app.

This is exactly what users expect to see.
So take advantage of the fact
that you can upload localized names, descriptions,
and screenshots to the App Store.
And lastly, I wanted to talk about surprise and delight.
What you can do to go above and beyond to make a great product
for people in the -- using a specific language
or in a specific country.
I'll give a couple of examples.

One is if you have any kind of predefined content
such as templates and pages.
You could create different customized content
for different languages.
And so for example, in Pages you have custom templates
for cards for some languages.

And just one more example I'll give is
for more advanced feature, let's say you're supporting --
you're a calendar app, and you want to have a really great app
for the Middle East and also for a lot of Asian countries
like China where they use a lunar calendar.
Well, you could support the lunar calendar
in your calendar app just like iOS does and iOS and OS X do
because this is going to deliver a much richer experience
for those users.

Now what your app does is really --
depends on what your app does.
And so you need to take a look at your own app and see
if there's an area where you can deliver a surprise to the user.
That's really all I wanted to talk about today.
So in summary, localize your app.

Use standard system APIs like Formatter and Bundle.
Make sure that the apps' layout is flexible and works well
for languages with shorter translations,
longer translations, which have normal -- not normal-sized,
English-sized scripts or taller scripts.
When designing the iconography for your app,
make sure that it is a world-ready design
and doesn't tailor to a specific language too much.
And finally, at the end localize your app's name,
if appropriate, and screenshots.
Now for more information, you can follow this link
to get some other useful links
about internationalization and localization.
There are also some really cool other talks
that I mentioned during my presentation.

So for example, there's What's New
in International User Interfaces.
And there's also a What's New in Auto Layout.

One talk that I wanted to call
out specifically is Inclusive App Design.
It kind of will talk more about some of the things I mentioned
at the end about how you can keep an inclusive design in mind
for both internationalization and for users
that need accessibility support.

And that's all.
Thank you very much.

Looking for something specific? Enter a topic above and jump straight to the good stuff.