
Flask i18n: направите вишејезичну апликацију помоћу Flask-Babel
Од основа gettext система до постављања у продукцију: интернационализујте Flask апликацију помоћу Flask-Babel, PO датотека и аутоматизованог AI превођења.
Инсталирајте Flask-Babel
Flask-Babel је стандардни додатак за Flask интернационализацију. Интегрише GNU gettext са Flask и Jinja2 шаблонима и одмах пружа функције за превођење, избор локала и подршку за временске зоне.
pip install Flask-BabelПодесите Babel
Направите датотеку babel.cfg да алатки pybabel наведете где да тражи преводиве текстове, а затим иницијализујте Flask-Babel функцијом за избор локала која одређује језик за сваки захтев.
# 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)Означите текстове за превођење
Обухватите сваки текст намењен кориснику функцијом gettext() у Python коду и _() у Jinja2 шаблонима. Користите 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>Издвојте поруке
Покрените pybabel extract да скенирате изворни код и шаблоне у потрази за преводивим текстовима. Тиме се прави .pot (Portable Object Template) датотека. Затим иницијализујте каталоге за сваки циљни језик или ажурирајте постојеће када се изворни текстови промене.
# 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 translationsПреведите PO датотеке
Отворите генерисане .po датотеке и попуните вредности msgstr за сваки msgid. PO датотеке су обичан текст — можете директно да их уређујете, користите PO уређивач као што је Poedit или аутоматизујете превођење помоћу AI алатки.
# 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"Компајлирајте преводе
Компајлирајте .po датотеке у бинарне .mo датотеке помоћу pybabel compile команде. Flask-Babel током извршавања чита .mo датотеке — не може директно да чита .po датотеке. Морате поново да их компајлирате после сваког ажурирања превода.
# 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.Обрадите множину и променљиве
Користите ngettext() за текстове осетљиве на множину. Функција прима облик једнине, облик множине и број. Babel аутоматски користи исправно правило множине за сваки језик — енглески има 2 облика, руски 3, арапски 6, а јапански 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 товаров в вашей корзине"Додајте промену локала
Направите бирач језика који чува избор корисника у Flask сесији. Ажурирајте функцију locale_selector тако да прво провери сесију, па пређе на откривање из прегледача.
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>Аутоматизујте преводе
Када завршите подешавање Flask-Babel система, преведите PO датотеке помоћу AI технологије. Аутоматизујте циклус издвајања, превођења и компајлирања у CI/CD pipeline систему да преводи остану усклађени са изворним кодом.
# 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 translationsДодатно: паметни резервни локали уз flask-babel-locale-chain
Flask-Babel подразумевано одмах прелази на подразумевани локал када жељени локал корисника није доступан. Корисник локала pt-BR који има само преводе за pt-PT види енглески уместо португалског. flask-babel-locale-chain додаје подесиве ланце резервних локала како би се сродни локали природно надовезивали.
# 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)Аутоматизујте квалитет превода
Уобичајене замке
Заборављено компајлирање .po у .mo
Употреба gettext() на нивоу модула
Издвајање пропушта текстове
Грешке кодирања PO датотеке
Препоручена структура датотека
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/Испробајте i18n Agent сада
Пустите датотеку за превођење овде
JSON, YAML, PO, XML, CSV, Markdown, Properties
или кликните за избор
Циљни језици