localize.dev

Documenti / iOS

Localizzazione iOS e macOS con String Catalogs, automatizzata

Trova testo hardcoded in SwiftUI e UIKit, traducilo in Localizable.xcstrings per ogni lingua ed incapsula le stringhe UIKit in String(localized:), in un solo comando o pull request.

Come funziona

SwiftUI cerca autonomamente il testo di Text("…"), Button, Label, TextField, .navigationTitle e altre viste nel catalogo stringhe, in modo che il codice rimanga invariato. UIKit accetta stringhe semplici, quindi label.text = "…", setTitle("…", for:) e i titoli degli avvisi diventano String(localized: "…").

Un conteggio con la sua parola, "\(n) \(n == 1 ? "item" : "items")", diventa "\(n) items": il catalogo varia %lld items in base al conteggio, con le forme plurali di ogni lingua.

Ogni stringa va in Localizable.xcstrings, indicizzata dal suo testo nel modo in cui Xcode lo scrive (Welcome back, %@!), con la traduzione di ogni lingua nello stesso file e segnaposto numerati (%1$@, %2$lld) quando ce n'è più di uno. Text(verbatim:), nomi di immagini e commenti vengono lasciati invariati.

Prima e dopo

L'output effettivo del motore per questo file. In un'esecuzione reale, il modello ospitato nomina le chiavi dal contesto.

Shop/CartView.swift · prima
import SwiftUI

struct CartView: View {
    let name: String
    var body: some View {
        VStack {
            Text("Welcome back, \(name)!")
            Button("Checkout") {}
        }
        .navigationTitle("Your cart")
    }
}

final class LoginController: UIViewController {
    let label = UILabel()
    override func viewDidLoad() {
        label.text = "Sign in to continue"
    }
}
Shop/CartView.swift · dopo
import SwiftUI

struct CartView: View {
    let name: String
    var body: some View {
        VStack {
            Text("Welcome back, \(name)!")
            Button("Checkout") {}
        }
        .navigationTitle("Your cart")
    }
}

final class LoginController: UIViewController {
    let label = UILabel()
    override func viewDidLoad() {
        label.text = String(localized: "Sign in to continue")
    }
}
locales/en.json
{
  "sourceLanguage" : "en",
  "strings" : {
    "Checkout" : {

    },
    "Sign in to continue" : {

    },
    "Welcome back, %@!" : {

    },
    "Your cart" : {

    }
  },
  "version" : "1.0"
}

Cosa aggiunge la configurazione

La prima esecuzione imposta String Catalogs (Localizable.xcstrings) se il progetto non lo ha ancora:

  • Localizable.xcstrings, trovato ovunque nel progetto o creato alla radice: aggiungilo una volta al target dell'app in Xcode

Eseguilo

La CLI richiede Node.js 22 o versioni successive, nient'altro: npx lo esegue senza aggiungere un package.json al progetto. Non hai Node sulla tua macchina? La GitHub Action qui sotto lo esegue per te.

npx localize-dev login

# Preview, then write the changes
npx localize-dev run --dry-run -l es,fr,de
npx localize-dev run -l es,fr,de

# Or open a pull request instead
npx localize-dev pr -l es,fr,de

Oppure aggiungi la GitHub Action e ottieni una pull request a ogni push. Provalo prima sul tuo codice nel playground.