flufl-i18n
flufl.i18n is a Python library providing a high-level, convenient API for managing internationalization (i18n) translation contexts. It supports both single-context applications like command-line tools and more complex, multi-context applications such as servers. The current version is 6.0.0, released in November 2025, with a consistent release cadence for updates and Python version compatibility.
Common errors
-
ModuleNotFoundError: No module named 'flufl.i18n'
cause The `flufl-i18n` package is not installed in the active Python environment.fixInstall the package using pip: `pip install flufl-i18n`. -
TypeError: 'NoneType' object is not callable
cause The translation function `_()` was called before `flufl.i18n.initialize()` or a similar setup function had properly bound a callable translator to it, or the bound function went out of scope.fixEnsure `initialize()` is called once at application startup, and that the returned translation function (e.g., `_ = initialize(...).gettext()`) is accessible in the scope where translations are needed. -
Translations are not applied; original strings are returned even after setup.
cause The translation catalogs (`.mo` files) are either missing, malformed, or the `LOCPATH` environment variable (or custom `TranslationStrategy` configuration) does not correctly point to the directory structure where the compiled message files are located. By default, `flufl.i18n` returns the original string if a translation is not found.fixVerify that your `.mo` files are correctly compiled (e.g., using `msgfmt`) and placed in the expected directory structure: `LOCPATH/<language_code>/LC_MESSAGES/<application_name>.mo`. Ensure that `os.environ['LOCPATH']` is set to the parent directory containing these language directories, or configure a custom `TranslationStrategy` to locate them.
Warnings
- breaking Version 6.0.0 of `flufl.i18n` requires Python 3.10 or newer. Support for Python 3.9 and earlier versions has been dropped. Ensure your environment meets the minimum Python version requirement before upgrading.
- gotcha The `initialize()` function and `SimpleStrategy` by default heavily rely on the `$LANG` and `$LOCPATH` environment variables for discovering translation catalogs. If these variables are not set, or you require dynamic language switching not based on environment variables (e.g., per-request in a web app), you'll need to use the more flexible `Application` and `RuntimeTranslator` APIs with custom `TranslationStrategy` implementations.
- gotcha Historically, there have been inconsistencies in how package names with dots (e.g., `flufl.i18n`) versus hyphens (`flufl-i18n`) are handled by PyPI and wheel specifications, affecting packaging tools. This could lead to issues during build or upload with certain older or non-standard build backends.
Install
-
pip install flufl-i18n
Imports
- initialize
from flufl.i18n import initialize
- Application
from flufl.i18n import Application
- RuntimeTranslator
from flufl.i18n import RuntimeTranslator
- TranslationStrategy
from flufl.i18n import TranslationStrategy
- _
_ = initialize('my_app_name', os.path.dirname(__file__)).gettext
Quickstart
import os
from flufl.i18n import initialize
# --- Create a dummy messages.py for demonstration ---
# In a real application, this would be a Python package
# containing your compiled .mo files in subdirectories.
# e.g., messages/en/LC_MESSAGES/my_app_name.mo
# messages/xx/LC_MESSAGES/my_app_name.mo (for our example 'xx')
# Simulate a simple translation catalog (rot13 for 'xx' locale)
# In a real scenario, this would involve gettext and .po/.mo files.
class MockTranslator:
def gettext(self, message):
if os.environ.get('LANG') == 'xx':
return message.encode('rot13').decode('utf-8')
return message
class MockApplication:
def __init__(self, name, localepath):
self.name = name
self.localepath = localepath
def gettext(self):
return MockTranslator()
# Patch initialize for this example to use our mock app
# In a real app, initialize() would handle catalog loading from LOCPATH
def _mock_initialize(app_name, package_path=None):
print(f"Initializing i18n for app: {app_name}")
print(f"Using LOCPATH: {os.environ.get('LOCPATH')}")
print(f"Using LANG: {os.environ.get('LANG')}")
return MockApplication(app_name, package_path)
flufl.i18n.initialize = _mock_initialize
# --- End of dummy setup ---
# Example usage:
app_name = 'my_app_name'
# 1. Set up environment variables (typically done outside the script)
# For demonstration, we set them here.
# IMPORTANT: Use os.path.dirname(__file__) to point to where your 'messages' package is
# For this quickstart, we're simulating, so package_path isn't strictly used by our mock.
package_path = os.path.join(os.path.dirname(__file__), 'messages') # Placeholder
os.environ['LANG'] = 'en' # Default language
os.environ['LOCPATH'] = package_path # Path to your translation catalogs
# Initialize the application and bind the translation function
_ = initialize(app_name, package_path).gettext()
print(f"English: {_('Hello, world!')}")
print(f"English: {_('How are you?')}")
# 2. Switch language context (e.g., for a web server or specific user session)
os.environ['LANG'] = 'xx' # A faux language for demonstration
# Re-initialize or push a new context (initialize here for simplicity in single-context example)
_ = initialize(app_name, package_path).gettext()
print(f"Faux (XX): {_('Hello, world!')}")
print(f"Faux (XX): {_('How are you?')}")
# Clean up environment variables (optional)
del os.environ['LANG']
del os.environ['LOCPATH']