Skip to main content

iOS 應用程式本地化完整指南

從 Localizable.strings 到 App Store 元數據:使用 Xcode、SwiftUI、Fastlane 和自動化 AI 翻譯來本地化 iOS 應用程式。

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
Base 本地化會將 UI 與字串分離。新增語言時,Xcode 會建議為 storyboard、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

遷移到 String Catalog(Xcode 15+)

String Catalog(.xcstrings)是 Apple 對 .strings 檔案的現代替代方案,提供 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")
String Catalog 會把所有語言存儲在單個 .xcstrings JSON 檔案中。對於團隊而言,多人新增字串時會頻繁產生 Git 合併衝突。大型項目可考慮每個模組使用一個 catalog。
4

在 SwiftUI 和 UIKit 中使用本地化字串

SwiftUI 的 Text 視圖會自動本地化字串字面量,UIKit 則使用 NSLocalizedString。iOS 16+ 可使用現代 String(localized:comment:) API,以更簡潔的語法獲得內置編譯器支援。

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"
            )
        }
    }
}
當 name 是普通 String 變數時,Text("Hello \(name)") 會在沒有提示的情況下無法本地化。SwiftUI 字串插值會建立 LocalizedStringKey,但只有特定類型(Int、Double 等)能正確插值。對於 String 變數,請先使用 String(localized:) 構建本地化字串。
5

處理複數

iOS 使用 .stringsdict 檔案處理複數規則,並支援全部 CLDR 複數類別:zero、one、two、few、many、other。String Catalog 可通過 Xcode 的視覺化編輯器處理複數,比手寫 stringsdict XML 簡單得多。

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 類別。String Catalog 的視覺化複數編輯器讓這項工作更加簡單。
6

使用 Fastlane 本地化 App Store 元數據

使用 Fastlane 的 deliver 工具,將 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 scheme 覆蓋以任意語言執行應用程式,通過語言環境預覽 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 產生偽譯文來測試 UI。
8

自動翻譯

使用 AI 翻譯 .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-PT 譯文時,pt-BR 用戶會看到英語而非葡萄牙語。LocaleChain 通過可設定回退鏈修復此問題。

LocaleChain 是開源 Swift Package。在 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 檔案。

SwiftUI Text 插值未本地化

Text("Hello \(stringVar)") 未按預期本地化。計算字串應使用 String(localized:);也可確保插值變數使用 LocalizedStringKey.StringInterpolation 支援的正確類型。

小元件或擴展顯示原始鍵

應用程式擴展擁有單獨的 bundle。請確保 .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 本地化常見問題