Grüße, liebe Hacker!
Heute möchte ich eine interessante Erfahrung bei der Lösung des Lokalisierungsproblems teilen. In iOS ist die Lokalisierung aus Sicht eines Ziels oder mehrerer Ziele recht bequem angeordnet, wobei die Schlüssel in localizable.strings nicht sehr wiederholt werden. Aber alles wird komplizierter, wenn Sie ein Dutzend Ziele haben, bei denen mehr als die Hälfte der Schlüssel wiederholt werden, aber gleichzeitig unterschiedliche Bedeutungen haben, und es gibt auch eine Reihe von Schlüsseln, die für ein bestimmtes Ziel eindeutig sind.
Für diejenigen, die dies noch nicht erlebt haben, werde ich das Problem anhand eines Beispiels näher erläutern.
Nehmen wir an, wir haben ein großes Projekt, in dem 90% des allgemeinen Codes und drei Ziele enthalten sind : MyApp1 , MyApp2 , MyApp3 , die eine Reihe spezifischer Bildschirme haben und jeweils einen eigenen Namen und Text haben. Ein Ziel ist im Wesentlichen eine unabhängige Anwendung. Jeder von ihnen muss in 10 Sprachen übersetzt werden. Wir möchten jedoch KEINE Lokalisierungsschlüssel wie app1_localizable_key1 , app2_localizable_key1 usw. hinzufügen . Wir möchten, dass alles im Code schön ist und in einer Zeile lokalisiert wird
NSLocalizedString(@"localizable_key1", nil)
Ohne if und ifdef , sodass wir beim Hinzufügen eines neuen Ziels nicht den gesamten Code eines großen Projekts nach Orten mit NSLocalizedString durchsuchen und dort neue Schlüssel registrieren müssen. Wir möchten auch, dass einige der Schlüssel an bestimmte Zielbildschirme gebunden sind, d. H. Es gab Schlüssel app2_screen1_key , app3_screen2_key .
Jetzt können Sie mit Standard-Xcode-Tools Folgendes tun:
- Kopieren Sie den gemeinsamen Teil localizable.strings in jedes Ziel, und wir erhalten 3 Kopien dieser Dateien.
- Fügen Sie den entsprechenden localizable.strings zielspezifische Schlüssel hinzu.
Welche Probleme bekommen wir:
- Das Hinzufügen eines neuen öffentlichen Schlüssels zu einem Projekt ist ziemlich teuer. Die Anzahl der Sitze entspricht der Anzahl der Ziele multipliziert mit der Anzahl der Sprachen. In unserem Beispiel sind dies 30 Stellen.
- Es besteht die Möglichkeit eines Fehlers, wenn wir 1-2 aktuellen Zielen, mit denen wir aktiv arbeiten, eine Zeile hinzugefügt haben, und ein Jahr später beschlossen sie, ein oder mehrere Ziele wiederzubeleben. Sie müssen Lokalisierungen manuell miteinander synchronisieren oder ein Skript dafür schreiben. Und wenn beim Hinzufügen oder Zusammenführen von Zweigen eine gewisse Schlamperei festgestellt wurde und allgemeine Schlüssel mit bestimmten gemischt werden, gibt es eine echte Suche.
- Das Volumen der Lokalisierungsdateien. Sie wachsen alle ständig, dies erschwert die Zusammenarbeit und erhöht die Konfliktwahrscheinlichkeit beim Zusammenführen von Zweigen.
Was ich möchte:
- Damit werden alle öffentlichen Schlüssel in einer separaten Datei gespeichert.
- Für jedes Ziel gab es eine Datei, in der nur die dafür spezifischen Schlüssel gespeichert waren, sowie allgemeine Schlüssel mit Werten für dieses Ziel.
In unserem Beispiel eine gemeinsame Datei localizable.strings mit Strings
"shared_localizable_key1" = "MyApp title"
"shared_localizable_key2" = "MyApp description"
"shared_localizable_key3" = "Shared text1"
"shared_localizable_key4" = "Shared text2"
Ich hätte gerne eine localizable_app2.strings- Datei mit den Schlüsseln
"shared_localizable_key1" = "MyApp2 another title"
"shared_localizable_key2" = "MyApp2 another description"
"app2_screen1_key" = "Profile screen title"
Jene. Organisieren Sie das Prinzip der Vererbung in Lokalisierungsdateien .
Leider ist Xcode nicht darauf zugeschnitten, so dass ich mein eigenes "Fahrrad" neu erfinden musste, das lange nicht mehr fahren wollte, da Xcode hier und da eine Speiche in die Räder steckte.
Wir haben ein Projekt mit 18 Zielen und 12 Sprachen. Und das ist kein Scherz, das Projekt ist wirklich groß und es werden dort so viele Ziele benötigt. Jedes Mal, wenn wir einen neuen öffentlichen Schlüssel für die Übersetzung hinzufügen müssen, handelt es sich um 216 Lokalisierungsdateien. Es benötigt viel Zeit. Das Hinzufügen eines neuen Ziels führt dazu, dass Sie 12 weitere lokalisierbare Zeichenfolgen kopieren müssen . Im Allgemeinen wurde uns irgendwann klar, dass es nicht mehr möglich war, so zu leben, und wir mussten nach einer Lösung suchen.
Ich werde nicht lange über alle Methoden sprechen, die ich in diesem Prozess getestet habe, sondern direkt zur Arbeitslösung übergehen.
Also mussten wir zuerst alle gemeinsam genutzten Schlüssel finden. Dies kann mit einem Skript erfolgen, ich werde nicht auf Details eingehen, dies ist eine eher triviale Aufgabe.
Wenn wir eine gemeinsame (Basis-) Lokalisierungsdatei oder vielmehr 12 physische Dateien sowie eine Reihe von Dateien für jedes Ziel erhalten haben, gehen Sie zu Xcode und fügen Sie dort alle Dateien hinzu. Gleichzeitig hängen wir keine Dateien an ein Ziel an, d. H. Der rechte Bereich unter Zielmitgliedschaft sollte deaktiviert sein.
Wir werden diese Markierungen nur für die Datei setzen, was das Ergebnis der Arbeit des Skripts zum Zusammenstellen von Dateien ist.
Dann beginnt das gleiche "Fahrrad":
- Localization, build_localization.py.
- Localizable. localizable.strings.
- Localizable .
Wir brauchen es nur, um einen Link zu den Dateien zum Projekt korrekt hinzuzufügen, damit Xcode sie korrekt erkennt. Andernfalls werden sie nicht zum Auffinden von Schlüsseln verwendet. Zum Beispiel, wenn Sie einen erstellen Localizable Ordner mit den richtigen localizable.strings Dateien nach innen, und es das Projekt als ein In - Ordner Referenzen , dann egal , was Xcode nicht verstehen , dass wir gab es Tasten Lokalisierung. Nehmen Sie daher den lokalisierbaren Ordner , ziehen Sie ihn als Gruppe (Gruppe erstellen ) und deaktivieren Sie das Kontrollkästchen Elemente bei Bedarf kopieren , damit er wie im Bild unten aussieht.
Löschen Sie den lokalisierbaren Ordnerund füge es zu den Ausnahmen für die Gita hinzu. Da wir das Ergebnis des Skripts in der Gita nicht benötigen, ändert es sich für jedes Ziel und verstopft die Commits.
Jetzt müssen wir das Skript zur Erstellungsphase hinzufügen. Klicken Sie dazu in Build-Phasen auf Neue Skriptphase ausführen und schreiben Sie unser Skript mit Parametern.
python3 ${SRCROOT}/Localization/build_localization.py -b “${SRCROOT}/BaseLocalization" -s "${SRCROOT}/Target1Localization" -d "${SRCROOT}/Localization/Localizable"
b ist der Ordner mit der Basislokalisierung, s ist die Lokalisierung des aktuellen Ziels, d ist der Ergebnisordner.
Verschieben Sie die neue Phase nach oben. Sie darf nicht niedriger sein als die Phase " Bundle-Ressourcen kopieren" . Jene. Zuerst generiert das Skript Dateien und erst dann werden sie in das Bundle aufgenommen.
Jetzt ist es wichtig, Xcode mitzuteilen, dass während der Ausführung des Skripts die Dateien geändert werden. Andernfalls wird beim Erstellen ein Fehler ausgegeben, dass die Dateien nicht gefunden werden konnten. Darüber hinaus tritt der Fehler nur bei einer sauberen Baugruppe auf, und es ist nicht sofort klar, wo das Problem liegt. Fügen Sie in der Erstellungsphase alle Lokalisierungsdateien zu den Ausgabedateien hinzu
Dies muss für jedes Ziel durchgeführt werden. Der einfachste Weg, dies zu tun, besteht darin, das Projekt mit einem Texteditor zu öffnen, da Xcode keine Phase zwischen Zielen kopieren / einfügen kann. Dementsprechend sind die Skriptparameter -s für jedes Ziel unterschiedlich.
Jetzt nimmt das Skript bei jedem Build die Basislokalisierungsdatei, überträgt Änderungen aus der Zieldatei (Hinzufügen, Überschreiben von Schlüsseln) und generiert die Lokalisierung im Ordner " Lokalisierbar " , mit dem iOS Schlüssel findet.
Im Allgemeinen haben wir das bekommen, was bei der Implementierung des Vererbungsmechanismus geplant war:
- Freigegebene Schlüssel befinden sich in einer Datei und stören andere nicht. Die Zeit für die Eingabe neuer Schlüssel wurde um 18 verkürzt ! Zeit.
- Schlüssel, die sich auf ein bestimmtes Ziel beziehen, befinden sich in der entsprechenden Datei.
- Die Dateigröße ist erheblich gesunken. Wir haben die Unordnung sich wiederholender Zeilen beseitigt.
- Das Hinzufügen einer neuen Sprache zu einem Projekt wird ebenfalls erheblich vereinfacht.
- Wenn Sie ein neues Ziel erstellen, müssen Sie die Lokalisierung nicht mit einer Reihe unnötiger Zeilen kopieren. Erstellen Sie eine neue Datei mit dem Namen localizable.strings und fügen Sie nur das hinzu, was für dieses Ziel benötigt wird.
- Wenn Sie das alte Ziel wiederbeleben möchten, müssen Sie überhaupt nichts mit den Zeilen tun. Alles wird aus der Basisdatei abgerufen.
- Das Skript verschmutzt den Git nicht, das Ergebnis der Arbeit bleibt lokal und kann schmerzlos entfernt werden.
→ Das fertige Skript kann hier aufgenommen werden.
Ich gebe nicht vor, ein perfektes Skript zu sein. Pull-Anfragen sind willkommen.