
Flask i18n: Bumuo ng Multi-Language App gamit ang Flask-Babel
Mula sa mga batayan ng gettext hanggang production deployment: i-internationalize ang inyong Flask app gamit ang Flask-Babel, PO files, at automated AI translation.
I-install ang Flask-Babel
Ang Flask-Babel ang standard na internationalization extension para sa Flask. Ini-integrate nito ang GNU gettext sa Flask at mga template ng Jinja2, at nagbibigay ng translation functions, pagpili ng locale, at timezone support out of the box.
pip install Flask-BabelI-configure ang Babel
Gumawa ng babel.cfg file para sabihan ang pybabel kung saan mag-scan ng mga translatable string, pagkatapos ay i-initialize ang Flask-Babel gamit ang isang locale selector function na tumutukoy kung aling wika ang ihahain sa bawat request.
# 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)Markahan ang Mga String para sa Pagsasalin
Balutin ang bawat user-facing string sa gettext() sa Python code at _() sa mga template ng Jinja2. Gamitin ang lazy_gettext() para sa mga string na dinefine sa module load time (tulad ng mga label ng form at configuration) na kailangang maisalin sa request time.
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>I-extract ang Mga Mensahe
Patakbuhin ang pybabel extract para i-scan ang inyong source code at mga template para sa mga translatable string. Gumagawa ito ng .pot (Portable Object Template) file. Pagkatapos, i-initialize ang mga catalog para sa bawat target language, o i-update ang mga umiiral kapag nagbago ang mga source string.
# 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 translationsIsalin ang Mga PO File
Buksan ang mga nagawang .po file at punan ang mga value ng msgstr para sa bawat msgid. Plain text ang mga PO file — maaari ninyo itong i-edit nang direkta, gumamit ng PO editor tulad ng Poedit, o i-automate ang pagsasalin gamit ang mga AI tool.
# 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"I-compile ang Mga Pagsasalin
I-compile ang inyong mga .po file sa binary .mo file gamit ang pybabel compile. Binabasa ng Flask-Babel ang mga .mo file sa runtime — hindi nito direktang mababasa ang mga .po file. Kailangan ninyong mag-recompile pagkatapos ng bawat pag-update ng pagsasalin.
# 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.Hawakan ang Mga Plural at Variable
Gumamit ng ngettext() para sa mga string na sensitibo sa plural. Tumatanggap ito ng singular form, plural form, at count. Awtomatikong ginagamit ng Babel ang tamang plural rule para sa bawat wika — may 2 anyo ang English, 3 ang Russian, 6 ang Arabic, at 1 ang Japanese.
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 товаров в вашей корзине"Magdagdag ng Pagpapalit ng Locale
Bumuo ng language selector na nag-iimbak ng pagpili ng user sa Flask session. I-update ang inyong locale_selector function para suriin muna ang session, saka mag-fallback sa browser detection.
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>I-automate ang Mga Pagsasalin
Kapag kumpleto na ang inyong Flask-Babel setup, isalin ang inyong mga PO file gamit ang AI. I-automate ang extract-translate-compile cycle sa inyong CI/CD pipeline upang panatilihing naka-sync ang mga pagsasalin sa inyong source code.
# 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 translationsBonus: Smart Locale Fallback gamit ang flask-babel-locale-chain
Bilang default, diretsong nagfa-fallback ang Flask-Babel sa default locale kapag hindi available ang preferred locale ng user. Ang pt-BR user na mayroon lang pt-PT translations ay makakakita ng English sa halip na Portuguese. Nagdaragdag ang flask-babel-locale-chain ng mga nako-configure na fallback chain para natural na mag-cascade ang mga magkakaugnay na locale.
# 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)I-automate ang Kalidad ng Pagsasalin
Mga Karaniwang Pagkakamali
Nakalimutang I-compile ang .po sa .mo
Paggamit ng gettext() sa Module Level
Hindi Nai-e-extract ang Mga String
Mga Error sa Encoding ng PO File
Inirerekomendang File Structure
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/Subukan ang i18n Agent Ngayon
I-drop dito ang inyong translation file
JSON, YAML, PO, XML, CSV, Markdown, Properties
o i-click para mag-browse
Mga target language