Internationalization and Localization Guide Contents

About Internationalization and Localization 7 At a Glance 8 Learn About Language and Region Settings 8 Internationalize Your App 8 Localize Your App 9 Test Your App 9 See Also 10

Reviewing Language and Region Settings 11 Reviewing Language and Region Settings on iOS Devices 12 Setting the Language on iOS Devices 12 Setting the Region on iOS Devices 14 Setting the Calendar on iOS Devices 15 Reviewing Language and Region Preferences on Your Mac 17 Setting the Language on Your Mac 17 Setting the Region on Your Mac 19 Setting the Calendar on Your Mac 22

Internationalizing the User Interface 24 Using Base Internationalization 24 Using Auto Layout 24 Detecting Problems Using Pseudolocalizations 25 Enabling Base Internationalization 27

Internationalizing Your Code 30 Separating User-Facing Text from Your Code 30 Using Strings 32 Accessing Characters in Strings 32 Enumerating Strings 32 Searching Strings 33 Sorting Strings 34 Displaying Text 34 Parsing Text Input 34 Detecting Personal Names, Mailing Addresses, and Phone Numbers 35

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 2 Contents

Getting the Current Language 36

Formatting Data Using the Locale Settings 37 About Locale Formats 37 Using the Locale Object 38 Getting the User’s Locale 38 Getting Information About a Locale 39 Getting Localized Language and Dialect Names 39 Getting Language-Specific Quotes 40 Formatting Strings 41 Creating Formatted Strings 41 Changing the Case of Strings 41 Formatting Dates and Times 42 Using Preset Date and Time Styles 42 Using Custom Date and Time Styles 43 Parsing Localized Date Strings 44 Formatting Numbers 45 Using Preset Number Styles 46 Parsing Localized Number Strings 47 Computing Dates Using Calendars 47 Registering for Locale and Time Zone Changes 49

Supporting Right-to-Left Languages 50 Creating Right-to-Left User Interfaces 50 Getting the Layout Direction 52 Setting Text Alignment 52 Handling Bidirectional Text 53 Using Natural Writing Direction 53 Adding Unicode Markup to Bidirectional Text 53 Flipping Cocoa Touch Views and Controls Programmatically 54 Flipping Images in an iOS App 54 Flipping Cocoa Views and Controls Programmatically 55 Flipping Images 55 Flipping Toolbars 56 Flipping a Table View in a Mac App 56 Testing Right-to-Left Locale Formats 58

Localizing Your App 60 Choosing Languages 60 Locking Views 61

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 3 Contents

Exporting Localizations 62 Importing Localizations 65 Verifying Your Steps 68 Exporting Localizations Using Command-Line Utilities 69 Adding Additional Resources You Want to Localize 70 Handling Noun Plurals and Units of Measurement 71 Localizing the Information Property List Files 75 Localizing the App Name and Copyright Notice 75 Getting the Localized App Name 76 Adding Languages 76

Testing Your Internationalized App 79 Previewing Localizations in Interface Builder 79 Testing Using Pseudolanguages 80 Testing Right-to-Left Layouts 81 Detecting Non-localized Strings (OS X v10.10 and later) 82 Testing Specific Languages and Regions 83 Testing Supported Languages and Regions on Devices 84

Managing Strings Files Yourself 85 Viewing Language Folders in the Finder 85 Creating Strings Files for User-Facing Text in Your Code 86 Localizing Strings Files 88 Localizing Strings Files Using AppleGlot 88 Updating Storyboard and Xib Strings Files Using ibtool 90 Creating a Pseudolocalization 91

Language and Locale IDs 92 Language Designators 92 Region Designators 93 Language IDs 93 Locale IDs 95 Using Subtag Designators 95

Stringsdict File Format 97 Localized String Properties 97 Localized Format String Properties 98 Plural Rule Properties 98

Document Revision History 100

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 4 Contents

Glossary 101

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 5 Tables

Internationalizing Your Code 30 Table 3-1 Unicode Encoding of User Characters 32

Formatting Data Using the Locale Settings 37 Table 4-1 Data formats in United States and Germany 37 Table 4-2 Quotes in China, France, and Japan 41 Table 4-3 Preset date and time styles in English for the United States 42 Table 4-4 Preset date and time styles in different languages and regions 43 Table 4-5 Non-localized and localized date formats in different regions 44 Table 4-6 Preset number styles in different languages and regions 46 Table 4-7 Variations in regional calendars 48

Localizing Your App 60 Table 6-1 Locking levels 61

Language and Locale IDs 92 Table B-1 Language designator examples 92 Table B-2 Regional designator examples 93 Table B-3 Language ID syntax and examples 93 Table B-4 language ID examples 94 Table B-5 Locale ID syntax and examples 95

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 6 About Internationalization and Localization

Note: This document was previously titled Internationalization Programming Topics.

Localization is the process of translating your app into multiple languages. But before you can localize your app, you internationalize it. Internationalization is the process of making your app able to adapt to different languages, regions, and cultures. Because a single language can be used in multiple parts of the world, your app should adapt to the regional and cultural conventions of where a person resides. An internationalized app appears as if it is a native app in all the languages and regions it supports.

The App Store is available in over 150 different countries, and internationalizing your app is the first step to reach this global market. Using iTunes Connect, you specify whether your app is available in all territories or specific territories. Then you customize your app for each target market that you want to support. Users in other countries want to use your app in a language they understand and see dates, times, and numbers in familiar, regional formats.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 7 About Internationalization and Localization At a Glance

At a Glance Xcode supports incremental localization of your project. First you internationalize your user interface and code during development. Then you test your app using pseudolocalizations and different region settings. When you are ready to localize your app, you export the localizable text using standard file formats and submit them to a localization team for translation into multiple languages. While you are waiting for these translations, you can continue developing your app and perform additional localization steps yourself—perhaps add language-specific audio and image files to your project. Then import the localizations into your project and thoroughly test your app in each supported language and region. During the next iteration of your app, you only translate changes and add additional languages.

Learn About Language and Region Settings Start by familiarizing yourself with the language and region settings available to the user.

Related Chapter: Reviewing Language and Region Settings (page 11)

Internationalize Your App Prepare your app for localization by separating language and locale differences from the rest of your user interface and code.

● Use base internationalization to separate user-facing text from your .storyboard and .xib files.

● In Interface Builder, use Auto Layout so views adjust to the localized text.

● Separate other user-facing text from your code.

● Use standard APIs to handle the complexity of different writing systems and locale formats.

● Adhere to the user’s settings when formatting, sorting, searching, and parsing data.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 8 About Internationalization and Localization At a Glance

● If the app supports right-to-left languages, mirror the user interface and change the text direction as needed.

Related Chapter: Internationalizing the User Interface (page 24), Internationalizing Your Code (page 30), Formatting Data Using the Locale Settings (page 37), Supporting Right-to-Left Languages (page 50)

Localize Your App Export and import the localizations using standard file formats.

● Lock views in the user interface.

● Export the localizations.

● Submit the exported files to translators.

● Import the localization files and confirm the changes.

● Perform additional localization steps yourself.

Xcode doesn’t translate text for you. For links to third-party localization vendors, see Build Apps for the World.

Related Chapter: Localizing Your App (page 60)

Test Your App Test your internationalized app, using a variety of techniques, during development and after localization.

Before you localize your app:

● In Interface Builder, preview the user interface using pseudolanguages.

● Run the app using different pseudolanguages.

After you import localizations:

● In Interface Builder, preview the localizations.

● Run the app with options that detect non-localized text.

● Run the app using all supported languages and regions.

● Ask native-language speakers to test the app.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 9 About Internationalization and Localization See Also

Related Chapter: Internationalizing the User Interface (page 24), Testing Your Internationalized App (page 79)

See Also The following documents provide more information about related topics:

● Xcode Overview describes Xcode features and contains links to other Xcode books.

● Data Formatting Guide describes how to present and interpret calendrical and numerical data according to the user’s region settings.

● Date and Time Programming Guide describes how to manage dates and times according to different calendars and time zones in use around the world.

● Internationalization and Localization for OS X provides code samples that illustrate internationalization and localization techniques and APIs.

Before you submit your localized app to the App Store or Mac App Store, add territories and localize your metadata using iTunes Connect:

● Viewing and Changing Your App’s Metadata in iTunes Connect Developer Guide

● Displaying on the Store in More Than One Language (Optional) in iTunes Connect Developer Guide

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 10 Reviewing Language and Region Settings

For iOS and Mac, the language, region, and calendar are user preferences. The language setting determines which localization the app uses. The region setting determines the format of data—such as dates, times, and numbers—and also cultural conventions of the area. For Mac, you can also customize regional formats. For iOS and Mac, you can choose a different calendar that may change the era and affect other calendar calculations.

For iOS, changing the language restarts Springboard and quits running apps. So the next time you launch an iOS app, it uses the new language setting. For Mac apps, the language doesn’t change until you restart the app. To localize all apps and the entire desktop on a Mac, you log out and log in. For iOS and Mac, the region and calendar settings can be changed at any time, even when your app is running. An internationalized app respects all these user settings and takes the appropriate action when they change.

Before internationalizing your app, review the language, region, and calendar settings on the target device. Notice how localized apps adjust to the changes you make to these settings.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 11 Reviewing Language and Region Settings Reviewing Language and Region Settings on iOS Devices

Reviewing Language and Region Settings on iOS Devices The language, region, and calendar settings are in the International section of the Settings app. Experiment by changing the language, region, and calendar settings independently. For example, if your language is English and you change the region from United States to Germany, notice how the format of dates and times in Calendar changes. The day moves before the month and the time changes to a 24-hour clock. If you change the language to German, notice how all other text in Calendar changes to German.

Setting the Language on iOS Devices You select the language independent of the region.

To change the language on iOS devices

1. Tap Settings > General > Language & Region.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 12 Reviewing Language and Region Settings Reviewing Language and Region Settings on iOS Devices

2. Tap iPhone Language, select the language, and tap Done.

3. Tap “Change to [Language].” Wait while iOS changes the language.

For example, see how Calendar localizes its views in Spanish, Chinese, and Arabic below. In Arabic, the title and location text fields are right-aligned because Arabic is a right-to-left language.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 13 Reviewing Language and Region Settings Reviewing Language and Region Settings on iOS Devices

Setting the Region on iOS Devices The region setting is independent of the language setting. The region setting doesn’t automatically change when you set the language. For example, if you change the language from English (United States) to German, the region is still United States, and the month appears before the day in date formats. If you want the date and time formats to conform to the German styles, change the region to Germany. Conversely, you can change only the region to localize date and time formats.

To set the region on iOS devices

1. Tap Settings > General > Language & Region. 2. Tap Region, and select the region from the list.

3. To return to the Language & Region settings, tap Back.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 14 Reviewing Language and Region Settings Reviewing Language and Region Settings on iOS Devices

Setting the Calendar on iOS Devices You can also specify the preferred calendar. For example, the era is different in the Gregorian, Buddhist, and Japanese calendars.

To change the calendar on iOS devices

1. Tap Settings > General > Language & Region.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 15 Reviewing Language and Region Settings Reviewing Language and Region Settings on iOS Devices

2. Tap Calendar, and select the calendar from the list.

3. To return to the International settings, tap Back.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 16 Reviewing Language and Region Settings Reviewing Language and Region Preferences on Your Mac

Reviewing Language and Region Preferences on Your Mac For Mac, you can best observe language and region changes using Calendar. Notice how the date and times reformat when the region changes. Calendar also adjusts for cultural differences. For example, if you change the region from United States to France, the month view shows Monday as the first day of the week. Other text in Calendar doesn’t appear in French unless you change the language to French.

The language, region, and calendar settings are in the Language & Region pane of System Preferences. You can also create custom regional data formats on a Mac.

Setting the Language on Your Mac You can add and remove languages from a list of preferred languages. The first language in the list is the primary language used for localizations.

To change the language your Mac uses

1. In System Preferences, click Language & Region. 2. Either click the Add button (+) to add a language, or drag a different language to the top of the “Preferred languages” list.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 17 Reviewing Language and Region Settings Reviewing Language and Region Preferences on Your Mac

If OS X or an app supports the primary language, menus and messages are shown in that language. If it doesn’t, it uses the second language in the list, and so on.

3. If you click the Add button, in the dialog that appears, select a language, and click Add. In the dialog that appears, click Use [Language] to move the language to the top of the “Preferred languages” list.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 18 Reviewing Language and Region Settings Reviewing Language and Region Preferences on Your Mac

Setting the Region on Your Mac The region you select is independent of the language you select. For example, if you live in Quebec, you can select French as the language and Canada, or United States, as the region.

To choose a region and customize formats

1. In System Preferences, click Language & Region. 2. Choose a geographic region from the Region pop-up menu.

3. To customize formats, click Advanced.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 19 Reviewing Language and Region Settings Reviewing Language and Region Preferences on Your Mac

4. In the General pane, choose the language to use for showing dates, times, and numbers, and set formats for numbers, currency, and measurements.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 20 Reviewing Language and Region Settings Reviewing Language and Region Preferences on Your Mac

5. In the Dates and Times panes, you can create custom number and date formats by entering text and dragging elements.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 21 Reviewing Language and Region Settings Reviewing Language and Region Preferences on Your Mac

Setting the Calendar on Your Mac You can also specify the preferred calendar. Calendar adapts to all of these user settings. For example, you can choose Russian as the language, Russia as the region, and Hebrew as the calendar. The 24-hour clock is also optional.

To change the calendar on Mac

1. In System Preferences, click Language & Region.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 22 Reviewing Language and Region Settings Reviewing Language and Region Preferences on Your Mac

2. Choose a calendar from the Calendar pop-up menu.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 23 Internationalizing the User Interface

Xcode provides several technologies to help you develop an internationalized app. Xcode separates user-facing text from your views and layout so user-facing text can be easily translated independent of your Xcode project. Xcode also provides tools to maintain this separation when you change the user interface. In addition, you may have different sets of other types of resource files for each language you support.

Using Base Internationalization

Base internationalization separates user-facing strings from .storyboard and .xib files. It relieves localizers of the need to modify .storyboard and .xib files in Interface Builder. Instead, an app has just one set of .storyboard and .xib files where strings are in the development language—the language that you used to create the .storyboard and .xib files. These .storyboard and .xib files are called the base internationalization. When you export localizations, the development language strings are the source that is translated into multiple languages. When you import localizations, Xcode generates language-specific strings files for each .storyboard and .xib file. The strings files don’t appear in the project navigator until you import localizations or add languages.

In Xcode 5 and later, base internationalization is enabled by default. If you have an older project, enable base internationalization before continuing, as described in Enabling Base Internationalization (page 27).

Using Auto Layout Use Auto Layout to lay out your views relative to each other without fixed origins, widths, and heights, so that views reposition and resize appropriately when the language or locale changes. Auto Layout makes it possible to have one set of .storyboard and .xib files for all languages.

Follow these tips when using Auto Layout for internationalized apps:

Remove fixed width constraints. Allow views that display localized text to resize. If you use fixed width constraints, localized text may appear cropped in some languages.

Use intrinsic content sizes. The default behavior for text fields and labels is to resize automatically. If a view is not adjusting to the size of localized text, select the view and choose Editor > Size To Fit Content.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 24 Internationalizing the User Interface Detecting Problems Using Pseudolocalizations

Use leading and trailing attributes. When adding constraints, use the attributes leading and trailing for horizontal constraints. For left-to-right languages, such as English, the attributes leading and trailing are equivalent to left and right. For right-to-left language, such as Hebrew or Arabic, leading and trailing are equivalent to right and left. The leading and trailing attributes are the default values for horizontal constraints.

Pin views to adjacent views. Pinning causes a domino effect. When one view resizes to fit localized text, other views do the same. Otherwise, views may overlap in some languages.

Constantly test your layout changes. Test your app using different language settings, as described in Testing Your Internationalized App (page 79).

Don’t set the minimum size or maximum size of a window. Let the window and its content view adjust to the size of the containing views, which may change when the language changes.

Auto Layout is enabled by default when you create a new project. To enable Auto Layout for an older project, read Adopting Auto Layout in Auto Layout Guide. To learn how to add constraints and resolve constraint issues, read Auto Layout Guide.

Detecting Problems Using Pseudolocalizations In Interface Builder, you can preview the user interface using pseudolocalizations to detect Auto Layout problems. Before you localize your app and add languages, only pseudolocalizations are available in Interface Builder.

To preview the user interface in a pseudolocalization

1. In project navigator, select the .storyboard or .xib file you want to preview. 2. Choose View > Assistant Editor > Show Assistant Editor. 3. In the assistant editor jump bar, open the Assistant pop-up menu, scroll to the Preview item, and choose the .storyboard or .xib file. If a preview of the app’s user interface doesn’t appear in the assistant editor, select the window or view you want to preview in the icon or outline view.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 25 Internationalizing the User Interface Detecting Problems Using Pseudolocalizations

4. In the assistant editor, choose the pseudolocalization you want to use from the language pop-up menu in the lower-right corner.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 26 Internationalizing the User Interface Enabling Base Internationalization

For example, choose “Double-Length Pseudo-Language” from the menu to replace all user-facing strings with duplicate strings. A preview of the localization appears in the assistant editor.

Enabling Base Internationalization Verify that your project is using base internationalization and if necessary, enable it before continuing.

To enable base internationalization

1. In the project navigator, select the project (not a target) and click Info.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 27 Internationalizing the User Interface Enabling Base Internationalization

2. If necessary, click the disclosure triangle next to Localizations to reveal the settings.

3. If necessary, select the Use Base Internationalization checkbox.

4. In the dialog that appears, specify the development language for your .storyboard and .xib files.

Select the .storyboard and .xib files in the Resource File column and the development language in the Reference Language column.

Xcode modifies your project folder according to the selections you make in this dialog. Xcode creates a Base.lproj folder in your project folder and adds to it the resource files you select. Xcode creates a language folder for the development language but only adds resources that need translation to the folder. For example, if you select English as the development language, Xcode inserts the resource file in the Base.lproj project folder but not the en.lproj folder because the resource is already in English.

If no resources appear in the dialog, add your .storyboard and .xib files to a language, as described in Adding Languages (page 76), and repeat these steps.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 28 Internationalizing the User Interface Enabling Base Internationalization

5. Click the Finish button. In the Language table, the number of localized resource files for the Development Language changes from 0 to the number of files you selected.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 29 Internationalizing Your Code

In addition to internationalizing your user interface, write code that handles text in multiple languages. First store international text in strings files similar to the strings files used by base internationalization in Internationalizing the User Interface (page 24). Also use language and locale-sensitive APIs for enumerating, searching, and sorting text in your code. Use standard text views for displaying and parsing text input as well. Let these APIs handle the complexity of different writing and input systems for you.

Separating User-Facing Text from Your Code All user-facing text supplied by your app programmatically needs to be localized—that is, user-facing text that is not contained in .storyboard or .xib files, such as error messages, needs to be translated into the current language before it’s presented to the user. iOS and OS X provide a mechanism to retrieve localized text from strings files at runtime. In your code, replace strings containing user-facing text with the return value of an NSLocalizedString macro. When you export localizations, Xcode searches your code for the macros and includes the strings files in the exported localization file for translation. When you import localizations, Xcode adds the strings files, used by your code, to your Xcode project.

For example, instead of using the @"26.22 miles" string in your code, use:

NSLocalizedString(@"RunningDistance", @"distance for a marathon") where @"RunningDistance" is the key for text that is retrieved from a localized strings file. The @"distance for a marathon" parameter is a comment about the key-value pair stored in the strings file as a hint to localizers. If you want different behavior, use one of the other NSLocalizedString macros that take more parameters, described in Foundation Functions Reference.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 30 Internationalizing Your Code Separating User-Facing Text from Your Code

Tip: Don’t overload keys or compose phrases from multiple keys. Some languages have gender articles, adjective endings, and completely different word order. Instead, add a separate key-value pair to the strings file for all unique phrases. For example, replace these key-value pairs:

/* Go to next page/chapter */

"GoToNext" = "Go to next %@";

"chapter" = "chapter";

"page" = "page";

with separate key-value pairs for each phrase:

/* Go to next chapter */

"GoToNextChapter" = "Go to next chapter";

/* Go to next page */

"GoToNextPage" = "Go to next page";

Don’t put numbers in localizable strings because different regions can use different numbers.

You don’t need to store all your key-value pairs in the same strings files. You can use other NSLocalizedString macros to create separate strings files and optionally, store them in different bundles. For more information on NSLocalizedString macros, read String Resources in Resource Programming Guide.

To retrieve a localized string from a strings file, rather than adding it to a strings file, use the localizedStringForKey:value:table: method in the NSBundle class. When the strings file corresponding to the specified table is not in your project, the NSLocalizedString macros and the localizedStringForKey:value:table: method return the value parameter as the localized string.

Later, when you import localizations, as described in Importing Localizations (page 65), the localized strings files are added to your project. (Alternatively, you can generate the development language strings files from NSLocalizedString macros directly, as described in Creating Strings Files for User-Facing Text in Your Code (page 86).)

If your strings contain plurals of nouns or units of measurement, read Handling Noun Plurals and Units of Measurement (page 71) for how to extend this mechanism for languages that have different plural rules.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 31 Internationalizing Your Code Using Unicode Strings

Using Unicode Strings

For all user-facing text, use string objects—instances of NSString, NSAttributedString, and their subclasses—that support Unicode. Unicode is a standard for encoding characters from all the world’s writing systems. String objects encapsulate a Unicode string encoded in UTF-16 format. What the user sees as a character may be represented and encoded as multiple characters in a Unicode string. Therefore, use string methods that manipulate composed character sequences, not individual characters in a string. Use the appropriate string APIs for iteration, searching, and sorting too. Use standard views and controls that display Unicode string objects correctly.

For comprehensive documentation on string objects, read String Programming Guide.

Accessing Characters in Strings The NSString class handles the complexity of for you by allowing you to access character clusters or ranges. Use the rangeOfComposedCharacterSequenceAtIndex: and rangeOfComposedCharacterSequencesForRange: methods to ensure that you don’t split user characters in a string and break the text. These methods return a range within a string that represents the user character.

For example, Table 3-1 shows the numeric representation of user characters in UTF-16 and UTF-32 encoding. Note that the user characters have different lengths no matter what encoding format you use.

Table 3-1 Unicode Encoding of User Characters

User Character UTF-16 UTF-32

D85E DFFD 27BFD

1100 1161 11A8 01100 01161 011A8

Video: WWDC 2013 Making Your App World-Ready: International Text > Composed Character Se- quences

Enumerating Strings Enumerate strings by composed character sequence, word, sentence, or paragraph, not individual characters in a string. To enumerate a string by composed character sequence, use the enumerateSubstringsInRange:options:usingBlock: method and pass NSStringEnumerationByComposedCharacterSequences as the options parameter. To enumerate a string by word (skipping over ), pass NSStringEnumerationByWords as the options parameter.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 32 Internationalizing Your Code Using Unicode Strings

For example, if you pass NSStringEnumerationByComposedCharacterSequences to the enumerateSubstringsInRange:options:usingBlock: method, it returns the user characters, as in the composed character sequences:

If the string is

and you pass NSStringEnumerationByWords as the options parameter, the following words are returned:

Notice that spaces and punctuation are not included in the words.

Video: WWDC 2013 Making Your App World-Ready: International Text > String APIs: Iteration

Searching Strings To search the contents of a string or verify the presence of a string within a string using locale-sensitive comparison algorithms, use the rangeOfString:options:range:locale: method, passing the current locale as the locale parameter. The constants you can combine and pass as the options parameter are:

NSCaseInsensitiveSearch Case-insensitive search. For example, ‘B’ is the same as ‘b’.

NSDiacriticInsensitiveSearch Ignores marks. For example, ‘ö’ is equal to ‘o’.

NSBackwardsSearch Search backwards. (The default is forwards.)

NSAnchoredSearch Search at the starting point.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 33 Internationalizing Your Code Using Unicode Strings

For example, if you are searching for user text in a string, pass the NSCaseInsensitiveSearch and NSDiacriticInsensitiveSearch constants as the options parameter to the rangeOfString:options:range:locale: method. Typically, searching text is a case and diacritic insensitive operation, but sorting text is case and diacritic sensitive.

Sorting Strings For text you display to users, use locale-sensitive APIs for sorting and comparing strings. Different languages and regions have different sort order standards. For example, in French the are significant, and in English they are not. In some languages multiple letters are combined and affect the sort order.

To use the locale-sensitive comparison algorithms, use the localizedStandardCompare: method which produces the same results as the Finder.

If you don’t want the same results as the Finder, use the compare:options:range:locale: method, passing the current locale as the locale parameter, or the localizedCompare: method.

Don’t use the localizedCaseInsensitiveCompare: method for sorting.

Video: WWDC 2013 Making Your App World-Ready: International Text > String APIs: Sorting

Displaying Text Use standard views and controls that handle the complexity of Unicode text layout and display for you. Characters in a string do not directly correspond to text rendered on the screen. What appears on the screen is a sequence of glyphs. A glyph is the smallest displayable unit in a font. A glyph may represent one character, more than one character, or part of a character. The mapping of characters to glyphs is not simple—it can be many-to-many. In addition, the order and position of glyphs in a line is complex. The standard views and controls even lay out bidirectional text properly for you—for example, the order of characters in a string containing an English word followed by a Hebrew word is not the same order used to lay out the text in a view, as described in Handling Bidirectional Text (page 53).

If you need to write custom display code, use the appropriate low-level text APIs. To learn about the text classes for iOS, read Text Programming Guide for iOS and for Mac, read Text Layout Programming Guide.

Parsing Text Input The user might enter text in any language and format. iOS and OS X can recognize the language the user is typing and provide the appropriate keyboard options. If you are parsing text as the user enters it, keep in mind that there’s a many-to-many mapping from keyboard characters to language characters.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 34 Internationalizing Your Code Detecting Personal Names, Mailing Addresses, and Phone Numbers

Parsing Language Characters For some languages, the user doesn’t enter text one character at a time. That is, keys the user presses on a keyboard don’t necessarily correspond to characters in the language. In French, the user adds an accent at the insertion point by choosing it from a pop-up menu. In Japanese and Chinese languages, the user enters phonetic representations and selects a candidate from the candidate list to confirm the marked text. In both cases, preliminary text is inserted first and then converted to final text when the user confirms it.

Video: WWDC 2013 Making Your App World-Ready: International Text > Text Input

Determining When the User Confirms Marked Text (iOS Only) To determine if the user confirmed marked text, send markedTextRange to a text view. If this method returns an empty string, the user confirmed some entered text.

Determining the Typed Language (iOS Only) To get the language that the user is currently typing, use the textInputMode property in the UIResponder class, as in:

NSString *languageID = [[[UIApplication sharedApplication] textInputMode] primaryLanguage];

The returned string is a language ID, as described in Language and Locale IDs (page 92), that identifies a written language or dialect.

To get the set of languages that the user enables:

NSArray *languages = [[[UIApplication sharedApplication] textInputMode] activeInputModes]; where the returned array contains instances of the UITextInputMode class.

Detecting Personal Names, Mailing Addresses, and Phone Numbers Worldwide, the format of personal names, mailing addresses, and phone numbers varies considerably. Personal names have many different formats including different ordering of the components. For example, in Asian countries, the family name is followed by the given name with no spaces between. The format of mailing addresses depends on the country. Phone numbers have different amounts of digits and punctuation between

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 35 Internationalizing Your Code Getting the Current Language

them. To handle varying input formats in your text views, use Interface Builder to add data detectors to your text views. A data detector identifies addresses and phone numbers in many different international formats and optionally turns them into links.

To detect this type of data in strings programmatically, read NSDataDetector Class Reference.

Getting the Current Language

To get the language that the app is using from the main application bundle, use the preferredLocalizations method in the NSBundle class:

NSString *languageID = [[NSBundle mainBundle] preferredLocalizations].firstObject;

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 36 Formatting Data Using the Locale Settings

Different countries and regions have different conventions for formatting numerical and time-based information. Locale settings provide information about the formats used by the current user and must be considered when writing code that handles user-facing data types. The user sets the locale by choosing a region in Settings on iOS devices and System Preferences on a Mac. The user can also change locale settings while the app is running. Therefore, if you manipulate data objects in your code and then present them to the user, use the locale APIs to format the data correctly.

You do not need to know how to format data in all the different locales. You can use preset styles that automatically generate locale-sensitive formats. You can use custom formats as long as you convert them to locale-sensitive formats before presenting them to users. This chapter explains how to write locale-sensitive code.

About Locale Formats Locales represent the formatting choices for a particular user, not the user’s preferred language. These are often the same but can be different. For example, a native English speaker who lives in Germany might select English as the language and Germany as the region. Text appears in English but dates, times, and numbers follow German formatting rules. The day precedes the month and a 24-hour clock represents times, as shown in Table 4-1.

Table 4-1 Data formats in United States and Germany

Language (Region) Dates Times Numbers

English (United States) Sunday, January 5, 2014 7:08:09 AM PST 1,234.56 1/5/14 7:08 AM $4,567.89

English (Germany) Sunday 5 January 2014 07:08:09 PST 1.234,56 05/01/14 07:08 €4.567,89

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 37 Formatting Data Using the Locale Settings Using the Locale Object

On a Mac, you can preview modified locale preferences in System Preferences. When you choose a geographic region from the Region pop-up menu, samples of the date, time, and number formats appear. This screenshot shows sample data formats when English is the language and Japan is the region:

Mac users can also customize the formats of dates, times, and numbers by clicking the Advanced button, as described in Reviewing Language and Region Preferences on Your Mac (page 17).

Using the Locale Object

An NSLocale object encapsulates information about the formatting standards of a particular region. When you format user-facing text, you pass an NSLocale object representing the user’s selected region. The NSLocale class provides class methods for obtaining the user’s locale object and other information about supported locales.

Getting the User’s Locale You can obtain the user’s locale using either the currentLocale or autoupdatingCurrentLocale class methods in the NSLocale class.

If you use the currentLocale method, the property values of the returned object are guaranteed not to change. Therefore, use the currentLocale method if you want to perform operations that need to be consistent.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 38 Formatting Data Using the Locale Settings Using the Locale Object

If you use the autoupdatingCurrentLocale method, the property values can change when the user changes the region settings. However, you are not notified if the returned object changes.

To observe locale preference changes, read Registering for Locale and Time Zone Changes (page 49).

Tip: The system settings are not the same as the user’s settings. Don’t use the systemLocale class method to get the user’s locale.

Getting Information About a Locale Use the objectForKey: instance method in the NSLocale class to access information about a locale. For example, pass the NSLocaleUsesMetricSystem key to this method to get a Boolean number that determines whether the locale uses the metric system:

NSNumber *metricSystem = [[NSLocale currentLocale] objectForKey:NSLocaleUsesMetricSystem];

Pass the NSLocaleCurrencySymbol key to get a string representation of the locale’s currency symbol:

NSString *currencySymbol = [[NSLocale currentLocale] objectForKey:NSLocaleCurrencySymbol];

For a complete list of locale property keys, see NSLocale Component Keys.

Getting Localized Language and Dialect Names The identifiers that specify languages and dialects in APIs and folder names—for example, de-CH, en-AU, and pt-PT—shouldn’t be displayed to users. To get a human-readable, localized language or dialect name, use the displayNameForKey:value: method in the NSLocale class, passing NSLocaleIdentifier as the key parameter.

To get the localized name for languages and dialects

1. Get the language that the app is using.

NSString *languageID = [[NSBundle mainBundle] preferredLocalizations].firstObject;

The returned string is a language ID that identifies a written language or dialect, as described in Language and Locale IDs (page 92).

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 39 Formatting Data Using the Locale Settings Using the Locale Object

2. Get the associated locale object.

NSLocale *locale = [NSLocale localeWithLocaleIdentifier:languageID];

If you pass the language ID as the locale ID parameter, a locale for the language is returned. For example, if you pass de-CH as the language, the Switzerland locale is returned. 3. Get the localized language name.

NSString *localizedString = [locale displayNameForKey:NSLocaleIdentifier value:languageID];

The format of the string is [Language] ([Dialect]). For example, if the language ID is de-CH, the localized language string is “Deutsch (Schweiz).” If the language ID is de, the localized language string is “Deutsch.”

Getting Language-Specific Quotes Beginning and ending quotes, which vary in different languages, can be obtained from the locale object. Use the same technique, described in Getting Localized Language and Dialect Names (page 39), to obtain the default locale for the language, and then use the locale component keys to obtain the language-specific quotes.

To create a string that uses locale-sensitive quotes

1. Get the language that the app is using.

NSString *languageID = [[NSBundle mainBundle] preferredLocalizations].firstObject;

2. Get the associated locale object.

NSLocale *locale = [NSLocale localeWithLocaleIdentifier:languageID];

3. Get the beginning and ending symbols for quotes from the locale object.

bQuote = [locale objectForKey:NSLocaleQuotationBeginDelimiterKey]; eQuote = [locale objectForKey:NSLocaleQuotationEndDelimiterKey];

4. Format a string using the locale-sensitive quotes.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 40 Formatting Data Using the Locale Settings Formatting Strings

quotedString = [NSString stringWithFormat:@"%@%@%@", bQuote, myText, eQuote];

Table 4-2 shows the results when myText is “@iPhone”for different regions.

Table 4-2 Quotes in China, France, and Japan

Region quotedString = @"%@iPhone%@"

China “iPhone”

France

Japan

Formatting Strings

If available, use the alternative, locale-sensitive NSString method for user-facing text. There are locale-sensitive methods for creating strings with formats, changing the case, obtaining ranges within a string, and comparing strings.

Creating Formatted Strings At a minimum, use the localizedStringWithFormat: method in the NSString class, not the stringWithFormat: method to format user-facing text. A simple fix to existing code is to replace occurrences of the stringWithFormat: method with the alternate localizedStringWithFormat: method throughout your code, as in:

NSString *localizedString = [NSString localizedStringWithFormat:@"%3.2f", myNumber];

This method uses the system locale. To specify the user’s locale preference, pass [NSLocale currentLocale] as the locale parameter to either the initWithFormat:locale: or initWithFormat:locale:arguments: method. For best results, use data-specific formatter objects and preset styles, described in Formatting Dates and Times (page 42) and Formatting Numbers (page 45).

Changing the Case of Strings The process of changing the case in strings is not the same for all languages. Use these locale-sensitive NSString methods to change the case:

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 41 Formatting Data Using the Locale Settings Formatting Dates and Times

uppercaseStringWithLocale:

lowercaseStringWithLocale:

capitalizedStringWithLocale:

If you pass nil as the locale parameter, the system locale is used, which is incorrect. To specify the user’s locale preference, pass [NSLocale currentLocale] as the locale parameter.

Formatting Dates and Times

You use the NSDateFormatter class to create localized string representations of NSDate objects that are also locale-sensitive. NSDateFormatter objects are often attached directly to text fields in an Interface Builder file, but if you create NSDateFormatter objects programmatically, be sure to use methods that return localized string representations.

Note: The NSDateFormatter class is not thread-safe. See ThreadingProgrammingGuide for details.

Using Preset Date and Time Styles To obtain a localized string representation of a date and time using a preset style, use the localizedStringFromDate:dateStyle:timeStyle: class method in the NSDateFormatter class:

NSString *localizedDateTime = [NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterMediumStyle timeStyle:NSDateFormatterShortStyle];

For example, specify a medium style to abbreviate text—such as “Jun 10, 2013”—by passing NSDateFormatterMediumStyle as the style parameter. Specify a short style for numerical only representations—such as “6/10/13” or “11:03 AM”—by passing NSDateFormatterShortStyle as the style parameter. Table 4-3 shows the results of using preset formats when English is the language and United States is the region.

Table 4-3 Preset date and time styles in English for the United States

Style Date Time Description

Short 6/10/13 11:03 AM Numeric only

Medium Jun 10, 2013 11:03:15 AM Abbreviated text

Long June 10, 2013 11:03:15 AM PDT Full text

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 42 Formatting Data Using the Locale Settings Formatting Dates and Times

Style Date Time Description

Full Friday, June 10, 2013 11:03:15 AM Pacific Daylight Time Complete details

No Style Output suppressed

Table 4-4 shows the results of passing NSDateFormatterMediumStyle for the date style and NSDateFormatterShortStyle for the time style for different languages and regions.

Table 4-4 Preset date and time styles in different languages and regions

Language (Region) Medium style Short style

English (United States) Jun 6, 2013 10:14 AM

French (France) 6 Jun 2013 10:14

Chinese (China)

Video: WWDC 2013 Making Your App World-Ready: Data Formatting > Preset Date Styles

Using Custom Date and Time Styles Use custom date and time styles only when the preset styles don’t meet your needs. However, convert your custom format to a locale-sensitive format before getting string representations of the date and time. The dateFormatFromTemplate:options:locale: class method in the NSDateFormatter class rearranges the given template to adhere to the specified locale.

To get a localized string representation of a date and time using a custom style

1. Create an NSDateFormatter object.

NSDateFormatter *dateFormatter = [NSDateFormatter new];

2. Use the dateFormatFromTemplate:options:locale: class method to get a localized format string from a template that you provide.

NSString *localeFormatString = [NSDateFormatter dateFormatFromTemplate:@"dMMM" options:0 locale:dateFormatter.locale];

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 43 Formatting Data Using the Locale Settings Formatting Dates and Times

The template parameter of the dateFormatFromTemplate:options:locale: method should adhere to Unicode Technical Standard #35, described in Use Format Strings to Specify Custom Formats. For example, the template @”dMMM” specifies that the day of the month and abbreviation for the month should be in the format string. The order of the symbols and any non-symbol characters in the template are ignored.

3. Set the format of the NSDateFormatter instance to the locale-sensitive format string.

dateFormatter.dateFormat = localeFormatString;

4. Use the stringFromDate: method to get a localized string representation of the date.

NSString *localizedString = [dateFormatter stringFromDate:[NSDate date]];

For example, if you don’t convert the @“MMM d” string to a locale-sensitive format, the results are not localized, as shown in the second column in Table 4-5.

Table 4-5 Non-localized and localized date formats in different regions

Language (Region) Date using format string Date using template “MMM d” “dMMM”

English (United States) Nov 13 Nov 13

French (France) nov. 13 13 nov.

Chinese (China)

Video: WWDC 2013 Making Your App World-Ready: Date Formatting > Custom Date and Time Styles

Parsing Localized Date Strings The user enters dates using localized formats, so parse input strings accordingly. Use an NSDateFormatter object to convert a localized string to a date object. Set the date formatter’s style using one of the preset styles. (Use a template format string only if a preset style doesn’t work.) Also, allow the date formatter to use heuristics when parsing the string.

To convert a localized date string to a date object

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 44 Formatting Data Using the Locale Settings Formatting Numbers

1. Create a date formatter object.

NSDateFormatter *dateFormatter = [NSDateFormatter new];

2. Set the formatter’s style to a preset style.

dateFormatter.dateStyle = NSDateFormatterMediumStyle;

Replace NSDateFormatterMediumStyle with the style you expect the user to enter. 3. If the input string is not expected to contain a time, set the time style to none.

dateFormatter.timeStyle = NSDateFormatterNoStyle;

4. Set the leniency to YES (enables the heuristics).

dateFormatter.lenient = YES];

5. Convert the string to a date object.

NSDate *date = [dateFormatter dateFromString:inputString];

For example, if the locale is United States, the input string is 9/3/14, and the preset style is NSDateFormatterShortStyle, the date is interpreted as 2014-09-03 07:00:00 +0000. However, if the locale is Germany, the date becomes 2014-03-09 08:00:00 +0000.

Formatting Numbers Locale settings affect the format of numbers—such as the decimal, thousands separator, currency, and percentage symbols. For example, the number 1,234.56 is formatted as 1.234,56 in Italy. So use the NSNumberFormatter class to create localized string representations of NSNumber objects.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 45 Formatting Data Using the Locale Settings Formatting Numbers

Note: The NSNumberFormatter class is not thread-safe. See Threading Programming Guide for details.

Using Preset Number Styles To obtain a localized string representation of a number using a preset style, use the localizedStringFromNumber:numberStyle: class method in the NSNumberFormatter class:

NSString *localizedString = [NSNumberFormatter localizedStringFromNumber:myNumber numberStyle:NSNumberFormatterDecimalStyle];

Table 4-6 lists the preset styles available and compares United States preset formats to other regions.

Table 4-6 Preset number styles in different languages and regions

Style Formatted string, Formatted string, English (United States) Language (Region)

Decimal 1,234.56 1.234,56 Italian (Italy)

Currency $1,234.56 Chinese (China)

Percent 123,456% Arabic (Egypt)

Scientific 1.23456E+03 1,23456E3 Italian (Italy)

Spell Out one thousand two hundred thirty-four point five six Chinese (China)

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 46 Formatting Data Using the Locale Settings Computing Dates Using Calendars

Video: WWDC 2013 Making Your App World-Ready: Number Formatting

Parsing Localized Number Strings The user may enter numbers using localized formats, so parse these input strings accordingly. Use an NSNumberFormatter object to convert a string to a number object. Set the number formatter’s style using one of the preset styles. Also, allow the number formatter to use heuristics when parsing the string.

To convert a localized number string to a number object

1. Create a number formatter object.

NSNumberFormatter *numberFormatter = [NSNumberFormatter new];

2. Set the formatter’s style to a preset style.

numberFormatter.numberStyle = NSNumberFormatterDecimalStyle;

Replace NSNumberFormatterDecimalStyle with the style you expect the user to enter.

3. Set the leniency to YES (enables the heuristics).

numberFormatter.lenient = YES;

4. Convert the string to a number object.

NSNumber *number = [numberFormatter numberFromString:inputString];

Computing Dates Using Calendars

The NSCalendar class encapsulates all the regional differences and complexities of calendars, shown in Table 4-7. The era changes more frequently in some calendars than others—for example, the era in the Japanese calendar changes with each new emperor. The number of months per year can be 12 or 13. The length of a month can vary from year to year. Even in the Gregorian calendar, the first day of the week can be Saturday, Sunday, or Monday. NSCalendar objects know about time zones and which regions observe daylight savings time. Calendar calculations—such as the third Tuesday of the month—depend on the user’s calendar and region.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 47 Formatting Data Using the Locale Settings Computing Dates Using Calendars

Table 4-7 Variations in regional calendars

Calendar unit Possible values

Year 2011, 1432, 2554, 5771

Era AD, Heisei

Number of months per year 12, 13, variable

Lengths of months From 5 to 31 days

First day of week Saturday, Sunday, Monday

When years change

Therefore, use the NSCalendar class for all calendrical calculations such as computing the number of days in a month, computing delta values, and getting components of a date. You can use an NSDate object for internal calculations but use an NSCalendar object for computations of user-facing dates.

To get the calendar for the user’s locale, use the currentCalendar class method in NSCalendar class:

NSCalendar *currentCalendar = [NSCalendar currentCalendar];

Use an NSDateComponents object to access the calendar units of a date.

To get the components of a date

1. Create an NSDateComponents object.

NSDateComponents *components = [[NSCalendar currentCalendar] components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit | NSEraCalendarUnit fromDate:[NSDate date]];

2. Access the values for day, month, year, and era.

NSInteger day = [components day]; NSInteger month = [components month]; NSInteger year = [components year]; NSInteger era = [components era];

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 48 Formatting Data Using the Locale Settings Registering for Locale and Time Zone Changes

Tip: Any time you fetch or set the year, also fetch or set the era. Era is not required for the Gregorian calendar, but it is for several other calendars.

For more information on using the NSCalendar and NSDateComponents classes, read Date and Time Programming Guide or watch WWDC 2013: Solutions to Common Date and Time Challenges.

Registering for Locale and Time Zone Changes To receive notification of locale changes, add your object as an observer of the NSCurrentLocaleDidChangeNotification notification:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(localeDidChange:) name:NSCurrentLocaleDidChangeNotification object:nil];

To receive notification of time zone changes, observe the NSSystemTimeZoneDidChangeNotification notification. For example, if the user is traveling, the time zone might change while your app is running. A long time may elapse since the last time your app was active.

Implement the change notification method to reformat and display all user-facing dates, times, and numbers using the user’s new locale settings.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 49 Supporting Right-to-Left Languages

Your user interface should be mirrored when displaying right-to-left languages. If you use base internationalization and Auto Layout, most of the user interface will appear mirrored automatically for you. The text direction changes to right-to-left, with the exception of phone numbers and country codes which are always left-to-right. Some views and controls in your user interface may not change direction automatically; when appropriate, you can fix this programmatically.

Creating Right-to-Left User Interfaces Support right-to-left languages by using base internationalization and Auto Layout, as described in Internationalizing the User Interface (page 24). In general, if the development language is left-to-right, align the views starting in the upper-left corner and add constraints that expand views to the bottom-right. When you use the Auto Layout leading and trailing attributes (not the right and left attributes), most of the

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 50 Supporting Right-to-Left Languages Creating Right-to-Left User Interfaces

user interface appears mirrored in right-to-left languages. For Mac apps, most controls—such as segmented controls, progress indicators, and outline views—also appear flipped. In iOS apps, UIKit controls appear flipped when the app links against iOS 9 and later.

Types of controls and content that should not flip in a right-to-left language are:

● Video controls and timeline indicators

● Images, unless they communicate a sense of direction, such as arrows

● Clocks

● Music notes and sheet music

● Graphs (x– and y–axes always appear in the same orientation)

Use base internationalization and if necessary, provide language-specific images and audio files for the right-to-left languages that you support. To localize other resource files, read Adding Additional Resources You Want to Localize (page 70).

Thoroughly test your user interface in a right-to-left language, as described in Testing Right-to-Left Layouts (page 81), and only if necessary, modify your code to support right-to-left languages.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 51 Supporting Right-to-Left Languages Getting the Layout Direction

Getting the Layout Direction

In iOS apps, you get the layout direction of an instance of UIView by calling the userInterfaceLayoutDirectionForSemanticContentAttribute: method. For example:

if ([UIView userInterfaceLayoutDirectionForSemanticContentAttribute:view.semanticContentAttribute] == UIUserInterfaceLayoutDirectionRightToLeft) { … }

In Mac apps, you get the layout direction of an instance of NSView by examining the view’s userInterfaceLayoutDirection property. For example:

if (view.userInterfaceLayoutDirection == NSUserInterfaceLayoutDirectionRightToLeft) { … }

Setting Text Alignment By default, text alignment in iOS is natural; in OS X, it’s left. Using natural text alignment aligns text on the left in a left-to-right language, and automatically mirrors the alignment for right-to-left languages. For example, if you set the alignment of an NSMutableParagraphStyle object using the setAlignment: method, pass NSNaturalTextAlignment as the parameter.

[[(NSMutableParagraphStyle *)paraStyle setAlignment:NSNaturalTextAlignment];

However, if you want to align a control to the right in a left-to-right language (and to the left in a right-to-left language), get the layout direction, as described in Getting the Layout Direction (page 52), and set the alignment to NSLeftTextAlignment for a right-to-left language.

For Mac apps:

if ([NSApp userInterfaceLayoutDirection] == NSUserInterfaceLayoutDirectionRightToLeft) { [[(NSMutableParagraphStyle *)paraStyle setAlignment:NSLeftTextAlignment]; } else {

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 52 Supporting Right-to-Left Languages Handling Bidirectional Text

[[(NSMutableParagraphStyle *)paraStyle setAlignment:NSRightTextAlignment]; }

Handling Bidirectional Text Bidirectional (or "Bidi") text is text that contains segments that run in different directions. Languages such as Arabic and Hebrew are written from right to left, but numbers and Latin text (such as nonlocalized product names) are written from left to right. Use standard views and controls that automatically handle bidirectional text, as described in Displaying Text (page 34). If you create custom controls for text input, you need to handle bidirectional text yourself.

Video: WWDC 2013 Making Your App World-Ready: International Text > Bidirectional Text

Using Natural Writing Direction For text and controls, use natural writing direction that determines the writing direction at runtime by examining the first few characters of text to be displayed.

For iOS apps, use the setBaseWritingDirection:forRange: method in theUITextInput protocol and pass UITextWritingDirectionNatural as the writing direction parameter. For Mac apps, set the base writing direction of a control and other types of objects using the setBaseWritingDirection: method, passing NSWritingDirectionNatural as the parameter.

Although direction and alignment are different settings, it’s common for text in left-to-right languages to be left aligned and for text in right-to-left languages to be right aligned. Read Setting Text Alignment (page 52) for how to set the text alignment for a right-to-left language.

Adding Unicode Markup to Bidirectional Text In a few cases, the default behavior produces incorrect results. To handle these cases, the Unicode Bidirectional Algorithm provides a number of invisible characters that can be used to force the correct behavior.

For example, phone numbers are laid out from left-to-right in all languages. If a localized string contains a variable for a phone number, insert a left-to-right embedding (LRE) character, U+202A, before the variable and a pop directional formatting (PDF) character, U+202C, after the variable.

// Wrap the plus (+) prefix and phone number in left-to-right directional markers NSString *phoneNumber = @"408-555-1212";

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 53 Supporting Right-to-Left Languages Flipping Cocoa Touch Views and Controls Programmatically

NSString *localizedPhoneNumber = [NSString stringWithFormat:@"\u202A%@\u202C", phoneNumber];

Conversely, to always display a variable right-to-left in a left-to-right language, insert a right-to-left embedding (RLE) character, U+202B, before the variable and a pop directional formatting (PDF) character, U+202C, after the variable.

If a variable appears at the beginning of a string, natural direction causes the entire string to use the directionality of the variable. This is incorrect behavior if the variable directionality is unknown—for example, the variable could be an Arabic or English user name. In this case, insert a right-to-left mark (RLM) character, U+200F, before the variable for right-to-left languages, or a left-to-right mark (LRM) character, U+200E, before the variable for strings for left-to-right languages. Use this technique for left-to-right localizations even if you don’t have localizations for right-to-left languages.

Flipping Cocoa Touch Views and Controls Programmatically

Some Cocoa Touch views shouldn’t automatically flip when the language is right-to-left. In iOS 9 and later, you can use the semantic content attributes defined for UIView to specify how some views should appear in a right-to-left context.

For example, if your app displays a slider that represents a video scrubber, you can use the UISemanticContentAttributePlayback value to indicate that this view should not flip in a right-to-left context. To learn more about the attributes you can use, see UISemanticContentAttribute.

Flipping Images in an iOS App To flip image resources for right-to-left languages, you can choose one of the following three options:

● Flip images programmatically for right-to-left languages by calling the UIImage method imageFlippedForRightToLeftLayoutDirection.

● Provide separate, localized resources for the right-to-left languages you support, as described in Adding Additional Resources You Want to Localize (page 70)

● Add alternate, right-to-left image resources to your Xcode project, and in your code, use the alternate image for right-to-left languages

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 54 Supporting Right-to-Left Languages Flipping Cocoa Views and Controls Programmatically

Flipping Cocoa Views and Controls Programmatically Some Cocoa views don’t automatically flip when the language is right-to-left. In your Mac app, you can fix the text alignment in Interface Builder and the order of views programmatically to produce the desired mirrored results. You can also flip the views that don’t mirror in your app.

Flipping Images To flip image resources for right-to-left languages, choose one of three approaches. You can provide separate, localized resources for the right-to-left languages you support, as described in Adding Additional Resources You Want to Localize (page 70). You can add alternate, right-to-left image resources to your Xcode project, and in your code, use the alternate image for right-to-left languages. You can also flip images programmatically for right-to-left languages in the app delegate’s awakeFromNib method.

For example, invoke this flipImage: method to return a mirrored image.

- (NSImage *)flipImage:(NSImage *)image { NSImage *existingImage = image; NSSize existingSize = [existingImage size]; NSSize newSize = NSMakeSize(existingSize.width, existingSize.height); NSImage *flippedImage = [[[NSImage alloc] initWithSize:newSize] autorelease];

[flippedImage lockFocus]; [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];

NSAffineTransform *transform = [NSAffineTransform transform]; [transform translateXBy:existingSize.width yBy:0]; [transform scaleXBy:-1 yBy:1]; [transform concat];

[existingImage drawAtPoint:NSZeroPoint fromRect:NSMakeRect(0, 0, newSize.width, newSize.height) operation:NSCompositeSourceOver fraction:1.0];

[flippedImage unlockFocus];

return flippedImage; }

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 55 Supporting Right-to-Left Languages Flipping Cocoa Views and Controls Programmatically

Flipping Toolbars In a Mac app, toolbars don’t automatically mirror in right-to-left languages. You can fix this programmatically by either reversing the order of toolbar items in the awakeFromNib method or implementing the toolbarDefaultItemIdentifiers: delegate method to return items in reverse order.

For example, add this code fragment to the app delegate’s awakeFromNib method implementation where toolbar is the NSToolbar object you want to flip.

// Flip toolbar items order for RTL support if ([NSApp userInterfaceLayoutDirection] == NSUserInterfaceLayoutDirectionRightToLeft) { NSArray *toolbarItems = [[self.toolbar items] copy];

for (NSToolbarItem *item in toolbarItems) { [self.toolbar removeItemAtIndex:toolbarItems.count-1]; [self.toolbar insertItemWithItemIdentifier:item.itemIdentifier atIndex:0]; } }

If the images on controls communicate direction—for example, left and right arrows—they should be flipped as well.

Flipping a Table View in a Mac App

Note: In iOS, tables have only one column, so you don’t need to worry about mirroring the column order.

Tables don’t automatically mirror when the layout is right-to-left. The order of the columns does not change. The views in view-based tables flip automatically if using Auto Layout and base internationalization but headers and cells in cell-based tables don’t change their text alignment.

Changing Text Alignment For cell-based tables, set the alignment of columns and cells to natural writing direction using Interface Builder.

To set the text alignment of a column and its cell

1. In Interface Builder, select the Table Column in the outline view. 2. If necessary, show the Attributes inspector.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 56 Supporting Right-to-Left Languages Flipping Cocoa Views and Controls Programmatically

3. Select natural from the Alignment control. 4. In the outline view, click the disclosure triangle next to the Table Column and select its Text Field Cell. 5. In the Attributes inspector, select natural (– – –) from the Alignment control.

Alternatively, set the object’s alignment property to NSNaturalTextAlignment programmatically.

Reversing Column Order For Mac apps, add this method to the NSTableView class (using an Objective-C category) that reverses the order of columns in a table.

@implementation NSTableView (RTLSupport) - (void)reverseColumnOrder { if ([[NSApplication sharedApplication] userInterfaceLayoutDirection] != NSUserInterfaceLayoutDirectionRightToLeft) return; unsigned long index = self.tableColumns.count-1; while (index > 0) { [self moveColumn:0 toColumn:index]; index--;

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 57 Supporting Right-to-Left Languages Testing Right-to-Left Locale Formats

} } @end

Testing Right-to-Left Locale Formats You don’t need to change the language to Arabic or Hebrew to test the right-to-left locale formats. Instead, change the language and region in the scheme editor, described in Testing Specific Languages and Regions (page 83). To change the text direction without changing the language or region, read Testing Right-to-Left Layouts (page 81).

To test right-to-left locale formats on an iOS device, you select the region and format language together in Settings, as described in Setting the Region on iOS Devices (page 14). A language submenu appears in the Region pop-up menu for languages that are used in multiple regions. To test the locale of an Arabic speaking country, choose the country from the Arabic submenu. To test the locale format in Hebrew, choose Hebrew (Israel) from the Region pop-up menu.

To test right-to-left locale formats on a Mac, you select the region and format language separately in System Preferences. If you want to test the locale formats in Arabic, set the Region setting to a locale that uses Arabic and change the format language to Arabic. Similarly, to test locale formats in Hebrew, set the Region setting to Israel and the format language to Hebrew. Alternatively, you can set the region and then set the preferred language to either Arabic or Hebrew.

To test the locale format in a right-to-left language on Mac

1. In System Preferences, click Language & Region. 2. Choose a region that uses the language from the Region pop-up menu. The calendar setting automatically changes to match the region.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 58 Supporting Right-to-Left Languages Testing Right-to-Left Locale Formats

3. Click Advanced.

4. In the General pane, choose the right-to-left language from the “Format language” pop-up menu.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 59 Localizing Your App

When you are done internationalizing the app’s user interface and code, begin the localization process. Export all the development language strings files that contain user-facing text to a standard XML Localization Interchange File Format (XLIFF). Submit the XLIFF file to a localization team for translation into multiple languages. Continue developing your app while waiting for the translations. Import the XLIFF translations into the project and test the app in each language you added. Repeat the process as needed, translating just the changes between each app revision. As necessary, perform additional localization steps yourself.

Choosing Languages You can choose from more than 100 different languages and dialects designated by regions to localize your app. However, the more general you make your localized resources, the more regions you can support with a single set of resources. This can save a lot of in your app bundle and help reduce localization costs. For example, if you don’t need to distinguish between different regions that use the English language, you can

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 60 Localizing Your App Locking Views

add English to support users in the United States, United Kingdom, and Australia. Even if you provide region-specific resources always provide a complete set of language-specific resources for all the languages you support.

When searching for resources, the bundle APIs try to find the best match between the languages the app supports and the user’s language and region settings. The region-specific resource folders are searched before the language-specific resource folders. For example, if you add English (United States), English (United Kingdom), and English (Australia) to your project, the bundle APIs search the appropriate region-specific folders first, followed by the English language folder. For more information about how the bundle APIs find localized resources, read The Bundle Search Pattern in Bundle Programming Guide.

If you are unsure about what languages to add, consider the primary languages used in the App Store territories you choose in iTunes Connect to market your app. The App Store territories are listed in App Store Territories in iTunes Connect Developer Guide.

Locking Views In Interface Builder, lock views you don’t want to accidentally change while waiting for translations. When a view is locked, you can’t change some or all of its properties in the inspector or the project editor. You specify the set of properties to lock by choosing a locking level (see Table 6-1).

Table 6-1 Locking levels

Locking level Description

Nothing You can edit all properties of the view.

All properties You can’t edit any properties of the view.

Localizable properties You can’t change any user-visible strings and can’t change a limited set of other attributes, such as the view’s size. You can make other changes; for example, you can change the enabled state of a control or cell.

Non-localizable properties You can change user-visible strings and attributes—such as the size of the view—but can’t change any other attributes of the view.

You can set the lock attribute for a single view or the entire nib file. By default, views inherit their lock attribute from their parent view and top-level views inherit their lock attribute from the .storyboard or .xib file. If you set a view’s lock attribute, it sets the lock attribute for all its descendant views.

To change the locking level of a view

1. In Interface Builder, select the view you want to lock.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 61 Localizing Your App Exporting Localizations

2. In the Identity inspector (under the Document section), choose a locking level from the Lock pop-up menu. Refer to Table 6-1 (page 61) for a description of the locking choices in this menu. To obtain the lock value from its parent view, choose Inherited.

For example, choose Localizable Properties to continue developing your app while waiting for a nib or strings file to be localized. Choose Non-localizable Properties if you are incorporating translations into a nib file and don’t want to make other changes inadvertently.

To change the locking level of the nib file

1. In project navigator, select a .storyboard or .xib file. 2. Choose a locking level from the Editor > Localization Locking menu. Refer to Table 6-1 (page 61) for a description of the locking choices in this menu. To unlock all the views in the file, choose Reset Locking Controls.

For example, to prevent any edits to the nib file that would impact localized strings files, choose Reset Locking Controls followed by Localizable Properties.

Exporting Localizations Export the development language resources to an XLIFF file and submit it to a localization team for translation into multiple languages.

The first time you export localizations, only the base internationalization—the .storyboard and .xib resource files—exist in the project folder. Xcode generates the strings files from your project files and includes them in the exported .xliff file. Xcode doesn’t add the strings files to the project until you import localizations later. The exported [Language ID].xliff file encodes the strings files in the standard XML Localization Interchange File Format (XLIFF). (Most third-party localization tools support this XLIFF file format.) For example, if the development language is English, the en.xliff file contains base internationalization strings files (one for each .storyboard and .xib file), a Localizable.strings file, and an InfoPlist.strings file. The source text in the strings files is in English.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 62 Localizing Your App Exporting Localizations

Translators should return a separate .xliff file for each language. The files should use the language ID as the prefix. For example, if you request en.xliff for English be translated into German and Russian, the returned files should be named de.xliff for German and ru.xliff for Russian. The individual .xliff files contain the actual translations.

The first step to localize your app is to export the development language or base localization for translation. Before doing this, verify that the development language copyright notice in the Info.plist file is correct. Xcode includes the human-readable copyright notice in the XLIFF file. For a complete list of the localizable Info.plist keys, read Locking Views (page 61).

To export the development language translation

1. In the Xcode project editor, select the project or target. 2. Choose Editor > Export For Localization. 3. In the sheet that appears, enter a location in the Save As field and click Save.

Xcode saves the file to the location you specified with a .xliff extension. Xcode creates the folder (if it doesn’t exist) and places a file named [Language ID].xliff in the folder where Language ID is the identifier for the development language. For example, if the development language is English, the filename is en.xliff.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 63 Localizing Your App Exporting Localizations

If you never added a language to your project, the export dialog appears similar to this screenshot:

The next time you export localizations, optionally export the development language resources, specific language resources, or all language resources.

To export multiple localizations for translation

1. In the Xcode project editor, select the project or target. 2. Choose Editor > Export For Localization. 3. In the sheet that appears, enter a location in the Save As field.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 64 Localizing Your App Importing Localizations

If you added a language to your project, the export dialog appears similar to this screenshot:

4. From the Include pop-up menu, choose Existing Translations or Development Language Only. To export all or specific language resources, choose Existing Translations and then deselect the languages that you don’t want to include in the export in the Languages section below. To export the development language resources, choose Development Language Only. 5. Click Save.

For each language you select, Xcode saves an XLIFF file (a file with a language ID prefix and .xliff extension) to the location you specified in the Save As field. For example, if you select German and French from the language list, Xcode adds a de.xliff and fr.xliff file to the folder.

Importing Localizations When you import localizations, Xcode adds the language and a set of localized strings files for the language to the project. For example, if you import ru.xliff in the standard XML Localization Interchange File Format (XLIFF) that includes the target language attribute, the Russian language is added to the project. The first time you import localizations, the base internationalization files change to a group containing the strings files in the project navigator. Xcode stores the language-specific strings files in language folders. For example, Xcode creates a ru.lproj folder in the project folder and adds a localized copy of the Localizable.strings and

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 65 Localizing Your App Importing Localizations

InfoPlist.strings files to the ru.lproj folder. The localized strings files are extracted from the corresponding [Language ID].xliff file. The next time you import localizations, the strings files are merged with your existing project files.

To import localizations from translators

1. In the Xcode project editor, select the project or target. 2. Choose Editor > Import Localizations.

3. In the sheet that appears, select a file with a .xliff extension and click Open.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 66 Localizing Your App Importing Localizations

A sheet appears showing the differences between the imported XLIFF file and the existing resources in the project folder.

4. Click Import. Xcode decodes the localized strings files from the XLIFF file and adds them to the project folder. Xcode replaces existing strings files.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 67 Localizing Your App Importing Localizations

Verifying Your Steps After you import localizations, Xcode updates the project navigator to show the new language-specific resources. Localized .storyboard and .xib files now appear as groups in the project navigator. Click the disclosure triangle next to a .storyboard or .xib file to reveal the base resource and language-specific strings files.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 68 Localizing Your App Exporting Localizations Using Command-Line Utilities

Select a strings file to view and optionally, edit the contents. The strings file contains key-value pairs that Xcode automatically generates from the text it finds in the corresponding .storyboard or .xib file. If you use NSLocalizedString macros in your code, as described in Separating User-Facing Text from Your Code (page 30), a Localizable.strings group also appears in the project navigator.

Another kind of strings file is InfoPlist.strings, which you use for localizing app properties that are visible to users (such as the app’s name). For the keys you can localize in an InfoPlist.strings file, read Locking Views (page 61).

Exporting Localizations Using Command-Line Utilities

Alternatively, you can use the xcodebuild command-line utility to export localizations.

To export localizations, enter this command in Terminal, replacing the and arguments:

xcodebuild -exportLocalizations -localizationPath -project [[-exportLanguage ]]

The exported XLIFF files are placed in . Optionally, use the exportLanguage argument to export other localizations.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 69 Localizing Your App Adding Additional Resources You Want to Localize

Adding Additional Resources You Want to Localize You can explicitly add language-specific resource files to your project. For example, you may want to use different sets of image and audio files for different languages and dialects because of cultural differences. At runtime, the app searches the language-specific folder before the base folder to find a resource file, so you can add a resource to the Base.lproj folder and then specific language folders as needed.

Note: If the language doesn’t appear in the Localizations section in the Info pane of your project, add the language before following these steps, as described in Using Base Internationalization (page 24).

To localize a resource

1. In the project navigator, select a resource you want to localize. 2. If necessary, open the File inspector. 3. In the Localization section, click the Localize button.

4. In the dialog that appears, choose a language from the pop-up menu and click the Localize button.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 70 Localizing Your App Handling Noun Plurals and Units of Measurement

For example, choose Base if you want to use the resource file for all languages.

After localizing a resource, you can add it to additional languages using the File inspector.

To add localizations to a resource

1. In the project navigator with the File inspector open, select the resource. 2. In the Localization section, choose the additional languages you want to add. Xcode duplicates the file in the corresponding language folder and it appears in the project navigator.

Handling Noun Plurals and Units of Measurement If a string contains a noun plural or units of measurement, provide alternate strings for languages that have different plural rules. To specify language plural rules that can’t be represented by key-value pairs in a strings file, use a .stringsdict file, an XML property list with a .stringsdict file extension. Languages vary in how they handle plurals of nouns or units of measurement. Some languages have a single form, some have

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 71 Localizing Your App Handling Noun Plurals and Units of Measurement

two categories, and others have three or more categories to represent quantities. If you display a formatted string containing a variable quantity, you can use one string in your code that is localized using plural rules specified in a .stringsdict file.

Similar to how you retrieve localized text from strings files, use NSLocalizedString macros in your code to retrieve the format string for different plural forms from a .stringsdict file. Next, provide a localized .stringsdict file for all the supported languages that have different plural rules. The NSLocalizedString macros search an existing .stringsdict file before the associated strings file that has the same filename prefix. For example, the macros search the Localizable.stringsdict file for the %d file(s) remaining key first. If it is not found, the macros search the Localizable.strings file for the key. Therefore, only add .stringsdict files for languages that have different plural rules.

To create language plural rules

1. In your code, use a NSLocalizedString macro, passing a formatted string to retrieve a plural phrase. For example, to display a variable number of files as text:

localizedString = [NSString localizedStringWithFormat:NSLocalizedString(@"%d file(s) remaining", @"Message shown for remaining files"), count];

Pass a format string as the key parameter to the NSLocalizedString macro.

2. To create the Localizable.strings file for each language, export and import localizations, as described in Exporting Localizations (page 62) and Importing Localizations (page 65).

Xcode generates a Localizable.strings file from the NSLocalizedString macros in your code. For example, this key-value pair appears in the development language Localizable.strings from the previous code fragment:

/* Message shown for remaining files */ "%d file(s) remaining" = "%d file(s) remaining";

Alternatively, you can create the development language Localizable.strings file yourself, as described in Creating Strings Files for User-Facing Text in Your Code (page 86).

3. Create a .stringsdict property list file and localize it for each language that has different plural rules. Add a property list file to the project (choose File > New > File and select Property List from the sheet). In the project navigator, change the filename to Localizable.stringsdict and localize it in selected languages, as described in Adding Additional Resources You Want to Localize (page 70).

4. Add the language-specific plural rules to each .stringsdict file.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 72 Localizing Your App Handling Noun Plurals and Units of Measurement

The .stringsdict file contains a collection of plural rules for each phrase. The top-level key is the same key you pass to an NSLocalizedString macro in your code. The value for this key is a dictionary that specifies the plural rule details. The dictionary contains the text to use for each number category. The types of categories and meaning vary depending on the language.

For example, the English .stringsdict file for the %d file(s) remaining key is:

%d file(s) remaining NSStringLocalizedFormatKey %#@files@ files NSStringFormatSpecTypeKey NSStringPluralRuleType NSStringFormatValueTypeKey d one %d file remaining other %d files remaining

In English, the one category is used for the number 1, and the other category is used for all other numbers in English.

The Russian .stringsdict file for the %d file(s) remaining key is:

%d file(s) remaining

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 73 Localizing Your App Handling Noun Plurals and Units of Measurement

NSStringLocalizedFormatKey %#@files@ files NSStringFormatSpecTypeKey NSStringPluralRuleType NSStringFormatValueTypeKey d one Остался %d файл many Осталось %d файлов other Осталось %d файла

5. Test the plural rules in multiple languages. Follow the steps in Testing Specific Languages and Regions (page 83) to run the app in Xcode using different language settings.

For example, the above English plural rules for the %d file(s) remaining key should result in the following localized strings:

Category Example numbers Localized string

one 1 1 file remaining

other 0, 2, 3, … 2 files remaining 3 files remaining For Russian, there are three possible categories with different formats:

Category Example numbers Localized string

one 1, 21, 31, 41, 51, 61, … Остался 1 файл Остался 21 файл

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 74 Localizing Your App Localizing the Information Property List Files

Category Example numbers Localized string

many 0, 5–20, 25–30, 35–40, … Осталось 0 файлов Осталось 20 файлов

other 2–4, 22–24, 32–34, … Осталось 2 файла Осталось 22 файла

For a complete description of the .stringsdict file properties, read Stringsdict File Format (page 97). For the plural categories and rules for each language, see CLDR Language Plural Rules.

Video: WWDC 2013 Making Your App World-Ready: Localization > Using stringsdict

Localizing the Information Property List Files

When you export localizations, Xcode includes an InfoPlist.strings file for translation. However, this file contains properties about your app and company, so you may want to verify or translate this file yourself. This strings file allows you to optionally localize some property values in the information property list, such as the app name (bundle display name) and copyright notice.

Xcode automatically adds these keys to the InfoPlist.strings file:

● CFBundleDisplayName

● CFBundleName

● CFBundleShortVersionString

● NSHumanReadableCopyright

For a complete description of the information property list, read Information Property List Key Reference.

Localizing the App Name and Copyright Notice To localize the app name and copyright notice, add values for the CFBundleDisplayName and NSHumanReadableCopyright keys to the InfoPlist.strings file. For example, add these lines to the InfoPlist.strings (French) file in the project navigator:

CFBundleDisplayName = "Maisons"; NSHumanReadableCopyright = "Copyright © 2014 My Great Company Tous droits réservés.";

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 75 Localizing Your App Adding Languages

Getting the Localized App Name If you localize the app name, use it in menu items and elsewhere in the user interface. You can get the localized app name programmatically with the CFBundleDisplayName key:

NSString *appName = [[[NSBundle mainBundle] localizedInfoDictionary] objectForKey:@"CFBundleDisplayName"];

For Mac apps, the user can rename the app in the Finder, so use the NSFileManager class to get the app name:

NSString *bundlePath = [[NSBundle mainBundle] bundlePath]; NSString *appName = [[NSFileManager defaultManager] displayNameAtPath:bundlePath];

Adding Languages Add languages to your project if you want to add language-specific resources, as described in Adding Additional Resources You Want to Localize (page 70), before importing localizations. (Xcode automatically adds languages to your project when importing localizations.) For example, add language-specific image and audio files to your project or test language-specific plural rules before you begin localizing all the strings files.

When Xcode adds a language to your project, it creates a separate language folder to store the language-specific resources. Xcode adds a strings file for each .storyboard and .xib file in the Base.lproj folder to the language folder. The strings file has the same name as the .storyboard or .xib file but with the strings extension. For example, if you have a storyboard named MyStoryboard.storyboard, the generated strings file is named MyStoryboard.strings.

To add a language to a project

1. In the project navigator, select the project (not a target) and click Info.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 76 Localizing Your App Adding Languages

2. In the Localizations section, click the Add button (+) under the Language column and choose the language you want to add from the pop-up menu.

The menu items contain the language name followed by the language ID in parentheses, as in German (de), Japanese (ja), and Arabic (ar). Menu items for scripts or dialects contain the region in parentheses, as in German (Switzerland). The language ID for scripts or dialects uses subtags, as in pt-PT where pt is the code for Portuguese and PT is the code for Portugal. For example, use pt as the language ID for Portuguese as it is used in Brazil and pt-PT as the language ID for Portuguese as it is used in Portugal. The Other submenu (at the bottom of the list) contains more languages and dialects.

These same language IDs are used in the names of the corresponding .lproj language folders, described in Choosing Languages (page 60). 3. In the dialog that appears, deselect the resource files you don’t want to localize for this language.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 77 Localizing Your App Adding Languages

For the file type Localizable Strings, Xcode creates a strings file for that resource. If you prefer to maintain a separate .storyboard or .xib file for the language, choose the type of resource file from the File Types pop-up menu instead—for example, choose Interface Builder Cocoa Touch Storyboard for a Mac storyboard file.

4. Click the Finish button.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 78 Testing Your Internationalized App

Test your internationalized app during different stages of development, even before localizing your app. Preview your app in Interface Builder to detect Auto Layout problems and non-localized strings, similarly run your app using pseudolanguages, simulate right-to-left languages, and test specific languages and regions. After importing localizations, test your app in all the languages you support.

Previewing Localizations in Interface Builder In Interface Builder, you can preview localizations of the user interface without running your app. Preview pseudolocalizations before localizing your app to detect Auto Layout problems. Later, preview localizations you import to detect if strings files are out of sync with .storyboard or .xib files. Before you import localizations, as described in Importing Localizations (page 65), only pseudolocalizations are available for preview unless you explicitly added a language to the project.

To preview a localization in Interface Builder

1. In project navigator, select the .storyboard or .xib file you want to preview. 2. Choose View > Assistant Editor > Show Assistant Editor. 3. In the assistant editor jump bar, open the Assistant pop-up menu, scroll to and choose the Preview item, and choose the .storyboard or .xib file from the submenu. If a preview of the app’s user interface doesn’t appear in the assistant editor, select the window or view you want to preview in the icon or outline view.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 79 Testing Your Internationalized App Testing Using Pseudolanguages

4. In the assistant editor, choose the localization you want to preview from the language pop-up menu in the lower-right corner. A preview of the localization appears in the assistant editor. If you choose a real language, strings that do not need to be localized or need to be localized, but currently are not, appear in uppercase.

If you detect that the strings files are out of sync with the base internationalization files (perhaps you made changes to the user interface after importing localizations), export and import localizations again, as described in Localizing Your App (page 60). You only need to translate the text that changed since the last time you imported localizations. (Alternatively, read Updating Storyboard and Xib Strings Files Using ibtool for how to update strings files after you make changes to the base internationalization .storyboard and .xib files.)

When previewing iOS apps, you can also change the iOS version, orientation, and form factor, as described in Previewing Your Layout for Different Devices and Localizations.

Testing Using Pseudolanguages Before you localize your app, make sure views reposition and resize appropriately for international text using pseudolocalizations. To test whether your user interface is flexible enough to adapt to different language fonts and string lengths, edit the scheme to use a pseudolocalization.

To test using pseudolanguages

1. Click the target in the Run destination menu and choose Edit Scheme. 2. On the right, select Options. 3. Choose a pseudolocalization from the Application Language pop-up menu.

● To test Auto Layout, choose Double Length Pseudolanguage. All the localized strings appear duplicated, changing the size and position of the views.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 80 Testing Your Internationalized App Testing Right-to-Left Layouts

● To test right-to-left writing direction, choose “Right to Left Pseudolanguage.”

4. Click the Close button. 5. Click Run to launch your app in the pseudolanguage you specified in your scheme.

Alternative, to double the length of all the localized strings, add the NSDoubleLocalizedStrings launch argument in the Arguments pane of the scheme editor or set the equivalent user default. For how to set the right-to-left language launch arguments, read Testing Right-to-Left Layouts.

Testing Right-to-Left Layouts You can test the layout of your app for right-to-left languages without adding a right-to-left language to your project. Follow the steps in Testing Using Pseudolanguages (page 80) and choose “Right to Left Pseudolanguage” from the Application Language pop-up menu. If you want to test the localization of a right-to-left language, choose the right-to-left language from the Application Language pop-up menu instead. If the user interface doesn’t appear mirrored, read Supporting Right-to-Left Languages (page 50) to fix the problem.

Alternatively, to test right-to-left layouts, add launch arguments or set the equivalent user defaults. For iOS apps, enter this line in the Arguments pane of the scheme editor:

-AppleTextDirection YES

For Mac apps, enter both these launch arguments:

-NSForceRightToLeftWritingDirection YES

-AppleTextDirection YES

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 81 Testing Your Internationalized App Detecting Non-localized Strings (OS X v10.10 and later)

Detecting Non-localized Strings (OS X v10.10 and later) If you use strings files to separate user-facing text, you can run your app using an option that detects strings in the user interface that are not localized. The non-localized strings appear in uppercase when you run your app. Use this feature to identify problems with out-of-date localizations.

To detect non-localized strings

1. Click the target in the Run destination menu and choose Edit Scheme. 2. On the right, select Options. 3. Select the “Show non-localized strings” checkbox.

4. Click the Close button. 5. Click Run to launch your app in this mode.

Alternatively, add the NSShowNonLocalizedStrings launch argument. To identify stings that are not localizable, add the NSShowNonLocalizableStrings launch argument in the Arguments pane of the scheme editor or set the equivalent user default.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 82 Testing Your Internationalized App Testing Specific Languages and Regions

Testing Specific Languages and Regions You can test specific languages that you have localizations for and regions by selecting options in the scheme editor before launching your app.

As soon as possible, test your app in at least one language other than the development language. (Read Exporting Localizations (page 62) and Importing Localizations (page 65) for how to localize your app.) If you are testing a right-to-left language—such as Arabic or Hebrew—read Testing Right-to-Left Layouts (page 81) for additional launch arguments. Remember that data won’t use regional formats unless you also change the region setting.

As soon as you write code that adheres to locale settings, as described in Formatting Data Using the Locale Settings (page 37), test your app using a region that changes the data formats.

To launch your app in a specific language and region

1. Click the target in the Run destination menu and choose Edit Scheme. 2. On the right, select Options. 3. Optionally, choose a language from the Application Language pop-up menu.

4. Optionally, choose a region from the Application Region pop-up menu. 5. Click the Close button. 6. Click Run to launch your app in the language and region you specified.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 83 Testing Your Internationalized App Testing Supported Languages and Regions on Devices

Alternatively, add AppleLanguages and AppleLocale launch arguments using the scheme editor—for example, add -AppleLanguages "(de)" to specify the German language and -AppleLocale "fr_FR" to specify the France region.

Testing Supported Languages and Regions on Devices For the most accurate test of an iOS app, run your app in Simulator or on a device and change the user’s language and region settings, as described in Setting the Language on iOS Devices (page 12) and Setting the Region on iOS Devices (page 14).

For Mac apps, you can test locale changes by simply changing your region settings on your Mac, as described in Setting the Region on Your Mac (page 19) or by using the locale launch argument, as described in Testing Specific Languages and Regions (page 83). However, to test the user’s language settings, export your app and launch it from another system account. Some system services will not be in the new language until you log out and log in again. To change the language settings on your Mac, read Setting the Language on Your Mac (page 17).

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 84 Managing Strings Files Yourself

Follow the steps in this appendix if you want to generate and translate strings files stored in the project folder yourself. In this case, you add the languages you want to support, generate the strings files, and localize the strings files using AppleGlot glossaries or some other process. You are responsible for updating the strings files when you change the user interface or add user-facing text to your code.

If you want to manage your own strings files, first add the languages you want to support to your project, as described in Using Base Internationalization (page 24).

Important: Alternatively, Xcode will automatically generate the strings files and add them to your project if you export localizations, edit the XLIFF files (which contain the strings files), and import them, as described in Localizing Your App (page 60).

Viewing Language Folders in the Finder After importing localizations or adding languages, you can view the different language folders in the Finder. Localized resources, which appear in groups in the project navigator, reside in separate language folders in the project folder. Xcode manages these folders for you when you export and import localizations. To view the language folders in the Finder, Control-click the project in the project navigator and choose “Show in Finder” from the shortcut menu.

The project folder should contain one folder named Base.lproj and other language-specific folders with the .lproj extension. The prefix for the language folders is the language ID, as described in Language and Locale IDs (page 92).

The Base.lproj folder contains all the .storyboard or .xib files in the development language. The folders for languages that you add to your project contain a strings file for each .storyboard or .xib file in your project. The development language folder doesn’t contain strings files for the .storyboard and .xib files because they don’t require translation in the development language. All the language folders contain a InfoPlist.strings file used to localize bundle properties, such as the app name. Any other localized resources—such as strings files that you generate and use from your code—appear in these language folders.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 85 Managing Strings Files Yourself Creating Strings Files for User-Facing Text in Your Code

For example, for a universal iOS app that uses English as the development language, the Base.lproj folder contains Main_iPad.storyboard and Main.iPhone.storyboard, and the en.lproj folder contains InfoPlist.strings. If you add the German language, Xcode creates a de.lproj folder containing a InfoPlist.strings, Main_iPad.strings, and Main_iPhone.strings file. The files in the de.lproj folder contain placeholder text that needs to be translated to German.

For a Mac app that uses English as the development language, the file structure may be similar to:

Creating Strings Files for User-Facing Text in Your Code

After you replace strings containing user-facing text with the NSLocalizedString macros, as described in Separating User-Facing Text from Your Code (page 30), you can create and localize the corresponding strings files.

To create a strings file for user-facing text

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 86 Managing Strings Files Yourself Creating Strings Files for User-Facing Text in Your Code

1. Use the genstrings script to create the development language version of the Localizable.strings file. In Terminal, run these commands: cd [Project folder]

find . -name \*.m | xargs genstrings -o .

For each occurrence of an NSLocalizedString macro in the source files, the script adds the comment followed by the key-value pair (using placeholder text for the value) to the Localizable.strings file, as in:

/* distance for a marathon */ "RunningDistance" = "RunningDistance";

If you use the NSLocalizedString macro in your code, the value for the key defaults to the key. If you want different behavior, use one of the other NSLocalizedString macros that take more parameters, described in Foundation Functions Reference.

2. Add the Localizable.strings file to all the language folders. Add the file to your Xcode project, as described in Adding Languages (page 76). Don’t add Localizable.strings to the Base localization when the dialog appears.

Note: If Xcode warns you that the Localizable.strings file appears to be Unicode (UtF-16), you can convert it to Unicode (UTF-8) using the File inspector. To convert a file to UTF-8, select the file in the project navigator and open the File inspector. In the Text Settings section, choose Unicode (UTF-8) from the Text Encoding pop-up menu. In the dialog that appears, click Convert.

3. Localize the Localizable.strings file in each language folder.

For example, in the en.lproj/Localizable.strings file, enter the English translation for the RunningDistance key:

/* distance for a marathon */ "RunningDistance" = "26.22 miles";

In the ja.lproj/Localizable.strings file, enter the Japanese translation for the RunningDistance key:

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 87 Managing Strings Files Yourself Localizing Strings Files

/* distance for a marathon */ "RunningDistance" = "42.20 ";

4. Test your app in multiple languages, as described in Testing Your Internationalized App (page 79). Incrementally test your app when making these types of changes to your code. Localize one set of language files or use pseudolocalization techniques, described in Testing Using Pseudolanguages (page 80).

Localizing Strings Files

When you add a language to your project, Xcode adds all the user-facing text it finds in the .storyboard or .xib file to the corresponding strings file. Xcode inserts a comment before each key-value pair that identifies the view that displays the text. For example, in this fragment of a strings file, the column header Location and the text field labels Address: and for: require translation.

/* Class = "NSTableColumn"; headerCell.title = "Location"; ObjectID = "f0Y-kT-hVz"; */ "f0Y-kT-hVz.headerCell.title" = "Location";

/* Class = "NSTextFieldCell"; title = "Address:"; ObjectID = "gfa-oA-9cr"; */ "gfa-oA-9cr.title" = "Address:";

/* Class = "NSTextFieldCell"; title = "for:"; ObjectID = "gsV-Sg-yiA"; */ "gsV-Sg-yiA.title" = "for:";

The genstrings script also searches your code for user-facing text and adds it to a strings file, as described in Separating User-Facing Text from Your Code (page 30). The file format is the same except your code provides the comment for translators. To localize a strings file, instruct translators to replace the placeholder text—that appears to the right of the equal sign below the comment—with localized text.

Localizing Strings Files Using AppleGlot Alternatively, use AppleGlot to perform some of the initial translations of strings files. For example, use AppleGlot to localize the text for views that Xcode added to your user interface based on the template you chose when creating the project. Then you can focus on localizing only the app-specific text that you added to the user interface.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 88 Managing Strings Files Yourself Localizing Strings Files Using AppleGlot

AppleGlot is a localization tool for iOS and Mac app developers. AppleGlot provides iOS and Mac language glossaries to assist you in translating common text strings. It can also export user-facing text into standard formats that localizers can easily translate into multiple languages. AppleGlot supports incremental development so that you only need to translate the changes to user text with each release.

To download AppleGlot and the language glossaries, go to Build Apps for the World. Under Programming Resources > Downloads, click “AppleGlot and Localization Glossaries.” If necessary, enter your Apple ID and click Sign In. Download the .dmg files for AppleGlot and the languages you support. To install AppleGlot, open the AppleGlot.dmg file and double-click AppleGlot.pkg.

Before you localize your files, you can translate all the common text strings using AppleGlot language glossaries.

To translate your .storyboard and .xib strings files using AppleGlot glossaries

1. In Terminal, create an AppleGlot environment. mkdir [MyAppleGlotEnvironment]

cd [MyAppleGlotEnvironment]

appleglot -w create .

2. Set the source and target languages. appleglot -w setlangs [base_language_id] [target_langauge_id]

For example, if the development language is English and the target is Russian, pass en for the base_language_id and ru for target_langauge_id.

3. In the Finder, paste the language resource folders into the AppleGlot environment _NewBase folder.

If you use base internationalization, paste the language-specific folder, [target_language_id].lproj, into the _NewBase folder, and change the name of the folder to [base_language_id].lproj. For example, paste ru.lproj into _NewBase, and change the name to en.lproj.

Otherwise, if you don’t use base internationalization, the [base_language_id].lproj folder should contain all the strings files that you want translated into the target language.

4. Open the target language glossary .dmg, and copy the glossaries (files with the .lg extension) into the _LanguageGlossaries folder.

5. In Terminal, populate the _NewLoc folder. appleglot -w populate

This creates a .ad file in the _ApplicationDictionaries folder with previously translated strings and a .wg file in the _WorkGlossary folder that contains all the strings in your project with as much of the translations from your Language Glossaries as possible.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 89 Managing Strings Files Yourself Updating Storyboard and Xib Strings Files Using ibtool

6. Optionally, localize the remaining strings in the files with the ad and wg extensions using a third-party localization tool that supports these file formats. 7. In Terminal, integrate the translations back into your strings files. appleglot -w update

appleglot -w finalize

8. In the Finder, paste the localized resources into your Xcode project folder.

Paste the contents of the _NewLoc/[base_language_id].lproj folder into your [target_language_id].lproj folder in the Xcode project folder. For example, paste the contents of the _NewLoc/en.lproj folder into the ru.lproj folder if the target language is Russian. 9. To test the localization, launch your app using the target language, as described in Testing Specific Languages and Regions (page 83). For Mac apps, the main menu items from an Xcode template appear translated except occurrences of the app name.

For more information on AppleGlot, read the AppleGlot 4 User’s Guide located in the AppleGlot.dmg file.

Updating Storyboard and Xib Strings Files Using ibtool

When you change user-facing text in .storyboard or .xib files, use the ibtool command to generate new strings files. Use another tool—for example, FileMerge—to identify the changes and merge them into the existing strings files for each language you support. Xcode doesn’t automatically update the corresponding strings files when you edit a .storyboard or .xib file.

In Terminal, change to the Base.lproj folder, and run this command to generate a strings file for an xib file:

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 90 Managing Strings Files Yourself Creating a Pseudolocalization

ibtool [MyNib].xib --generate-strings-file [MyNib_new.strings]

Optionally, localize the changes in the output file before merging the changes with the [MyNib].strings file in each lproj folder. To launch FileMerge from Xcode, choose Xcode > Open Developer Tool > FileMerge.

Alternatively, you can use the ibtool command to merge translations back into a nib file and perform other incremental localization updates, as described in the ibtool man page. Or use the appleglot command to manage changes to the strings files, as described in Importing Localizations (page 65).

Creating a Pseudolocalization If the pseudolocalization options, described in Testing Your Internationalized App (page 79), are not sufficient to test your app, create your own pseudolocaliation. Add a language to your project, as described in Using Base Internationalization (page 24). Edit the strings files in the language folder by replacing the placeholder text with pseudotext. Set the language launch argument, as described in Testing Specific Languages and Regions (page 83), and run your app.

For example, edit the placeholder text in a strings file by adding characteristics of world languages but keeping the original text readable, as in:

/* distance for a marathon */ "RunningDistance" = "[ŔûüñńîńɠƊïšṱáäńçêè]";

One technique is to add a prefix and suffix to each string. Then you can easily identify where these prefixes and suffixes do not appear when testing your app. Use multibyte characters for prefixes to verify whether your app supports such characters.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 91 Language and Locale IDs

Language IDs identify a language, dialect, or script and are used to name language-specific resource folders stored in the app bundle. Locale IDs identify a set of regional conventions and are used in APIs—such as the NSLocale, NSDateFormatter, NSNumberFormatter, and NSCalendar classes—where region information is needed to format data. OS X and iOS use standard language ID and locale ID formats that consist of language and region designators. For example, using a language combined with a region designator, a language ID can distinguish between different languages and regional dialects.

Language Designators A language designator is a code that represents a language. Use the two-letter ISO 639-1 standard (preferred) or the three-letter ISO 639-2 standard. If an ISO 639-1 code is not available for a particular language, use the ISO 639-2 code instead. For example, there is no ISO 639-1 code for the Hawaiian language, so use the ISO 639-2 code. Table B-1 lists language designators for a subset of languages.

Table B-1 Language designator examples

Language ISO 639-1 Code ISO 639-2 Code

English en eng

French fr fre

German de ger

Japanese ja jpn

Hawaiian no designator haw

For a complete list of ISO 639-1 and ISO 639-2 codes, see ISO 639.2 Codes for the Representation of Names and Languages.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 92 Language and Locale IDs Region Designators

Region Designators A region designator is a code that represents a country. Use the ISO 3166-1 standard, a two-letter, capitalized code shown in Table B-2.

Table B-2 Regional designator examples

Region ISO 3166-1 Code

United States US

United Kingdom GB

Australian AU

France FR

Canadian CA

For a complete list of ISO 3166-1 codes, see ISO 3166-1 Decoding Table.

Language IDs A language ID identifies a language used in many regions, a dialect used in a specific region, or a script used in multiple regions. To specify a language used in many regions, use a language designator by itself. To specify a specific dialect, use a hyphen to combine a language designator with a region designator. To specify a script, combine a language designator with a script designator. For example, to specify common English, use the en language designator as the language ID. To specify the English language as it is used in the United Kingdom, use en-GB as the language ID.

Table B-3 shows the supported language ID syntax and examples of common languages and dialects.

Table B-3 Language ID syntax and examples

Language ID syntax Examples Description

[language designator] en for English Specifies a language only. fr for French de for German

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 93 Language and Locale IDs Language IDs

Language ID syntax Examples Description

[language en-AU for English as used in Australia Specifies a dialect of a language. designator]-[region en-GB for English as used in United designator] Kingdom fr-FR for French as used in France fr-CA for French as used in Canada de-AT for German as used in Austria de-CH for German as used in Switzerland

[language See Table B-4. Specifies a script of a designator]-[script language. designator]

For the script designator, use the ISO 15924 standard, four letters with the first letter uppercase and the last three lowercase, as shown in Table B-4.

Table B-4 Script language ID examples

Script language ID Description

az-Arab Azerbaijani in the .

az-Cyrl Azerbaijani in the Cyrillic script.

az-Latn Azerbaijani in the Latin script.

sr-Cyrl Serbian in the Cyrillic script.

sr-Latn Serbian in the Latin script.

uz-Cyrl Uzbek in the Cyrillic script.

uz-Latn Uzbek in the Latin script.

zh-Hans Chinese in the simplified script.

zh-Hant Chinese in the traditional script.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 94 Language and Locale IDs Locale IDs

See the “ISO 639-3 and Macro Languages” section of Understanding the New Language Tags for more Chinese language ID examples. For the complete BCP 47 specification for language tags, go to BCP 47: Tags for Identi- fying Languages. However, iOS and OS X only support the language ID syntax consisting of a language designator and optional region or script designator.

Locale IDs A locale ID identifies a specific region and its cultural conventions—such as the formatting of dates, times, and numbers. To specify a locale, use an underscore character to combine a language ID with a region designator, as shown in Table B-5. For example, the locale ID for English-language speakers in the United Kingdom is en_GB, while the locale for English-speaking residents of the United States is en_US.

Table B-5 Locale ID syntax and examples

Locale ID syntax Examples Description

[language designator] en An unspecified region where the language is used. fr

[language designator]_[region en_GB The language used by and regional preference of the user. designator] zh_HK

[language designator]-[script az-Arab An unspecified region where the script is used. designator] zh-Hans

[language designator]-[script zh-Hans_HK The script used by and regional designator]_[region designator] preference of the user.

Only use a script designator in a locale ID when there is ambiguity. For example, because Traditional Chinese is the default language in Hong Kong, use zh_HK, where zh is the code for Traditional Chinese and HK is the code for the Hong Kong region. For Simplified Chinese used in Hong Kong, use zh-Hans_HK as the locale ID, where zh-Hans is the code for the Simplified Chinese script.

Using Subtag Designators

If necessary, you can use a language or locale code that is not known to the NSBundle class or Core Foundation bundle functions. For example, you could create your own language designators for a language that is not yet listed in the ISO conventions or available as a language in Xcode.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 95 Language and Locale IDs Using Subtag Designators

If you choose to create a new designator, be sure to follow the rules found in sections 2.2.1 and 4.5 of BCP 47: Tags for Identifying Languages. Tags that do not follow these conventions are not guaranteed to work. When using subtags, ensure that the abbreviation stored by the user’s language settings matches the designator used by your .lproj directory exactly.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 96 Stringsdict File Format

A .stringsdict file is a property list used to define language plural rules.

Localized String Properties

Each key-value pair in the .stringsdict file defines a plural rule for a specific string, as in:

%d file(s) remaining %d service hour(s) %d award(s)

You pass the same strings—for example, @”%d file(s) remaining”, @”%d service hour(s)” and @”%d award(s)”—to a NSLocalizedString macro in your code.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 97 Stringsdict File Format Localized Format String Properties

Localized Format String Properties

The plural rule determines the format string returned by the NSLocalizedString macro. You supply a format string for each category of numbers the language defines. The value of this dictionary has the following keys:

NSStringLocalizedFormatKey A format string that contains variables. A variable is preceded by the %#@ characters and followed by the @ character, as in:

NSStringLocalizedFormatKey %#@files@

where the variable name is files. The format string can contain multiple variables, as in %#@files@ (%#@bytes@, %#@minutes@).

[variable] A dictionary of key-value pairs specifying the rule to use for [variable], as in:

files NSStringFormatSpecTypeKey NSStringPluralRuleType NSStringFormatValueTypeKey d one %d file remaining other %d files remaining

For example, if the number is 2, the @”%d files remaining” format string is returned and the localized string becomes @”2 files remaining”.

Add plural rules for each variable that appears in the NSStringLocalizedFormatKey format string.

Plural Rule Properties

The [variable] dictionary contains the following keys:

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 98 Stringsdict File Format Plural Rule Properties

NSStringFormatSpecTypeKey Specifies the type of language rule. The only possible value is NSStringPluralRuleType, which indicates a language plural rule.

NSStringFormatValueTypeKey A string format specifier for a number, as in %d for an integer. For a list of format specifiers, see String Format Specifiers in String Programming Guide. zero The format string to use for the number 0. one The format string to use for the number 1. two The format string to use for the number 2. few, many Format strings to use for additional language-dependent categories. other The format string to use for all numbers not covered by the other categories. This key is required.

● The meaning of the categories is language-dependent, and not all languages have the same categories.

For example, English only uses the one, and other categories to represent plural forms. Arabic has different plural forms for the zero, one, two, few, many, and other categories. Although Russian also uses the many category, the rules for which numbers are in the many category are not the same as the Arabic rules.

● All of the categories are optional except other. However, your text may be grammatically incorrect if you don’t supply a rule for all the language-specific categories. Conversely, if you provide a rule for a category not used by a language, it is ignored and the other format string is used.

● Using the NSStringFormatValueTypeKey format specifier in the zero, one, two, few, many, and other format strings is optional.

For example, the one format string can be One file remaining while the other format string can be %d files remaining for English.

● Use the format specifier or spell out numbers in the format strings.

If you use a numeric in the format string, as in 1 file remaining for English, it may not be localized when the user changes the region (for example, if the number set changes). Instead, use the format specifier, as in %d file remaining; otherwise, spell out the number, as in One file remaining.

For the plural categories and rules for each language, see CLDR Language Plural Rules.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 99 Document Revision History

This table describes the changes to Internationalization and Localization Guide.

Date Notes

2015-09-16 Described enhancements to the support for right-to-left languages and layout in iOS 9.

2014-12-18 Applied minor edits throughout.

2014-10-16 Updated per Xcode 6.1.

2014-09-17 Updated per Xcode 6.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 100 Glossary

base internationalization An Xcode feature that strings files Type of resource that contains separates user-facing text from .storyboard and key-value pairs for user-facing text. .xib files. composed character sequence Multiple characters in a string used to represent a single user-visible language character. glyph The smallest unit of displayable text in a font. internationalization The process of designing and building an app to handle different user language, region, and calendar settings, as well as handling content in multiple languages. language ID Identifies a written language and can reflect either the generic language or a specific dialect of that language. locale Determines the region, data formats, and cultural preferences of the user. locale ID Identifies a particular locale. localization The process of translating your app into different languages. localizer A person who translates app resources—such as, strings, nib, and storyboard files—into different languages. pseudolocalization A method of testing internationalized apps that translates text into pseudotext. development language The language that you used to create resources.

2015-09-16 | Copyright © 2015 Apple Inc. All Rights Reserved. 101 Apple Inc. Copyright © 2015 Apple Inc. All rights reserved.

No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation on a single computer or device for personal use only and to print copies of documentation for personal use provided that the documentation contains Apple’s copyright notice. No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights associated with the technology described in this document. This document is intended to assist application developers to develop applications only for Apple-branded products. Apple Inc. 1 Infinite Loop Cupertino, CA 95014 408-996-1010

Apple, the Apple logo, Cocoa, Cocoa Touch, Finder, iPad, iPhone, iTunes, Mac, Numbers, Objective-C, OS X, and Xcode are trademarks of Apple Inc., registered in the U.S. and other countries. App Store and Mac App Store are service marks of Apple Inc. IOS is a trademark or registered trademark of Cisco in the U.S. and other countries and is used under license. Times is a registered trademark of Heidelberger Druckmaschinen AG, available from Linotype Library GmbH. APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. AS A RESULT, THIS DOCUMENT IS PROVIDED “AS IS,” AND YOU, THE READER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT, ERROR OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages. Some jurisdictions do not allow the exclusion of implied warranties or liability, so the above exclusion may not apply to you.