feat: status translation overrides via YAML config

report.status_translation in YAML config overrides/extends the builtin
STATUS_TRANSLATION dictionary; without the section behavior is unchanged.

- AppConfig.report_status_translation + _resolve_str_dict (warns and
  skips non-scalar values, resolves ${VAR} references)
- Config.get_status_translation() returns merged copy (lazy import,
  builtin dict never mutated)
- build_grouped_report() accepts optional status_translation parameter
- --init-config template gains commented example, docs/CONFIG.md updated

Closes #65
This commit is contained in:
Кокос Артем Николаевич
2026-07-17 15:18:27 +07:00
parent 09f6062e8c
commit 8614062ecd
7 changed files with 332 additions and 2 deletions

View File

@@ -277,3 +277,27 @@ def test_group_rows_preserves_row_data():
def test_group_rows_empty():
"""Пустой список — пустой словарь."""
assert group_rows_by_project_and_version([]) == {}
# -- #65: кастомный перевод статусов --
def test_build_grouped_report_custom_status_translation():
"""status_translation переопределяет встроенный словарь (#65)."""
issue = MockIssue("P", "S", "New", "v1.0", 1)
rows = build_grouped_report([(issue, 1.0)], status_translation={"New": "Новая"})
assert rows[0]["status_ru"] == "Новая"
def test_build_grouped_report_custom_status_translation_passthrough():
"""Статус вне кастомного словаря возвращается как есть (#65)."""
issue = MockIssue("P", "S", "Closed", "v1.0", 1)
rows = build_grouped_report([(issue, 1.0)], status_translation={"New": "Новая"})
assert rows[0]["status_ru"] == "Closed"
def test_build_grouped_report_none_translation_uses_builtin():
"""status_translation=None — используется встроенный словарь (#65)."""
issue = MockIssue("P", "S", "Closed", "v1.0", 1)
rows = build_grouped_report([(issue, 1.0)], status_translation=None)
assert rows[0]["status_ru"] == "Закрыто"