58 lines
2.3 KiB
Python
58 lines
2.3 KiB
Python
# Copyright (c) 2026 Patrick Motsch
|
|
# All rights reserved.
|
|
"""Validation: every label in feature ``main*.py`` catalog lists must be wrapped in ``t(...)``.
|
|
|
|
Background:
|
|
``UI_OBJECTS``, ``DATA_OBJECTS``, ``RESOURCE_OBJECTS``, ``WORKFLOW_DEFINITIONS`` etc.
|
|
in ``gateway/modules/features/<x>/main*.py`` define labels that the UDB and other
|
|
UI surfaces display. Bare-string labels (``"label": "Konfiguration"``) are not
|
|
registered with the i18n catalog at module-import time, so non-DE renders show
|
|
them as ``[Konfiguration]`` (the missing-translation marker from
|
|
``modules.shared.i18nRegistry.t()``).
|
|
|
|
This test scans every ``main*.py`` under ``gateway/modules/features`` and fails
|
|
if it finds bare-string labels, blocking the regression in CI.
|
|
|
|
Allowed exceptions:
|
|
- Labels that are NOT user-visible (e.g. internal demo seed data, fixtures).
|
|
Add their file to ``_ALLOWED_FILES_WITH_BARE_LABELS`` with a justification.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
|
|
_FEATURES_DIR = Path(__file__).resolve().parents[2] / "modules" / "features"
|
|
|
|
_BARE_LABEL_PATTERN = re.compile(r'^\s*"label"\s*:\s*"[^"]+"', re.MULTILINE)
|
|
|
|
# mainRealEstate.py contains "label": "AA1704" inside a multi-line f-string
|
|
# that is used as a JSON example in an AI prompt -- not a real catalog entry.
|
|
_ALLOWED_FILES_WITH_BARE_LABELS: set[str] = {
|
|
"mainRealEstate.py",
|
|
}
|
|
|
|
|
|
def _findFeatureMainFiles() -> list[Path]:
|
|
return sorted(_FEATURES_DIR.glob("*/main*.py"))
|
|
|
|
|
|
@pytest.mark.parametrize("mainFile", _findFeatureMainFiles(), ids=lambda p: p.name)
|
|
def test_noBareLabelsInFeatureCatalog(mainFile: Path) -> None:
|
|
if mainFile.name in _ALLOWED_FILES_WITH_BARE_LABELS:
|
|
pytest.skip(f"{mainFile.name} explicitly allowed (legacy seed data)")
|
|
|
|
text = mainFile.read_text(encoding="utf-8")
|
|
matches = _BARE_LABEL_PATTERN.findall(text)
|
|
assert not matches, (
|
|
f"\n{mainFile.relative_to(_FEATURES_DIR.parent.parent)} contains "
|
|
f"{len(matches)} bare-string labels that are NOT registered with i18n.\n"
|
|
f"Wrap each label with t(\"...\", context=\"UI\") so non-DE locales\n"
|
|
f"don't render them as [missing-key].\n\n"
|
|
f"Sample offending lines:\n "
|
|
+ "\n ".join(matches[:5])
|
|
)
|