
Flask i18n: izdelajte večjezično aplikacijo s Flask-Babelom
Od osnov gettext do uvedbe v produkcijo: internacionalizirajte svojo aplikacijo Flask s Flask-Babelom, datotekami PO in avtomatiziranim prevajanjem z umetno inteligenco.
Namestite Flask-Babel
Flask-Babel je standardna razširitev za internacionalizacijo Flaska. GNU gettext poveže s Flaskom in predlogami Jinja2 ter že ob namestitvi zagotovi funkcije za prevajanje, izbiro področnih nastavitev in podporo časovnim pasovom.
pip install Flask-BabelNastavite Babel
Ustvarite datoteko babel.cfg, s katero določite, kje naj pybabel poišče prevedljive nize, nato pa inicializirajte Flask-Babel s funkcijo za izbiro področnih nastavitev, ki za vsak zahtevek določi jezik vsebine.
# 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)Označite nize za prevajanje
Vsak niz, ki ga vidi uporabnik, v kodi Python ovijte z gettext(), v predlogah Jinja2 pa z _(). Za nize, opredeljene ob nalaganju modula (na primer oznake obrazcev in nastavitve), ki morajo biti prevedeni pozneje med obdelavo zahtevka, uporabite 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>Izvlecite sporočila
Zaženite pybabel extract, da v izvorni kodi in predlogah poiščete prevedljive nize. S tem ustvarite datoteko .pot (Portable Object Template). Nato inicializirajte kataloge za vsak ciljni jezik oziroma posodobite obstoječe, ko se izvorni nizi spremenijo.
# 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 translationsPrevedite datoteke PO
Odprite ustvarjene datoteke .po in za vsak msgid izpolnite vrednost msgstr. Datoteke PO so navadno besedilo — urejate jih lahko neposredno, uporabite urejevalnik PO (na primer Poedit) ali pa prevajanje avtomatizirate z orodji umetne inteligence.
# 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"Prevedite prevode v strojno obliko
Datoteke .po prevedite v binarne datoteke .mo z ukazom pybabel compile. Flask-Babel med izvajanjem bere datoteke .mo — datotek .po ne more brati neposredno. Po vsaki posodobitvi prevodov jih morate znova prevesti v strojno obliko.
# 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.Obravnavajte množinske oblike in spremenljivke
Za nize, katerih oblika je odvisna od števila, uporabite ngettext(). Funkcija sprejme edninsko obliko, množinsko obliko in število. Babel samodejno uporabi ustrezno pravilo za množinske oblike posameznega jezika — angleščina ima 2 obliki, ruščina 3, arabščina 6, japonščina pa 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 товаров в вашей корзине"Dodajte preklapljanje področnih nastavitev
Izdelajte izbirnik jezika, ki uporabnikovo izbiro shrani v sejo Flask. Funkcijo locale_selector posodobite tako, da najprej preveri sejo in šele nato uporabi zaznavanje brskalnika.
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>Avtomatizirajte prevajanje
Ko je nastavitev Flask-Babela končana, svoje datoteke PO prevedite z umetno inteligenco. Cikel izvlečenja, prevajanja in prevajanja v strojno obliko avtomatizirajte v cevovodu CI/CD, da bodo prevodi usklajeni z izvorno kodo.
# 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 translationsDodatek: pametno nadomestno izbiranje področnih nastavitev s flask-babel-locale-chain
Flask-Babel privzeto uporabi neposredno privzete področne nastavitve, kadar uporabnikove želene področne nastavitve niso na voljo. Uporabnik pt-BR, za katerega so na voljo samo prevodi pt-PT, zato namesto portugalščine vidi angleščino. flask-babel-locale-chain doda nastavljive verige nadomestnih področnih nastavitev, da se sorodne različice jezika uporabijo v naravnem zaporedju.
# 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)Avtomatizirajte preverjanje kakovosti prevodov
Pogoste pasti
Datoteke .po niste prevedli v .mo
Uporaba gettext() na ravni modula
Nizi med izvlečenjem niso zajeti
Napake kodiranja datotek PO
Priporočena struktura datotek
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/Preizkusite i18n Agent zdaj
Spustite prevajalsko datoteko sem
JSON, YAML, PO, XML, CSV, Markdown, Properties
ali kliknite za izbiro
Ciljni jeziki