Um wiederholte Meldungen in einer Mac-App zusammenzuführen, gib jeder gemeinsamen Bedeutung einen Lokalisierungsschlüssel und eine Swift-Definition und verwende sie dann überall dort, wo die Meldung erscheint. Fasse ihre Argumente, Pluralregeln und den Kontext für Übersetzer zusammen; übereinstimmender englischer Text allein reicht nicht aus.
Diese Anleitung richtet sich an Mac-Entwickler, die eine Zusammenfassung der Auswahl sowohl in SwiftUI als auch in einem Interface-Builder-Fenster pflegen. Die konkrete Aufgabe besteht darin, Meldungen wie 2 items selected in Batch A. konsistent anzuzeigen, ohne separate Satzvorlagen in einer XIB-Datei und im Swift-Code zu pflegen. Alle folgenden Zahlen und Bezeichnungen sind fiktiv.
Entscheiden, welche wiederholten Meldungen zusammengehören
Bevor du Kataloge bearbeitest, definiere den Nachrichtenvertrag: Was bedeutet der Satz, welche Werte nimmt er entgegen und wo erscheint er? Für dieses Beispiel gilt:
| Vertragselement | Definition |
|---|---|
| Bedeutung | Anzahl der aktuell ausgewählten Elemente innerhalb einer benannten Sammlung |
| Schlüssel | selection.summary |
| Tabelle | Localizable |
| Bundle | Haupt-App-Bundle |
| Argument 1 | Eine Auswahlanzahl vom Typ Int64 |
| Argument 2 | Eine wörtliche Bezeichnung der Sammlung, etwa Batch A |
| Variation | Pluralform, bestimmt durch die Anzahl der Auswahlen |
| Kontext | Ein vollständiger Statussatz, der in SwiftUI und einem AppKit-Label angezeigt wird |
Verwende diesen Vertrag als Maßstab für die Zusammenführung. Zwei Vorkommen können dieselbe Meldung verwenden, wenn Bedeutung, Argumente und grammatische Funktion übereinstimmen. Eine Anzahl ausgewählter Elemente und eine Gesamtanzahl von Elementen sollten getrennt bleiben, selbst wenn beide derzeit 2 items anzeigen. Auch eine Schaltfläche mit der Bezeichnung Select braucht eine eigene Meldung, da sie eine Aktion ausdrückt.
Apple unterstützt ausdrücklich Schlüssel mit separaten Standardwerten, um Texte eindeutig zuzuordnen. So kannst du eine Meldung nach ihrem Zweck benennen und gleichzeitig eine lesbare Formulierung im Quelltext beibehalten. Ein Kommentar liefert Kontext; der Schlüssel identifiziert den Eintrag. Der Initialisierer von String mit explizitem Schlüssel.
Betrachte auch Tabelle und Bundle als Teil des Suchvertrags. Ein Schlüssel in einer anderen Tabelle ist ein separates Suchziel. Apple dokumentiert die Tabellenauswahl über den Parameter table oder tableName und empfiehlt, lokalisierbaren Text über LocalizedStringResource zu übergeben. Verwende für dieses Beispiel das Hilfsprogramm und den Katalog im App-Target sowie das Haupt-Bundle. App-Texte für die Übersetzung vorbereiten.
Die Abgrenzung zwischen Extraktion und Formatierung zur Laufzeit verstehen
Die Extraktion erfolgt beim Erstellen des Xcode-Builds: Dabei werden unterstützte lokalisierbare Ausdrücke erkannt und ihr Quelltext mit Katalogen abgeglichen. Die Lokalisierung zur Laufzeit erfolgt, wenn die App eine Meldung auflöst und tatsächliche Werte einsetzt. Ein Eintrag im Katalog beweist, dass er extrahiert wurde; es beweist nicht, dass jedes Steuerelement ihn korrekt anzeigt.
Interface Builder hat einen eigenen Ressourcen-Workflow. Apple dokumentiert Kataloge in Verbindung mit einem Storyboard oder einer XIB-Datei, während Swift-Quelltext üblicherweise zur Tabelle Localizable beiträgt. Der dokumentierte Workflow beschreibt keinen Ressourcen übergreifenden Alias, der Meldungen allein deshalb zusammenführt, weil ihr sichtbarer Wortlaut übereinstimmt. Ein praktischer, unterstützter Weg besteht darin, die gemeinsame lokalisierte Meldung nach dem Laden der Oberfläche aus Swift zuzuweisen. Diese Implementierung leitet sich aus den von Apple dokumentierten APIs ab. String-Kataloge entdecken.
SwiftUI unterscheidet außerdem zwischen einem literalen Lokalisierungsschlüssel und einem gewöhnlichen Zeichenfolgenwert. Zum Beispiel fordert Text("Summary") die Lokalisierung an, während die Übergabe einer String-Variablen ihren Wert ohne diese Suche anzeigt. Wenn du eine Zeichenfolge zur Laufzeit in LocalizedStringKey verpackst, wird eine Suche angefordert; das darf jedoch nicht mit dem Nachweis verwechselt werden, dass die Extraktion die möglichen Werte erkannt hat. LocalizedStringKey.
Der folgende Entwurf belässt den extrahierbaren literalen Text daher in einem einzigen Hilfsprogramm. Es übergibt Anzahl und Bezeichnung in einer LocalizedStringResource und löst diese Ressource dann dort auf, wo eine fertige Zeichenfolge benötigt wird. Apple beschreibt diesen Ressourcentyp als Möglichkeit, die Lokalisierungssuche aufzuschieben. Er ist ab macOS 13 verfügbar, der Mindestversion für dieses Beispiel. LocalizedStringResource.
Die gemeinsame Meldung einmal in Swift definieren
Erstelle ein macOS-App-Projekt mit SwiftUI, lege als Bereitstellungsziel macOS 13 oder neuer fest und füge dem App-Target Localizable.xcstrings hinzu. In der aktuellen Xcode-Dokumentation lautet der Pfad zum Erstellen File > New > File from Template; suche nach string und wähle String Catalog. Text mit einem Zeichenfolgenkatalog lokalisieren und variieren.
Ersetze den generierten App-Einstiegspunkt durch das vollständige Programm unten. Entferne den ursprünglichen App-Einstiegspunkt, damit das Target nur eine @main-Deklaration enthält. Das SwiftUI-Fenster läuft unabhängig von einer XIB-Datei; die enthaltene AppKit-Unterklasse kommt im nächsten Abschnitt zum Einsatz, wenn ein bestehendes Interface-Builder-Label angepasst wird.
import AppKit
import Foundation
import SwiftUI
enum SelectionMessages {
static func summary(
count: Int64,
collectionLabel: String
) -> LocalizedStringResource {
LocalizedStringResource(
"selection.summary",
defaultValue: "\(count) items selected in \(collectionLabel).",
table: "Localizable",
comment: "Complete selection-status sentence used in SwiftUI and an AppKit label. Argument 1 is the selected-item count; argument 2 is a literal collection label. Pluralize by argument 1."
)
}
}
struct SelectionDemoView: View {
private let counts: [Int64] = [0, 1, 2]
private let collectionLabel = "Batch A"
var body: some View {
VStack(alignment: .leading, spacing: 12) {
ForEach(counts, id: \.self) { count in
Text(String(localized: SelectionMessages.summary(
count: count,
collectionLabel: collectionLabel
)))
}
}
.padding(24)
.frame(minWidth: 360, minHeight: 160)
}
}
final class SelectionSummaryField: NSTextField {
override func awakeFromNib() {
super.awakeFromNib()
// Synthetic initial state for the Interface Builder example.
updateSelection(count: 2, collectionLabel: "Batch A")
}
func updateSelection(count: Int64, collectionLabel: String) {
stringValue = String(localized: SelectionMessages.summary(
count: count,
collectionLabel: collectionLabel
))
}
}
@main
struct SelectionDemoApp: App {
var body: some Scene {
WindowGroup {
SelectionDemoView()
}
}
}
Der statische Schlüssel identifiziert die Meldung; der interpolierte Standardwert liefert ihren Ausgangssatz und die Argumente zur Laufzeit. Der Initialisierer akzeptiert außerdem Tabelle, Bundle und Kommentar für Übersetzer. Standardmäßig wird das Haupt-Bundle verwendet. Initialisierer von LocalizedStringResource mit explizitem Schlüssel.
Die Bezeichnung Batch A ist ein Beispielinhalt, der in den Satz eingefügt wird. Sie ist kein weiterer Meldungsschlüssel. So bleiben Bezeichnungen von Sammlungen vom umgebenden Oberflächentext getrennt. Wenn deine reale Anwendung vorgegebene, übersetzte Sammlungsnamen verwendet, lokalisiere diese Namen über eigene Definitionen, bevor du sie hier übergibst.
Setze diesen Satz nicht aus unabhängig lokalisierten Teilen wie einer Anzahl, items selected in und einer Bezeichnung zusammen. Wenn der vollständige Satz Teil des Vertrags bleibt, haben Lokalisierer eine Einheit, deren Formulierung und Argumentreihenfolge gemeinsam angepasst werden können.
Das Interface-Builder-Label über dieselbe Definition führen
Verwende für eine bestehende XIB- oder Storyboard-Datei ein statisches NSTextField-Label für die Zusammenfassung. Setze seine benutzerdefinierte Klasse auf SelectionSummaryField und sein Modul auf das App-Target. Lösche den alten Satz aus dem Entwurfswert des Texts, da dieses Label seinen Text nun aus der gemeinsamen Swift-Definition erhält.
Beim Laden der Oberfläche ruft die Unterklasse super.awakeFromNib() auf und weist die fiktive Anfangszusammenfassung zu. Apple dokumentiert awakeFromNib() als Hook nach dem Laden, wenn Outlet- und Action-Verbindungen hergestellt sind, und verlangt, die Implementierung der Oberklasse aufzurufen. awakeFromNib().
Rufe im echten Fenster bei jeder Änderung der Auswahl updateSelection(count:collectionLabel:) für das verbundene Label auf und verwende dabei dieselben Modellwerte wie für SwiftUI. Ersetze die fiktive Anfangszuweisung durch den tatsächlichen Initialisierungspfad des Fensters. Eine einmalige Zuweisung beim Laden kann spätere Änderungen der Auswahl nicht verfolgen.
Der AppKit-Adapter setzt stringValue, eine dokumentierte Methode, um den Text eines NSTextField zuzuweisen. So bleibt das Layout in Interface Builder, während Swift die Verantwortung für die Meldung übernimmt. Sorge für genügend Breite oder Zeilenumbruch, damit der vollständige Satz lesbar ist. NSTextField.
Belasse nicht damit zusammenhängenden statischen Oberflächentext in seinem bestehenden Ressourcen-Workflow. Diese Umstellung betrifft eine gemeinsame Meldung; es ist nicht nötig, jedes Label nach Swift zu verschieben. Prüfe außerdem, dass eine Bindung oder eine weitere Zuweisung durch einen Controller die Zusammenfassung nicht später durch den alten Wortlaut ersetzt.
Pluralvarianten einrichten, ohne die Argumente zu ändern
Wähle Product > Build, öffne Localizable.xcstrings und suche nach selection.summary. Klicke bei gedrückter Control-Taste auf den Eintrag, wähle Vary by Plural und wähle das numerische Argument für die Anzahl aus, falls Xcode fragt, welches Argument variiert werden soll. Apple dokumentiert diesen Workflow für interpolierte Meldungen. Text mit einem Zeichenfolgenkatalog lokalisieren und variieren.
Lass für die englische Ausgangslokalisierung die Singularvariante 1 item selected in Batch A. und die andere Variante Sätze wie 2 items selected in Batch A. ergeben. Bewahre beide von Xcode bereitgestellten Argument-Platzhalter. Bearbeite den umgebenden Wortlaut, anstatt einen Platzhalter durch eine Beispielanzahl oder -bezeichnung zu ersetzen.
| Fiktive Eingabe | Erwartetes englisches Ergebnis nach der Konfiguration der Pluralformen |
|---|---|
Anzahl 0, Bezeichnung Batch A |
0 items selected in Batch A. |
Anzahl 1, Bezeichnung Batch A |
1 item selected in Batch A. |
Anzahl 2, Bezeichnung Batch A |
2 items selected in Batch A. |
Anzahl 2, Bezeichnung Batch B |
2 items selected in Batch B. |
Dies sind veranschaulichende Abnahmefälle, keine gemessenen Ergebnisse. Vor der Konfiguration der Pluralformen enthält der Standardsatz der Ausgangslokalisierung für jede Anzahl weiterhin items. Die Extraktion erhält die interpolierte Meldung; sie korrigiert ihre Grammatik nicht eigenständig.
Die wechselnde Bezeichnung in der letzten Zeile ist diagnostisch hilfreich: Wenn die Anzeige weiterhin Batch A lautet, wurde möglicherweise ein Beispielwert in einer Variante fest codiert oder ein Aufrufer übergibt einen veralteten Zustand. Wenn die Bezeichnung verschwindet, prüfe die Platzhalter der Variante, bevor du die Signatur des Hilfsprogramms änderst.
Jeden Anzeigeweg prüfen, bevor alte Einträge entfernt werden
Teste das SwiftUI-Fenster und das tatsächliche Interface-Builder-Fenster getrennt. Verwende in beiden dieselben Anzahlen und Bezeichnungen. Prüfe das Laden, eine spätere Änderung der Auswahl und eine längere fiktive Bezeichnung wie Batch A Extended. Vergewissere dich, dass der Wortlaut übereinstimmt und der Satz lesbar bleibt.
Wähle für jede unterstützte Lokalisierung Product > Scheme > Edit Scheme, dann Run, öffne Options und lege unter App Language die App-Sprache fest. Starte die App erneut und prüfe beide Anzeigewege. Apple dokumentiert diese Schemaeinstellungen, um Lokalisierungen zu testen, ohne die Systemsprache zu ändern. Lokalisierungen beim Ausführen deiner App testen.
Gehe wie folgt vor, wenn ein Ergebnis nicht stimmt:
- Eintrag fehlt: Prüfe, ob der Katalog zum App-Target gehört, und erstelle einen Build des relevanten Schemas. Prüfe, ob
Use Compiler to Extract Swift Stringsaktiviert ist. - Unerwartet erscheint der Ausgangswortlaut: Prüfe Schlüssel, Tabelle, Bundle und Übersetzung, bevor du einen lesbaren Fallback-Text als Erfolg wertest.
- Nur das Interface-Builder-Label weicht ab: Prüfe dessen benutzerdefinierte Klasse, Modul, Ladepfad und spätere Zuweisungen.
- Nur spätere Werte weichen ab: Prüfe, ob beide Oberflächen aktualisierte Modellwerte erhalten.
- Der Pluralwortlaut ist falsch: Prüfe das für die Variation ausgewählte numerische Argument und jede zutreffende Variante.
Apple dokumentiert die Compiler-Einstellung für die Extraktion und erklärt, dass übersetzte Einträge, die im Quelltext nicht mehr gefunden werden, als Stale markiert bleiben können. Dieser Status ist ein Signal für Aufräumarbeiten, aber kein Beweis dafür, dass eine Ressource ungenutzt ist. Prüfe die alte Zuweisung in der Oberfläche und die Swift-Aufrufer, bevor du einen Eintrag und seine Übersetzungen löschst. String-Kataloge entdecken.
Die Zusammenführung ist abgeschlossen, wenn beide Oberflächen dieselbe kontextbezogene Meldung aus einer Definition beziehen, ihre Argumente erhalten bleiben und die alten Satzvorlagen keine Aufrufer mehr haben. Bewahre den Vertrag und die Abnahmefälle neben dem Hilfsprogramm auf, damit künftige Änderungen des Wortlauts die gemeinsame Bedeutung beider Fenster erhalten.
Quellen
Text mit einem Zeichenfolgenkatalog lokalisieren und variieren — Apple
String-Kataloge entdecken — Apple
LocalizedStringKey — Apple
LocalizedStringResource — Apple
init(localized:defaultValue:table:bundle:locale:comment:) — Apple
NSTextField — Apple
awakeFromNib() — Apple