With the majority of Apple's market outside of the US, it's critical to learn about the latest advancements in Internationalization support to make your app truly localized. Gain insight into best practices for using formatters to display information correctly, how to easily handle pluralization in any language, how to avoid the most common localization pitfalls, and much more. Whether you are looking to significantly expand your market or want to take advantage of powerful new features for all languages, you don't want to miss this session.
NAT HILLARD: Good morning, everyone.
Now, good morning, or should I say, zao an,
dobry den, buenas dias.
My name is Nat Hillard.
Today I will be going over what is new in internationalization.
I will be going over new APIs that we have introduced,
as well as improvements to existing APIs that you can use
in your apps to make them ready for use all around the world.
To begin with, this is the Earth.
There are over 7 billion people on this Earth.
To these 7 billion people, Apple has sold
over 1 billion iOS devices.
Additionally, our install base
for Mac OS X is 80 million devices.
We have over 450 physical stores located all around the world
and your apps, numbering 1.4 million or more,
have gone from developers just like you,
have gone to users all around the world.
So, that's a lot of numbers, but if you only take away one number
from today's presentation, let it be this.
69%. 69% of Apple's current revenue comes
from international markets.
Now this is huge.
To see this in perspective, let's look at a graph.
Over two-thirds of Apple's revenue is coming from places
that are not the United States.
Users in these areas have different expectations
about how they'll interact with your app.
These include linguistic differences,
regional differences, and cultural differences
that you will have to keep in mind.
Now let's break this down even more.
Interestingly, here, is that a combined 41%
of your users are coming from China and Japan.
Now, I think it's a common misconception
that internationalizing your app means making it work in Europe.
Now, indeed, this is important, but additionally you have
to keep in mind that users in China
and Japan present additional challenges.
That is to say, they don't use an alphabetic script.
There are no spaces to separate words.
And, additionally, what may work
in your UI will be often a lot terser in Chinese and Japanese.
So, the good news, here,
is if you use our APIs we will help you
to internationalize your app easily and effortlessly.
So, today we will be going over four major areas
that you'll have to think about: localization, formatting,
handling text, and layout.
So, to begin with, let's discuss localization.
Now, by localization, I mean
to say making your app speak your customer's language.
I mean this both literally, in the sense
of translating the words that appear on the screen,
as well as more metaphorically,
translating linguistic concepts behind the things you wish
So, it might be helpful actually to begin this section
with taking a look at how users interact with these settings
on our operating systems.
On the left, we have OS X, on the right, iOS.
These are the language and region preference panes.
So, on the left-hand side here, on the OS X screenshot,
you will see the preferred languages list.
Now, in fact, it's important here
that this is an ordered list of languages.
Users can add multiple languages and,
if a given language is not available for the display
of your UI, it will actually fall back
to the language below it.
Here, for instance, the user has chosen Swiss German
as their primary language.
But Swiss German is, in fact, not a language
that we localize into.
Therefore, for this UI, we have fallen back to English.
Now, these fall backs are, in fact, somewhat common,
so you will have to think about this
from a developer perspective as well.
So, in addition, though,
to the language your app is displayed in,
we have additional regional preferences.
These are off to the right-hand side of OS X
and a little further down on the iOS screenshot.
Now, these actually inform the way the given units,
as well as times and calendar dates,
display in a given locale.
So, that is to say that it's not simply the language
that you are translating into,
but often the concepts behind the things you wish
Now, for a lot more information about the differences
between the preferred language and the locale settings,
do check out last year's talk, "Advanced Topics
in Internationalization," which goes
into a lot more detail about this.
So, we provide a lot of settings out of the box,
but we additionally allow users to customize these settings
if they have individual preferences.
So, new in iOS 9 and El Capitan, we have the ability
to customize your number system, as you can see here.
So let's say we have a user who is an Urdu speaker.
They have chosen as their primary language, Urdu,
and it has therefore fallen back to English
in our operating system display language.
By default this user would receive the standard Arabic
We allow, though, in iOS 9 and OS X, El Capitan, to go in
and customize these settings
to override the existing numeric system.
A lot of people don't realize, in fact,
there are multiple numeric systems in use around the world.
On the top we have the Arabic system
and below we have the so-called Perso-Arabic numeral system,
commonly in use in the Middle East.
So a user can choose this setting,
and it has interesting repercussions throughout the
Here, for instance, we have the Weather app.
Now, without any additional changes on the part
of the developer, all they have called is 'localized string
with format' or the NS number formatter APIs;
they have gotten these numeric changes for free.
On the left, we have a user using the Arabic numeral system,
and on the right, the Perso-Arabic numerals.
We noticed that every, every instance
of Arabic numerals have changed in this UI, including, in fact,
the timestamp at the top of the screen.
So, this is interesting, as a developer,
simply calling 'localized string
of format' you will get this behavior for free.
Now, in addition to the language that the user is seeing
on the screen, the user is also inputting text
into your application.
New in iOS 9 we add five new keyboards for Indic languages.
On the right, here, you see the Telugu keyboard.
Now, additionally, we've added predictive typing
for four existing languages: Korean,
Mexican Spanish, Russian, and Turkish.
Now, from a developer perspective, it's interesting
to realize that, in fact,
often these characters are not what we would typically call
Here in the Telugu keyboard we have combining mark characters,
that, in fact, will combine with other characters
to represent a single visible unit.
So, we'll get into that a little bit later.
Now, so, we have seen how users can change the settings
on your operating system.
But, how then do localizers translate the strings
that users are seeing?
The primary interface for localizers is the .strings file.
The .strings file has this format.
First you have a comment, in C-style comment syntax,
followed by the development language on the left-hand side,
and the target language on the right.
Here we have a German.strings file.
Now, .strings files are stored in lproj directories
of your bundle, within the resources directory.
English has its own .strings files, as, here, does German.
Now, additionally, we allow you, and we have allowed you
since XCode 6, to export localizations
in the commonly used XLIFF file format.
You can then re-import those as strings files into your project.
But for a lot more information about this,
I would encourage you to check out last year's talk,
"Localizing with XCode 6."
So, we have seen how users are changing these settings.
We have seen how localizers can then translate the strings
that you see on your screen, but, then,
how do you as a developer make use of these settings?
Here's where NSLocalizedString comes into play.
In Objective-C, this is a macro.
In Swift, we promoted this to a first class function.
It takes five parameters, three of which have default values.
Interestingly, in Swift, we've made it
such that the comment argument is non-optional.
This is really emphasizing this is a critical argument.
It provides context for your translators.
A given word may be ambiguous in certain contexts
and this comment parameter will allow you to customize that.
So, the key is the string you wish to translate,
and the comment is the comment explaining it.
Now, this works for simple localized strings, but,
additionally, we allow you to get a localized,
formatted string, that is to say,
a string with variable arguments to be populated.
So for that, you call 'localized string with format,
passing in a format string with certain format arguments as well
as the arguments to populate the variables within that string.
And in fact, it's actually very common to use these together.
You call 'localized string with format' on the result
of having called NSLocalizedString.
Now, to see what this looks like in action,
it might be helpful to give a brief demo.
So, let's say we wish to translate the string location:X.
Now, let's also say that we have a variable location
which has been populated by our translators
to be the user's physical location.
Here is what our strings files may look like.
On the left-hand side is the string to be translated,
and on the right is the translated variant.
We see here that in fact the translated variant still has a
Percent add is meant to be filled with a string variable.
So, this works in English -- we have location, San Francisco --
as well as in Japanese.
This is the equivalent string.
So, now that you know this,
you may have some certain assumptions
that come into your head.
One being that the arguments as presented to 'localized string
with format' will be in the same order that they are in English.
Now, we will see why this is wrong.
We call 'localized string with format' here
on the result of NSLocalizedString.
We wish to translate the string 'copy X is Y'
where X is the user name and Y is the thing we wish to copy.
Here, we're passing "hairForce1,"
which is Craig Federighi's chosen InstaMessage handle,
In our lproj, in our .strings files
within our different lprojs, a developer may assume
that the arguments will appear in the same order.
While this may work for English,
in fact it doesn't work for German.
These arguments need to be reversed
to make sense in German.
So, here is where a localizer can actually go in
and add these positional formatting arguments.
This allows what was formerly the second argument
to become the first, and vice versa.
So, here, then, a developer doesn't have to do anything.
They call 'localized string with format' and NSLocalizedString.
But, it's important to keep in mind
from a developer perspective
that what you think may be the first character may not be.
So if you have an operation that operates on the assumption
that the arguments will come in in the same order, you may want
to rethink that assumption.
So, now we know how the .strings files are stored and in
which directories they're stored.
But at this point you may be tempted
to do something like this.
You set the language variable to the first object
in your preferred language's array.
This corresponds to the UI element we saw before,
the preferredLanguages list.
Additionally, you append the suffix lproj to this,
and you call a 'path for resource.'
Let's say we wish to localize a stop sign graphic.
So, here, let's say, though,
that our individual bundle only has an es.lproj,
corresponding to Spanish.
But let's say our user's preferred language is
Using this particular technique, the user will get nothing back.
Now, why is this?
Well, it's because we are not using the standard
NSBundle will intelligently fall back
to an available localization if one is not currently available.
So es-MX will fall back to es.
Additionally, we have other smart, fall back logics,
such as en-IN, Indian English, falling back to en-GB,
the English as used in the United Kingdom.
So if you call, if you call these APIs,
you will get back the appropriate resource
with the appropriate fall backs.
'Image for resource' will give you the image.
'Path for sound resource' will give you the sound resource.
And 'URL for resource,' the most generic,
will give you back any given other file format.
So, we are seeing, here, using NSBundle APIs makes it easy
to find the resources you are interested in.
And, additionally, however, you may think
that there are certain things that can only be done in code.
Now, how many of you have written code like this?
You wish to say, you wish
to translate the string 'X days remaining.'
We know that in English, if there is only a single day,
we use 'X day remaining,' and if there are two
or more we say 'blank days remaining.'
Now, this may work in English.
It works for one day and five days.
But other languages don't have the same logic
about how things are pluralized, given a given numeric component.
Here in Russian, for instance, we only have, we have one form
for one, we also have a form for few, many,
and even more than many.
So this simply doesn't work for languages
that have different pluralization rules.
Now, to help you with this,
we provide the string stick mechanism.
This has been around for a few releases
but it's important to emphasize here.
A string stick file is essentially a plist file
that you store within your project.
It's a localized resource,
so it falls within your lproj directory
for a given localization.
As well, you have a given key.
That key, in conjunction with a numeric argument,
will then have different realizations, depending on what
that numeric argument is.
I realize this is a lot of text,
especially when you add the Russian component here.
But, that is to say, you know English has one form for one
and a different form for other, whereas Russian
as one, few, many, and other.
Now, to format string stick files I would really encourage
you to check out the "Internationalization
and Localization Guide."
This goes into a lot more detail than we can provide here
as to how to format and create these files on your own.
So, using this is in fact super easy
from a developer perspective.
Again, all you call is a 'localized string with format'
on the result of NSLocalizedString.
The string that you are passing in is the key
to the string stick dictionary.
Then you pass a numeric argument which will fill in the variable,
from the formatted string which has been returned to you.
Therefore, it will do the right thing for English, for one, two,
and five days, as well as for Russian.
We note here that the form for two
and five is different in Russian.
So, more on the topic of string stick.
We have a new mechanism in iOS 9 to allow you to make use
of string stick for formatting strings on the screen.
It's also in El Capitan, I should say.
So, to begin that, let's say, this is a common problem,
and in your InterfaceBuilder you have set up a string to appear
in the center of your screen: "Welcome to the store!"
This may work on an iPad Air, but it may not work as well
on an iPhone 6, and it may work even worse on an iPod Touch.
Now, one way to solve this is in fact using auto layout
and certain constraints.
And, often, that's the solution to this problem.
We'll get into that later.
But in fact, another way to solve this is
by using a new mechanism, 'variable width rule type.'
This is an entry you can add within your string stick
which will provide different realizations depending
on the amount of space available to you.
On iOS, this refers to the M width available on the screen,
that is to say, the visible width of a capital M
in the standard system font.
We have three different goal posts here.
We define if there are 20Ms available,
we present the string "Hi."
If they are 25, we give "Welcome."
And if there are 50, we say, "Welcome to the store!"
To use this, again as the developer, super easy.
You call NSLocalizedString on the key
within your string stick file.
Then you set it to a UI label object.
This works on iPad Air, iPhone 6, and iPod Touch,
and the realization is different.
Now, interestingly, we have used English for these examples
but in fact this has important repercussions
for international users as well.
Often a translation into another language will be much longer
than that in English.
So this allows you to flexibly choose
from among different translations for a given string
in a different language as well, so this is a super useful tool.
On OS X, things are a little bit different.
So, on OS X, likewise, you call NSLocalizedString and you pass
in the key to your string stick dictionary.
Then you call 'variant fitting presentation width.'
Now, on OS X, this integer variable is
in fact an arbitrary quantity.
This can be anything, as long as it's defined relative
to other quantities within the string stick.
So calling this with an integer value of 20 will yield "Hi," 25,
"Welcome," and 50, "Welcome to the store!"
So, in general then we have made it a lot easier for you
to translate strings as they appear on the screen
in a flexible manner that works for all
of the world's languages.
Next up, let's discuss formatting.
It's often not enough to simply translate the strings
that appear on your screen.
Additionally, you will have to think about the way dates,
numbers, times, and, new in iOS 9 and El Capitan, names.
So, to begin with, there is a right way
and a wrong way to format numbers.
Let's say we wish to present the constant pi to our users.
One naive way to do this would be
to initialize a string variable
with a format argument percent.3F, that is to say,
a 3 precision float argument.
This works in English, 3.142.
If you translate, if your user is running
in a German localization, however,
they get back this string.
This may appear correct at first glance,
but in fact a German user would read this 3,142,
because in German, the decimals digit and the, sorry,
the thousands digit and the decimals digit are, in fact,
switched, so that is to say, where we would use a period
in U.S. English, they use a comma, and vice versa.
So, to take advantage of this fact,
you can call 'localized string with format,
passing in the same format argument you used before.
Now this will have different realizations depending
on a user's locale.
And this means now the same thing
for an English user and a German user.
Now, under the hood, 'localized string
with format' is using NS number formatter.
And we have some improvements to NS number formatter we would
like to discuss as well.
New in iOS 9 and El Capitan are different number styles
for the NS number formatter.
In addition to the already existing 'currency style,
we now have 'currency ISO code style,
as well 'currency plural style' and 'currency accounting style.'
Interestingly here for 'currency accounting style,
if you pass it a negative number,
it presents it surrounded by parentheses.
This is common in accounting circles.
As well, we added an 'ordinal style,' that is to say,
how the number would appear in an ordered list.
So from 42, you get back 42nd.
So, in addition to formatting numbers, another thing
that commonly goes wrong is formatting dates.
Now here is a very naive way to format a date.
We initialize an NS String with this format argument.
That is to say, this represents today's date at 9:00
in the morning to a U.S. English speaker.
So in U.S. English we would get back this string,
which looks appropriate and correct.
But for an Italian user we get back the same string.
Now this means something very different in Italy.
This is in fact the 6th day of the 12th month, and furthermore,
the time itself could be a little more clarified.
We'll get to that in a second.
So, one way you could attempt to solve this is
by creating an NS date formatter.
Indeed, NS date formatter is the correct solution,
but this is the incorrect way to use it.
Here, we're setting a date format argument.
Now, the date format implies an explicit ordering of strings.
The exact variables that you provided here will then be
expanded in whatever locale you are using, to the exact sequence
of characters you see.
So, again, we are getting back the incorrect string in Italy.
Now, the easiest way to fix this is in fact
by setting a date style and a time style
on your NS date formatter.
We provide certain out of the box styles for NS date formatter
that allow you to specify the amount of space available
to you relative to the width of the string.
So here we call, here we set ShortStyle
for both date and time style.
What we get back in Italy, therefore, is the same string
but with the variables flipped.
So that is to say, this now reads the 12th day
of the 6th month to a user in Italy,
which is the same thing would read as an English-US user.
Now, sometimes, though, these date styles
and time styles aren't as specific
as you may need them to be.
For that, new in iOS 9 and El Capitan, we allow you
to set 'localized date format from template.'
Here you provide a template and the variables are rearranged
as appropriate for your given locale.
Now this is when the individual styles
out of the box don't provide enough information.
Here, for instance, the user wishes
to present the second string as well,
which doesn't typically come with a short style.
So using this template, we have allowed for 24-hour time
as well, as well as rearranging the month and day arguments.
So, we have looked at how you can format numbers,
how you can format dates,
but also important is how you format units.
Now, this is in fact a very naive example but one
which is very real and we have seen in the real world.
Let's say you wish to translate the quantity
"6 pounds" to another language.
One very naive way to solve this would be in fact
to literally translate the string.
You have on the left-hand side, "X pounds.'
We have translated this for an Italian user to "X chilogrammi,"
that is to say the Italian word for the word 'kilogram.'
Now, this may be obviously very wrong.
In English we have 6 pounds.
In Italian we have 6 kilograms.
These quantities are not equal.
6 pounds is not equal to 6 kilograms.
These quantities are not, in fact, equal.
6 pounds as a unit is not equal to 6 kilograms.
So this is a very wrong way to do this.
An easier way is to use NSMassFormatter.
Now, NSMassFormatter, as well as NSEnergyFormatter
and LengthFormatter, assume
that under the hood you are working in metric units.
So when you assign a float here to the variable weight,
it assumes that you are working with kilograms.
So you initialize an NSMassFormatter,
you set its unitStyle to long, and then, furthermore,
you call 'string from kilograms' on the weight in kilograms.
This will return back in English 44.092,
which is in fact a conversion of the units
into those used in the United States.
Furthermore, in Italian you will get back 20 chilogrammi
which is both the correct unit as well
as the correct translated term for the amount of weight
that you are providing.
So using NSMassFormatter makes it super easy to present
in units for your user.
Now, new in iOS 9, we allow you
to format names -- iOS 9 and El Capitan.
Now, to see why this is useful, let's take a look
at two names side by side.
The first is "Grace Murray Hopper."
This is a famous computer scientist
from the United States.
She coined the term "bug" and invented the first compiler.
Additionally, let's look at a Chinese name, "Wang Dongling."
Now, this is a famous calligrapher,
who does the calligraphy outside of the Hangzhou Apple Store.
So, both of these have three parts to them.
But the way we interpret them is important and different.
In English we would typically call this the first,
the middle, and the last name.
We will see what happens when we attempt
to apply this concept for a Chinese user.
What was formerly the last name is now, spatially speaking,
first from left to right.
The middle name itself doesn't exist at all.
And what's formerly the first name is now, spatially speaking
from left to right, the last name.
So, we can see here that terminology is important as well
as the labels we choose to apply to these concepts.
So we are introducing NS Person Name Components
and NS Person Name Components Formatter.
We have already gotten the joke
that people can't fit this into Tweets.
But it's a little long and it's a little difficult to work with,
but, that is to say, it's very precise as to what it does.
It formats person names.
So here is how you would use it.
You initialize an NS Person Name Components object.
You populate the given name, the middle name,
and the family name fields.
Here is how you would do this for an English-US user.
For a Russian user, then, you would populate
"Fyodor Mikhailovich Dostoyevsky."
Likewise, you are populating the same fields.
Here is then how you would format it.
You initialize as NS Person Name Components Formatter object.
As we've seen with other NS formatters,
it has a style component.
Here we specify short style.
Then you call 'string from person name components'
on your Person Name Components object.
The result of this call is the following,
for our five available styles: default, short, medium, long,
and abbreviated, we have done the right thing
for each language.
A couple of things to note here,
that in fact the short style differs depending on, one,
the user's locale, and depending as well
on the individual user's override settings
within the mail, contacts, and calendar settings.
As well, for Russian names, we have determined
that abbreviated names in this form with first, middle,
and last all shortened
to the first character doesn't really exist and so, therefore,
we have fallen back to the short style.
So it's really easy out of the box
to format names for your users.
So that's numbers, dates, times, units, and names.
We have looked at how you can translate now,
translate the strings in your UI,
how you can format the units the users are seeing.
Additionally important is how you handle text received
from the user.
Now, this involves looking at what a character is,
how it changes based on casing, how you search
for that character, and, as well, how you transform
that into another script, for instance.
To begin with, with this section,
let's ask a philosophical question.
What is a character?
To begin with, let's ask,
how many characters is this emoticon?
This was introduced recently on iOS and it's possible
to type this on our keyboards.
The answer here is not immediately straightforward,
although visually it constitutes a single unit.
Under the hood it's represented by one, two, three, four, five,
six, seven, eight individual characters.
Now, actually these are Unicode code points and depending
on the encoding you are using it may in fact be more than 8.
It may be 11, for instance, but,
that is to say you shouldn't have to think about this.
Now, one place where this becomes really obvious is
in enumerating over a string.
Let's say you have a string test followed
by the emoji character we just discussed.
Now you wish to enumerate over each character within the string
and call 'character at index.'
This will return the unichars constituting the
But this isn't what you want.
In fact, this presents question mark characters
and sometimes three unprintable characters, and there is a heart
in the middle for some reason, so it's not,
this is definitely the incorrect way to do this.
The correct way to enumerate over a string is
to call 'enumerate substrings in range.'
Additionally, you pass the 'by composed character sequences.'
This makes it such that the
under the hood representation matches the user's visual
representation of the character.
Therefore, when we call it on this string,
we get back exactly six characters.
So this is how you would enumerate over a string.
But sometimes you wish to transform that string
into a different form.
New in iOS 9 we are providing the ability,
iOS 9 and El Capitan, we are providing the ability
to transform that string.
So let's say your string is "istanbul."
A naÃ¯ve way to capitalize the string would be
to simply call the 'capitalize string' property.
For English-US users this may look correct.
Indeed, this is, for English users,
the correct way to capitalize this.
But for a speaker of Turkish, the dotted lower case i
in fact becomes a dotted upper case I.
To immediately gain the benefit of this,
you can simply call 'localized capitalized string'
on that string.
And, therefore, you will get the appropriate capitalized
representation of the string, that is to say,
the string with the first character upper cased.
Now, in addition to 'localized capitalized string,
we are also providing 'localized uppercase string'
and 'localized lowercase string.'
Here is what these look like.
So you can out of the box make use of these characters
by simply using the localized variants
of the already existing APIs.
So, that's how you transform the case of your string,
but let's say you wish to search for a string within another.
Here is also where we get back
to our question, what is a character?
And what are our users expecting when they expect
to search for a given string?
So, let's say we have the variable here representing the
German word "uber."
Now this has a capital U,
and happens to use an umlaut over the U.
A user might expect, given the way we typically write this word
in English, that lower case "uber" will find the string.
As a developer you may call 'range of string' to find it,
when in fact this will return nil.
The correct way to search for this, and new in iOS 9
and El Capitan, is 'localized standard range of string.'
This will allow you to search for this string
within the other using diacritic insensitivity as well
as capitalization insensitivity.
Additionally, it provides allowances
for a given user's locale.
So, here, we've found the lowercase string "uber"
within 'capital U-umlaut-ber' by simply calling these new APIs.
So, in addition to searching through the string,
sometimes you may wish to transform the entire string.
Now, this is where transforms come in.
Transforms allow you to translate between an uppercase
and a lowercase variant of an entire string.
Additionally they allow you to do Unicode normalization.
That is to say, they take out the diacritic characters
and separate them out, such that A
with an umlaut becomes A plus umlaut character.
Additionally, we allow you
to script-to-script conversion, or transliteration.
That is to say, going from Chinese Han characters
to their Latin representation.
Now, formerly this was available to you only
at the Core Foundation level.
New in iOS 9 and El Capitan, we allow you to access this
at the Foundation level.
You simply call a 'string by applying transform.'
Then you provide a string or here a constant,
representing how you wish to transform the string.
Here, we wish to translate the emoji character or, sorry,
transliterate the emoji character "thumbs up"
into an XML representation.
To do this, it's as simple as calling 'string
by applying transform'
and provide 'NS String Transform to XML Hex.'
We additionally provide such transforms as Han characters
to Latin, and between different European scripts as well.
So it's super easy, then, to translate,
transliterate your string from one script to another,
and provide transforms from your individual characters
to different representations.
So, that's how you handle text within our operating system
as received from the user.
Additionally important is the way you lay
out visual elements on the screen.
Now, here is where auto layout comes in.
Auto layout was released several releases ago
and the original intention was
to format given UI differently based on the amount
of screen real estate available to you.
This has become increasingly important
as we've released different form factors
for our devices both on iOS and OS X.
But I should say an additional benefit of auto layout is
in localizing the UI of your application.
Here is what a UI would look like.
So, let's say, for instance,
we wish to add a new calendar to iCloud.
Here is what a sample UI may look like in English.
This UI may have been worked on meticulously and may work
when you test it in different orientations
and may work even dynamically with content added at runtime.
But if you haven't taken allowances for how this works
in other UIs or in other languages,
in fact it may break these assumptions
that you've had up until now.
So here is the same UI in Greek, and this may work, this may seem
to work on first glance.
When you take a little closer look, we realize, in fact,
this character is now 3.5 characters long.
There are additional sections of the UI
that have this problem as well.
Now, I should say that it's not necessary to localize your app
to test it in a different localization.
Thanks to XCode's Skin menu you can test your app using a
as well as a right-to-left pseudo-language,
that doesn't require you to have a translation on hand
to see how your UI would operate in different contexts.
So, assuming then you are using auto layout
and you have set your hugging priorities
and your compression resistance priorities correctly,
here is what your UI would look like.
We have seen what was formerly 3.5 characters is now 12.
This is a huge difference.
We have allowed our label to expand the available space given
to us by specifying not static constraints
but rather those that can grow.
We say that the constraint is less than or equal to the width
to the edge of the screen.
So, for a lot more information about this,
I would really encourage you to check out yesterday's talk,
"Mysteries of Auto Layout, Part 1 and 2."
Those go into a lot more detail
about how you can use auto layout to make your app work
around the world, as well as for different device orientations.
So, also a thing to keep in mind in laying out your UI is
that table cells themselves may change size.
This relates to dynamic type.
On the left, we have an English-US UI,
on the right, we have Hindi.
Now, notice that, actually,
individual cells are different heights here.
This is because the cells are auto resizing.
We have allowed the cells to take up the amount
of space dictated by the line height of that language.
So if you use standard UI controls and UI views,
you will see, you will get this behavior for free.
But important to keep in mind from a developer perspective is
that you shouldn't assume
that a given table cell will be a certain height.
It may expand in different locales to take
up a different amount of space.
So additionally important and critical in iOS 9 is
that we have now provided full support
for right-to-left languages.
On the left, we have an English UI, and on the right, an Arabic.
Now, the changes here are deep.
We have gone through the standard controls and views,
and switched the overall control flow.
In English, you would go from one menu into a detail menu
by going left to right.
Now, in right-to-left languages you go to right to left.
Note that the chevrons themselves have shifted.
The accessory views are on the other side and much
of the text itself has been flipped.
Important to keep in mind, though, is not everything
in the UI may shift, and may not automatically shift for you.
Sometimes you may wish to customize the behavior.
As we see here in the 'do not disturb' icon which is, in fact,
still left to right, as well as the Latin text
which is still left to right as well.
Now, for a lot more information about this,
I would really encourage you to check out "New UIKit Support
for International Interfaces" which happened yesterday.
This goes through how you can use standard controls
to make use of and gain the benefit
of the full right-to-left support in iOS 9,
additionally how you may wish to customize this
for your individual app needs.
So, overall, it's important to remember to keep in mind
in internationalizing your app, first the localization aspect,
how it is that your strings are translated,
how it is that the concepts behind the translations are
themselves translated to your users.
Additionally, formatting, how it is that units, dates, numbers,
times, and now names are formatted to your user.
Handling text, how is it that you take the text from the user
and perform operations on it.
This brings back the eternal question, what is a character?
Something you should always keep in mind in processing text.
Finally we have layout, how it is that your UI elements appear
on the screen to international users.
Now, luckily if you're using the localized variants
of existing APIs, as well as standard views and controls,
you should get all of this behavior for free.
Now, if you keep all of this in in mind,
you will find internationalization opens the
world to your application.
For more information, do check out these slides here,
or do check out the documentation here.
Contact our developer forums or our App Frameworks Evangelist,
Paul Marcos, and also check out these related sessions.
These have in fact already happened, so check them
out in your app or online.
Also, however, we will be offering an internationalization
lab today from 11:00 to 1:10 p.m. So do come check us out.
I will be there as well as my team
to answer questions you have about internationalizing
and localizing your apps.
So, thank you.
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.