Software-Lokalisierung
Der ultimative Guide zur Python-Lokalisierung

Die Lokalisierung von Python-Anwendungen ist ein Prozess mit vielen beweglichen Teilen. Aber wenn es richtig gemacht wird, kann die Zugänglichkeit verbessert, die Nutzerbindung erhöht und die Marktreichweite erweitert werden.
Um den Einstieg zu erleichtern, werden in diesem Tutorial bewährte Praktiken gezeigt, wie Python-Apps mit JSON- oder YAML-Dateien für die Lokalisierung vorbereitet werden können, und gängige Module besprochen, die dabei helfen.
Es bietet wertvolle Einblicke sowohl für Entwickler, die die globale Anziehungskraft verbessern möchten, als auch für Unternehmen, die in neue Märkte expandieren wollen.
UI-Strings mit Python internationalisieren – so geht’s.
Einige wichtige Fragen dazu, wie eine Python-App am besten für die Lokalisierung vorbereitet wird.
Warum werden Übersetzungsdateien für die Benutzeroberfläche verwendet?
Es gibt einige Vorteile bei der Verwendung von Übersetzungsdateien anstelle von fest codierten Übersetzungstexten in der Anwendung:
- Es ist einfacher zu bearbeiten und zu übersetzen, da die meisten Übersetzer mit Code nicht vertraut sind.
- Falsche Übersetzungstexte lassen sich leicht identifizieren, ohne im Code suchen zu müssen
- Es ist nicht notwendig, Anwendungen neu zu erstellen, wenn es eine Änderung an einer Übersetzung gibt (abhängig von den verwendeten Programmiersprachen und Frameworks)
Im Kern können Übersetzungsdateien in verschiedenen Formaten vorliegen. Im folgenden Abschnitt wird gezeigt, wie die Internationalisierung einer Python-Anwendung erfolgen kann:
- Benutzerdefinierte Implementierung mit JSON/YAML als Übersetzungsdateien
babel
undgettext
für die Arbeit mit PO- und MO-Übersetzungsdateien
Installation
Bevor es losgeht, sollten die folgenden Python-Pakete installiert werden:
babel
: Tools für die Internationalisierung und Lokalisierung in Pythonpyyaml
: Unterstützung beim Lesen und Schreiben von YAML-Dateien
Die folgenden Befehle können in der Kommandozeile ausgeführt werden, um die Pakete zu installieren.
pip install pyyaml
pip install babel
JSON-Übersetzungsdateien laden – so geht’s
Eine der einfachsten Methoden, um Übersetzungsdateien zu speichern, ist per JSON. Zum Beispiel kann eine neue Datei namens en.json
mit den folgenden Elementen erstellt werden:
{
"title": "Dialogstation",
"ques-name": "Namen eingeben:",
"ques-age": "Bitte Alter eingeben:",
"ans-name": "Hallo, $name!" Willkommen bei Phrase
"ans-age": {
"eins": "Du bist $count Jahr alt",
"Sonstiges": "Du bist $count Jahre alt"
},
"ques-dob": "Bitte Geburtsdatum eingeben (JJJJ-MM-TT):",
"ans-dob": Geboren am $dob
}
Code-Sprache: JSON / JSON mit Kommentaren (json)
Dann einfach mit dem integrierten json
Paket wie folgt laden:
import json
mit open('filename.json', 'r', encoding='utf8') als f:
data = json.load(f)
Code-Sprache: JavaScript (javascript)
YAML-Übersetzungsdateien laden – so geht’s
YAML-Dateien können anstelle von JSON verwendet werden. Das pyyaml
-Paket wird benötigt, um YAML zu unterstützen.
Angenommen, en.yaml
ist die Übersetzungsdatei für Englisch mit dem folgenden Inhalt:
title: Interaktives Terminal
Fragenname: "Name eingeben:"
Fragenalter: "Alter eingeben:"
ans-name: Hallo, $name! Willkommen bei Phrase
Antwortalter:
eins: Du bist $count Jahre alt
Sonstiges: Du bist $count Jahre alt
ques-dob: "Geburtsdatum eingeben (JJJJ-MM-TT):"
ans-dob: Du wurdest am $dob
geboren
Ebenso sollte die deutsche Übersetzungsdatei de.yaml
heißen:
title: Dialogstation
ques-name: "Name eingeben:"
ques-age: "Alter eingeben:"
ans-name: Hallo, $name! Willkommen bei Phrase
Antwort-Alter:
eins: Man ist $count Jahre alt
Sonstiges: Man ist $count Jahre alt
ques-dob: Geburtsdatum (JJJJ-MM-TT) eingeben:
ans-dob: Geburtsdatum ist der $dob
Code-Sprache: PHP (php)
Es kann mit dem pyyaml
Paket wie folgt geladen werden:
import yaml
mit open('filename.yml', 'r', encoding='utf8') als f:
data = yaml.safe_load(f)import json
Code-Sprache: JavaScript (javascript)
Translator-Klasse
Mit dem bisher Gelernten wird ein individuelles Modul mit einer Translator
-Klasse mit den folgenden Features erstellt:
- Übersetzungsdateien beim Start laden
- Die aktive Locale wird festgelegt
- Die Pluralregeln werden festgelegt
- Der Übersetzungstext wird übersetzt und formatiert
Zusätzlich beinhaltet das Modul auch 2 weitere Funktionen, um:
- Ein String wird in ein datetime-Objekt umgewandelt
- Ein datetime-Objekt wird als String formatiert
Darauf achten, dass die Dateistruktur wie folgt aussieht:
.
├── data (Ordner mit JSON- oder YAML-Übersetzungsdateien)/
│ ├── en.json
│ ├── de.json
│ ├── en.yaml
│ └── de.yaml
├── i18n.py (benutzerdefiniertes Modul)
└── main.py (Hauptanwendung)
Code-Sprache: Klartext (plaintext)
Eine neue Python-Datei namens i18n.py
mit folgendem Code erstellen:
import json
import glob
import os
import yaml
from datetime import datetime
from babel.dates import format_datetime
supported_format = ['json', 'yaml']
class Translator():
def __init__(self, translations_folder, file_format='json', default_locale='en'):
# Initialisierung
self.data = {}
self.locale = 'en'
# prüfen, ob das Format unterstützt wird
wenn file_format in supported_format enthalten ist
# Liste der Dateien mit spezifischen Erweiterungen bekommen
files = glob.glob(os.path.join(translations_folder, f'*.{file_format}'))
für fil in files:
# Den Namen der Datei ohne Erweiterung holen, wird als Locale-Name verwendet
loc = os.path.splitext(os.path.basename(fil))[0]
mit open(fil, 'r', encoding='utf8') als f:
if file_format == 'json':
self.data[loc] = json.load(f)
elif file_format == 'yaml':
self.data[loc] = yaml.safe_load(f)
def set_locale(self, loc):
wenn loc in self.data:
self.locale = loc
else:
print('Ungültiges Gebietsschema')
def get_locale(self):
return self.locale
def translate(self, key):
# Den Schlüssel statt des Übersetzungstextes zurückgeben, wenn das Gebietsschema nicht unterstützt wird
if self.locale not in self.data:
return key
text = self.data[self.locale].get(key, key)
return text
def str_to_datetime(dt_str, format='%Y-%m-%d'):
return datetime.strptime(dt_str, format)
def datetime_to_str(dt, format='MMMM dd, yyyy', loc='en'):
return format_datetime(dt, format=format, locale=loc)
Das glob
-Modul wird verwendet, um die Übersetzungsdateien je nach file_format
-Wert dynamisch zu laden. Es werden entweder json
oder yaml
akzeptiert:
def __init__(self, folder, file_format='json', default_locale='en'):
# Prüfen, ob das Format unterstützt wird
wenn file_format in supported_format:
# Liste von Dateien mit bestimmten Erweiterungen abrufen
Dateien = glob.glob(os.path.join(Ordner, f'*.{file_format}'))
für Datei in Dateien:
# Den Namen der Datei ohne Erweiterung holen, der als Locale-Name verwendet wird
Ort = os.path.splitext(os.path.basename(Datei))[0]
mit open(Datei, 'r', encoding='utf8') als f:
wenn file_format == 'json':
self.data[Ort] = json.load(f)
elif file_format == 'yaml':
self.data[loc] = yaml.safe_load(f)
Code-Sprache: PHP (php)
Die Kernfunktion ist die translate
-Funktion, die den Übersetzungstext basierend auf der aktuell aktiven Locale zurückgibt:
def translate(self, key):
# stattdessen den Schlüssel zurückgeben
wenn self.locale nicht in self.data enthalten ist:
Schlüssel zurückgeben
text = self.data[self.locale].get(key, key)
Text zurückgeben
Code-Sprache: PHP (php)
Das Modul enthält außerdem 2 zusätzliche globale Funktionen für die Datumsformatierung:
def str_to_datetime(dt_str, format='%Y-%m-%d'):
return datetime.strptime(dt_str, format)
def datetime_to_str(dt, format='MMMM dd, yyyy', loc='en'):
return format_datetime(dt, format=format, locale=loc)
Code-Sprache: JavaScript (javascript)
Zur Translator-Klasse wird Interpolation hinzugefügt
Für die Zeichenfolgeninterpolation kann das integrierte Template-String-Modul verwendet werden. Folgende Import-Anweisung wird hinzugefügt:
from string import Template
Code-Sprache: JavaScript (javascript)
Anstatt die Variable text
direkt unter der Funktion translate
zurückzugeben, wird sie mit der Klasse Template
instanziiert und die Funktion safe_substitute
wie folgt aufgerufen:
def translate(self, key, **kwargs):
# Wenn das Gebietsschema nicht unterstützt wird, wird der Schlüssel anstelle des Übersetzungstextes zurückgegeben
Falls self.locale nicht in self.data enthalten ist:
Gibt den Schlüssel zurück
text = self.data[self.locale].get(key, key)
# String-Interpolation
return Template(text).safe_substitute(**kwargs)
Code-Sprache: PHP (php)
Pluralisierung zur Translator-Klasse hinzufügen
Die babel.plural.PluralRule
Klasse kann für Pluralisierungsunterstützung importiert werden:
from babel.plural import PluralRule
Code-Sprache: JavaScript (javascript)
Unter der __init__
-Funktion eine neue plural_rule
-Variable wie folgt initialisieren:
def __init__(self, folder, file_format='json', default_locale='en'):
self.data = {}
self.locale = default_locale
self.plural_rule = PluralRule({'one': 'n ist
Code-Sprache: PHP (php)
class Translator():
def set_locale(self, loc):
if loc in self.data:
self.locale = loc
else:
print('Ungültige Locale')
def get_locale(self):
return self.locale
def set_plural_rule(self, rule):
versuchen:
self.plural_rule = PluralRule(rule)
except Exception:
print('Ungültige Pluralregel')
def get_plural_rule(self):
return self.plural_rule
Änderung des Codes unter der translate
Funktion zur Einbeziehung einer Pluralisierungsprüfung:
class Translator():
...
def translate(self, key, **kwargs):
# Rückgabe des Schlüssels statt des Übersetzungstextes, wenn das Gebietsschema nicht unterstützt wird
if self.locale not in self.data:
Schlüssel zurückgeben
text = self.data[self.locale].get(key, key)
# Typ dict steht für Schlüssel in Pluralform
if type(text) == dict:
count = kwargs.get('count', 1)
# Anzahl in einen Integer umwandeln
Versuchen:
count = int(count)
außer Exception:
print('Ungültige Anzahl')
Schlüssel zurückgeben
text = text.get(self.plural_rule(count), key)
Rückgabe von Template(text).safe_substitute(**kwargs)
Der komplette Code für die Translator
-Klasse sieht wie folgt aus:
from babel.plural import PluralRule
import json
from string import Template
import glob
import os
import yaml
from datetime import datetime
from babel.dates import format_datetime
supported_format = ['json', 'yaml']
class Translator():
def __init__(self, translations_folder, file_format='json', default_locale='en'):
# Initialisierung
self.data = {}
self.locale = 'en'
self.plural_rule = PluralRule({'one': 'n ist 1'})
# prüfen, ob das Format unterstützt wird
wenn file_format in supported_format:
# Liste von Dateien mit bestimmten Erweiterungen anzeigen
Dateien = glob.glob(os.path.join(translations_folder, f'*.{file_format}'))
für Datei in Dateien:
# Den Namen der Datei ohne Erweiterung holen, wird als Locale-Name genutzt
loc = os.path.splitext(os.path.basename(fil))[0]
mit open(Datei, 'r', encoding='utf8') als f:
wenn file_format == 'json':
self.data[loc] = json.load(f)
elif file_format == 'yaml':
self.data[loc] = yaml.safe_load(f)
def set_locale(self, loc):
if loc in self.data:
self.locale = loc
else:
print('Ungültige Locale')
def get_locale(self):
return self.locale
def set_plural_rule(self, rule):
try:
self.plural_rule = PluralRule(rule)
except Exception:
print('Ungültige Pluralregel')
def get_plural_rule(self):
return self.plural_rule
def translate(self, key, **kwargs):
# Den Schlüssel anstelle des Übersetzungstextes zurückgeben, wenn das Gebietsschema nicht unterstützt wird
wenn self.locale nicht in self.data enthalten ist:
Schlüssel zurückgeben
text = self.data[self.locale].get(key, key)
# Typ dict repräsentiert Schlüssel in der Pluralform
wenn type(text) == dict:
count = kwargs.get('count', 1)
# parse count to int
Versuch:
count = int(count)
außer Exception:
print('Ungültige Anzahl')
return key
text = text.get(self.plural_rule(count), key)
return Template(text).safe_substitute(**kwargs)
def parse_datetime(dt, input_format='%Y-%m-%d', output_format='MMMM dd, yyyy', output_locale='en'):
dt = datetime.strptime(dt, input_format)
return format_datetime(dt, format=output_format, locale=output_locale)
Einsatz des Translator-Moduls in der Anwendung
Nun kann die Übersetzer
Klasse als Modul in der Anwendung genutzt werden. Schau dir das folgende Code-Schnipsel an, es dient als Referenz für die grundlegende Nutzung des individuellen Übersetzer
Moduls:
# Modul importieren
import i18n
# Eine neue Übersetzer-Klasse mit dem Pfad zu den Daten erstellen
translator = i18n.Translator('data/')
Code-Sprache: PHP (php)
name = 'John Doe'
print(translator.translate('ans-name', name=name))
# Hallo, John Doe! Willkommen bei Phrase
# Die aktive Locale auf de ändern
translator.set_locale('de')
print(translator.translate('ans-name', name=name))
# Hallo, John Doe! Willkommen bei Phrase
Alter = 30
print(translator.translate('ans-age', count=Alter))
# Du bist 30 Jahre alt
dob = '1992-01-01'
dob = i18n.parse_datetime(dob)
print(translator.translate('ans-dob', dob=dob))
# Am 01. Januar 1992 geboren
Code-Sprache: PHP (php)
Es ist einfach, die Funktionalität des i18n
Moduls zu erweitern, um mehr Funktionen je nach Bedarf zu unterstützen.
Wie kann die Python-UI mit gettext internationalisiert werden?
Alternativ kann das gettext
Modul zur Internationalisierung von Python-Anwendungen genutzt werden. gettext
verwendet PO (auch bekannt als POT) und MO-Nachrichtenkatalogdateien.
🗒 Hinweis » PO-Dateien stellen die von Menschen bearbeitbaren Übersetzungsdateien dar, während MO-Dateien maschinenlesbar für den Gebrauch durch gettext
sind.
Zum Glück ergänzt das babel
Paket das gettext
Modul hervorragend. babel
bietet folgende praktische Funktionen für die Arbeit mit Nachrichtenkatalogen:
extract
: Nachrichten aus Quelldateien extrahieren, um eine POT-Datei zu generiereninit
: neue Nachrichtenkataloge aus einer POT-Datei erstellenupdate
: vorhandene Nachrichtenkataloge in einer POT-Datei updatencompile
: POT-Dateien zu MO-Dateien kompilieren
Grundlegende Übersetzungsnachrichten
In der ersten Phase werden Strings in den Quelldateien als übersetzbar markiert. Einfach übersetzbare Strings mit der _()
Funktion umschließen:
# unmarkierte Strings
print('Interaktives Terminal')
print('title')
# Als übersetzbar markierte Strings
print(_('Interaktives Terminal'))
print(_('title'))
Code-Sprache: PHP (php)
pybabel extract -o data/messages.pot main_babel.py
Folgender Inhalt sollte in der Ausgabedatei data/messages.pot
enthalten sein:
msgid ""
msgstr ""
"Project-Id-Version: PROJEKT-VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Erstellungsdatum: 2022-06-17 23:04+0800\n"
"PO-Überarbeitungsdatum: JAHR-MO-TA STUNDE:MINUTE+ZONE\n"
"Letzter Übersetzer: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.10.1\n"
#: main_babel.py:11
msgid "title"
msgstr ""
#: main_babel.py:14
msgid "ques-name"
msgstr ""
#
Code-Sprache: PHP (php)
Die Grundübersetzungsdatei wird dargestellt. msgid
ist der einzigartige Bezeichner für jede zu übersetzende Nachricht, während msgstr
den Übersetzungstext repräsentiert. msgstr
kann vorerst leer bleiben, da der eigentliche Übersetzungstext in den PO-Dateien stehen sollte.
Während der Initialisierungsphase erzeugt das babel
Modul automatisch die relevanten Dateien für jede Locale. Durch Ausführen des folgenden Befehls für die en
Locale kann ein Test durchgeführt werden.
pybabel init -l en -i data/messages.pot -d data/
pybabel init -l de -i data/messages.pot -d data/
Der Inhalt jeder messages.po
Datei sollte derselbe wie der der Basis-POT-Datei sein. Als nächstes wird der entsprechende Übersetzungstext in die PO-Dateien eingefügt:
.
├── messages.pot
├── de/
│ └── LC_MESSAGES/
│ └── messages.po
└── en/
└── LC_MESSAGES/
└── messages.po
Code-Sprache: Klartext (plaintext)
#: main_babel.py:11
msgid "title"
msgstr "Interaktives Terminal"
#: main_babel.py:14
msgid "ques-name"
msgstr "Name eingeben:"
#: main_babel.py:16
msgid "ans-name"
msgstr "Hallo, {name}!" Willkommen bei Phrase"
#: main_babel.py:19
msgid "ques-age"
msgstr "Alter eingeben:"
#: main_babel.py:21
msgid "ans-age"
msgid_plural "ans-age-plural"
msgstr[0] "Du bist {count} Jahre alt"
msgstr[1] "Es sind {count} Jahre vergangen"
Am Ende wird der folgende Befehl ausgeführt, um PO-Dateien in MO-Dateien zu kompilieren:
pybabel compile -d data/
Der Ordner data
sollte wie folgt aussehen:
.
├── messages.pot
├── de/
│ └── LC_MESSAGES/
│ ├── messages.mo
│ └── messages.po
└── en/
└── LC_MESSAGES/
├── messages.mo
└── messages.po
Code-Sprache: Klartext (plaintext)
Sobald das erledigt ist, kann mit der gettext.translation
Funktion die Übersetzungsdateien geladen werden.
Zum Beispiel kann die install
Funktion aufgerufen werden, um sie als die aktuell aktive Locale festzulegen und den Übersetzungstext wie folgt zu erhalten:
import gettext
# Initialisierung
lang_en = gettext.translation('messages', localedir='data', languages=['en'])
# aktuelle Sprache auf en setzen
lang_en.install()
print(_('ans-name'))
# Hallo, John! Willkommen bei Phrase
Code-Sprache: PHP (php)
#: main_babel.py:16
msgid "ans-name"
msgstr "Hallo, {name}!" Willkommen bei Phrase
Code-Sprache: PHP (php)
import gettext
# Initialisierung
lang_en = gettext.translation('messages', localedir='data', languages=['en'])
# aktuelle Sprache auf en setzen
lang_en.install()
print(_('ans-name').format(name='John'))
# Hallo, John! Willkommen bei Phrase
print(_('ans-name').format(name='Kelly'))
# Hallo, Kelly! Willkommen bei Phrase
Code-Sprache: PHP (php)
Pluralisierungsunterstützung mit ngettext hinzufügen
Für Pluralisierungsunterstützung die ngettext
Funktion nutzen. 3 Eingabeargumente werden akzeptiert:
singular
: ID für Einzahlformplural
: ID für die Pluralformn
: Pluralbestimmer
print(ngettext('ans-age', 'ans-age-plural', age))
Code-Sprache: PHP (php)
Wie die gettext
-Funktion, gibt auch ngettext
die übersetzte Zeichenfolge zurück. Mit einer Funktion wie format
lässt sich im Ausgabestring einfach interpolieren:
print(ngettext('ans-age', 'ans-age-plural', age).format(count=age))
Code-Sprache: PHP (php)
Nach der Extraktion zeigt sich eine andere Syntax in der Basisübersetzungsdatei (POT):
#: main_babel.py:21
msgid "ans-age"
msgid_plural "ans-age-plural"
msgstr[0] ""
msgstr[1] ""
Code-Sprache: PHP (php)
Die Anzahl von msgstr
basiert auf der Anzahl der für das Gebietsschema festgelegten Pluralformen. Verschiedene Sprachregionen haben unterschiedliche Anzahlen an Pluralformen: Im Englischen gibt es 2 Pluralformen, im Arabischen 6.
Ein Kommentar am Anfang der Datei zeigt, wie die Pluralform einer Nachricht für eine Sprachregion bestimmt wird. Zum Beispiel:
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
Code-Sprache: JSON / JSON mit Kommentaren (json)
# 2 Pluralformen
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
# 3 plural forms
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
# 6 plural forms
"Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : "
"n%100>=3 && n%100<=10 ? 3 : n%100>=0 && n%100<=2 ? 4 : 5)\n"
Code-Sprache: HTML, XML (xml)
Der pluralisierte Text kann wie folgt erhalten werden:
import gettext
# Initialisierung
lang_en = gettext.translation('messages', localedir='data', languages=['en'])
# aktuelle Sprache auf en setzen
lang_en.install(names=['gettext', 'ngettext'])
print(ngettext('ans-age', 'ans-age-plural', age).format(count=1))
# Man ist 1 Jahr alt
print(ngettext('ans-age', 'ans-age-plural', age).format(count=12))
# Man ist 12 Jahre alt
Code-Sprache: PHP (php)
Einsatz von gettext in der Anwendung
Anstatt jede Locale einzeln zu laden, können die Übersetzungsdateien dynamisch geladen und in einem dict
Objekt wie folgt gespeichert werden:
import gettext
Übersetzungen = {}
supported_langs = ['en', 'de']
# Übersetzungsdateien dynamisch laden
für lang in supported_langs:
translations[lang] = gettext.translation('messages', localedir='data', languages=[lang])
Code-Sprache: PHP (php)
Einfach die gewünschte Locale festlegen und entweder die _
oder ngettext
Funktionen aufrufen, um die gewünschten Übersetzungstexte zu bekommen:
import gettext
Übersetzungen = {}
supported_langs = ['en', 'de']
# Übersetzungsdateien dynamisch laden
für lang in supported_langs:
translations[lang] = gettext.translation('messages', localedir='data', languages=[lang])
# aktive Sprache auf en einstellen
translations['en'].install(names=['gettext', 'ngettext'])
name = 'John Doe'
print(_('ans-name').format(name=name))
# Hallo, John Doe! Willkommen bei Phrase
# aktive Sprache auf de umstellen
translations['de'].install(names=['gettext', 'ngettext'])
print(_('ans-name').format(name=name))
# Hallo, John Doe! Willkommen bei Phrase
age = 30
text = ngettext('ans-age', 'ans-age-plural', age)
print(text)
# Du bist 30 Jahre alt
text = text.format(count=age)
print(text)
# Du bist 30 Jahre alt
Code-Sprache: PHP (php)
Die Datei wie gewohnt ausführen, und es sollte die gleiche Ausgabe wie zuvor mit JSON oder YAML erscheinen.
🤿 Mehr erfahren » Schau dir unseren Leitfaden zum Übersetzen von Python-Anwendungen mit dem GNU gettext-Modul an, um mehr über das gettext
Modul zu erfahren.
Wie kann eine Python-App Unterstützung für Sprachen von rechts nach links bieten?
Python kommt nicht mit einer sofort einsatzbereiten Implementierung zum Anzeigen von Text für Sprachen von rechts nach links, aber für solche Anwendungsfälle kann das python-bidi
Modul genutzt werden. python-bidi
ist eine Python-Umsetzung eines bidirektionalen (BiDi) Layouts. Es stellt eine praktische Funktion zur Verfügung, um Sprachen von rechts nach links darzustellen. Mit dem folgenden Befehl wird es installiert:
pip install python-bidi
Mit der get_display
Funktion kann ein String bidirektional angezeigt werden:
from bidi.algorithm import get_display
get_display('اَلْعَرَبِيَّةُ')
Code-Sprache: JavaScript (javascript)
You should get the following output when you print the result:
اَلْعَرَبِيَّةُ
How do I format localized dates and times in Python?
Python has its own built-in datetime
module for manipulating dates and times. It supports arithmetic operations on objects, making it extremely useful for localization and internationalization.
How do I work with date and time duration?
A timedelta
object represents the difference between 2 dates or times. You can think of it as a duration. It accepts the following input arguments:
datetime.timedelta(milliseconds=0, microseconds=0, seconds=0, minutes=0, hours=0, days=0, weeks=0)
Ein neues timedelta
kann wie folgt erstellt werden:
from datetime import timedelta
delta = timedelta(
seconds=27,
minutes=5,
hours=8,
50 Tage,
2 Wochen
)
64 Tage, 8:05:27
Code-Sprache: JavaScript (javascript)
from datetime import datetime, timedelta, timezone
# naive datetime-Obj
dt = datetime.now()
# 2022-06-12 15:48:40.014838
# Aware-Datetime-Objekt (GMT+8)
tz = timezone(timedelta(hours=8))
dt = datetime.now(tz=tz)
# 2022-06-12 15:48:40.014838+08:00
Code-Sprache: PHP (php)
Ein datetime
-Objekt unterstützt die folgenden Methoden zur Konvertierung von Datum und Uhrzeit:
strftime
: eindatetime
-Objekt gemäß einem gegebenen Format in eine Zeichenfolge umwandelnstrptime
: eine Zeichenfolge gemäß einem entsprechenden Format in eindatetime
-Objekt parsen
Die strftime
-Funktion akzeptiert eine Zeichenfolge, die das entsprechende Datums- und Uhrzeitformat angibt. Das ist praktisch, wenn der Inhalt einer Anwendung lokalisiert wird.
🤿 Tiefer eintauchen » In der strftime und strptime Dokumentation kann mehr darüber erfahren werden.
Schau dir den folgenden Code-Schnipsel an, der unterschiedliche String-Ausgaben je nach Eingabeformat-String anzeigt.
from datetime import datetime, timezone
dt = datetime(year=2022, month=6, day=12, hour=16, minute=32, second=45, tzinfo=timezone.utc)
dt.strftime('%Y-%m-%d %H:%M:%S')
# 2022-06-12 16:32:45
dt.strftime('%b %d, %Y')
# Jun 12, 2022
dt.strftime('%A (%I.%M %p)')
# Sonntag (16:32 Uhr)
dt.strftime('%c')
# So 12. Juni 16:32:45 2022
Code-Sprache: PHP (php)
Das Format ist abhängig von der aktuellen Spracheinstellung der Anwendung. Mit dem eingebauten locale
Modul lässt sich das ändern.
import locale
# aktuelle Spracheinstellung abrufen
locale.getlocale()
# ('English_Singapur', '1252')
locale.setlocale(locale.LC_ALL, 'de_DE')
# ('de_DE', 'ISO8859-1')
Code-Sprache: PHP (php)
from datetime import datetime, timezone
import locale
locale.setlocale(locale.LC_ALL, 'de_DE')
dt = datetime(year=2022, month=6, day=12, hour=16, minute=32, second=45, tzinfo=timezone.utc)
dt.strftime('%Y-%m-%d %H:%M:%S')
# 2022-06-12 16:32:45
dt.strftime('%b %d, %Y')
# Jun 12, 2022
dt.strftime('%A (%I.%M %p)')
# Sonntag (04.32 )
dt.strftime('%c')
# 12.06.2022 16:32:45
Code-Sprache: PHP (php)
Auf der anderen Seite nimmt die strptime
-Funktion 2 Eingabeargumente entgegen:
date_string
: eine Zeichenfolgen-Darstellung eines Datums, basierend auf dem 1989 C Standard.format
: das Format, um die Eingabedate_string
zu parsen
🗒 Hinweis » Beim Einlesen der Eingabe berücksichtigt die strptime
-Funktion die aktuelle Locale.
from datetime import datetime
text = '2022-06-12 16:32:45'
format = '%Y-%m-%d %H:%M:%S'
datetime.strptime(text, format)
# 2022-06-12 16:32:45
Code-Sprache: PHP (php)
Wie lokalisierte Datumsangaben mit Babel formatiert werden, wird hier erklärt.
Alternativ kann das babel.dates
Modul zur Formatierung von Datum und Uhrzeit genutzt werden.
Eine Anmerkung zu Babel
Das babel
Modul bietet eine Reihe von Hilfsmitteln für l10n und i18n in Python. Es wird aktiv gepflegt und bietet folgende Funktionen:
- Datums- und Zeitformatierung
- Zahlenformatierung
- Währungsformatierung
- Nachrichtenkataloge (Übersetzungsdateien) erstellen
🤿 Mehr erfahren » Um mehr über das babel
Modul zu erfahren, Babels i18n-Vorteile für mehrsprachige Apps anschauen.
OK, zurück zur Datumsformatierung. babel.dates
kommt mit den folgenden Funktionen:
- format_time
- format_date
- format_datetime
Hier ist ein Code-Schnipsel, der zeigt, wie die Formatierungsfunktionen von Babel genutzt werden:
from datetime import datetime, timezone
from babel.dates import format_time, format_date, format_datetime
dt = datetime(year=2022, month=6, day=12, hour=16, minute=32, second=45, tzinfo=timezone.utc)
# Nutzung des Standard-Medium-Formats
format_time(dt, locale='en_US')
# 16:32:45 Uhr
format_date(dt, locale='en_US')
# 12. Juni 2022
format_datetime(dt, locale='de_DE')
# 12. Juni 2022, 16:32:45
# Verwendung des vollständigen Formats
format_time(dt, format='full', locale='de_DE')
# 16:32:45 Uhr Koordinierte Weltzeit
format_date(dt, format='full', locale='de_DE')
# Sonntag, 12. Juni 2022
format_datetime(dt, format='full', locale='de_DE')
# Sonntag, 12. Juni 2022 um 16:32:45 Uhr Koordinierte Weltzeit
# Verwendung des deutschen Gebietsschemas
format_time(dt, format='full', locale='de_DE')
# 16:32:45 Koordinierte Weltzeit
format_date(dt, format='full', locale='de_DE')
# Sonntag, der 12. Juni 2022
format_datetime(dt, format='full', locale='de_DE')
# Sonntag, 12. Juni 2022 um 16:32:45 Koordinierte Weltzeit
Code-Sprache: PHP (php)
Das format
-Argument ist optional und kann eine der folgenden Optionen sein:
- Kurz
- Mittel (der Standardwert)
- Lang
- Komplett
🗒 Hinweis » Das endgültige Ergebnis hängt vom Eingabeargument locale
ab.
🤿 Tiefer eintauchen » In der Dokumentation zu den babel.dates Feldern gibt es mehr Informationen über individuelle Muster.
Wie kann Babel zur Arbeit mit Zeitzonen verwendet werden?
Mit der get_timezone
Funktion lässt sich ein neues Zeitzonenobjekt erstellen, das auf Zeitzonennamen wie US/Eastern
oder Europe/Berlin
basiert. Dann wird das Objekt als Eingabe für das tzinfo
-Argument übergeben:
from datetime import datetime, timezone
from babel.dates import get_timezone, format_datetime
dt = datetime(year=2022, month=6, day=12, hour=16, minute=32, second=45, tzinfo=timezone.utc)
eastern = get_timezone('US/Eastern')
berlin = get_timezone('Europe/Berlin')
# Verwendung der Eastern Time Zone
format_datetime(dt, format='full', locale='en_US', tzinfo=eastern)
# Sonntag, 12. Juni 2022 um 12:32:45 PM Eastern Daylight Time
# Verwendung der Berliner Zeitzone
format_datetime(dt, format=format, locale='en_US', tzinfo=berlin)
# Sonntag, 12. Juni 2022 um 18:32:45 Uhr Mitteleuropäische Sommerzeit
Code-Sprache: PHP (php)
Lokalisierte Zahlen in Python formatieren – so geht’s.
Die Zahlenformatierung kann bei der Internationalisierung knifflig sein. Zum Beispiel hat der Text 12,345
unterschiedliche Bedeutungen für Englisch US (en_US
) und Deutsch (de_DE
). Das liegt hauptsächlich daran, dass in verschiedenen Sprachen unterschiedliche Symbole für Dezimalpunkte und Tausendertrennzeichen verwendet werden.
🤿 Tiefer eintauchen » Unser prägnanter Leitfaden zur Zahlenlokalisierung deckt Gruppierungen, Trennzeichen, Zahlensysteme und mehr ab.
Das eingebaute Locale-Modul verwenden, um Zahlen zu formatieren – so geht’s.
Für die Umwandlung von Zeichenfolgen in Ganzzahlen oder Fließkommazahlen ist das Modul locale
eine gute Option. Es verfügt über die folgende eingebaute Funktion:
atoi
: Umwandlung einer Zeichenfolge in eine Ganzzahl unter Verwendung der aktuellen lokalen Zahlenkonventionenatof
: Ein String wird nach den aktuellen lokalen numerischen Konventionen in eine Fließkommazahl umgewandelt
Wenn 12,345
der Eingabestring ist, sehen die Ergebnisse von atof
für beide Sprachen so aus:
import locale
# English
locale.setlocale(locale.LC_ALL, 'en_US')
locale.atof('12,345')
# 12345.0
# Deutsch
locale.setlocale(locale.LC_ALL, 'de_DE')
locale.atof('12,345')
# 12.345
# English
locale.setlocale(locale.LC_ALL, 'en_US')
locale.atof('12.345')
# 12.345
# Deutsch
locale.setlocale(locale.LC_ALL, 'de_DE')
locale.atof('12.345')
# 12345.0
Code-Sprache: PHP (php)
Andererseits kann die format_string
Funktion genutzt werden, um eine Zahl in eine lokalisierte Zeichenfolge zu konvertieren. Folgendes Eingabe-Argument wird akzeptiert:
format
: eine Zeichenfolge, die die Format-Spezifikation darstelltval
: eine ZahlGruppierung
: ob die Gruppierung berücksichtigt wird. Gruppierung bezieht sich auf eine Zahlenfolge, die angibt, an welchen relativen Positionen das Tausendertrennzeichen erwartet wird. Standardmäßig istFalse
eingestellt.
Schau dir den folgenden Code-Ausschnitt an:
import locale
locale.setlocale(locale.LC_ALL, 'en_US')
locale.format_string('%10.2f', 123456.78)
# 123456.78
locale.format_string('%10.2f', 123456.78, grouping=True)
# 123.456,78
locale.setlocale(locale.LC_ALL, 'de_DE')
locale.format_string('%10.2f', 123456.78, grouping=True)
123.456,78
locale.format_string('%10.2f', 123456.78)
123.456,78
Code-Sprache: PHP (php)
Lokalisierte Zahlen mit Babel formatieren – so geht’s
Alternativ lassen sich die folgenden lokalspezifischen Formatierungsfunktionen aus dem babel.numbers
Modul nutzen:
format_decimal
: formatiert eine gegebene Zahl basierend auf dem Eingabe-Localeformat_percent
: formatiert eine gegebene Zahl prozentual basierend auf dem Eingabe-Localeformat_scientific
: formatiert eine gegebene Zahl in wissenschaftlicher Notation basierend auf dem Eingabe-Locale. Es wirdE
als Notation für die Zehnerpotenz verwendet
Der folgende Code-Schnipsel veranschaulicht die Ausgabe für format_decimal
bei Verwendung verschiedener Gebietsschemas:
from babel.numbers import format_decimal, format_percent, format_scientific
format_decimal(12345, locale='en_US')
# 12.345
format_decimal(12345.67, locale='en_US')
12.345,67
format_decimal(12345, locale='de_DE')
# 12.345
format_decimal(12345.67, locale='de_DE')
12.345,67
format_percent(0.34, locale='en_US')
# 34%
format_percent(0.34, locale='de_DE')
# 34 %
format_scientific(1234567, locale='en_US')
# 1.234567E6
format_scientific(1234567, locale='de_DE')
# 1.234567E6
Code-Sprache: PHP (php)
import locale
from babel.numbers import format_currency
locale.setlocale(locale.LC_ALL, 'en_US')
locale.currency(1234.56)
# $1234.56
locale.currency(1234.56, international=True)
# USD1234.56
format_currency(1234.56, 'USD', locale='en_US')
# $1,234.56
# die Währung auf EURO setzen
format_currency(1234.56, 'EUR', locale='en_US')
# €1.234,56
# die Währung auf Japan YEN setzen
format_currency(1234.56, 'JPY', locale='en_US')
# JPY1.234,56
locale.setlocale(locale.LC_ALL, 'de_DE')
locale.currency(1234.56)
# 1234,56 €
locale.currency(1234.56, international=True)
# 1234,56 EUR
format_currency(1234.56, 'USD', locale='de_DE')
1.234,56 $
format_currency(1234.56, 'EUR', locale='de_DE')
1.234,56 €
format_currency(1234.56, 'JPY', locale='de_DE')
1.234,56 JPY
Code-Sprache: PHP (php)