Das Erstellen einer guten Anwendung ist nicht einfach. Unabhängig davon, welche einzigartige und nützliche Anwendung Sie schreiben, wenn der Benutzer sie nicht mag, haben Sie, wie er sagt, ein großes Problem. Die meisten Menschen mögen und verscheuchen nicht alles, was sie nicht verstehen. Häufig sind die Benutzeroberfläche und die Buchstaben die sichtbare Spitze des Eisbergs Ihrer Anwendung, anhand derer der Benutzer sie bewertet. Daher ist die Lokalisierung von allem, was der Benutzer sieht, äußerst wichtig.
Denken Sie daran, dass es vor zehn Jahren, als das Internet gerade erst begann, in das Leben der Massen einzutreten, und viele der heutigen IT-Giganten sich mit ein paar Dutzend Mitarbeitern in der Phase der Start-up-Zwerge befanden, in der Reihenfolge der Dinge lag, dem Benutzer einen Brief in englischer Sprache zu senden. Und die Benutzer waren damit einverstanden. Wenn heute alles im Internet vorhanden ist und Sie nicht sieben Felder in Ihrer Stirn haben müssen, keine Hochschulausbildung haben oder Englisch sprechen müssen, um es zu verwenden, wird es als schlechte Form angesehen, die Lokalisierung in Ihrer Anwendung nicht zu unterstützen. Übrigens wird in unserem Unternehmen die Lokalisierung aller UI-Texte bereits in 20 Sprachen durchgeführt und die Liste der unterstützten Sprachen wächst ständig.
In Go werden wie in einer eher jungen Sprache alle modernen Webentwicklungstrends auf der Ebene von Basispaketen implementiert und erfordern kein zusätzliches „Tanzen mit einem Tamburin“. (Ich habe vor ein paar Jahren angefangen, Go zu lernen, aber ich erinnere mich noch an das Gefühl „entdeckter Superkräfte“, das ich in den ersten Tagen nach dem Erlernen dieser Sprache erlebt habe. Es schien, dass ich jetzt jede Aufgabe realisieren kann, indem ich nur ein paar Zeilen schreibe.)
Natürlich haben sie auch die Lokalisierung in Go nicht umgangen. Die darin enthaltene Lokalisierung ist mit den folgenden Basispaketen praktisch sofort verfügbar: golang.org/x/text/language , golang.org/x/text/message und golang.org/x/text/feature/plural . Schauen wir uns an, wie einfach es in Go in nur einer halben Stunde ist. Mit diesen Paketen können Sie eine nicht triviale Aufgabe wie die Lokalisierung von Nachrichten implementieren.
Mit Blick auf die Zukunft möchte ich sagen, dass der Zweck dieses Artikels in erster Linie darin besteht, die Leistungsfähigkeit und Schönheit von Go aufzuzeigen und die grundlegenden Funktionen von Nachrichtenpaketen für die Arbeit mit Lokalisierungen hervorzuheben. Wenn Sie nach einer Lösung für eine Produktionsanwendung suchen, möchten Sie möglicherweise eine bessere Standardbibliothek . Die Vorteile von go-i18n sind viele Sterne auf Github (darunter auch meine) und große Flexibilität. Es gibt jedoch Argumente gegen seine Verwendung: Möglicherweise benötigen Sie nicht all diese Flexibilität und Funktionalität. Warum eine externe Bibliothek verwenden, wenn alles bereits in der Sprache selbst implementiert ist? Wenn Sie bereits ein eigenes Übersetzungssystem mit eigenen Formaten haben, funktioniert diese Bibliothek "wie sie ist" höchstwahrscheinlich nicht und Sie müssen sie trotzdem ändern. und am Ende ist die Verwendung einer Bibliothek eines Drittanbieters nicht so interessant und informativ wie die Verwendung von etwas selbst.
Wir formulieren die Grundvoraussetzungen für die umzusetzende Aufgabe. Es gibt: a) Beschriftungen im Yaml-Format: "Beschriftungsname: Übersetzungstext" ; Die Übersetzungssprache wird im Dateinamen angegeben, z. B. ru.yml. b) E-Mail-Vorlagen in HTML. Basierend auf den Eingabeparametern: Gebietsschema und Datenarray muss lokalisierter Text der Nachricht generiert werden.
Und fangen wir an ... Aber zuerst noch ein paar Worte zum Nachrichtenpaket (golang.org/x/text/message). Es dient zum Formatieren der Ausgabe lokalisierter Zeichenfolgen. Message implementiert die Schnittstelle des Standard-FMT-Pakets und kann diese ersetzen. Anwendungsbeispiel:
message.SetString(language.Russian, "toxic", "") message.SetString(language.Japanese, "toxic", "毒性") message.NewPrinter(language.Russian).Println(“toxic”) message.NewPrinter(language.Japanese).Println(“toxic”)
Damit das Paket das Etikett „sehen“ kann, muss es zuerst deklariert werden. Im Beispiel wird hierfür die SetString-Funktion verwendet. Als Nächstes wird ein Drucker für die ausgewählte Sprache erstellt und eine lokalisierte Zeichenfolge direkt angezeigt.
Um unser Problem zu lösen, könnten wir eine Go-Datei mit allen Tags generieren. Dies ist jedoch nicht sehr praktisch, da Sie diese Datei jedes Mal neu generieren und die Anwendung erneut erstellen müssen, wenn Sie neue Tags hinzufügen. Eine andere Möglichkeit, Nachrichten über unsere Tags zu senden, ist die Verwendung von Wörterbüchern. Ein Wörterbuch ist eine Struktur, die die Beschriftungssuchschnittstelle Lookup (Schlüsselzeichenfolge) (Datenzeichenfolge, ok bool) implementiert.
Die Option Wörterbücher passt zu uns. Zunächst definieren wir die Struktur des Wörterbuchs und implementieren die Lookup-Schnittstelle dafür:
type dictionary struct { Data map[string]string } func (d *dictionary) Lookup(key string) (data string, ok bool) { if value, ok := d.Data[key]; ok { return "\x02" + value, true } return "", false }
Sparsimieren Sie alle Beschriftungen aus Yaml-Dateien in eine Sammlung von Wörterbüchern, bei denen es sich um eine Map im Wörterbuchformat handelt , wobei lang ein Sprach-Tag im BCP47- Format ist.
func parseYAMLDict() (map[string]catalog.Dictionary, error) { dir := "./translations" files, err := ioutil.ReadDir(dir) if err != nil { return nil, err } translations := map[string]catalog.Dictionary{} for _, f := range files { yamlFile, err := ioutil.ReadFile(dir + "/" + f.Name()) if err != nil { return nil, err } data := map[string]string{} err = yaml.Unmarshal(yamlFile, &data) if err != nil { return nil, err } lang := strings.Split(f.Name(), ".")[0] translations[lang] = &dictionary{Data: data} } return translations, nil }
Wir installieren die Sammlung von Wörterbüchern in der Init-Funktion, damit die Wörterbücher vom Nachrichtenpaket verwendet werden können, wenn die Anwendung gestartet wird.
func init() { dict, err := parseYAMLDict() if err != nil { panic(err) } cat, err := catalog.NewFromMap(dict) if err != nil { panic(err) } message.DefaultCatalog = cat }
Im Moment haben wir also die Verfügbarkeit der Lokalisierung von Etiketten aus unseren Dateien an einer beliebigen Stelle im Programm erreicht:
message.NewPrinter(language.Russian).Println(“label_name”)
Es ist Zeit, mit dem zweiten Teil der Aufgabe fortzufahren und unsere lokalisierten Etiketten in den E-Mail-Vorlagen zu ersetzen. Stellen Sie sich zum Beispiel eine einfache Nachricht vor - einen Begrüßungsbrief bei der Registrierung eines Benutzers:
Hallo, Bill Smith!
Zum Parsen verwenden wir ein anderes Standardpaket - html / template . Wenn Sie Vorlagen in Vorlagen analysieren, können Sie Ihre Funktionen über .Funcs () festlegen :
template.New(tplName).Funcs(fmap).ParseFiles(tplName)
Fügen Sie der Vorlage eine Funktion hinzu, die Beschriftungen übersetzt und Variablen in ihnen ersetzt, und nennen Sie sie übersetzen . Analysecode für Vorlagen:
Die resultierende Briefvorlage ./templates/hello.html:
<!DOCTYPE html> <head> <title>{{translate "hello_subject"}}</title> </head> <body> {{translate "hello_msg" .Name .LastName}} </body> </html>
Da wir in
translate die
Sprintf- Funktion zur Lokalisierung verwenden, werden die Variablen im Beschriftungstext mit der Syntax dieser Funktion genäht. Beispielsweise ist
% s eine Zeichenfolge,
% d eine Ganzzahl.
Markierte Dateien
en.yml
hello_subject: Greeting mail hello_msg: Hello, %s %s!
ru.yml
hello_subject: hello_msg: , %s %s!
Damit ist im Prinzip die Lokalisierung von Buchstaben fertig! Nachdem wir nur ein paar Dutzend Codezeilen geschrieben haben, verfügen wir über leistungsstarke Funktionen, mit denen Buchstaben beliebiger Komplexität in Dutzenden von Sprachen lokalisiert werden können.
Wenn Ihnen dieses Beispiel gefallen hat, können Sie die Pluralisierung selbst implementieren, indem Sie Variablennamen für Variablen in Beschriftungen anstelle von % s verwenden und Funktionen in Beschriftungen verwenden. Ich habe dies absichtlich nicht getan, um Ihrer Fantasie Raum zu lassen.
Der Code in den Beispielen wurde speziell geschrieben, um die Funktionen des Nachrichtenpakets zu demonstrieren, und erhebt keinen Anspruch auf Idealheit . Eine vollständige Auflistung des Codes ist auf github verfügbar.