There is a slight distinction between internationalization and localization:
- Internationalization - the process of making your app able to adapt to different languages, regions, and cultures.
- Localization - the process of translating your app into multiple languages.
You must first internationalize your app before you can take advantage of localization. Together, internationalization and localization allow you to better serve users around the globe by making your app appear as though it was built natively for whatever language and region it's being used in.
Using NSLocalizedString()
or String(localized:)
from the start of a project will ensure that supporting additional languages can be done in the future with minimal effort.
The comment
parameter of NSLocalizedString()
or String(localized:)
is used by translators when you add additional languages to your app. Adding some context here can make the job of the translators easier and help the overall quality of the translations. You should describe the interface element, the context, and what each variable is. Simply echoing the string itself is not recommended. The translator may not have access to the UI so it is important to provide good comments.
NSLocalizedString("Order", comment: "Button: confirms purchase of a book")
String(localized: "Orders", comment: "Title: a list of current book orders")
NSLocalizedString("Order", comment: "Order")
String(localized: "Orders", comment: "Orders")
Once you import translations into your app, Xcode will automatically generate a Localizable.strings
file for the various languages you support. Avoid editing this file by hand since your edits might get blown away the next time you go through the localization export/import process.
Consolidating all user-facing copy into a LocalizedStrings
enum (inside of a LocalizedStrings.swift
file) makes it easier to change and audit user-facing copy.
enum LocalizedStrings {
// MARK: - General
enum General {
static let back = NSLocalizedString("Back", comment: "Button: generic back button used throughout the app.")
static let next = NSLocalizedString("Next", comment: "Button: generic next button used throughout the app.")
// ...
}
// MARK: - Account
enum Account {
// ...
}
// MARK: - Home
enum Home {
static let welcome = NSLocalizedString("Welcome, %@", comment: "Message: home screen welcome. Translations should preserve the '%@' characters.")
// ...
}
// MARK: - Login
enum Login {
// ...
}
}
nextButton.setTitle(LocalizedStrings.General.next, for: .normal)
When using placeholders in localized strings, it can be helpful to remind translators that the %@
placeholder should be included in the translations (see the comment
parameter for LocalizedStrings.Home.welcome
in the example above). From here, you can use the String(format:)
initializer to populate the string appropriately:
welcomeLabel.text = String(format: LocalizedStrings.Home.welcome, user.name)
Not all languages handle pluralization of words in the same way. Do not hard-code pluralization logic into your app to programmatically select a word's plurality. Instead, you should use a .stringsdict
file to handle pluralization.
return NSLocalizedString("Purchased %d days ago", comment: "Message: describes when items were purchased")
With corresponding Localizable.stringsdict
:
if daysSincePurchase < 1 {
return NSLocalizedString("Purchased today", comment: "Purchase made today.")
} else if daysSincePurchase < 2 {
return NSLocalizedString("Purchased yesterday", comment: "Purchase made yesterday.")
} else {
return NSLocalizedString("Purchased %d days ago", comment: "Purchase made '%d' days ago.")
}
Asset catalogs are great to organize and manage different types of assets. There are several asset types that support localization. They include: color sets, image sets, symbol sets, watch complications, Apple TV image stacks, and Sprite Atlases. In the asset catalog, click the asset you want to localize. Next, click Localize in the Attributes inspector and select the localizations you want to add. Other resources not supported by asset catalogs can be localized by selecting them in the Project navigator and clicking Localize in the inspector.
Use the formatters built-in to Foundation to format values according to the device's current locale. Some of the more common ones include:
DateFormatter
- localized representations of dates and times.DateComponentsFormatter
- localized representations of quantities of time.DateIntervalFormatter
- localized representations of time intervals.LengthFormatter
- localized representations of linear distances.NumberFormatter
- localized representations of numeric values (including currency).PersonNameComponentsFormatter
- localized representations of a person's name.
Make use of Auto Layout to ensure that views will automatically adjust for different languages. Follow Apple's tips:
- Avoid fixed width constraints. Text elements with a fixed width will likely be truncated or cropped in some languages.
- Use intrinsic content size. This allows built-in elements like
UILabel
andUITextView
to automatically size themselves according to their content. You can also use this technique for your own custom views. - Use leading and trailing constraints. This will allow your views to automatically adjust for right-to-left languages when appropriate.
- Pin adjacent views together. This allows views to maintain their spacing between each other when resizing to fit localized text.
During development, you can modify your app's scheme to get a sense for how your app will support localization. The "Application Language" drop down has several options for testing a variety of languages as well as pseudolanguages:
As always, Apple's Localization guide is a good hub for learning more about internationalization and localization.