Install & Compatibility
Where this runs
tested against v6.8.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.040s · 19.2MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 1.9s · import 0.038s · 20MB
20MB installed
● package 20MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
TranslatorFactory
✓ from oslo_i18n import TranslatorFactory
translate
✓ from oslo_i18n import translate
_ (primary translation marker)
✓ from myapp._i18n import _
✗ from oslo_i18n.gettextutils import _
Marker functions like '_' should be exposed through a project's own integration module, not directly from internal oslo_i18n modules like gettextutils, which are considered private API.
_LI, _LW, _LE, _LC (log translation markers)
✓ from myapp._i18n import _LI
Similar to '_', log markers should be imported from the project's integration module.
This quickstart demonstrates how to set up `oslo.i18n` by creating an integration module (conceptually), initializing a `TranslatorFactory`, obtaining marker functions (`_`, `_LW`), marking strings for lazy translation, and finally translating them to a specific locale using `oslo_i18n.translate()`.
import os
from oslo_i18n import TranslatorFactory, enable_lazy, translate
# 1. Create an integration module (conceptually, e.g., myapp._i18n.py)
# In a real project, this would be in a separate file and imported.
DOMAIN = 'myproject'
_translators = TranslatorFactory(domain=DOMAIN)
_ = _translators.primary # Primary translation marker
_LW = _translators.log_warning # Log warning translation marker
# 2. Enable lazy translation (optional, but common)
enable_lazy()
# 3. Mark strings for translation
message = _('Hello, %(name)s!') % {'name': 'World'}
warning_message = _LW('Something went wrong: %s') % 'file not found'
# 4. Simulate a different locale for translation at display/log time
# In a real app, this might come from user settings or request headers
current_locale = os.environ.get('TEST_LOCALE', 'en_US') # Example: 'es_ES'
# 5. Translate and display
# Note: 'message' is a lazy translation object until explicitly translated or cast to string.
# The 'translate' function is used when the target locale is known.
translated_message = translate(message, desired_locale=current_locale)
print(f"Original (lazy) message type: {type(message)}")
print(f"Translated message for '{current_locale}': {translated_message}")
# Log messages would typically be handled by a logging configuration
# with a TranslationHandler, but for demonstration, we can show direct translation.
print(f"Translated log warning for '{current_locale}': {translate(warning_message, desired_locale=current_locale)}")
Debug
Known issues
gotchaMarker functions like `_()` must receive string literals as arguments, not variables. For example, `_('My message.')` is correct, while `_(variable_containing_msg)` is wrong, as translation tools rely on static string analysis.fixAlways pass string literals to `_()`, `_LI()`, etc. If a message needs dynamic parts, use string interpolation (e.g., `_('Hello, %s!') % name`). affects: All versions
breakingStarting with the OpenStack Pike series, log translation guidelines changed significantly. Marker functions like `_LI()`, `_LW()`, `_LE()`, and `_LC()` should ONLY be used for messages that go *directly* and *exclusively* to the log. If a message might be exposed to the user (e.g., via an exception or API response), the primary `_()` marker MUST be used.fixReview all uses of log-specific marker functions (`_LI`, `_LW`, `_LE`, `_LC`). If the message might ever be presented to a user, switch to using `_()` instead. `_()` is also appropriate if a message is used for both logging and user output.
affects: oslo.i18n versions roughly from 3.10.0 onwards (Pike series)
gotchaLazy translated message objects (returned by `_()` when lazy translation is enabled) do not support all string manipulation operations, specifically concatenation with the `+` operator. They are designed for string interpolation using the `%` operator or `.format()` (though `%` is more commonly shown in examples).fixAlways use string interpolation (e.g., `_('Error: %s') % details`) or f-strings (Python 3.6+) with explicit `str()` conversion if needed (`str(_('Error')) + details`). Avoid `_('Error: ') + details`. affects: All versions with lazy translation enabled
deprecatedThe `oslo_i18n.gettextutils.Message` class was an internal implementation detail and was not part of the public API. Direct instantiation or reliance on this class is discouraged and may break in future versions.fixInstead of directly using `Message` objects, use `oslo_i18n.translate()` to convert a lazy translation object to a string when the locale is known. To create a new lazy message, use the marker functions (e.g., `_()`) provided by `TranslatorFactory`.
affects: All versions
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'oslo.i18n'
The `oslo_i18n` library is not installed or is not available in the current Python environment.
fixInstall the library using pip: `pip install oslo.i18n`
oslo_i18n translation not working for variables
Marker functions like `_()` must receive string literals as arguments, not variables, because translation tools rely on static string analysis to extract translatable messages.
fixAlways pass string literals to marker functions and use string interpolation (e.g., `%` operator or f-strings with explicit `str()` conversion) for dynamic parts. Example: `_('Hello, %s!') % name` instead of `_('Hello, ' + name + '!')` TypeError: unsupported operand type(s) for +: 'Message' and 'str'
Lazy translated message objects (returned by `_()` when lazy translation is enabled) do not support direct concatenation using the `+` operator.
fixUse string interpolation (e.g., `_('Error: %s') % details`) or explicitly convert the lazy message object to a string using `str()` before concatenation (e.g., `str(_('Error: ')) + details`). NameError: name '_' is not defined
The `_()` (or other marker) translation function has not been properly initialized or imported into the current scope. The global `install()` method is deprecated.
fixInitialize a `TranslatorFactory` and obtain the marker function(s) from it. Example: `from oslo_i18n import TranslatorFactory; _ = TranslatorFactory('my_app').primary` Upgrade
Version history
6.9.0latest on PyPI · released Jul 10, 2026
Audit
Dependencies
No dependency data recorded yet.