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
Hier besprechen wir, was nötig ist, um eine Python-App am besten für die Lokalisierung vorzubereiten.
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:
- Sie lassen sich einfacher bearbeiten und ü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
JSON bietet eine der einfachsten Methoden, Übersetzungsdateien zu speichern. 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": {
"one": "Du bist $count Jahr alt",
"other": "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)
Danach lädt man die Datei wie folgt mit dem integrierten json
Paket hoch:
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
Statt JSON-Dateien lassen sich auch YAML-Dateien verwenden. Dafür wird das pyyaml
-Paket benötigt, um YAML zu unterstützen.
Angenommen, en.yaml
ist die Übersetzungsdatei für Englisch, mit dem folgenden Inhalt:
title: Interaktives Terminal
ques-name: "Name eingeben:"
ques-age: "Alter eingeben:"
ans-name: Hallo $name! Willkommen bei Phrase
ans-age:
one: Du bist $count Jahr alt
other: Du bist $count Jahre alt
ques-dob: "Bitte Geburtsdatum eingeben (JJJJ-MM-TT):",
ans-dob: Geboren am: $dob
Code-Sprache: PHP (php)
Entsprechend 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
ans-age:
one: Du bist $count Jahr alt
other: Du bis $count Jahre alt
ques-dob: "Bitte Geburtsdatum eingeben (JJJJ-MM-TT):",
ans-dob: Geboren am: $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 noch zwei weitere Funktionen:
- Ein String wird in ein datetime-Objekt umgewandelt
- Ein datetime-Objekt wird als String formatiert
Man sollte darauf aachten, 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
if file_format in supported_format:
# Liste der Dateien mit spezifischen Erweiterungen abrufen
files = glob.glob(os.path.join(translations_folder, f'*.{file_format}'))
for fil in files:
# Den Namen der Datei ohne Erweiterung abrufen, 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):
if loc in self.data:
self.locale = loc
else:
print('Invalid locale')
def get_locale(self):
return self.locale
def translate(self, key):
# Den Key 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
if file_format in supported_format:
# Liste der Dateien mit spezifischen Erweiterungen abrufen
Dateien = glob.glob(os.path.join(Ordner, f'*.{file_format}'))
for fil in files:
# Den Namen der Datei ohne Erweiterung abrufen, 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)
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
if self.locale not in self.data:
return key
text = self.data[self.locale].get(key, key)
return text
Code-Sprache: PHP (php)
Das Modul enthält außerdem zwei 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)
Interpolation zur Translator-Klasse hinzufügen
Für die Interpolation von Zeichenfolfen 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):
# Den Key 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)
# String-Interpolation
return Template(text).safe_substitute(**kwargs)
Code-Sprache: PHP (php)
Pluralisierung zur Translator-Klasse hinzufügen
Die Klasse babel.plural.PluralRule
kann für die Unterstützung der Pluralisierung importiert werden:
from babel.plural import PluralRule
Code-Sprache: JavaScript (javascript)
Unter der __init__
-Funktion lässt sich 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():
<code></code><//code>
def set_locale(self, loc):
if loc in self.data:
self.locale = loc
else:
print('Invalid 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
Code-Sprache: HTML, XML (xml)
Änderung des Codes unter der Funktion translate
zur Einbeziehung einer Pluralisierungsprüfung:
class Translator():
<code></code><//code>
def translate(self, key, **kwargs):
# Den Key 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)
# Typ dict steht für Schlüssel in Pluralform
if type(text) == dict:
count = kwargs.get('count', 1)
# Anzahl in einen Integer umwandeln
try:
count = int(count)
except Exception:
print('Invalid count')
return key
text = text.get(self.plural_rule(count), key)
return Template(text).safe_substitute(**kwargs)
Code-Sprache: HTML, XML (xml)
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
if file_format in supported_format:
# Liste der Dateien mit spezifischen Erweiterungen abrufen
files = glob.glob(os.path.join(translations_folder, f'*.{file_format}'))
for fil in files:
# Den Namen der Datei ohne Erweiterung abrufen, 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):
if loc in self.data:
self.locale = loc
else:
print('Invalid 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 Key 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)
# Typ dict steht für Schlüssel in Pluralform
if type(text) == dict:
count = kwargs.get('count', 1)
# Anzahl in einen Integer umwandeln
try:
count = int(count)
except Exception:
print('Invalid count')
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 Klasser Translator
als Modul in der Anwendung genutzt werden. Der folgende Code dient als Referenz für die grundlegende Nutzung des individuellen Translator
-Moduls:
# Modul importieren
import i18n
# Eine neue Translator-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
age = 30
print(translator.translate('ans-age', count=age))
# Du bist 30 Jahre alt
dob = '1992-01-01'
dob = i18n.parse_datetime(dob)
print(translator.translate('ans-dob', dob=dob))
#Geboren am: 01. Januar 1992
Code-Sprache: PHP (php)
Die Funktionalität des i18n
Moduls lässt sich problemlos erweitern, um je nach Bedarf weitere Funktionen 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. Dabei lassen sich übersetzbare Strings einfach mit der Funktion _()
umschließen:
# unmarkierte Strings
print('Interactive Terminal')
print('title')
# Als übersetzbar markierte Strings
print(_('Interactive 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: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2022-06-17 23:04+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: 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)
Dies bildet die Grundübersetzungsdatei. msgid
ist der einzigartige Identifier 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 Locale 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 sein wie der der Basis-POT-Datei. 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 "Interactive 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] "Du bist {count} Jahre alt"
Code-Sprache: PHP (php)
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, können mit der Funktion gettext.translation
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 abzurufen:
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)
Pluralisierung mit ngettext hinzufügen
Für die Unterstützung einer Pluralisierung lässt sich die Funktion ngettext
nutzen. Dabei werden drei Eingabeargumente 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. So gibt es im Englischen zwei, im Arabischen sechs Pluralformen.
Ein Kommentar am Anfang der Datei zeigt, wie die Pluralform einer Nachricht für eine Locale bestimmt wird. Ein 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 Pluralformen
"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 Pluralformen
"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 abgerufen 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))
# Du bist 1 Jahr alt
print(ngettext('ans-age', 'ans-age-plural', age).format(count=12))
# Du bist 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
translations = {}
supported_langs = ['en', 'de']
# Übersetzungsdateien dynamisch laden
for 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 Funktionen _
oder ngettext
aufrufen, um die gewünschten Übersetzungstexte abzurufen:
import gettext
translations = {}
supported_langs = ['en', 'de']
# Übersetzungsdateien dynamisch laden
for 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
# Die aktive Locale auf de ändern
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)
Dann einfach 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 wird nicht mit einer sofort einsatzbereiten Implementierung zum Anzeigen von Text für Sprachen von rechts nach links geliefert. 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. Das Modul wird mit dem folgenden Befehl installiert:
pip install python-bidi
Mit der Funktion get_display
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
lässt sich wie folgt erstellen:
from datetime import timedelta
delta = timedelta(
seconds=27,
minutes=5,
hours=8,
days=50,
weeks=2
)
# 64 Tage, 8:05:27
Code-Sprache: PHP (php)
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.
🤿 Mehr erfahren » In der strftime und strptime-Dokumentation finden sich genauere Informationen.
Der folgende Code zeigt unterschiedliche String-Ausgaben je nach Eingabeformat-String an:
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')
# 12. Jun 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')
# 12. Jun 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 akzeptiert die strptime
-Funktion zwei Eingabeargumente:
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)
Hier wird erklärt, wie sich lokalisierte Datumsangaben mit Babel formatieren lassen.
Alternativ kann das Modul babel.dates
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 » Mehr Informationenüber das babel
-Modul findest du unter Babels i18n-Vorteile für mehrsprachige Apps.
Okay, zurück zur Datumsformatierung. babel.dates
bietet die folgenden Funktionen:
- format_time
- format_date
- format_datetime
Dieser Code zeigt, wie sich die Formatierungsfunktionen von Babel nutzen lassen
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. Jun 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 der deutschen Locale
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, der 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.
🤿 Mehr erfahren » In der Dokumentation zu den babel.dates-Feldern gibt es mehr Informationen über individuelle Muster.
Wie lässt sich Babel für den Umgang mit Zeitzonen nutzen?
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 amerikanisches Englisch (en_US
) und Deutsch (de_DE
). Das liegt hauptsächlich daran, dass in verschiedenen Sprachen unterschiedliche Symbole für Dezimalpunkte und Tausendertrennzeichen verwendet werden.
🤿 Mehr erfahren » Unser umfassender Leitfaden zur Zahlenlokalisierung deckt Gruppierungen, Trennzeichen, Zahlensysteme und mehr ab.
Das Locale-Modul zur Zahlenformatierung verwenden – 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
# Englisch
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
# Englisch
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 Funktion format_string
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)
123.456,78
locale.format_string('%10.2f', 123456.78, grouping=True)
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.E
wird als Notation für die Zehnerpotenz verwendet
Der folgende Code 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)