Skip to main content

Flask i18n: Flask-Babel ile çok dilli bir uygulama geliştirin

gettext temellerinden üretim ortamına dağıtıma kadar Flask uygulamanızı Flask-Babel, PO dosyaları ve otomatik yapay zeka çevirisiyle uluslararasılaştırın.

1

Flask-Babel'i kurun

Flask-Babel, Flask için standart uluslararasılaştırma uzantısıdır. GNU gettext'i Flask ve Jinja2 şablonlarıyla bütünleştirerek kullanıma hazır çeviri işlevleri, yerel ayar seçimi ve saat dilimi desteği sağlar.

Flask-Babel, Babel'i (Python i18n kitaplığı) sarmalar ve Flask'ın istek yaşam döngüsüyle bütünleştirir. gettext(), ngettext() ve lazy_gettext() işlevlerinin yanı sıra tarayıcı üst bilgilerinden otomatik yerel ayar algılama olanağı sunar.
Terminal
pip install Flask-Babel
2

Babel'i yapılandırın

pybabel'e çevrilebilir dizeleri nerede tarayacağını bildirmek için bir babel.cfg dosyası oluşturun. Ardından her istekte hangi dilin sunulacağını belirleyen bir yerel ayar seçici işleviyle Flask-Babel'i başlatın.

babel.cfg
# babel.cfg — tells pybabel where to find translatable strings
[python: **.py]
[jinja2: **/templates/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_
app.py
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)
locale_selector işlevi her istekte çağrılır. Derlenmiş bir .mo dosyası bulunmayan yerel ayarı döndürürse Flask-Babel sessizce varsayılan yerel ayara geçer. Hata oluşmaz; dizeler yalnızca çevrilmeden görünür.
3

Dizeleri çeviri için işaretleyin

Kullanıcıya gösterilen her dizeyi Python kodunda gettext(), Jinja2 şablonlarında ise _() ile sarmalayın. Modül yüklenirken tanımlanan ve daha sonra istek sırasında çevrilmesi gereken dizeler (form etiketleri ve yapılandırma gibi) için lazy_gettext() kullanın.

app.py
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'))
templates/index.html
{# 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>
Jinja2 şablonlarında gettext() yerine _() kullanın; bu, standart gettext kısaltmasıdır ve şablonlarınızı sade tutar. Flask-Babel, _() işlevini otomatik olarak Jinja2 globali şeklinde kaydeder.
4

İletileri ayıklayın

Kaynak kodunuzu ve şablonlarınızı çevrilebilir dizeler için taramak üzere pybabel extract komutunu çalıştırın. Bu işlem bir .pot (Portable Object Template) dosyası oluşturur. Ardından her hedef dil için katalogları başlatın veya kaynak dizeler değiştiğinde mevcut katalogları güncelleyin.

Terminal
# 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
İlk ayıklama işleminden sonra her zaman pybabel update komutunu çalıştırın; init komutunu kullanmayın. Mevcut bir dil klasöründe init komutunu çalıştırmak tüm mevcut çevirilerin üzerine yazar. update komutu, mevcut çevirileri korurken yeni dizeleri birleştirir.
5

PO dosyalarını çevirin

Oluşturulan .po dosyalarını açın ve her msgid için msgstr değerlerini doldurun. PO dosyaları düz metindir; bunları doğrudan düzenleyebilir, Poedit gibi bir PO düzenleyicisi kullanabilir veya çeviriyi yapay zeka araçlarıyla otomatikleştirebilirsiniz.

translations/de/LC_MESSAGES/messages.po
# 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 dosyaları, her dizenin kaynak kodunuzda nerede kullanıldığını gösteren bağlam yorumlarını (#: ile başlayan satırlar) içerir. Çevirmenler bağlamı anlamak için bunlardan yararlanır. Bunları koruyun; pybabel extract tarafından otomatik olarak oluşturulurlar.
6

Çevirileri derleyin

pybabel compile kullanarak .po dosyalarınızı ikili .mo dosyalarına derleyin. Flask-Babel çalışma zamanında .mo dosyalarını okur; .po dosyalarını doğrudan okuyamaz. Her çeviri güncellemesinden sonra yeniden derlemeniz gerekir.

Terminal
# 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.
Bir .po dosyasını düzenledikten sonra çeviriler görünmüyorsa büyük olasılıkla pybabel compile komutunu çalıştırmayı unutmuşsunuzdur. Bu, en yaygın Flask-Babel sorunudur. Üretim ortamında bu sorunu önlemek için derleme adımını dağıtım betiğinize ekleyin.
7

Çoğulları ve değişkenleri yönetin

Çoğul biçimine duyarlı dizeler için ngettext() kullanın. Bu işlev tekil biçimi, çoğul biçimi ve sayıyı alır. Babel her dil için doğru çoğul kuralını otomatik olarak kullanır; İngilizcede 2, Rusçada 3, Arapçada 6 ve Japoncada 1 biçim vardır.

app.py
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)
Plural forms in .po files
# 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 товаров в вашей корзине"
Çoğul mantığı için asla if count == 1 kullanmayın. Fransızca gibi diller 0'ı tekil kabul eder. Rusçada ve Arapçada İngilizcede bulunmayan biçimler vardır. Seçimi ngettext() ve Babel'in CLDR çoğul kurallarına bırakın.
8

Yerel ayar değiştirme özelliği ekleyin

Kullanıcının seçimini Flask oturumunda saklayan bir dil seçici geliştirin. locale_selector işlevinizi önce oturumu denetleyecek, ardından tarayıcı algılamasına geçecek şekilde güncelleyin.

app.py
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']
    )
templates/components/language_switcher.html
{# 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>
Oturumdaki yerel ayarı değiştirdikten sonra Flask-Babel'i geçerli isteğin yerel ayarını yeniden okumaya zorlamak için flask_babel.refresh() işlevini çağırın. refresh() olmadan eski yerel ayar bir sonraki isteğe kadar kullanılmaya devam eder.
9

Çevirileri otomatikleştirin

Flask-Babel kurulumunuz tamamlandıktan sonra PO dosyalarınızı yapay zeka kullanarak çevirin. Çevirileri kaynak kodunuzla eş zamanlı tutmak için ayıklama-çeviri-derleme döngüsünü CI/CD işlem hattınızda otomatikleştirin.

Terminal
# 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
Aşamalı çeviri yapın: yeni dizeler ekleyip pybabel update komutunu çalıştırdığınızda her şeyi yeniden oluşturmak yerine yalnızca yeni ve çevrilmemiş girdileri (boş msgstr değerlerini) çevirin. Böylece insanlar tarafından incelenmiş çeviriler korunur.

Ek özellik: flask-babel-locale-chain ile akıllı yerel ayar yedeklemesi

Flask-Babel, kullanıcının tercih ettiği yerel ayar kullanılamadığında varsayılan olarak doğrudan varsayılan yerel ayara geçer. Yalnızca pt-PT çevirileri bulunan bir pt-BR kullanıcısı Portekizce yerine İngilizce görür. flask-babel-locale-chain, ilişkili yerel ayarların doğal biçimde birbirine geçmesini sağlayan yapılandırılabilir yedekleme zincirleri ekler.

app.py
# 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)
flask-babel-locale-chain açık kaynaklı bir Python paketidir. GitHub'da github.com/i18n-agent/flask-babel-locale-chain adresinden inceleyebilirsiniz.

Çeviri kalitesini otomatikleştirin

Eksik anahtarları ve bozuk yer tutucuları kullanıma sunulmadan önce i18n-validate ile yakalayın. Gerçek çeviriler gelmeden önce kullanıcı arayüzünüzü i18n-pseudo ile sözde çeviriler kullanarak sınayın.

Yaygın hatalar

.po dosyasını .mo biçimine derlemeyi unutmak

Flask-Babel, .po dosyalarını değil derlenmiş .mo dosyalarını okur. .po dosyalarını düzenledikten sonra çeviriler görünmüyorsa pybabel compile -d translations komutunu çalıştırın. Bu adımı dağıtım betiğinize ekleyin.

Modül düzeyinde gettext() kullanmak

gettext() bir istek bağlamı gerektirir. Çevrilen dizeleri modül düzeyinde (sınıf öznitelikleri, sabitler) tanımlıyorsanız bunun yerine lazy_gettext() kullanın. Bu işlev, dize bir istekte gerçekten işlenene kadar çeviriyi erteler.

Ayıklama sırasında dizelerin atlanması

pybabel extract yalnızca babel.cfg içindeki kalıplarla eşleşen dosyaları tarar. Dizeler ayıklanmıyorsa babel.cfg kalıplarınızın dosya yapınızla eşleştiğini denetleyin, gecikmeli çağrıları ayıklamak için -k lazy_gettext ekleyin ve Jinja2 şablonlarının doğru uzantıyı (.html, .jinja2) kullandığından emin olun.

PO dosyası kodlama hataları

PO dosyaları UTF-8 ile kodlanmalıdır. UnicodeDecodeError görürseniz .po dosyanızdaki Content-Type üst bilgisini denetleyin; charset=UTF-8 yazmalıdır. Bazı düzenleyiciler farklı kodlamalarla kaydeder; düzenledikten sonra her zaman doğrulayın.

Önerilen dosya yapısı

Project 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/

i18n Agent'ı şimdi deneyin

Çeviri dosyanızı buraya bırakın

JSON, YAML, PO, XML, CSV, Markdown, Properties

veya göz atmak için tıklayın

Hedef diller

Kayıt gerekmezAnında fiyat tahmini

Flask i18n hakkında sık sorulan sorular