Skip to content

Translation

Translation package for gllm-intl utilities.

This package provides the translation manager, provider abstractions, backend implementations, and custom exceptions.

BabelBackend(locales_dir=None, translations=None, domain='messages')

Bases: TranslationBackend

Babel gettext backend for standard translation files.

This backend uses Babel's support for gettext .po/.mo files, providing CLDR-compliant plural rules and standard gettext message extraction.

File Structure

locales_dir/ ├── en/ │ └── LC_MESSAGES/ │ ├── messages.po │ └── messages.mo # Compiled, preferred ├── fr/ │ └── LC_MESSAGES/ │ └── messages.mo └── ...

Thread Safety
  1. Read operations are thread-safe
  2. Translation cache is protected by a lock during loading
  3. Once loaded, translations are immutable

Attributes:

Name Type Description
locales_dir str | None

Path to directory containing locale subdirectories.

translations dict[str, Translations | NullTranslations] | None

Pre-loaded Translations objects keyed by locale.

domain str

Gettext domain name (default: "messages").

Initialize the backend using filesystem or pre-loaded catalogs.

Exactly one of locales_dir or translations must be supplied so the backend knows where to source translation data.

Parameters:

Name Type Description Default
locales_dir str | None

Absolute or relative path with locale subdirectories (e.g., "./locales/en/LC_MESSAGES").

None
translations dict[str, Translations] | None

Mapping of locale identifiers to Translations instances (useful for tests or embedded catalogs).

None
domain str

Gettext domain name that determines which .po/.mo files to load. Defaults to "messages".

'messages'

Raises:

Type Description
ProviderConfigurationError

If both sources are provided, neither is provided, the directory is invalid, or the translations mapping is empty.

Example
backend = BabelBackend(locales_dir="./locales")

from babel.support import Translations

preloaded = {"en": Translations.load("./locales", ["en"])}
backend = BabelBackend(translations=preloaded)

format_message(message, **variables)

Interpolate variables into message using str.format.

Parameters:

Name Type Description Default
message str

Template containing {placeholder} tokens.

required
**variables

Mapping of placeholder names to values used for interpolation. These are forwarded as keyword arguments to str.format, e.g., {name}, {count:d}. Values need not be strings—non-strings are formatted via str.format automatically. If a required placeholder is missing or a format spec is invalid, interpolation is skipped and the original message is returned unchanged.

{}

Returns:

Name Type Description
str str

Formatted string when interpolation succeeds, otherwise the original message.

Example
backend.format_message("{count} files", count=3)

get_context_message(key, locale, context)

Return a translation for key scoped by context.

Parameters:

Name Type Description Default
key str

Message identifier.

required
locale str

Locale identifier.

required
context str

Disambiguating context value.

required

Returns:

Type Description
str | None

str | None: Context-specific translation or None.

Example
backend.get_context_message("name", "en", "person")
backend.get_context_message("name", "en", "file")

get_context_plural_message(key, locale, context, count)

Return a context-aware plural translation.

Parameters:

Name Type Description Default
key str

Singular key stored in the catalog.

required
locale str

Locale identifier.

required
context str

Disambiguating context value.

required
count int

Quantity influencing plural selection.

required

Returns:

Type Description
str | None

str | None: Formatted template or None if unavailable.

Example
backend.get_context_plural_message("item", "en", "file", 3)

get_message(key, locale)

Return the gettext translation for key in locale.

Parameters:

Name Type Description Default
key str

Message identifier stored in the catalog.

required
locale str

Locale to retrieve the translation from.

required

Returns:

Type Description
str | None

str | None: Translated string or None when the key is missing.

Example
backend.get_message("greeting", "en")
backend.get_message("greeting", "fr")

get_plural_message(key, locale, count)

Return the plural translation selected by CLDR rules.

Parameters:

Name Type Description Default
key str

Singular form key in the catalog.

required
locale str

Locale identifier.

required
count int

Quantity influencing plural selection.

required

Returns:

Type Description
str | None

str | None: Pluralized template or None when missing.

Example
backend.get_plural_message("item", "en", 1)
backend.get_plural_message("item", "en", 5)

load_locale(locale)

Ensure the translation catalog for locale is cached.

Parameters:

Name Type Description Default
locale str

Locale identifier such as "en" or "zh-Hans-CN".

required

Raises:

Type Description
FileNotFoundError

Propagated if the locale catalog cannot be found and Babel raises during Translations.load.

OSError

Propagated on filesystem access issues during loading.

Notes

Prefers compiled .mo files, uses a lock for thread safety, and caches NullTranslations when the locale is missing.

LocaleNotFoundError(locale, message=None)

Bases: Exception

Raised when a requested locale is not available in the backend.

This exception is raised in strict mode when a locale is requested but cannot be found in the loaded translations.

Attributes:

Name Type Description
locale str

The locale identifier that was not found.

message str | None

Human-readable error message. Defaults to None.

Initialize LocaleNotFoundError.

Parameters:

Name Type Description Default
locale str

The locale identifier that was not found.

required
message str | None

Optional custom error message. Defaults to None, in which case a default message is generated.

None

__str__()

Return string representation of the error.

Returns:

Name Type Description
str str

Representation of the error.

LocaleProvider(default_locale=DEFAULT_LOCALE, strict_mode=False, backend='babel', backend_config=None)

Bases: ABC

Abstract base class for locale providers.

Attributes:

Name Type Description
default_locale str

Fallback locale identifier.

strict_mode bool

Strict error handling mode flag.

backend BaseTranslationBackend

Configured translation backend instance.

Initialize the locale provider.

Parameters:

Name Type Description Default
default_locale str

Default locale identifier. Defaults to "en".

DEFAULT_LOCALE
strict_mode bool

Whether to enable strict error handling. Defaults to False.

False
backend str | BaseTranslationBackend

Backend identifier to instantiate. Defaults to "babel". If given as a string, it will be used to create a backend instance using create_backend. If given as a BaseTranslationBackend instance, it will be used as is.

'babel'
backend_config dict[str, Any] | None

Configuration for backend factory. Defaults to None. Will be passed to create_backend if backend is a string.

None

Raises:

Type Description
ValueError

If default_locale is empty or no backend can be created.

LocaleNotFoundError

If strict_mode is enabled and the default locale is absent.

get_available_locales() abstractmethod

Return a sorted list of available locales.

This method is to be implemented by subclasses to enumerate all locales they can serve (normalized as defined by the provider).

Returns:

Type Description
list[str]

list[str]: A sorted list of available locales.

Raises:

Type Description
NotImplementedError

If the method is not implemented by a subclass.

get_context_plural_translation(key, locale, context, count, **variables)

Return context-specific plural translation for key and context.

Parameters:

Name Type Description Default
key str

Translation key to retrieve.

required
locale str

Locale identifier to retrieve translation for.

required
context str

Context value to use for translation.

required
count int

Count value to use for pluralization.

required
**variables

Additional variables to pass to the backend method.

{}

Returns:

Name Type Description
str str

The context-specific plural translated text.

get_context_translation(key, locale, context, **variables)

Return context-specific translation for key and context.

Parameters:

Name Type Description Default
key str

Translation key to retrieve.

required
locale str

Locale identifier to retrieve translation for.

required
context str

Context value to use for translation.

required
**variables

Additional variables to pass to the backend method.

{}

Returns:

Name Type Description
str str

The context-specific translated text.

get_context_translation_lazy(key, locale, context, **variables)

Return a lazy translation proxy for context-specific messages.

Parameters:

Name Type Description Default
key str

Translation key to retrieve.

required
locale str

Locale identifier to retrieve translation for.

required
context str

Context value to use for translation.

required
**variables

Additional variables to pass to the backend method.

{}

Returns:

Name Type Description
LazyProxy LazyProxy

A lazy translation proxy for the given key and locale.

get_plural_translation(key, locale, count, **variables)

Return pluralized translation for key and count.

Parameters:

Name Type Description Default
key str

Translation key to retrieve.

required
locale str

Locale identifier to retrieve translation for.

required
count int

Count value to use for pluralization.

required
**variables

Additional variables to pass to the backend method.

{}

Returns:

Name Type Description
str str

The pluralized translated text.

get_plural_translation_lazy(key, locale, count, **variables)

Return a lazy translation proxy for plural messages.

Parameters:

Name Type Description Default
key str

Translation key to retrieve.

required
locale str

Locale identifier to retrieve translation for.

required
count int

Count value to use for pluralization.

required
**variables

Additional variables to pass to the backend method.

{}

Returns:

Name Type Description
LazyProxy LazyProxy

A lazy translation proxy for the given key and locale.

get_translation(key, locale, **variables)

Return translated text for key and locale.

Parameters:

Name Type Description Default
key str

Translation key to retrieve.

required
locale str

Locale identifier to retrieve translation for.

required
**variables

Additional variables to pass to the backend method.

{}

Returns:

Name Type Description
str str

The translated text.

get_translation_lazy(key, locale, **variables)

Return a lazy translation proxy for key and locale.

Parameters:

Name Type Description Default
key str

Translation key to retrieve.

required
locale str

Locale identifier to retrieve translation for.

required
**variables

Additional variables to pass to the backend method.

{}

Returns:

Name Type Description
LazyProxy LazyProxy

A lazy translation proxy for the given key and locale.

has_locale(locale) abstractmethod

Return True if the given locale is available.

This method is to be implemented by subclasses to indicate whether a locale is available.

Parameters:

Name Type Description Default
locale str

Locale identifier to check.

required

Returns:

Name Type Description
bool bool

True if the locale is available, False otherwise.

Raises:

Type Description
NotImplementedError

If the method is not implemented by a subclass.

ProviderConfigurationError(message)

Bases: Exception

Raised when provider configuration is invalid.

This exception is raised during provider initialization when the configuration parameters are invalid or inconsistent.

Common causes: 1. Both locales_dir and translations provided (mutually exclusive) 2. Neither locales_dir nor translations provided (one required) 3. Invalid file paths or malformed translation data

Attributes:

Name Type Description
message str

Human-readable error message explaining the issue.

Initialize ProviderConfigurationError.

Parameters:

Name Type Description Default
message str

Error message explaining the configuration issue.

required

__str__()

Return string representation of the error.

Returns:

Name Type Description
str str

Representation of the error.

TranslationBackend

Bases: ABC

Abstract base class defining the translation backend interface.

All translation backends must implement this interface to ensure consistent behavior and allow the LocaleProvider to work with any backend implementation.

Backend responsibilities: 1. Load translation data from files or pre-loaded sources 2. Retrieve raw messages by key (gettext, ngettext, pgettext, npgettext) 3. Format messages with variable interpolation

Backend does NOT: 1. Implement fallback chains (LocaleProvider's responsibility) 2. Handle missing keys gracefully (returns None, provider decides) 3. Normalize locale identifiers (LocaleProvider's responsibility)

Thread Safety: 1. Implementations must be thread-safe for concurrent read operations. 2. Translation data should be loaded once and cached immutably.

format_message(message, **variables)

Format a message by interpolating variables.

This default implementation uses Python's str.format to interpolate variables. Subclasses may override this method to support alternative formatting syntaxes.

Parameters:

Name Type Description Default
message str

The message string with placeholders.

required
**variables

Mapping of placeholder names to values used for interpolation. These are forwarded as keyword arguments to str.format, e.g., {name}, {count:d}. Values need not be strings—non-strings are formatted via str.format automatically. If a required placeholder is missing or a format spec is invalid, interpolation is skipped and the original message is returned unchanged.

{}

Returns:

Name Type Description
str str

The formatted message string with variables replaced.

Example
backend.format_message("Hello, {name}!", name="Alice")
backend.format_message("You have {count} messages", count=5)

get_context_message(key, locale, context) abstractmethod

Retrieve a context-aware translated message (pgettext).

Context allows disambiguating translations for the same key but with different meanings. For example, "name" could mean "person name" or "file name" depending on context.

This method must be implemented by subclasses to provide a context- specific translation for the supplied key.

Parameters:

Name Type Description Default
key str

The message key/identifier.

required
locale str

The locale identifier.

required
context str

The context string to disambiguate the key.

required

Returns:

Type Description
str | None

str | None: The translated message for the given context,

str | None

or None if the key+context combination is not found.

Example
backend.get_context_message("name", "en", "person")  # "Full Name"
backend.get_context_message("name", "en", "file")    # "Filename"

get_context_plural_message(key, locale, context, count) abstractmethod

Retrieve a context-aware plural message (npgettext).

Combines context disambiguation with plural handling. Useful when the same key needs different translations based on context AND different plural forms based on count.

This method must be implemented by subclasses to resolve a context-aware plural translation for the given key and count.

Parameters:

Name Type Description Default
key str

The message key/identifier.

required
locale str

The locale identifier.

required
context str

The context string to disambiguate the key.

required
count int

The numeric count used to determine plural form.

required

Returns:

Type Description
str | None

str | None: The translated message with appropriate context and plural form,

str | None

or None if the key+context combination is not found.

Example
backend.get_context_plural_message("item", "en", "file", 1)  # "{count} file"
backend.get_context_plural_message("item", "en", "file", 5)  # "{count} files"

get_message(key, locale) abstractmethod

Retrieve a simple translated message (gettext).

This is the basic translation lookup - equivalent to GNU gettext's gettext() function. Returns the translated message for the given key in the specified locale.

This method must be implemented by subclasses to fetch a simple translated string from the underlying message store.

Example
backend.get_message("greeting.hello", "en")  # "Hello"
backend.get_message("greeting.hello", "fr")  # "Bonjour"
backend.get_message("nonexistent", "en")     # None

Parameters:

Name Type Description Default
key str

The message key/identifier.

required
locale str

The locale identifier.

required

Returns:

Type Description
str | None

str | None: The translated message string, or None if the key is not found in the specified locale. Backend should NOT implement fallback logic - return None to let the provider handle fallback.

Raises:

Type Description
NotImplementedError

If the method is not implemented by the subclass.

get_plural_message(key, locale, count) abstractmethod

Retrieve a plural-aware translated message (ngettext).

This method implements CLDR plural rules to select the grammatically correct plural form based on the count. Different languages have different numbers of plural forms (English: 2, Russian: 3, Arabic: 6).

This method must be implemented by subclasses to return a pluralized translation string appropriate for the given locale and count.

Example
backend.get_plural_message("item", "en", 1)  # "{count} item"
backend.get_plural_message("item", "en", 5)  # "{count} items"
backend.get_plural_message("item", "ru", 2)  # "{count} предмета"

Parameters:

Name Type Description Default
key str

The message key/identifier.

required
locale str

The locale identifier.

required
count int

The numeric count used to determine plural form.

required

Returns:

Type Description
str | None

str | None: The translated message with the appropriate plural form, or None if the key is not found in the specified locale.

Raises:

Type Description
NotImplementedError

If the method is not implemented by the subclass.

load_locale(locale) abstractmethod

Load translation data for a specific locale.

This method should load and cache the translation data for the specified locale. Subsequent calls with the same locale should be idempotent (no-op if already loaded).

This method must be implemented by subclasses to load locale-specific translation resources into memory.

Parameters:

Name Type Description Default
locale str

The locale identifier (e.g., "en", "fr", "zh-Hans-CN").

required

Raises:

Type Description
NotImplementedError

If the method is not implemented by the subclass.

Note

Implementations should cache loaded translations for performance.

TranslationKeyError(key, locale, message=None)

Bases: Exception

Raised when a translation key is not found in any locale.

This exception is raised in strict mode when a translation key is requested but cannot be found in the target locale or any fallback locales.

Attributes:

Name Type Description
key str

The translation key that was not found.

locale str

The locale where the key was requested.

message str | None

Human-readable error message. Defaults to None, in which case a default message is generated.

Initialize TranslationKeyError.

Parameters:

Name Type Description Default
key str

The translation key that was not found.

required
locale str

The locale where the key was requested.

required
message str | None

Optional custom error message. Defaults to None, in which case a default message is generated.

None

__str__()

Return string representation of the error.

Returns:

Name Type Description
str str

Representation of the error.

TranslationManager(provider, default_locale=None)

Convenience API layer for translation operations.

TranslationManager wraps a LocaleProvider and maintains a current locale context, allowing translation methods to be called without explicitly passing the locale parameter each time.

This layer is optional - applications can use LocaleProvider directly if they prefer explicit locale parameters.

Thread Safety

The current_locale attribute is instance-specific. For multi-threaded applications (e.g., web servers), either: 1. Create a manager instance per request/thread, or 2. Use LocaleProvider directly with explicit locale parameters

Attributes:

Name Type Description
provider LocaleProvider

The LocaleProvider instance.

current_locale str

Currently active locale identifier.

Initialize TranslationManager with a provider.

Parameters:

Name Type Description Default
provider LocaleProvider

LocaleProvider instance to delegate to.

required
default_locale str | None

Initial locale to set. Defaults to None, in which case the provider's default locale is used.

None

Raises:

Type Description
ValueError

If provider is None.

LocaleNotFoundError

If default_locale is not available (strict mode only).

Example
from gllm_intl.translation.manager import TranslationManager
from gllm_intl.translation.providers import FileSystemLocaleProvider

provider = FileSystemLocaleProvider(
    locales_dir="./locales",
    backend="babel",
    default_locale="en",
    strict_mode=False,
)
manager = TranslationManager(provider)

manager.set_locale("fr")
print(manager.translate("greeting"))  # "Bonjour"

get_locale()

Get the current locale.

Returns:

Name Type Description
str str

Current locale identifier.

Example
manager.get_locale()

set_locale(locale)

Set the current locale for subsequent translation operations.

Parameters:

Name Type Description Default
locale str

Locale identifier to set as current.

required

Raises:

Type Description
LocaleNotFoundError

If locale not available (strict mode only).

ValueError

If locale is empty.

Example
manager.set_locale("fr")
manager.set_locale("en-US")

translate(key, **variables)

Translate a message using the current locale (gettext).

Convenience method that uses current_locale automatically.

Parameters:

Name Type Description Default
key str

The message key/identifier.

required
**variables

Variables for message interpolation.

{}

Returns:

Name Type Description
str str

Translated and formatted message string.

Raises:

Type Description
TranslationKeyError

If key not found (strict mode only).

Example
manager.set_locale("fr")
manager.translate("greeting.hello", name="Alice")

translate_context(key, context, **variables)

Translate a context-aware message using the current locale (pgettext).

Convenience method that uses current_locale automatically.

Parameters:

Name Type Description Default
key str

The message key/identifier.

required
context str

Context string for disambiguation.

required
**variables

Variables for message interpolation.

{}

Returns:

Name Type Description
str str

Translated message for the given context.

Raises:

Type Description
TranslationKeyError

If key+context not found (strict mode only).

Example
manager.set_locale("en")
manager.translate_context("name", context="person")

translate_context_plural(key, context, count, **variables)

Translate a context+plural message using current locale (npgettext).

Convenience method that uses current_locale automatically.

Parameters:

Name Type Description Default
key str

The message key/identifier.

required
context str

Context string for disambiguation.

required
count int

Numeric count for plural form selection.

required
**variables

Variables for message interpolation.

{}

Returns:

Name Type Description
str str

Translated message with context and correct plural form.

Raises:

Type Description
TranslationKeyError

If key+context not found (strict mode only).

Example
manager.set_locale("en")
manager.translate_context_plural("item", context="file", count=5)

translate_lazy(key, **variables)

Get a lazy translation using the current locale (lazy gettext).

Returns a LazyProxy that evaluates the translation when converted to string.

Convenience method that uses current_locale automatically.

Parameters:

Name Type Description Default
key str

The message key/identifier.

required
**variables

Variables for message interpolation.

{}

Returns:

Name Type Description
LazyProxy LazyProxy

Object that evaluates translation on demand.

Example
manager.set_locale("en")
label = manager.translate_lazy("form.username")
print(str(label))  # Evaluates now

translate_plural(key, count, **variables)

Translate a plural message using the current locale (ngettext).

Convenience method that uses current_locale automatically.

Parameters:

Name Type Description Default
key str

The message key/identifier.

required
count int

Numeric count for plural form selection.

required
**variables

Variables for message interpolation.

{}

Returns:

Name Type Description
str str

Translated message with correct plural form.

Raises:

Type Description
TranslationKeyError

If key not found (strict mode only).

Example
manager.set_locale("en")
manager.translate_plural("item", count=5)