Skip to Content
Localization

Localization

ZwyLib provides a small helper for building a multi-language string table for your plugin, with attribute-style access, str.format-like templating, and Russian/Ukrainian-aware pluralization built in — the same mechanism ZwyLib itself uses for its own settings screen strings.

Getting Started

# ... metadata and zwylib import ... from zwylib import locales_controller _locales = { "en": { "greeting": "Hello, {name}!", "items_count": ["{n} item", "{n} items"], }, "ru": { "greeting": "Привет, {name}!", "items_count": ["{n} штука", "{n} штуки", "{n} штук"], }, } L = locales_controller.generate_locale_class(_locales) # ... print(L.greeting(name="World")) # "Hello, World!" (or the matching translation) print(L.plural("items_count", 3)) # "3 штуки" on a Russian device, "3 items" otherwise

Any string containing { and } becomes callable, so you can fill in placeholders the same way you would with str.format. If a key is missing for the active language, ZwyLib falls back to "en" (or the first available language if "en" isn’t present), and finally to the key itself.

zwylib.locales_controller

zwylib.locales_controller: LocalesController

This global object is created during ZwyLib initialization and tracks the app’s current language, notifying subscribers when it changes.

Methods

get_current_locale

LocalesController.get_current_locale() -> str

Returns the current plural-aware language code (e.g. "en", "ru"), refreshing it from the client first if it hasn’t been read yet.

Example

zwylib.locales_controller.get_current_locale()

refresh_locale

LocalesController.refresh_locale() -> None

Re-reads the current language from the client and notifies all subscribers registered via subscribe_to_refresh. Called automatically by ZwyLib whenever the app’s language changes.


subscribe_to_refresh

LocalesController.subscribe_to_refresh(sub: () -> None) -> None

Registers a callback to run whenever the app’s language changes (e.g. to rebuild cached UI that embeds localized strings). The calling plugin’s ID is inferred automatically from the call stack and used as the subscription key — a plugin can only have one active subscriber at a time. Automatically unsubscribed when the plugin unloads.

Parameters

  • sub (() -> None): Callback to run on language change.

Example

zwylib.locales_controller.subscribe_to_refresh(lambda: print("Language changed!"))

unsubscribe_from_refresh

LocalesController.unsubscribe_from_refresh(plugin_id: Optional[str] = None) -> None

Removes a previously registered language-change subscriber.

Parameters

  • plugin_id (Optional[str], default None): ID of the plugin whose subscriber should be removed. Inferred automatically from the call stack if omitted.

Example

zwylib.locales_controller.unsubscribe_from_refresh(__id__)

generate_locale_class

LocalesController.generate_locale_class(dictionaries: Dict[str, Dict[str, str]]) -> Locales

Builds a Locales lookup object out of a {language_code: {key: value}} mapping. See zwylib.Locales below for how to use the result.

Parameters

  • dictionaries (Dict[str, Dict[str, str]]): Per-language string tables, keyed by language code (e.g. "en", "ru", "uk").

Example

L = zwylib.locales_controller.generate_locale_class({ "en": {"hello": "Hello!"}, "ru": {"hello": "Привет!"}, })

zwylib.Locales

zwylib.locales_controller.generate_locale_class(...): Locales

The object returned by generate_locale_class. Should only be obtained that way, not constructed directly.

Methods

get

Locales.get(key: str, dictionary: Optional[Dict[str, str]] = None) -> Union[str, SmartString]

Looks up key in the current language’s dictionary (or a specific one, if dictionary is provided), falling back to the default language and then to key itself if not found. Equivalent to plain attribute access (L.key). If the resolved value contains { and }, it’s returned as a callable SmartString that can be filled in like str.format.

Parameters

  • key (str): The string key to look up.
  • dictionary (Optional[Dict[str, str]], default None): Look up in this specific dictionary instead of the current language’s.

Example

L.get("greeting") L.greeting # equivalent L.greeting(name="World") # if the string contains "{name}"

plural

Locales.plural(key: str, number: int) -> str

Looks up key as a list of plural forms and picks the correct one for number in the current language. For "ru"/"uk", uses the standard three-form Slavic pluralization rule (one/few/many); for other languages, falls back to a simple singular/plural (or single-form) rule. If key doesn’t resolve to a list, it’s stringified and returned as-is.

Parameters

  • key (str): The string key, expected to resolve to a list of plural forms.
  • number (int): The quantity to pick a form for.

Example

L.plural("items_count", 1) # "1 item" / "1 штука" L.plural("items_count", 3) # "3 items" / "3 штуки" L.plural("items_count", 5) # "5 items" / "5 штук"
Last updated on