Интернационализация (i18n) в Swift: NSLocalizedString и String Catalog

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Интернационализация (i18n) в Swift: полное руководство для iOS и macOS

Интернационализация (i18n) — это процесс проектирования приложения таким образом, чтобы оно могло быть адаптировано для различных языков и регионов без инженерных изменений. В экосистеме Apple (iOS, macOS, watchOS, tvOS) инструменты для локализации встроены непосредственно в Swift и Xcode. В этой статье мы подробно разберем, как использовать NSLocalizedString и современный String Catalog для создания мультиязычных приложений.

Основы: NSLocalizedString

Базовый механизм интернационализации в Swift — это функция NSLocalizedString. Она ищет перевод строки в файлах .strings или .xcstrings (String Catalog).

let greeting = NSLocalizedString("hello_world", comment: "Приветствие на главном экране")
print(greeting) // Выведет перевод в зависимости от языка устройства

Параметр comment служит подсказкой для переводчика. Ключ "hello_world" должен быть уникальным в рамках всего проекта.

Создание файлов локализации

В Xcode вы можете добавить поддерживаемые языки через Project Info > Localizations. После этого для каждого .strings файла или Storyboard будут созданы подфайлы локализации.

Пример содержимого Localizable.strings (английский):

"hello_world" = "Hello, World!";
"welcome_message" = "Welcome to our app %@";

Русская версия (Localizable.strings (Russian)):

"hello_world" = "Привет, мир!";
"welcome_message" = "Добро пожаловать в наше приложение %@";

Форматирование строк с параметрами

Для строк, содержащих динамические данные, используйте спецификаторы формата. В Swift это можно делать двумя способами:

Способ 1: String(format:)

let userName = "Иван"
let points = 150
let message = String(format: NSLocalizedString("user_score", comment: "Очки пользователя"), userName, points)
print(message) // "Иван набрал 150 очков"

В файле локализации:

"user_score" = "%@ набрал %d очков";

Способ 2: Swift String Interpolation (iOS 15+)

let message = "\(userName) набрал \(points) очков"

Однако этот способ не подходит для локализации, так как порядок слов в разных языках может отличаться. Используйте только String(format:) или AttributedString с инфлекцией.

Плюризация (множественные формы)

В русском языке есть сложные правила склонения: "1 файл", "2 файла", "5 файлов". Для этого Apple предоставляет stringsdict (XML) или String Catalog с правилами плюризации.

Пример stringsdict

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>files_count</key>
    <dict>
        <key>NSStringLocalizedFormatKey</key>
        <string>%#@files@</string>
        <key>files</key>
        <dict>
            <key>NSStringFormatSpecTypeKey</key>
            <string>NSStringPluralRuleType</string>
            <key>NSStringFormatValueTypeKey</key>
            <string>d</string>
            <key>one</key>
            <string>%d файл</string>
            <key>few</key>
            <string>%d файла</string>
            <key>many</key>
            <string>%d файлов</string>
            <key>other</key>
            <string>%d файлов</string>
        </dict>
    </dict>
</dict>
</plist>

Использование в коде:

let count = 3
let text = String.localizedStringWithFormat(
    NSLocalizedString("files_count", comment: "Количество файлов"),
    count
) // "3 файла"

String Catalog (xcstrings) — современный подход

Начиная с Xcode 15, Apple рекомендует использовать String Catalog вместо старых

Рекомендаций