python 46 lines · 8 steps

Per-request localization in Flask with Babel

How Flask-Babel picks a locale per request and localizes both messages and datetimes.

Explained by highlit
1from flask import Flask, request, g, jsonify
2from flask_babel import Babel, gettext as _, format_datetime
3from datetime import datetime
4 
5app = Flask(__name__)
6app.config["BABEL_DEFAULT_LOCALE"] = "en"
7app.config["BABEL_DEFAULT_TIMEZONE"] = "UTC"
8 
9SUPPORTED_LOCALES = ["en", "es", "fr", "de", "ja"]
10 
11 
12def select_locale():
13 requested = request.args.get("lang")
14 if requested in SUPPORTED_LOCALES:
15 return requested
16 
17 header = request.headers.get("X-User-Locale")
18 if header in SUPPORTED_LOCALES:
19 return header
20 
21 return request.accept_languages.best_match(SUPPORTED_LOCALES) or app.config["BABEL_DEFAULT_LOCALE"]
22 
23 
24babel = Babel(app, locale_selector=select_locale)
25 
26 
27@app.before_request
28def store_locale():
29 g.locale = str(select_locale())
30 
31 
32@app.route("/api/greeting")
33def greeting():
34 name = request.args.get("name", _("friend"))
35 return jsonify(
36 locale=g.locale,
37 message=_("Hello, %(name)s! Welcome back.", name=name),
38 server_time=format_datetime(datetime.utcnow(), format="long"),
39 )
40 
41 
42@app.after_request
43def expose_locale(response):
44 response.headers["Content-Language"] = g.get("locale", app.config["BABEL_DEFAULT_LOCALE"])
45 response.headers.add("Vary", "Accept-Language")
46 return response
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Locale selection should fall back through explicit choice, custom headers, then the client's Accept-Language.
  2. 2Storing the resolved locale on g makes it available across the whole request lifecycle without recomputing it.
  3. 3Advertising Content-Language and Vary lets caches and clients handle localized responses correctly.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Per-request localization in Flask with Babel — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code