Launch a website in several languages
A business website in three languages with a language switcher, translated page titles and URLs that search engines index per language.
1 Friday evening: decide languages and URLs
- Pick the languages from real customers (e.g. English, Spanish, French).
- Use one URL prefix per language:
/en/,/es/,/fr/. Search engines index each version separately, and links can be shared in a specific language. - List every page and every piece of text on it. Text inside images can't be translated; avoid it.
Done when: you have a table of pages × languages and who will check each translation.
2 Saturday morning: Flask-Babel setup
python -m venv .venv && source .venv/bin/activate
pip install flask flask-babel
# app.py
from flask import Flask, g, request, redirect, render_template, abort
from flask_babel import Babel, _
LANGS = ["en", "es", "fr"]
app = Flask(__name__)
babel = Babel(app, locale_selector=lambda: g.get("lang", "en"))
@app.url_value_preprocessor
def pull_lang(endpoint, values):
g.lang = (values or {}).pop("lang", "en")
if g.lang not in LANGS:
abort(404)
@app.url_defaults
def add_lang(endpoint, values):
if "lang" not in values and app.url_map.is_endpoint_expecting(endpoint, "lang"):
values["lang"] = g.get("lang", "en")
@app.route("/")
def root():
best = request.accept_languages.best_match(LANGS) or "en"
return redirect(f"/{best}/")
@app.route("/<lang>/")
def home():
return render_template("home.html", title=_("Web apps for your business"))
In templates wrap every string: {{ _("Contact us") }}.
Done when: /es/ renders the page (still in English) and url_for("home") keeps the current language.
3 Saturday afternoon: translate
pybabel extract -F babel.cfg -o messages.pot .
pybabel init -i messages.pot -d translations -l es
pybabel init -i messages.pot -d translations -l fr
# fill in translations/<lang>/LC_MESSAGES/messages.po, then:
pybabel compile -d translations
Use placeholders, never string concatenation: _("Hello, %(name)s", name=user), so each language can put the name where it belongs. Have a native speaker review the important pages.
Done when: all three languages show translated text, and adding a new string is extract → update → translate → compile.
4 Sunday morning: switcher and SEO
- A language switcher that links to the same page in the other language (not the homepage).
<html lang="{{ g.lang }}">, translated<title>and meta description.hreflanglinks in<head>so search engines connect the versions:
{% for l in ["en", "es", "fr"] %}
<link rel="alternate" hreflang="{{ l }}" href="{{ url_for(request.endpoint, lang=l, _external=True) }}">
{% endfor %}
<link rel="alternate" hreflang="x-default" href="{{ url_for(request.endpoint, lang='en', _external=True) }}">
Done when: every page shows the right lang, title and hreflang set in the page source.
5 Sunday afternoon: deploy
Deploy to Render with pybabel compile in the build command, add a sitemap.xml that lists every page in every language, and submit it in Google Search Console.
Done when: a search for your business in Spanish shows the /es/ page within a few weeks.
Mit diesen Lernpfaden tiefer einsteigen
Weitere Playbooks
- schedule_sendAutomate a daily report with Python, cron and emailA script that pulls data every morning, builds a short summary with a chart, and emails it to you, running unattended on a small Linux server.
- account_balance_walletBuild an offline budget tracker app (PWA)An installable app that records income and expenses, works offline, shows a monthly chart and exports to CSV, with no server and no account.
- event_availableBuild an online booking system for a small businessCustomers pick a free time slot, book it and get an email confirmation; the owner sees and cancels bookings in a simple admin page.