Skip to main content

Полное руководство по локализации приложений iOS

От Localizable.strings до метаданных App Store: локализуйте приложение iOS с помощью Xcode, SwiftUI, Fastlane и автоматического перевода на основе ИИ.

1

Включить локализацию в Xcode

Откройте настройки проекта Xcode, перейдите в Info > Localizations и добавьте языки, которые хотите поддерживать. Xcode автоматически создаст каталоги .lproj для каждого языка.

Xcode Project Settings
// In Xcode:
// 1. Select your project in the navigator
// 2. Go to Info tab > Localizations
// 3. Click + to add languages (e.g., German, Japanese)
// 4. Select which files to localize
//
// Xcode creates .lproj directories automatically:
// en.lproj/Localizable.strings
// de.lproj/Localizable.strings
// ja.lproj/Localizable.strings
Базовая локализация отделяет интерфейс от строк. При добавлении языка Xcode предлагает создать локализованные версии раскадровок, XIB и файлов строк.
2

Создать Localizable.strings

Стандартный файл локализации iOS использует пары «ключ — значение», разделённые знаками равенства, а каждая строка заканчивается точкой с запятой. Для исходного языка поместите его в папку Base.lproj.

Base.lproj/Localizable.strings
// Base.lproj/Localizable.strings

"welcome_title" = "Welcome to MyApp";
"login_button" = "Sign In";
"settings_label" = "Settings";
"greeting" = "Hello, %@!";    // %@ = string placeholder
"item_count" = "%d items";     // %d = integer placeholder
Отсутствующие точки с запятой вызывают сбои без уведомления: файл загружается без ошибки, но переводы остаются пустыми. Также убедитесь, что файл добавлен в этап сборки Copy Bundle Resources для Вашей цели, иначе он не попадёт в пакет приложения.
Common .strings Mistakes
// ❌ Common mistakes in .strings files:

// Missing semicolon — file loads but translations are empty
"welcome_title" = "Welcome"

// Unescaped quotes — causes parse error
"message" = "Click "here" to continue";

// ✅ Correct versions:
"welcome_title" = "Welcome";
"message" = "Click \"here\" to continue";
3

Перейти на каталоги строк (Xcode 15+)

Каталоги строк (.xcstrings) — современная замена файлов .strings от Apple. Они предлагают визуальный редактор в Xcode, автоматическое извлечение строк из представлений SwiftUI и встроенную поддержку форм множественного числа.

Localizable.xcstrings
// Xcode 15+ String Catalog (Localizable.xcstrings)
// Xcode automatically extracts strings from your code
// and manages translations in a visual editor.

// In SwiftUI, strings are automatically localizable:
Text("Welcome to MyApp")
Text("Hello, \(userName)!")

// Mark strings explicitly:
let title = String(localized: "welcome_title")
Каталоги строк хранят ВСЕ языки в одном файле JSON .xcstrings. При командной работе это означает частые конфликты слияния Git, когда несколько человек добавляют строки. Для крупных проектов стоит создать отдельный каталог для каждого модуля.
4

Использовать локализованные строки в SwiftUI и UIKit

Представление Text в SwiftUI автоматически локализует строковые литералы. UIKit использует NSLocalizedString. В iOS 16+ современный API String(localized:comment:) предлагает более понятный синтаксис со встроенной поддержкой компилятора.

ContentView.swift
import SwiftUI

struct ContentView: View {
    let userName: String

    var body: some View {
        VStack {
            // ✅ SwiftUI auto-localizes string literals
            Text("welcome_title")

            // ⚠️ This does NOT localize (String interpolation)
            // Text("Hello, \(userName)")

            // ✅ Use String(localized:) for dynamic strings
            Text(String(localized: "greeting \(userName)"))

            // ✅ UIKit style (works everywhere)
            let title = NSLocalizedString(
                "settings_label",
                comment: "Settings screen title"
            )

            // ✅ Modern API (iOS 16+)
            let modern = String(
                localized: "welcome_title",
                comment: "Main screen title"
            )
        }
    }
}
Text("Hello \(name)") не локализуется без сообщения об ошибке, если name — обычная переменная String. Интерполяция строк в SwiftUI создаёт LocalizedStringKey, но правильно интерполируются только определённые типы (Int, Double и другие). Для переменных String сначала создайте локализованную строку с помощью String(localized:).
5

Обработать формы множественного числа

iOS использует файлы .stringsdict для правил множественного числа с поддержкой всех категорий CLDR: zero, one, two, few, many, other. В каталогах строк формы множественного числа обрабатываются через визуальный редактор Xcode, что гораздо проще ручного написания XML stringsdict.

Localizable.stringsdict
<!-- Localizable.stringsdict -->
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
    <key>items_count</key>
    <dict>
        <key>NSStringLocalizedFormatKey</key>
        <string>%#@count@</string>
        <key>count</key>
        <dict>
            <key>NSStringFormatSpecTypeKey</key>
            <string>NSStringPluralRuleType</string>
            <key>NSStringFormatValueTypeKey</key>
            <string>d</string>
            <key>zero</key>
            <string>No items</string>
            <key>one</key>
            <string>%d item</string>
            <key>other</key>
            <string>%d items</string>
        </dict>
    </dict>
</dict>
</plist>

// Usage in Swift:
String(format: NSLocalizedString("items_count", comment: ""),
       itemCount)
В арабском 6 форм множественного числа, в русском — 3, в японском — 1. Всегда определяйте все категории CLDR, необходимые целевым языкам. Визуальный редактор множественного числа в каталогах строк упрощает эту задачу.
6

Локализовать метаданные App Store с помощью Fastlane

Используйте инструмент deliver в Fastlane, чтобы хранить метаданные App Store — название приложения, подзаголовок, описание, ключевые слова и примечания к выпуску — в репозитории под управлением версий как обычные текстовые файлы, организованные по локалям.

Terminal
# Install Fastlane
$ gem install fastlane

# Initialize deliver for App Store metadata
$ fastlane deliver init

# Directory structure created:
# fastlane/metadata/
# ├── en-US/
# │   ├── name.txt            # App name (30 chars)
# │   ├── subtitle.txt        # Subtitle (30 chars)
# │   ├── description.txt     # Full description
# │   ├── keywords.txt        # Search keywords (100 chars)
# │   ├── release_notes.txt   # What's New
# │   └── promotional_text.txt
# ├── de-DE/
# │   └── ...
# └── ja/
#     └── ...

# Push metadata to App Store Connect:
$ fastlane deliver
Перекрёстная локализация: App Store в США индексирует ключевые слова и на английском, и на испанском языке. Локализация метаданных на испанский позволяет охватить поисковые запросы испаноязычных пользователей в США без ориентации на отдельный рынок.
7

Протестировать локализацию

Тестируйте локализованное содержимое, не меняя язык устройства. Используйте переопределения схемы Xcode, чтобы запускать приложение на любом языке, предварительные просмотры SwiftUI со средой локали и XCUITest с аргументами запуска для автоматического тестирования.

Testing Localization
// 1. Xcode Scheme Override:
// Edit Scheme > Run > Options > App Language > Choose language

// 2. SwiftUI Preview with locale:
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .environment(\.locale, Locale(identifier: "de"))

        ContentView()
            .environment(\.locale, Locale(identifier: "ja"))

        ContentView()
            .environment(\.locale, Locale(identifier: "ar"))
    }
}

// 3. XCUITest with language override:
let app = XCUIApplication()
app.launchArguments += ["-AppleLanguages", "(de)"]
app.launchArguments += ["-AppleLocale", "de_DE"]
app.launch()
Тестируйте на немецком, где строки примерно на 30% длиннее английских, и японском, где они примерно на 50% короче, чтобы заранее выявлять проблемы с макетом. Используйте псевдолокализацию Xcode для стресс-тестирования макетов без настоящих переводов.

Автоматизировать контроль качества перевода

Выявляйте отсутствующие ключи, нарушенные заполнители и ошибки множественного числа до выпуска с помощью i18n-validate. Тестируйте интерфейс с псевдопереводами через i18n-pseudo, пока настоящие переводы ещё не готовы.
8

Автоматизировать перевод

Переводите файлы .strings, .xcstrings и метаданные Fastlane с помощью ИИ. Автоматизируйте перевод строк в приложении и метаданных App Store, чтобы полностью локализовать своё присутствие.

Terminal
# Translate .strings files
> Translate Base.lproj/Localizable.strings
  to Japanese, German, and Spanish

# Translate App Store metadata too
> Translate fastlane/metadata/en-US/
  to de-DE, ja, es-MX

✓ 6 files translated in 3.2s
Локализованная страница в App Store увеличивает число загрузок более чем на 30% на неанглоязычных рынках. Переводите метаданные вместе со строками приложения: такая локализация обеспечивает максимальную окупаемость.
+

Дополнение: умная резервная локаль с LocaleChain

По умолчанию iOS переходит на язык разработки, если точная локаль пользователя недоступна. Пользователь pt-BR при наличии только переводов pt-PT увидит английский вместо португальского. LocaleChain решает эту проблему с помощью настраиваемых цепочек резервных локалей.

LocaleChain — пакет Swift с открытым исходным кодом. Открыть на GitHub

Package Dependencies
// Swift Package Manager
// File > Add Package Dependencies >
// https://github.com/i18n-agent/ios-localechain.git
MyApp.swift
import LocaleChain

// In your App init or AppDelegate:
LocaleChain.configure()  // Activates all default chains

// pt-BR user with only pt-PT translations?
// → Shows Portuguese instead of falling back to English

// Custom overrides for your specific locales:
LocaleChain.configure(
    overrides: ["es-MX": ["es-419", "es"]]
)

Распространённые ошибки

Синтаксические ошибки в файле .strings

Отсутствующие точки с запятой, неэкранированные кавычки или неверная кодировка вызывают сбои без уведомления. Файл загружается, но переводы остаются пустыми. Всегда проверяйте файлы .strings перед фиксацией изменений.

Интерполяция Text в SwiftUI не локализуется

Text("Hello \(stringVar)") локализуется не так, как ожидается. Используйте String(localized:) для вычисляемых строк или убедитесь, что интерполируемые переменные имеют тип, подходящий для LocalizedStringKey.StringInterpolation.

В виджетах и расширениях отображаются исходные ключи

Расширения приложения имеют отдельные пакеты. Убедитесь, что файлы .strings или .xcstrings добавлены в этап Copy Bundle Resources цели расширения, а не только цели основного приложения.

В рабочей среде для отсутствующих переводов отображаются ключи

Если для ключа нет перевода на язык пользователя, iOS отображает сам ключ. Используйте стратегию резервного языка и протестируйте все поддерживаемые локали перед выпуском.

Рекомендуемая структура файлов

Project Structure
MyApp/
├── MyApp.xcodeproj
├── MyApp/
│   ├── Base.lproj/
│   │   ├── Localizable.strings       # Source strings
│   │   └── Localizable.stringsdict   # Plural rules
│   ├── en.lproj/
│   │   └── Localizable.strings
│   ├── de.lproj/
│   │   └── Localizable.strings
│   ├── ja.lproj/
│   │   └── Localizable.strings
│   ├── Localizable.xcstrings          # OR String Catalog
│   └── Info.plist
├── MyAppTests/
├── fastlane/
│   ├── Fastfile
│   └── metadata/
│       ├── en-US/
│       │   ├── name.txt
│       │   ├── description.txt
│       │   └── keywords.txt
│       ├── de-DE/
│       └── ja/
└── Package.swift

Попробовать i18n Agent

Перетащите сюда файл перевода

JSON, YAML, PO, XML, CSV, Markdown, Properties

или нажмите, чтобы выбрать

Целевые языки

Регистрация не требуетсяМгновенный расчёт

Резервные локали с ios-localechain

Когда в региональной локали, например de-AT, отсутствует ключ перевода, iOS сразу переходит на язык разработки, не проверяя сначала родительскую локаль de.

Terminal
// Swift Package Manager
// https://github.com/i18n-agent/ios-localechain
Configuration
import LocaleChain

LocaleChain.configure(overrides: [
    "de": ["en-GB", "en"],
    "pt-BR": ["pt", "en"],
    "zh-Hant-HK": ["zh-Hant", "zh", "en"],
])

Полный список поддерживаемых фреймворков и 75 встроенных цепочек приведён в нашем руководстве по резервным локалям. Learn more →

Частые вопросы о локализации iOS