
Flask i18n: izveidojiet daudzvalodu lietotni ar Flask-Babel
No gettext pamatiem līdz izvietošanai produkcijas vidē: internacionalizējiet Flask lietotni ar Flask-Babel, PO failiem un automatizētu MI tulkošanu.
Instalēt Flask-Babel
Flask-Babel ir standarta Flask internacionalizācijas paplašinājums. Tas integrē GNU gettext ar Flask un Jinja2 veidnēm, uzreiz nodrošinot tulkošanas funkcijas, lokalizācijas izvēli un laika joslu atbalstu.
pip install Flask-BabelKonfigurēt Babel
Izveidojiet babel.cfg failu, kas norāda pybabel, kur meklēt tulkojamas virknes, pēc tam inicializējiet Flask-Babel ar lokalizācijas izvēles funkciju, kas nosaka katram pieprasījumam apkalpojamo valodu.
# babel.cfg — tells pybabel where to find translatable strings
[python: **.py]
[jinja2: **/templates/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_from flask import Flask, request
from flask_babel import Babel
app = Flask(__name__)
app.config['BABEL_DEFAULT_LOCALE'] = 'en'
app.config['BABEL_DEFAULT_TIMEZONE'] = 'UTC'
# Directory where translations live (default: "translations")
app.config['BABEL_TRANSLATION_DIRECTORIES'] = 'translations'
def get_locale():
# 1. Check URL parameter or session
# 2. Fall back to browser Accept-Language header
return request.accept_languages.best_match(['en', 'de', 'ja', 'es', 'fr'])
babel = Babel(app, locale_selector=get_locale)Atzīmēt tulkojamas virknes
Katru lietotājiem paredzēto virkni Python kodā ietveriet ar gettext(), bet Jinja2 veidnēs — ar _(). Moduļa ielādes laikā definētām virknēm (piemēram, veidlapu etiķetēm un konfigurācijai), kas vēlāk jātulko pieprasījuma laikā, izmantojiet lazy_gettext().
from flask_babel import gettext, ngettext, lazy_gettext
# In views — gettext() for immediate translation
@app.route('/')
def index():
flash(gettext('Your profile has been updated.'))
return render_template('index.html',
title=gettext('Home'))
# In forms/config — lazy_gettext() for deferred translation
class LoginForm(FlaskForm):
username = StringField(lazy_gettext('Username'))
password = PasswordField(lazy_gettext('Password'))
submit = SubmitField(lazy_gettext('Sign In')){# In Jinja2 templates, use _() shorthand for gettext #}
<h1>{{ _('Welcome to our app') }}</h1>
<p>{{ _('Hello, %(name)s!', name=user.name) }}</p>
<footer>
{{ _('Copyright %(year)s Example Corp.', year=2026) }}
</footer>Izvilkt ziņojumus
Palaidiet pybabel extract, lai skenētu pirmkodu un veidnes, meklējot tulkojamas virknes. Tas izveido .pot (Portable Object Template) failu. Tad inicializējiet katalogus katrai mērķa valodai vai atjauniniet esošos, kad mainās avota virknes.
# Extract translatable strings from source code
pybabel extract -F babel.cfg -k lazy_gettext -o messages.pot .
# Initialize a new language (first time only)
pybabel init -i messages.pot -d translations -l de
pybabel init -i messages.pot -d translations -l ja
pybabel init -i messages.pot -d translations -l es
# Update existing catalogs when source strings change
pybabel update -i messages.pot -d translationsTulkot PO failus
Atveriet ģenerētos .po failus un aizpildiet msgstr vērtības katram msgid. PO faili ir vienkāršs teksts: varat tos rediģēt tieši, izmantot tādu PO redaktoru kā Poedit vai automatizēt tulkošanu ar MI rīkiem.
# translations/de/LC_MESSAGES/messages.po
msgid "Welcome to our app"
msgstr "Willkommen in unserer App"
msgid "Hello, %(name)s!"
msgstr "Hallo, %(name)s!"
msgid "Your profile has been updated."
msgstr "Ihr Profil wurde aktualisiert."
msgid "Username"
msgstr "Benutzername"
msgid "Password"
msgstr "Passwort"
msgid "Sign In"
msgstr "Anmelden"Kompilēt tulkojumus
Kompilējiet .po failus bināros .mo failos ar pybabel compile. Izpildlaikā Flask-Babel nolasa .mo failus — tas nevar tieši nolasīt .po failus. Pēc katra tulkojumu atjauninājuma tie jākompilē no jauna.
# Compile .po files to binary .mo files (required at runtime)
pybabel compile -d translations
# Flask-Babel reads .mo files, not .po files.
# You MUST compile after every translation update.Apstrādāt daudzskaitli un mainīgos
Daudzskaitlim jutīgām virknēm izmantojiet ngettext(). Tā pieņem vienskaitļa formu, daudzskaitļa formu un skaitu. Babel automātiski izmanto pareizo daudzskaitļa kārtulu katrai valodai: angļu valodā ir 2 formas, krievu — 3, arābu — 6, japāņu — 1.
from flask_babel import ngettext
@app.route('/cart')
def cart():
count = len(session.get('cart_items', []))
message = ngettext(
'%(num)d item in your cart', # singular
'%(num)d items in your cart', # plural
count # determines which form
)
return render_template('cart.html', message=message)# English: 2 forms (nplurals=2)
msgid "%(num)d item in your cart"
msgid_plural "%(num)d items in your cart"
msgstr[0] "%(num)d item in your cart"
msgstr[1] "%(num)d items in your cart"
# German: 2 forms (nplurals=2)
msgid "%(num)d item in your cart"
msgid_plural "%(num)d items in your cart"
msgstr[0] "%(num)d Artikel in Ihrem Warenkorb"
msgstr[1] "%(num)d Artikel in Ihrem Warenkorb"
# Japanese: 1 form (nplurals=1)
msgid "%(num)d item in your cart"
msgid_plural "%(num)d items in your cart"
msgstr[0] "カートに%(num)d個の商品があります"
# Russian: 3 forms (nplurals=3)
msgid "%(num)d item in your cart"
msgid_plural "%(num)d items in your cart"
msgstr[0] "%(num)d товар в вашей корзине"
msgstr[1] "%(num)d товара в вашей корзине"
msgstr[2] "%(num)d товаров в вашей корзине"Pievienot lokalizācijas pārslēgšanu
Izveidojiet valodas atlasītāju, kas glabā lietotāja izvēli Flask sesijā. Atjauniniet funkciju locale_selector, lai tā vispirms pārbaudītu sesiju un pēc tam atkāptos uz pārlūka noteikšanu.
from flask import session, redirect, url_for, request
from flask_babel import refresh
@app.route('/set-language/<lang>')
def set_language(lang):
session['lang'] = lang
refresh() # Force Flask-Babel to re-read the locale
return redirect(request.referrer or url_for('index'))
# Update get_locale to check session first
def get_locale():
# 1. Explicit user choice (stored in session)
if 'lang' in session:
return session['lang']
# 2. Browser Accept-Language header
return request.accept_languages.best_match(
['en', 'de', 'ja', 'es', 'fr']
){# Language switcher component #}
<nav class="language-switcher">
{% for lang, name in [('en','English'),('de','Deutsch'),
('ja','日本語'),('es','Español'),
('fr','Français')] %}
<a href="{{ url_for('set_language', lang=lang) }}"
class="{{ 'active' if get_locale() == lang }}">
{{ name }}
</a>
{% endfor %}
</nav>Automatizēt tulkošanu
Kad Flask-Babel iestatīšana ir pabeigta, tulkojiet PO failus ar MI. Automatizējiet izvilkšanas, tulkošanas un kompilēšanas ciklu CI/CD konveijerā, lai tulkojumi paliktu sinhronizēti ar pirmkodu.
# Translate your PO files with AI directly from your IDE
# or use the CLI in CI/CD:
npx i18n-agent translate translations/de/LC_MESSAGES/messages.po \
--source-lang en --target-lang de
# Bulk translate all languages at once:
npx i18n-agent translate messages.pot --lang de,ja,es,fr
# Then compile:
pybabel compile -d translationsPapildus: vieda lokalizācijas atkāpšanās ar flask-babel-locale-chain
Pēc noklusējuma Flask-Babel uzreiz atkāpjas uz noklusējuma lokalizāciju, ja lietotāja vēlamā lokalizācija nav pieejama. pt-BR lietotājs, kam ir tikai pt-PT tulkojumi, redz angļu, nevis portugāļu valodu. flask-babel-locale-chain pievieno konfigurējamas atkāpšanās ķēdes, lai saistītās lokalizācijas dabiski pārietu cita citā.
# pip install flask-babel-locale-chain
from flask_babel_locale_chain import LocaleChain
# Define fallback chains: pt-BR falls back to pt before en
locale_chain = LocaleChain({
'pt-BR': ['pt-BR', 'pt', 'en'],
'pt-PT': ['pt-PT', 'pt', 'en'],
'zh-Hant': ['zh-Hant', 'zh-Hans', 'en'],
'en-GB': ['en-GB', 'en', 'en-US'],
})
def get_locale():
requested = request.accept_languages.best_match(
['en', 'pt-BR', 'pt', 'zh-Hant', 'zh-Hans']
)
# Returns the best available locale from the chain
return locale_chain.resolve(requested)Automatizēt tulkojumu kvalitāti
Biežākās kļūdas
Aizmirsts kompilēt .po par .mo
gettext() lietošana moduļa līmenī
Izvilkšana izlaiž virknes
PO faila kodējuma kļūdas
Ieteicamā failu struktūra
my-flask-app/
├── app.py # Flask app with Babel config
├── babel.cfg # Extraction config
├── messages.pot # Template (extracted strings)
├── translations/
│ ├── de/
│ │ └── LC_MESSAGES/
│ │ ├── messages.po # German translations (editable)
│ │ └── messages.mo # Compiled binary (generated)
│ ├── ja/
│ │ └── LC_MESSAGES/
│ │ ├── messages.po
│ │ └── messages.mo
│ └── es/
│ └── LC_MESSAGES/
│ ├── messages.po
│ └── messages.mo
├── templates/
│ ├── base.html
│ ├── index.html
│ └── components/
│ └── language_switcher.html
├── requirements.txt
└── venv/Izmēģiniet i18n Agent tūlīt
Nometiet tulkošanas failu šeit
JSON, YAML, PO, XML, CSV, Markdown, Properties
vai noklikšķiniet, lai izvēlētos
Mērķa valodas