Localization¶
FlaskBB’s uses Weblate for crowdsourced translations.
There are two separate audiences for this workflow:
Translators who just want to translate existing strings into a language they speak. These contributors should use Weblate directly and never need to touch the CLI or a local checkout.
Developers who add or change translatable strings in the code, or who need to add support for a language that doesn’t have a translation yet.
Plugin Developers see the dedicated translations page Translating Plugins.
Getting Started¶
Which files Babel scans, and how, is configured in babel.cfg at the
project root:
[python: **/flaskbb/**.py]
[jinja2: **/templates/**.html]
In Python code, wrap user-facing strings in gettext/lazy_gettext
from flask_babelplus (conventionally aliased to _):
from flask_babelplus import gettext as _
flash(_("You have been logged in."), "success")
Use lazy_gettext instead of gettext for strings evaluated outside of
a request context (e.g. form labels defined at class-body scope), since it
defers translation until the string is actually rendered.
In Jinja templates, the gettext/ngettext helpers or the
{% trans %}{% endtrans %} blocks. See the Jinja documentation to see a complete
list of available translation functions.
<button>{{ gettext("Submit") }}</button>
<button>{% trans "Submit" endtrans%}</button>
What to mark for translation¶
Anything a forum user or admin might see in the browser: page text, flashed messages, form labels/errors, emails. This includes the admin panel, not just the public-facing forum.
CLI output (flaskbb ... command help text) is not
translated.
Submitting your own translation alongside a string change¶
If you’re adding/changing a string and can also translate it into a
language you speak, go ahead and edit that language’s messages.po
directly in the same PR — run flaskbb translations update first so the
msgid exists, then fill in your translation. Weblate merges against
whatever is already in the .po file rather than blindly overwriting it,
so your translation stays and simply shows up as already-translated (and
still editable) once Weblate picks up the change.
Plugins register their own translation directories via the
flaskbb_load_translations hook so their strings are
merged into the active locale alongside core FlaskBB’s. See
Translating Plugins for the plugin-specific workflow.
Adding new Languages¶
Core translations live under flaskbb/translations/<lang>/LC_MESSAGES,
one directory per language code (e.g. de, pt_BR). A plugin’s
translations live the same way under its own translations/ directory.
The flaskbb translations CLI group (see the CLI reference) drives the underlying pybabel calls:
flaskbb translations new LANGExtracts all marked strings into
messages.potand creates a newLANG/LC_MESSAGES/messages.pofor translators to fill in. Only needed once per language. Pass--plugin NAMEto add a language to a plugin instead of core.flaskbb translations update [--all] [--plugin NAME]Re-extracts strings from the source and merges any new/changed/removed
msgids into every existing.pofile. Run this after adding or changing translatable strings in code, before compiling.--allalso updates every installed plugin’s translations;--plugin NAMEupdates just one plugin.flaskbb translations compile [--all] [--plugin NAME]Compiles every
.pofile into the binary.moformat Flask-BabelPlus actually loads at runtime. Run this after editing a.pofile, or the changes won’t show up in the app.
A typical loop while adding a new string is:
flaskbb translations update
# edit flaskbb/translations/<lang>/LC_MESSAGES/messages.po by hand, or
# let Weblate pick up the new msgid from messages.pot
flaskbb translations compile
Weblate¶
Translators contribute through Weblate instead of opening
PRs against .po files directly. Weblate pulls messages.pot
straight from this repository, so as soon as a PR that ran flaskbb
translations update is merged to master, the new/changed strings show up
on Weblate for translators without any separate upload step. Weblate opens
PRs back against this repository with translated .po files, so as a
developer the only thing you need to keep current is the .pot template
whenever you touch a translatable string - Weblate and its translators
handle the rest.
To sign up as a translator, create a Weblate account and join the language you want to work on (or request a new one if it isn’t listed yet).
Style and fixing existing translations¶
There’s no formal style guide or glossary yet. FlaskBB doesn’t have a dedicated translation team, just whoever shows up on Weblate for a given language. If you spot a string that’s translated inconsistently or incorrectly, just fix it directly in Weblate; there’s no separate process to coordinate with anyone first.
Context for ambiguous strings¶
Weblate shows the source file and line number each msgid came from
(e.g. flaskbb/templates/auth/login.html:12), which is usually enough to
tell whether e.g. “Login” is a button (verb) or a page/field label (noun).
If that’s still ambiguous, the most reliable way to check is to run
FlaskBB locally and look at the string in place:
flaskbb translations compile
flaskbb run
Then switch your account’s language (or browser locale) to the one you’re
testing so the app renders with your in-progress .po file — remember to
re-run flaskbb translations compile after every edit, since the app
only reads the compiled .mo file.
Review and release cadence¶
FlaskBB currently has a single maintainer and no dedicated proofreading step - translated PRs from Weblate get merged in as they come, on no fixed schedule tied to releases. There’s no deadline to hit for a given release; translating at whatever pace works for you is fine.
Plugin translations¶
The stock plugins (Portal, Conversations) aren’t set up on Weblate yet.
For now, translating them means opening a PR directly against the plugin’s
own translations/ directory — see Translating Plugins.