Generated accessors

Generated classes often encode valid paths and return resource references, not final strings. Follow the expected conversion or backport function used by current call sites.

Vehicle icon names and fallback forms

The vehicle icon helpers accept different input forms for different resource trees. Ordinary, small and contour helpers normalize the full descriptor name by replacing colons and hyphens with underscores. The descriptor-taking shop helpers first select the name after the colon, then normalize it. For the synthetic name nation:Tank-1, those keys are nation_Tank_1 and Tank_1. Pass the raw descriptor name to its matching helper; a pre-normalized ordinary key loses the separator required by the shop conversion.

HelperReturned formPython fallback branch
getIconPath / getIconResourceImage path / resource IDFailed existence check returns '' / None
getSmallIconPath / getContourIconPathImage pathFailed existence check selects that tree's noImage
getIconShopPathImage pathFalsy requested path selects the size-specific empty_tank
getIconShopResourceResource IDFalsy requested ID selects the size-specific empty_tank

The lower-level getShopVehicleIconPath(size, name) already takes a shop name; it does not perform the descriptor's colon split and returns an empty path after a failed existence check. Choose the wrapper and output form expected by the consumer. A nonempty fallback path or ID does not establish that the requested variant was selected or rendered.

These are current Python helper and caller contracts. Resource accessors, installed asset catalogs, image decoding and actual rendering were not exercised.

Fallback pattern

This mod-owned adapter takes a numeric resource ID, such as the result of a generated string accessor, and an explicit fallback. Expected absent or nonpositive input returns the fallback quietly. It uses the current backport.text interface rather than assuming every resource object has one validity method.

import logging
from gui.impl import backport

_LOGGER = logging.getLogger(__name__)


def _localized_text(res_id, fallback, **kwargs):
    if res_id is None or res_id <= 0:
        return fallback
    try:
        value = backport.text(res_id, **kwargs)
    except Exception:
        _LOGGER.exception('Could not resolve localized text for resource %r.', res_id)
        return fallback
    return value or fallback

Fallback on empty text is this adapter's policy, not a universal missing-catalog guarantee. The stock wrapper catches formatting TypeError/ValueError on its argument-bearing paths and returns empty text; those errors do not reach the adapter's exception handler. Unexpected failures that do escape retain a traceback-bearing log before returning the fallback. The adapter needs no optional reporting package.

Controlled resolver and in-memory logging checks cover these fallback and diagnostic branches. Native translation, generated accessors, language catalogs and actual automatic reporting were not exercised.

Formatting boundaries

Prefer one localized resource with named placeholders when word order matters. The Scaleform text-style wrappers can translate a recognized key string, but pass no formatting arguments to that translation. Resolve a parameterized label before styling it: substitution in a surrounding template does not fill placeholders inside an inserted value. XML template loading translates its own source markers at a separate stage.

The Python template formatter inserts context values directly with % ctx. Literal-text escaping belongs to the producer; intentional styled fragments use the same insertion path. Styling and template substitution do not establish that literal text was escaped or that a renderer accepted the resulting markup.

When both contexts are dictionaries, template-owned entries overwrite conflicting caller values and mutate the supplied dictionary. Use a separate dictionary when its original values must survive. Caught formatting errors return the unformatted template after logging, so a nonempty result is not a successful substitution receipt. Missing collection keys instead create cached placeholders that return the key itself and ignore the supplied message context; nonempty output does not establish that the requested style exists. These latest-source contracts were checked with synthetic templates and translation/logging substitutes; catalogs, actual template assets, native APIs and rendering were not exercised.

Choose text cleanup by its input representation

The stripAllTags helper removes descriptor placeholders such as {colorTagOpen} and {colorTagClose}; its name does not mean every markup representation. For synthetic input {colorTagOpen}<b>A & B</b>{colorTagClose}, it leaves <b>A & B</b>. The separate stripHTMLTags applies an angle-tag regular expression, while html.escape encodes literal markup characters. These operations have different outputs and are not interchangeable plain-text conversion.

A concrete reward-view producer sends its chosen title to setName, then separately applies placeholder removal to its tooltip title and description. That establishes the Python payload transformation, not how a frontend renders arbitrary text. Preserve the source representation and intended output boundary instead of choosing a helper by its broad name.

Selected readable helpers were checked with synthetic marker, angle-tag and ampersand text. Original modules, translation catalogs, real view/model construction and rendering were not exercised; no malformed-input or live UI defect was established.

Mod-owned localization contract

When custom text has no native resource, keep language selection and translation in one owned boundary instead of mixing translated strings through calculations and DOM code.

  • Publish stable translation keys, named format arguments, and the value from helpers.getClientLanguage() in the view payload.
  • Load the localization module before the renderer. Let it own locale normalization, dictionaries, placeholder formatting, and fallback.
  • Resolve labels, notes, units, tooltip text, and custom group names at the final presentation boundary. Leave strings already localized by native helpers unchanged.
  • Normalize regional spellings and aliases first, then fall back from the regional locale to its base language and finally to English.
  • Fall back key by key inside a known but incomplete locale; one missing translation must not expose raw keys throughout the view.
  • Keep a non-executable translator template with the complete English key set. Validate key parity and preserve every named placeholder when adding a locale.

Browser resources

Gameface assets must be registered under a unique namespace and removed by the same owner. On WG 2.4.1, use a uniquely named per-mod gui/gen_resources declaration and an owned R.mods... subtree. On the historical WG path, prefer a per-feature map entry over modifying a shared resource map globally.

Common mistakes

  • Editing generated resource files instead of the source resource.
  • Assuming a resource exists in every realm, mode, or client build.
  • Displaying an internal key directly to users without a fallback.
  • Using one language's concatenation order for every localization.
  • Confusing persistent registration with view lifetime; declarations remain mounted while callbacks, models, DOM nodes, and windows still require explicit teardown.

Verification trail

Find the generated accessor, inspect current call sites, confirm the resolver and formatting path, then test at least one missing-resource and one alternate-language case.