diff --git a/README.md b/README.md index 5b0020a..3c5ffa0 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ up by bumping their devx dependency. - **Developer tools** — environment setup, CI tool installation, test speed enforcement, repository configuration. - **i18n** — built-in translations for English, Bulgarian, German, Russian, - and Chinese; projects can extend with their own keys. + Chinese, and Polish; projects can extend with their own keys. ## Installation @@ -324,7 +324,7 @@ The config system loads `.env` automatically via `python-dotenv`. | `DEVX_REPO_NAME` | **(none — must be set)** | Repository name (or `owner/repo`) | | `DEVX_TASK_PREFIX` | `DEVX` | Task ID prefix (GRM, OBL-INFRA, etc.) | | `DEVX_VIKUNJA_PROJECT_ID` | `6` | Vikunja project ID | -| `DEVX_LANG` | `en` | Language for i18n (en, bg, de, ru, zh) | +| `DEVX_LANG` | `en` | Language for i18n (en, bg, de, ru, zh, pl) | | `DEVX_TRANSLATIONS_PATH` | — | Path to a custom JSON translations file | | `DEVX_VERSION_FILE` | `src/devx/__init__.py` | Version source file (used by release) | | `DEVX_DOCS_DIR` | `docs` | Documentation directory (used by sync_wiki) | @@ -431,7 +431,7 @@ src/devx/ ├── i18n.py # Translation system (gettext-based, translations.json) ├── exceptions.py # Custom exception types (DevxError, APIError) ├── opentofu.py # OpenTofu output helpers -├── translations.json # Translation strings (en, bg, de, ru, zh) +├── translations.json # Translation strings (en, bg, de, ru, zh, pl) ├── ci/ # CI/CD automation modules (run by workflows) ├── tools/ # Developer tooling modules (run locally or by CI) └── molecule/ # Optional molecule testing helpers (for Ansible projects) diff --git a/docs/index.md b/docs/index.md index fc15da0..0ada69d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -42,7 +42,7 @@ via environment variables and `pyproject.toml`, and inherit: - **Developer tools** — environment setup, CI tool installation, test speed enforcement, repository configuration. - **i18n** — built-in translations for English, Bulgarian, German, Russian, - and Chinese; projects can extend with their own keys. + Chinese, and Polish; projects can extend with their own keys. ## Installation @@ -148,7 +148,7 @@ fallback. Key variables: | `DEVX_REPO_OWNER` | **(must be set)** | Repository owner | | `DEVX_REPO_NAME` | **(must be set)** | Repository name | | `DEVX_TASK_PREFIX` | `DEVX` | Task ID prefix (GRM, OBL-INFRA, etc.) | -| `DEVX_LANG` | `en` | Language for i18n (en, bg, de, ru, zh) | +| `DEVX_LANG` | `en` | Language for i18n (en, bg, de, ru, zh, pl) | | `REPO_TOKEN` | — | Gitea API token | | `VIKUNJA_TOKEN` | — | Vikunja API token | diff --git a/docs/tech/architecture.md b/docs/tech/architecture.md index 719f8c8..9a9e686 100644 --- a/docs/tech/architecture.md +++ b/docs/tech/architecture.md @@ -16,7 +16,7 @@ src/devx/ ├── i18n.py # Translation system (JSON-based, translations.json) ├── exceptions.py # Custom exception types (DevxError, APIError) ├── opentofu.py # OpenTofu output helpers -├── translations.json # Translation strings (en, bg, de, ru, zh) +├── translations.json # Translation strings (en, bg, de, ru, zh, pl) ├── ci/ # CI/CD automation modules (run by workflows) │ ├── __init__.py │ ├── _shared.py # Shared utilities (get_latest_tag) diff --git a/docs/user/cli-commands.md b/docs/user/cli-commands.md index 042c4a1..a6b4570 100644 --- a/docs/user/cli-commands.md +++ b/docs/user/cli-commands.md @@ -40,8 +40,8 @@ checks `src/devx/translations.json` against `src/devx/**/*.py`. Checks performed: - **Missing keys** — a `_()` call in code has no entry in the translations file - **Dead keys** — a key in the translations file is not used in any code -- **Missing languages** — a key exists but is missing one of the five - supported languages (en, bg, de, ru, zh) +- **Missing languages** — a key exists but is missing one of the six + supported languages (en, bg, de, ru, zh, pl) ```bash devx ci check-translations diff --git a/src/devx/ci/check_translations.py b/src/devx/ci/check_translations.py index 1173fc4..83199a6 100644 --- a/src/devx/ci/check_translations.py +++ b/src/devx/ci/check_translations.py @@ -11,8 +11,8 @@ Checks performed (all fail with exit code 1 on error): - **Missing keys**: a ``_()`` call in code has no entry in the corresponding translations file. - **Dead keys**: a key in a translations file is not used in any code. -- **Missing languages**: a key exists but is missing one of the 5 supported - languages (en, bg, de, ru, zh). This is an error — all supported languages +- **Missing languages**: a key exists but is missing one of the 6 supported + languages (en, bg, de, ru, zh, pl). This is an error — all supported languages must have translations for every key. Usage:: @@ -33,7 +33,7 @@ import click REPO_ROOT = Path(__file__).resolve().parent.parent.parent.parent -SUPPORTED_LANGS = ("en", "bg", "de", "ru", "zh") +SUPPORTED_LANGS = ("en", "bg", "de", "ru", "zh", "pl") # Default translation set: devx package itself DEFAULT_TRANS_FILE = REPO_ROOT / "src" / "devx" / "translations.json" @@ -101,9 +101,9 @@ def collect_keys(src_dir: Path) -> set[str]: if pyfile.name == "i18n.py": continue keys |= extract_keys(pyfile) - # Add dynamic keys for the default source directory - if src_dir == DEFAULT_SRC_DIR: - keys |= DYNAMIC_KEYS + # Dynamic keys are common status strings used via _(variable) that + # can't be detected by AST scanning. Include them for all projects. + keys |= DYNAMIC_KEYS return keys diff --git a/src/devx/i18n.py b/src/devx/i18n.py index aa35f98..4b9329e 100644 --- a/src/devx/i18n.py +++ b/src/devx/i18n.py @@ -1,7 +1,7 @@ """Simple i18n for devx scripts and tools. Set DEVX_LANG environment variable to override the default English. -Supported: en, bg, de, ru, zh. +Supported: en, bg, de, ru, zh, pl. Projects can extend translations by setting DEVX_TRANSLATIONS_PATH to a JSON file with additional keys. Keys from the project's file are merged @@ -45,7 +45,7 @@ def _(key: str, **kwargs: object) -> str: If unset, English is always returned regardless of system locale. """ lang = os.getenv("DEVX_LANG", "en") - if lang not in ("en", "bg", "de", "ru", "zh"): + if lang not in ("en", "bg", "de", "ru", "zh", "pl"): lang = "en" template = TRANSLATIONS.get(key, {}).get(lang, key) return template.format(**kwargs) diff --git a/src/devx/translations.json b/src/devx/translations.json index ccc08bb..d3c4f69 100644 --- a/src/devx/translations.json +++ b/src/devx/translations.json @@ -3,6 +3,7 @@ "bg": "\n=== Summary ===", "de": "\n=== Summary ===", "en": "\n=== Summary ===", + "pl": "\n=== Podsumowanie ===", "ru": "\n=== Summary ===", "zh": "\n=== Summary ===" }, @@ -10,6 +11,7 @@ "bg": "\nAll documentation coverage checks passed!", "de": "\nAll documentation coverage checks passed!", "en": "\nAll documentation coverage checks passed!", + "pl": "\nWszystkie kontrole pokrycia dokumentacji zakończone pomyślnie!", "ru": "\nAll documentation coverage checks passed!", "zh": "\nAll documentation coverage checks passed!" }, @@ -17,6 +19,7 @@ "bg": "\nCHANGELOG version ordering:", "de": "\nCHANGELOG version ordering:", "en": "\nCHANGELOG version ordering:", + "pl": "\nKolejność wersji w CHANGELOG:", "ru": "\nCHANGELOG version ordering:", "zh": "\nCHANGELOG version ordering:" }, @@ -24,6 +27,7 @@ "bg": "\nChecking CI script documentation in ci-cd-workflow.md...", "de": "\nChecking CI script documentation in ci-cd-workflow.md...", "en": "\nChecking CI script documentation in ci-cd-workflow.md...", + "pl": "\nSprawdzanie dokumentacji skryptów CI w ci-cd-workflow.md...", "ru": "\nChecking CI script documentation in ci-cd-workflow.md...", "zh": "\nChecking CI script documentation in ci-cd-workflow.md..." }, @@ -31,6 +35,7 @@ "bg": "\nChecking module documentation in architecture.md...", "de": "\nChecking module documentation in architecture.md...", "en": "\nChecking module documentation in architecture.md...", + "pl": "\nSprawdzanie dokumentacji modułów w architecture.md...", "ru": "\nChecking module documentation in architecture.md...", "zh": "\nChecking module documentation in architecture.md..." }, @@ -38,6 +43,7 @@ "bg": "\nDoc coverage: {covered}/{total} ({pct}%)", "de": "\nDoc coverage: {covered}/{total} ({pct}%)", "en": "\nDoc coverage: {covered}/{total} ({pct}%)", + "pl": "\nPokrycie dokumentacji: {covered}/{total} ({pct}%)", "ru": "\nDoc coverage: {covered}/{total} ({pct}%)", "zh": "\nDoc coverage: {covered}/{total} ({pct}%)" }, @@ -45,6 +51,7 @@ "bg": "\nDone! Created: {created}, Updated: {updated}, Skipped: {skipped}", "de": "\nDone! Created: {created}, Updated: {updated}, Skipped: {skipped}", "en": "\nDone! Created: {created}, Updated: {updated}, Skipped: {skipped}", + "pl": "\nGotowe! Utworzono: {created}, Zaktualizowano: {updated}, Pominięto: {skipped}", "ru": "\nDone! Created: {created}, Updated: {updated}, Skipped: {skipped}", "zh": "\nDone! Created: {created}, Updated: {updated}, Skipped: {skipped}" }, @@ -52,6 +59,7 @@ "bg": "\nERROR: Documentation coverage is not 100%. Use --fail-on-missing to enforce.", "de": "\nERROR: Documentation coverage is not 100%. Use --fail-on-missing to enforce.", "en": "\nERROR: Documentation coverage is not 100%. Use --fail-on-missing to enforce.", + "pl": "\nBŁĄD: Pokrycie dokumentacji nie wynosi 100%. Użyj --fail-on-missing, aby to wymusić.", "ru": "\nERROR: Documentation coverage is not 100%. Use --fail-on-missing to enforce.", "zh": "\nERROR: Documentation coverage is not 100%. Use --fail-on-missing to enforce." }, @@ -59,6 +67,7 @@ "bg": "\nFix the misaligned tags before creating new releases. Run 'python3 -m devx.ci.release --verify' for a full report.", "de": "\nFix the misaligned tags before creating new releases. Run 'python3 -m devx.ci.release --verify' for a full report.", "en": "\nFix the misaligned tags before creating new releases. Run 'python3 -m devx.ci.release --verify' for a full report.", + "pl": "\nNapraw niezgodne tagi przed utworzeniem nowych wydań. Uruchom 'python3 -m devx.ci.release --verify', aby uzyskać pełny raport.", "ru": "\nFix the misaligned tags before creating new releases. Run 'python3 -m devx.ci.release --verify' for a full report.", "zh": "\nFix the misaligned tags before creating new releases. Run 'python3 -m devx.ci.release --verify' for a full report." }, @@ -66,6 +75,7 @@ "bg": "\nIntegrity check FAILED ({count} issues):", "de": "\nIntegrity check FAILED ({count} issues):", "en": "\nIntegrity check FAILED ({count} issues):", + "pl": "\nKontrola integralności NIEUDANA ({count} problemów):", "ru": "\nIntegrity check FAILED ({count} issues):", "zh": "\nIntegrity check FAILED ({count} issues):" }, @@ -73,6 +83,7 @@ "bg": "\nIntegrity check passed — all {count} pages verified.", "de": "\nIntegrity check passed — all {count} pages verified.", "en": "\nIntegrity check passed — all {count} pages verified.", + "pl": "\nKontrola integralności zakończona pomyślnie — wszystkie {count} stron zweryfikowane.", "ru": "\nIntegrity check passed — all {count} pages verified.", "zh": "\nIntegrity check passed — all {count} pages verified." }, @@ -80,6 +91,7 @@ "bg": "\nLatest tag: {tag}", "de": "\nLatest tag: {tag}", "en": "\nLatest tag: {tag}", + "pl": "\nNajnowszy tag: {tag}", "ru": "\nLatest tag: {tag}", "zh": "\nLatest tag: {tag}" }, @@ -87,6 +99,7 @@ "bg": "\nMissing documentation:", "de": "\nMissing documentation:", "en": "\nMissing documentation:", + "pl": "\nBrakująca dokumentacja:", "ru": "\nMissing documentation:", "zh": "\nMissing documentation:" }, @@ -94,6 +107,7 @@ "bg": "\nResult: {status}", "de": "\nResult: {status}", "en": "\nResult: {status}", + "pl": "\nWynik: {status}", "ru": "\nResult: {status}", "zh": "\nResult: {status}" }, @@ -101,6 +115,7 @@ "bg": "\nReview #{review_id} posted on PR #{pr_number} with event '{event}' ({num_comments} inline comments).", "de": "\nReview #{review_id} posted on PR #{pr_number} with event '{event}' ({num_comments} inline comments).", "en": "\nReview #{review_id} posted on PR #{pr_number} with event '{event}' ({num_comments} inline comments).", + "pl": "\nRecenzja #{review_id} opublikowana na PR #{pr_number} ze zdarzeniem '{event}' ({num_comments} komentarzy w tekście).", "ru": "\nReview #{review_id} posted on PR #{pr_number} with event '{event}' ({num_comments} inline comments).", "zh": "\nReview #{review_id} posted on PR #{pr_number} with event '{event}' ({num_comments} inline comments)." }, @@ -108,6 +123,7 @@ "bg": "\nRunning full wiki integrity check...", "de": "\nRunning full wiki integrity check...", "en": "\nRunning full wiki integrity check...", + "pl": "\nUruchamianie pełnej kontroli integralności wiki...", "ru": "\nRunning full wiki integrity check...", "zh": "\nRunning full wiki integrity check..." }, @@ -115,6 +131,7 @@ "bg": "\nTag → Commit alignment:", "de": "\nTag → Commit alignment:", "en": "\nTag → Commit alignment:", + "pl": "\nTag → Commit: zgodność:", "ru": "\nTag → Commit alignment:", "zh": "\nTag → Commit alignment:" }, @@ -122,6 +139,7 @@ "bg": "\nUntagged release commits:", "de": "\nUntagged release commits:", "en": "\nUntagged release commits:", + "pl": "\nCommity wydania bez tagu:", "ru": "\nUntagged release commits:", "zh": "\nUntagged release commits:" }, @@ -129,6 +147,7 @@ "bg": "\nUser-facing changes ({count}):", "de": "\nUser-facing changes ({count}):", "en": "\nUser-facing changes ({count}):", + "pl": "\nZmiany widoczne dla użytkownika ({count}):", "ru": "\nUser-facing changes ({count}):", "zh": "\nUser-facing changes ({count}):" }, @@ -136,6 +155,7 @@ "bg": "\nVerification FAILED: {failures} page(s) have empty or mismatched content!", "de": "\nVerification FAILED: {failures} page(s) have empty or mismatched content!", "en": "\nVerification FAILED: {failures} page(s) have empty or mismatched content!", + "pl": "\nWeryfikacja NIEUDANA: {failures} strona(y) ma pustą lub niezgodną treść!", "ru": "\nVerification FAILED: {failures} page(s) have empty or mismatched content!", "zh": "\nVerification FAILED: {failures} page(s) have empty or mismatched content!" }, @@ -143,6 +163,7 @@ "bg": "\nVerification passed — all wiki pages have correct content.", "de": "\nVerification passed — all wiki pages have correct content.", "en": "\nVerification passed — all wiki pages have correct content.", + "pl": "\nWeryfikacja zakończona pomyślnie — wszystkie strony wiki mają poprawną treść.", "ru": "\nVerification passed — all wiki pages have correct content.", "zh": "\nVerification passed — all wiki pages have correct content." }, @@ -150,6 +171,7 @@ "bg": "\nVerifying wiki pages have content...", "de": "\nVerifying wiki pages have content...", "en": "\nVerifying wiki pages have content...", + "pl": "\nWeryfikowanie, czy strony wiki mają treść...", "ru": "\nVerifying wiki pages have content...", "zh": "\nVerifying wiki pages have content..." }, @@ -157,6 +179,7 @@ "bg": "\nWorkflow-only changes ({count}):", "de": "\nWorkflow-only changes ({count}):", "en": "\nWorkflow-only changes ({count}):", + "pl": "\nZmiany tylko w workflow ({count}):", "ru": "\nWorkflow-only changes ({count}):", "zh": "\nWorkflow-only changes ({count}):" }, @@ -164,6 +187,7 @@ "bg": "\n[dry-run] Changelog:\n{changelog}", "de": "\n[dry-run] Changelog:\n{changelog}", "en": "\n[dry-run] Changelog:\n{changelog}", + "pl": "\n[dry-run] Changelog:\n{changelog}", "ru": "\n[dry-run] Changelog:\n{changelog}", "zh": "\n[dry-run] Changelog:\n{changelog}" }, @@ -171,6 +195,7 @@ "bg": "\n{label} files changed ({count}):", "de": "\n{label} files changed ({count}):", "en": "\n{label} files changed ({count}):", + "pl": "\n{label} plików zmienionych ({count}):", "ru": "\n{label} files changed ({count}):", "zh": "\n{label} files changed ({count}):" }, @@ -178,6 +203,7 @@ "bg": "\n{tag} files ({count}):", "de": "\n{tag} files ({count}):", "en": "\n{tag} files ({count}):", + "pl": "\nPliki {tag} ({count}):", "ru": "\n{tag} files ({count}):", "zh": "\n{tag} files ({count}):" }, @@ -185,6 +211,7 @@ "bg": " - Автоматично изтриване на клон след сливане: да", "de": " - Branch nach Merge automatisch löschen: ja", "en": " - Auto-delete branch after merge: yes", + "pl": " - Auto-usuwanie gałęzi po scaleniu: tak", "ru": " - Автоудаление ветки после слияния: да", "zh": " - 合并后自动删除分支: 是" }, @@ -192,6 +219,7 @@ "bg": " - Блокиране на остарели клонове: да", "de": " - Veraltete Branches blockieren: ja", "en": " - Block outdated branches: yes", + "pl": " - Blokowanie nieaktualnych gałęzi: tak", "ru": " - Блокировать устаревшие ветки: да", "zh": " - 阻止过时分支: 是" }, @@ -199,6 +227,7 @@ "bg": " - Блокиране на отхвърлени рецензии: да", "de": " - Abgelehnte Reviews blockieren: ja", "en": " - Block rejected reviews: yes", + "pl": " - Blokowanie odrzuconych recenzji: tak", "ru": " - Блокировать отклонённые ревью: да", "zh": " - 阻止被拒绝的审查: 是" }, @@ -206,6 +235,7 @@ "bg": " - Direct pushes: BLOCKED (require PR, whitelisted users can push)", "de": " - Direct pushes: BLOCKED (require PR, whitelisted users can push)", "en": " - Direct pushes: BLOCKED (require PR, whitelisted users can push)", + "pl": " - Bezpośrednie push-e: ZABLOKOWANE (wymagają PR, użytkownicy z białej listy mogą pushować)", "ru": " - Direct pushes: BLOCKED (require PR, whitelisted users can push)", "zh": " - Direct pushes: BLOCKED (require PR, whitelisted users can push)" }, @@ -213,6 +243,7 @@ "bg": " - Анулиране на остарели одобрения: да", "de": " - Veraltete Genehmigungen ablehnen: ja", "en": " - Dismiss stale approvals: yes", + "pl": " - Odrzucanie nieaktualnych zatwierdzeń: tak", "ru": " - Отклонять устаревшие одобрения: да", "zh": " - 忽略过时审批: 是" }, @@ -220,6 +251,7 @@ "bg": " - Необходими одобрения: {count}", "de": " - Erforderliche Genehmigungen: {count}", "en": " - Required approvals: {count}", + "pl": " - Wymagane zatwierdzenia: {count}", "ru": " - Требуемые одобрения: {count}", "zh": " - 必需审批数: {count}" }, @@ -227,6 +259,7 @@ "bg": " - Необходими проверки на състоянието: {checks}", "de": " - Erforderliche Status-Checks: {checks}", "en": " - Required status checks: {checks}", + "pl": " - Wymagane kontrole statusu: {checks}", "ru": " - Требуемые проверки статуса: {checks}", "zh": " - 必需状态检查: {checks}" }, @@ -234,6 +267,7 @@ "bg": " Created: {title}", "de": " Created: {title}", "en": " Created: {title}", + "pl": " Utworzono: {title}", "ru": " Created: {title}", "zh": " Created: {title}" }, @@ -241,6 +275,7 @@ "bg": " FAIL: {title} — content mismatch or empty!", "de": " FAIL: {title} — content mismatch or empty!", "en": " FAIL: {title} — content mismatch or empty!", + "pl": " BŁĄD: {title} — treść niezgodna lub pusta!", "ru": " FAIL: {title} — content mismatch or empty!", "zh": " FAIL: {title} — content mismatch or empty!" }, @@ -248,6 +283,7 @@ "bg": " ЛИПСВА: devx {cmd}", "de": " FEHLT: devx {cmd}", "en": " MISSING: devx {cmd}", + "pl": " BRAK: devx {cmd}", "ru": " ОТСУТСТВУЕТ: devx {cmd}", "zh": " 缺失: devx {cmd}" }, @@ -255,6 +291,7 @@ "bg": " MISSING: {module}", "de": " MISSING: {module}", "en": " MISSING: {module}", + "pl": " BRAK: {module}", "ru": " MISSING: {module}", "zh": " MISSING: {module}" }, @@ -262,6 +299,7 @@ "bg": " MISSING: {script}", "de": " MISSING: {script}", "en": " MISSING: {script}", + "pl": " BRAK: {script}", "ru": " MISSING: {script}", "zh": " MISSING: {script}" }, @@ -269,6 +307,7 @@ "bg": " ОК: devx {cmd}", "de": " OK: devx {cmd}", "en": " OK: devx {cmd}", + "pl": " OK: devx {cmd}", "ru": " ОК: devx {cmd}", "zh": " 正常: devx {cmd}" }, @@ -276,6 +315,7 @@ "bg": " OK: {module}", "de": " OK: {module}", "en": " OK: {module}", + "pl": " OK: {module}", "ru": " OK: {module}", "zh": " OK: {module}" }, @@ -283,6 +323,7 @@ "bg": " OK: {script}", "de": " OK: {script}", "en": " OK: {script}", + "pl": " OK: {script}", "ru": " OK: {script}", "zh": " OK: {script}" }, @@ -290,6 +331,7 @@ "bg": " OK: {title} ({chars} chars)", "de": " OK: {title} ({chars} chars)", "en": " OK: {title} ({chars} chars)", + "pl": " OK: {title} ({chars} znaków)", "ru": " OK: {title} ({chars} chars)", "zh": " OK: {title} ({chars} chars)" }, @@ -297,6 +339,7 @@ "bg": " Updated: {title}", "de": " Updated: {title}", "en": " Updated: {title}", + "pl": " Zaktualizowano: {title}", "ru": " Updated: {title}", "zh": " Updated: {title}" }, @@ -304,6 +347,7 @@ "bg": "--skip-build: skipping package build and PyPI publish.", "de": "--skip-build: skipping package build and PyPI publish.", "en": "--skip-build: skipping package build and PyPI publish.", + "pl": "--skip-build: pomijanie budowania pakietu i publikacji PyPI.", "ru": "--skip-build: skipping package build and PyPI publish.", "zh": "--skip-build: skipping package build and PyPI publish." }, @@ -311,6 +355,7 @@ "bg": "=== Release Alignment Verification ===\n", "de": "=== Release Alignment Verification ===\n", "en": "=== Release Alignment Verification ===\n", + "pl": "=== Weryfikacja zgodności wydań ===\n", "ru": "=== Release Alignment Verification ===\n", "zh": "=== Release Alignment Verification ===\n" }, @@ -318,6 +363,7 @@ "bg": "API poll warning: {exc}", "de": "API poll warning: {exc}", "en": "API poll warning: {exc}", + "pl": "Ostrzeżenie sondowania API: {exc}", "ru": "API poll warning: {exc}", "zh": "API poll warning: {exc}" }, @@ -325,6 +371,7 @@ "bg": "All molecule tests passed.", "de": "All molecule tests passed.", "en": "All molecule tests passed.", + "pl": "Wszystkie testy molecule zakończone pomyślnie.", "ru": "All molecule tests passed.", "zh": "All molecule tests passed." }, @@ -332,6 +379,7 @@ "bg": "Another molecule runner failed. Stopping this runner early.", "de": "Another molecule runner failed. Stopping this runner early.", "en": "Another molecule runner failed. Stopping this runner early.", + "pl": "Inny runner molecule zakończył się niepowodzeniem. Wczesne zatrzymanie tego runnera.", "ru": "Another molecule runner failed. Stopping this runner early.", "zh": "Another molecule runner failed. Stopping this runner early." }, @@ -339,6 +387,7 @@ "bg": "Bumping version: {current} -> v{new_version}", "de": "Bumping version: {current} -> v{new_version}", "en": "Bumping version: {current} -> v{new_version}", + "pl": "Zmiana wersji: {current} -> v{new_version}", "ru": "Bumping version: {current} -> v{new_version}", "zh": "Bumping version: {current} -> v{new_version}" }, @@ -346,6 +395,7 @@ "bg": "Checking CLI command documentation...", "de": "Checking CLI command documentation...", "en": "Checking CLI command documentation...", + "pl": "Sprawdzanie dokumentacji poleceń CLI...", "ru": "Checking CLI command documentation...", "zh": "Checking CLI command documentation..." }, @@ -353,6 +403,7 @@ "bg": "Command failed ({cmd}): {stderr}", "de": "Command failed ({cmd}): {stderr}", "en": "Command failed ({cmd}): {stderr}", + "pl": "Polecenie nie powiodło się ({cmd}): {stderr}", "ru": "Command failed ({cmd}): {stderr}", "zh": "Command failed ({cmd}): {stderr}" }, @@ -360,6 +411,7 @@ "bg": "Comparing {base}..{head} ({count} files changed)", "de": "Comparing {base}..{head} ({count} files changed)", "en": "Comparing {base}..{head} ({count} files changed)", + "pl": "Porównywanie {base}..{head} ({count} zmienionych plików)", "ru": "Comparing {base}..{head} ({count} files changed)", "zh": "Comparing {base}..{head} ({count} files changed)" }, @@ -367,6 +419,7 @@ "bg": "Конфигуриране на защита на клона {branch}...", "de": "Konfiguriere Branch-Schutz für {branch}...", "en": "Configuring branch protection for {branch}...", + "pl": "Konfigurowanie ochrony gałęzi dla {branch}...", "ru": "Настройка защиты ветки {branch}...", "zh": "正在配置 {branch} 的分支保护..." }, @@ -374,6 +427,7 @@ "bg": "Конфигуриране на настройките на хранилището...", "de": "Repository-Einstellungen konfigurieren...", "en": "Configuring repository settings...", + "pl": "Konfigurowanie ustawień repozytorium...", "ru": "Настройка параметров репозитория...", "zh": "正在配置仓库设置..." }, @@ -381,6 +435,7 @@ "bg": "Could not extract conventional commit message from PR commits.", "de": "Could not extract conventional commit message from PR commits.", "en": "Could not extract conventional commit message from PR commits.", + "pl": "Nie udało się wyodrębnić konwencjonalnej wiadomości commit z commitów PR.", "ru": "Could not extract conventional commit message from PR commits.", "zh": "Could not extract conventional commit message from PR commits." }, @@ -388,6 +443,7 @@ "bg": "Could not find Vikunja task {task_id} in project {project_id}. Every PR must have a corresponding Vikunja task.", "de": "Could not find Vikunja task {task_id} in project {project_id}. Every PR must have a corresponding Vikunja task.", "en": "Could not find Vikunja task {task_id} in project {project_id}. Every PR must have a corresponding Vikunja task.", + "pl": "Nie znaleziono zadania Vikunja {task_id} w projekcie {project_id}. Każdy PR musi mieć odpowiadające zadanie Vikunja.", "ru": "Could not find Vikunja task {task_id} in project {project_id}. Every PR must have a corresponding Vikunja task.", "zh": "Could not find Vikunja task {task_id} in project {project_id}. Every PR must have a corresponding Vikunja task." }, @@ -395,6 +451,7 @@ "bg": "Could not find __version__ in {file}", "de": "Could not find __version__ in {file}", "en": "Could not find __version__ in {file}", + "pl": "Nie znaleziono __version__ w {file}", "ru": "Could not find __version__ in {file}", "zh": "Could not find __version__ in {file}" }, @@ -402,6 +459,7 @@ "bg": "Could not parse test execution time from output.", "de": "Could not parse test execution time from output.", "en": "Could not parse test execution time from output.", + "pl": "Nie udało się przeanalizować czasu wykonania testu z wyjścia.", "ru": "Could not parse test execution time from output.", "zh": "Could not parse test execution time from output." }, @@ -409,6 +467,7 @@ "bg": "Created issue #{issue_id}: {title}", "de": "Created issue #{issue_id}: {title}", "en": "Created issue #{issue_id}: {title}", + "pl": "Utworzono zgłoszenie #{issue_id}: {title}", "ru": "Created issue #{issue_id}: {title}", "zh": "Created issue #{issue_id}: {title}" }, @@ -416,6 +475,7 @@ "bg": "Created release commit.", "de": "Created release commit.", "en": "Created release commit.", + "pl": "Utworzono commit wydania.", "ru": "Created release commit.", "zh": "Created release commit." }, @@ -423,6 +483,7 @@ "bg": "Докер демонът вече работи", "de": "Docker-Daemon läuft bereits", "en": "Docker daemon already running", + "pl": "Demon Docker już uruchomiony", "ru": "Демон Docker уже работает", "zh": "Docker 守护进程已在运行" }, @@ -430,6 +491,7 @@ "bg": "Docker daemon failed to start", "de": "Docker-Daemon konnte nicht gestartet werden", "en": "Docker daemon failed to start", + "pl": "Nie udało się uruchomić demona Docker", "ru": "Не удалось запустить Docker-демон", "zh": "Docker 守护进程启动失败" }, @@ -437,6 +499,7 @@ "bg": "Docker daemon started", "de": "Docker-Daemon gestartet", "en": "Docker daemon started", + "pl": "Demon Docker uruchomiony", "ru": "Docker-демон запущен", "zh": "Docker 守护进程已启动" }, @@ -444,6 +507,7 @@ "bg": "Dry-run mode: on branch '{branch}' (not master). Some checks may behave differently.", "de": "Dry-run mode: on branch '{branch}' (not master). Some checks may behave differently.", "en": "Dry-run mode: on branch '{branch}' (not master). Some checks may behave differently.", + "pl": "Tryb dry-run: na gałęzi '{branch}' (nie master). Niektóre kontrole mogą zachowywać się inaczej.", "ru": "Dry-run mode: on branch '{branch}' (not master). Some checks may behave differently.", "zh": "Dry-run mode: on branch '{branch}' (not master). Some checks may behave differently." }, @@ -451,6 +515,7 @@ "bg": "ГРЕШКА: REPO_TOKEN не е зададен.", "de": "FEHLER: REPO_TOKEN ist nicht gesetzt.", "en": "ERROR: REPO_TOKEN is not set.", + "pl": "BŁĄD: REPO_TOKEN nie jest ustawiony.", "ru": "ОШИБКА: REPO_TOKEN не задан.", "zh": "错误:未设置 REPO_TOKEN。" }, @@ -458,6 +523,7 @@ "bg": "ГРЕШКА: Името на хранилището не е указано. Използвайте --repo или задайте DEVX_REPO_NAME.", "de": "FEHLER: Repository-Name nicht angegeben. Verwenden Sie --repo oder setzen Sie DEVX_REPO_NAME.", "en": "ERROR: Repository name not specified. Use --repo or set DEVX_REPO_NAME.", + "pl": "BŁĄD: Nazwa repozytorium nie jest określona. Użyj --repo lub ustaw DEVX_REPO_NAME.", "ru": "ОШИБКА: Имя репозитория не указано. Используйте --repo или задайте DEVX_REPO_NAME.", "zh": "错误:未指定仓库名称。请使用 --repo 或设置 DEVX_REPO_NAME。" }, @@ -465,6 +531,7 @@ "bg": "ERROR: Tag consistency check failed. Existing tags are misaligned:", "de": "ERROR: Tag consistency check failed. Existing tags are misaligned:", "en": "ERROR: Tag consistency check failed. Existing tags are misaligned:", + "pl": "BŁĄD: Kontrola zgodności tagów nie powiodła się. Istniejące tagi są niezgodne:", "ru": "ERROR: Tag consistency check failed. Existing tags are misaligned:", "zh": "ERROR: Tag consistency check failed. Existing tags are misaligned:" }, @@ -472,6 +539,7 @@ "bg": "ГРЕШКА: VIKUNJA_TOKEN не е зададен.", "de": "FEHLER: VIKUNJA_TOKEN ist nicht gesetzt.", "en": "ERROR: VIKUNJA_TOKEN is not set.", + "pl": "BŁĄD: VIKUNJA_TOKEN nie jest ustawiony.", "ru": "ОШИБКА: VIKUNJA_TOKEN не задан.", "zh": "错误:未设置 VIKUNJA_TOKEN。" }, @@ -479,6 +547,7 @@ "bg": "ERROR: mapping.json not found at {path}", "de": "ERROR: mapping.json not found at {path}", "en": "ERROR: mapping.json not found at {path}", + "pl": "BŁĄD: mapping.json nie znaleziono w {path}", "ru": "ERROR: mapping.json not found at {path}", "zh": "ERROR: mapping.json not found at {path}" }, @@ -486,6 +555,7 @@ "bg": "FAILED: {pair} exited with code {code}", "de": "FAILED: {pair} exited with code {code}", "en": "FAILED: {pair} exited with code {code}", + "pl": "NIEUDANE: {pair} zakończone kodem {code}", "ru": "FAILED: {pair} exited with code {code}", "zh": "FAILED: {pair} exited with code {code}" }, @@ -493,6 +563,7 @@ "bg": "Failed to create issue via tea: {error}", "de": "Failed to create issue via tea: {error}", "en": "Failed to create issue via tea: {error}", + "pl": "Nie udało się utworzyć zgłoszenia przez tea: {error}", "ru": "Failed to create issue via tea: {error}", "zh": "Failed to create issue via tea: {error}" }, @@ -500,6 +571,7 @@ "bg": "Found {count} existing wiki pages.", "de": "Found {count} existing wiki pages.", "en": "Found {count} existing wiki pages.", + "pl": "Znaleziono {count} istniejących stron wiki.", "ru": "Found {count} existing wiki pages.", "zh": "Found {count} existing wiki pages." }, @@ -507,6 +579,7 @@ "bg": "GITEA_URL/REPO_TOKEN/RUN_ID not set; running without cross-runner cancellation.", "de": "GITEA_URL/REPO_TOKEN/RUN_ID not set; running without cross-runner cancellation.", "en": "GITEA_URL/REPO_TOKEN/RUN_ID not set; running without cross-runner cancellation.", + "pl": "GITEA_URL/REPO_TOKEN/RUN_ID nie ustawione; uruchamianie bez anulowania między runnerami.", "ru": "GITEA_URL/REPO_TOKEN/RUN_ID not set; running without cross-runner cancellation.", "zh": "GITEA_URL/REPO_TOKEN/RUN_ID not set; running without cross-runner cancellation." }, @@ -514,13 +587,23 @@ "bg": "Generated {file} with prefix '{prefix}'.", "de": "Generated {file} with prefix '{prefix}'.", "en": "Generated {file} with prefix '{prefix}'.", + "pl": "Wygenerowano {file} z prefiksem '{prefix}'.", "ru": "Generated {file} with prefix '{prefix}'.", "zh": "Generated {file} with prefix '{prefix}'." }, + "Gitea release {tag} already exists — skipping creation.": { + "bg": "Gitea release {tag} вече съществува — прескачане на създаването.", + "de": "Gitea-Release {tag} existiert bereits — Erstellung übersprungen.", + "en": "Gitea release {tag} already exists — skipping creation.", + "pl": "Wydanie Gitea {tag} już istnieje — pomijanie tworzenia.", + "ru": "Gitea release {tag} уже существует — пропуск создания.", + "zh": "Gitea release {tag} 已存在 — 跳过创建。" + }, "HEAD is a release commit ('{msg}') but tag {tag} is missing. Recovering by creating tag.": { "bg": "HEAD is a release commit ('{msg}') but tag {tag} is missing. Recovering by creating tag.", "de": "HEAD is a release commit ('{msg}') but tag {tag} is missing. Recovering by creating tag.", "en": "HEAD is a release commit ('{msg}') but tag {tag} is missing. Recovering by creating tag.", + "pl": "HEAD jest commitem wydania ('{msg}') ale tag {tag} brakuje. Naprawa przez utworzenie tagu.", "ru": "HEAD is a release commit ('{msg}') but tag {tag} is missing. Recovering by creating tag.", "zh": "HEAD is a release commit ('{msg}') but tag {tag} is missing. Recovering by creating tag." }, @@ -528,6 +611,7 @@ "bg": "HEAD is a release commit for v{version} but tag {tag} points to a different commit ({tag_commit} vs HEAD {head_commit}). This indicates a tag/commit misalignment.", "de": "HEAD is a release commit for v{version} but tag {tag} points to a different commit ({tag_commit} vs HEAD {head_commit}). This indicates a tag/commit misalignment.", "en": "HEAD is a release commit for v{version} but tag {tag} points to a different commit ({tag_commit} vs HEAD {head_commit}). This indicates a tag/commit misalignment.", + "pl": "HEAD jest commitem wydania dla v{version} ale tag {tag} wskazuje na inny commit ({tag_commit} vs HEAD {head_commit}). Wskazuje to na niezgodność tag/commit.", "ru": "HEAD is a release commit for v{version} but tag {tag} points to a different commit ({tag_commit} vs HEAD {head_commit}). This indicates a tag/commit misalignment.", "zh": "HEAD is a release commit for v{version} but tag {tag} points to a different commit ({tag_commit} vs HEAD {head_commit}). This indicates a tag/commit misalignment." }, @@ -535,6 +619,7 @@ "bg": "HEAD is already a release commit ('{msg}') and tag {tag} points to HEAD. Skipping.", "de": "HEAD is already a release commit ('{msg}') and tag {tag} points to HEAD. Skipping.", "en": "HEAD is already a release commit ('{msg}') and tag {tag} points to HEAD. Skipping.", + "pl": "HEAD jest już commitem wydania ('{msg}') a tag {tag} wskazuje na HEAD. Pomijanie.", "ru": "HEAD is already a release commit ('{msg}') and tag {tag} points to HEAD. Skipping.", "zh": "HEAD is already a release commit ('{msg}') and tag {tag} points to HEAD. Skipping." }, @@ -542,6 +627,7 @@ "bg": "HTTP грешка: {status} — {message}", "de": "HTTP-Fehler: {status} — {message}", "en": "HTTP error: {status} — {message}", + "pl": "Błąd HTTP: {status} — {message}", "ru": "Ошибка HTTP: {status} — {message}", "zh": "HTTP 错误: {status} — {message}" }, @@ -549,6 +635,7 @@ "bg": "HTTP {status} Забранено — вашият токен няма администраторски права.\nУверете се, че токенът принадлежи на собственик на хранилище или администратор на организация.\nАлтернативно, конфигурирайте защитата на клона ръчно в Настройки → Клонове.", "de": "HTTP {status} Verboten — Ihr Token hat keine Admin-Rechte.\nStellen Sie sicher, dass das Token einem Repository-Besitzer oder Organisations-Admin gehört.\nAlternativ können Sie den Branch-Schutz manuell unter Einstellungen → Branches konfigurieren.", "en": "HTTP {status} Forbidden — your token lacks admin rights.\nMake sure the token belongs to a repo owner or organisation admin.\nAlternatively, configure branch protection manually in Settings → Branches.", + "pl": "HTTP {status} Forbidden — twój token nie ma uprawnień administratora.\nUpewnij się, że token należy do właściciela repozytorium lub administratora organizacji.\nAlternatywnie skonfiguruj ochronę gałęzi ręcznie w Ustawienia → Gałęzie.", "ru": "HTTP {status} Запрещено — у вашего токена нет прав администратора.\nУбедитесь, что токен принадлежит владельцу репозитория или администратору организации.\nЛибо настройте защиту ветки вручную в разделе Настройки → Ветки.", "zh": "HTTP {status} 禁止访问 — 您的令牌缺少管理员权限。\n请确保令牌属于仓库所有者或组织管理员。\n或者,您可以在 设置 → 分支 中手动配置分支保护。" }, @@ -556,6 +643,7 @@ "bg": "Head branch is behind master. Pulling and rebasing...", "de": "Head branch is behind master. Pulling and rebasing...", "en": "Head branch is behind master. Pulling and rebasing...", + "pl": "Gałąź head jest w tyle za master. Pobieranie i rebasing...", "ru": "Head branch is behind master. Pulling and rebasing...", "zh": "Head branch is behind master. Pulling and rebasing..." }, @@ -563,6 +651,7 @@ "bg": "Хост Docker не е наличен, стартиране на локален dockerd...", "de": "Host-Docker nicht verfügbar, lokaler dockerd wird gestartet...", "en": "Host Docker not available, starting local dockerd...", + "pl": "Host Docker niedostępny, uruchamianie lokalnego dockerd...", "ru": "Хост Docker недоступен, запускается локальный dockerd...", "zh": "主机 Docker 不可用,正在启动本地 dockerd..." }, @@ -570,6 +659,7 @@ "bg": "Инфраструктурен commit (без идентификатор на задача DEVX-N), пропускаме обновяването на Vikunja: {msg}", "de": "Infrastruktur-Commit (keine DEVX-N Task-ID), Vikunja-Update wird übersprungen: {msg}", "en": "Infrastructure commit (no DEVX-N task ID), skipping Vikunja update: {msg}", + "pl": "Commit infrastruktury (bez ID zadania DEVX-N), pomijanie aktualizacji Vikunja: {msg}", "ru": "Инфраструктурный коммит (без ID задачи DEVX-N), пропуск обновления Vikunja: {msg}", "zh": "基础设施提交(无 DEVX-N 任务 ID),跳过 Vikunja 更新: {msg}" }, @@ -577,6 +667,7 @@ "bg": "Integration tests cancelled — another runner failed.", "de": "Integration tests cancelled — another runner failed.", "en": "Integration tests cancelled — another runner failed.", + "pl": "Testy integracyjne anulowane — inny runner zakończył się niepowodzeniem.", "ru": "Integration tests cancelled — another runner failed.", "zh": "Integration tests cancelled — another runner failed." }, @@ -584,6 +675,7 @@ "bg": "Integration tests failed with exit code {code}", "de": "Integration tests failed with exit code {code}", "en": "Integration tests failed with exit code {code}", + "pl": "Testy integracyjne zakończone niepowodzeniem z kodem {code}", "ru": "Integration tests failed with exit code {code}", "zh": "Integration tests failed with exit code {code}" }, @@ -591,6 +683,7 @@ "bg": "Integration tests passed.", "de": "Integration tests passed.", "en": "Integration tests passed.", + "pl": "Testy integracyjne zakończone pomyślnie.", "ru": "Integration tests passed.", "zh": "Integration tests passed." }, @@ -598,6 +691,7 @@ "bg": "Lint failed — refusing to release. Fix lint errors first.\n{stderr}", "de": "Lint failed — refusing to release. Fix lint errors first.\n{stderr}", "en": "Lint failed — refusing to release. Fix lint errors first.\n{stderr}", + "pl": "Lint nie powiódł się — odmowa wydania. Najpierw napraw błędy lint.\n{stderr}", "ru": "Lint failed — refusing to release. Fix lint errors first.\n{stderr}", "zh": "Lint failed — refusing to release. Fix lint errors first.\n{stderr}" }, @@ -605,6 +699,7 @@ "bg": "Lint passed.", "de": "Lint passed.", "en": "Lint passed.", + "pl": "Lint zakończony pomyślnie.", "ru": "Lint passed.", "zh": "Lint passed." }, @@ -612,6 +707,7 @@ "bg": "Mapped file {file} is empty. Update the content or remove from mapping.json.", "de": "Mapped file {file} is empty. Update the content or remove from mapping.json.", "en": "Mapped file {file} is empty. Update the content or remove from mapping.json.", + "pl": "Mapowany plik {file} jest pusty. Zaktualizuj treść lub usuń z mapping.json.", "ru": "Mapped file {file} is empty. Update the content or remove from mapping.json.", "zh": "Mapped file {file} is empty. Update the content or remove from mapping.json." }, @@ -619,6 +715,7 @@ "bg": "Mapped file {file} not found. Update mapping.json or create the file.", "de": "Mapped file {file} not found. Update mapping.json or create the file.", "en": "Mapped file {file} not found. Update mapping.json or create the file.", + "pl": "Mapowany plik {file} nie znaleziony. Zaktualizuj mapping.json lub utwórz plik.", "ru": "Mapped file {file} not found. Update mapping.json or create the file.", "zh": "Mapped file {file} not found. Update mapping.json or create the file." }, @@ -626,6 +723,7 @@ "bg": "Merge failed after rebase retry: {error}\nPlease rebase the PR manually.", "de": "Merge failed after rebase retry: {error}\nPlease rebase the PR manually.", "en": "Merge failed after rebase retry: {error}\nPlease rebase the PR manually.", + "pl": "Scalanie nie powiodło się po ponownej próbie rebase: {error}\nProszę wykonać rebase PR ręcznie.", "ru": "Merge failed after rebase retry: {error}\nPlease rebase the PR manually.", "zh": "Merge failed after rebase retry: {error}\nPlease rebase the PR manually." }, @@ -633,6 +731,7 @@ "bg": "Сливането неуспешно с HTTP {status}: {message}\nПроверете дали PR е готов и имате права за сливане.", "de": "Merge fehlgeschlagen mit HTTP {status}: {message}\nBitte prüfen Sie, ob der PR bereit ist und Sie Merge-Rechte haben.", "en": "Merge failed with HTTP {status}: {message}\nPlease check the PR is ready and you have merge rights.", + "pl": "Scalanie nie powiodło się z HTTP {status}: {message}\nSprawdź czy PR jest gotowy i masz uprawnienia do scalania.", "ru": "Слияние не удалось: HTTP {status}: {message}\nПроверьте, что PR готов и у вас есть права на слияние.", "zh": "合并失败: HTTP {status}: {message}\n请检查 PR 是否准备就绪且您具有合并权限。" }, @@ -640,6 +739,7 @@ "bg": "Merged {count} reports: {tests} tests, {failures} failures → {output}", "de": "Merged {count} reports: {tests} tests, {failures} failures → {output}", "en": "Merged {count} reports: {tests} tests, {failures} failures → {output}", + "pl": "Scalono {count} raportów: {tests} testów, {failures} niepowodzeń → {output}", "ru": "Merged {count} reports: {tests} tests, {failures} failures → {output}", "zh": "Merged {count} reports: {tests} tests, {failures} failures → {output}" }, @@ -647,6 +747,7 @@ "bg": "Модул {mod} няма функция main()", "de": "Modul {mod} hat keine main()-Funktion", "en": "Module {mod} has no main() function", + "pl": "Moduł {mod} nie ma funkcji main()", "ru": "Модуль {mod} не имеет функции main()", "zh": "模块 {mod} 没有 main() 函数" }, @@ -654,20 +755,15 @@ "bg": "Директорията на molecule не е намерена: {path}", "de": "Molecule-Verzeichnis nicht gefunden: {path}", "en": "Molecule directory not found: {path}", + "pl": "Katalog molecule nie znaleziony: {path}", "ru": "Директория molecule не найдена: {path}", "zh": "未找到 molecule 目录: {path}" }, - "Gitea release {tag} already exists — skipping creation.": { - "bg": "Gitea release {tag} вече съществува — прескачане на създаването.", - "de": "Gitea-Release {tag} existiert bereits — Erstellung übersprungen.", - "en": "Gitea release {tag} already exists — skipping creation.", - "ru": "Gitea release {tag} уже существует — пропуск создания.", - "zh": "Gitea release {tag} 已存在 — 跳过创建。" - }, "Nice! Gitea release {tag} created.": { "bg": "Отлично! Gitea release {tag} е създаден.", "de": "Prima! Gitea-Release {tag} erstellt.", "en": "Nice! Gitea release {tag} created.", + "pl": "Świetnie! Wydanie Gitea {tag} utworzone.", "ru": "Отлично! Gitea release {tag} создан.", "zh": "不错!Gitea release {tag} 已创建。" }, @@ -675,6 +771,7 @@ "bg": "Отлично! PR #{pr_number} е squash-merge-нат със заглавие: {merge_title}", "de": "Prima! PR #{pr_number} wurde mit Titel {merge_title} squash-gemergt.", "en": "Nice! PR #{pr_number} squash-merged with title: {merge_title}", + "pl": "Świetnie! PR #{pr_number} squash-merged z tytułem: {merge_title}", "ru": "Отлично! PR #{pr_number} squash-merge с заголовком: {merge_title}", "zh": "不错!PR #{pr_number} 已 squash 合并,标题: {merge_title}" }, @@ -682,6 +779,7 @@ "bg": "Nice! Release v{version} tagged and pushed. The publish workflow will be triggered.", "de": "Nice! Release v{version} tagged and pushed. The publish workflow will be triggered.", "en": "Nice! Release v{version} tagged and pushed. The publish workflow will be triggered.", + "pl": "Świetnie! Wydanie v{version} otagowane i wypchnięte. Workflow publikacji zostanie uruchomiony.", "ru": "Nice! Release v{version} tagged and pushed. The publish workflow will be triggered.", "zh": "Nice! Release v{version} tagged and pushed. The publish workflow will be triggered." }, @@ -689,6 +787,7 @@ "bg": "Отлично! Задача Vikunja {task_id} (ID {vikunja_id}) е обновена и маркирана като готова.", "de": "Prima! Vikunja-Aufgabe {task_id} (ID {vikunja_id}) aktualisiert und als erledigt markiert.", "en": "Nice! Vikunja task {task_id} (ID {vikunja_id}) updated and marked done.", + "pl": "Świetnie! Zadanie Vikunja {task_id} (ID {vikunja_id}) zaktualizowane i oznaczone jako ukończone.", "ru": "Отлично! Задача Vikunja {task_id} (ID {vikunja_id}) обновлена и отмечена как выполненная.", "zh": "不错!Vikunja 任务 {task_id} (ID {vikunja_id}) 已更新并标记为完成。" }, @@ -696,6 +795,7 @@ "bg": "No JUnit reports found matching {pattern} — skipping merge.", "de": "No JUnit reports found matching {pattern} — skipping merge.", "en": "No JUnit reports found matching {pattern} — skipping merge.", + "pl": "Nie znaleziono raportów JUnit pasujących do {pattern} — pomijanie scalania.", "ru": "No JUnit reports found matching {pattern} — skipping merge.", "zh": "No JUnit reports found matching {pattern} — skipping merge." }, @@ -703,6 +803,7 @@ "bg": "No changes between {base} and {head}.", "de": "No changes between {base} and {head}.", "en": "No changes between {base} and {head}.", + "pl": "Brak zmian między {base} i {head}.", "ru": "No changes between {base} and {head}.", "zh": "No changes between {base} and {head}." }, @@ -710,6 +811,7 @@ "bg": "No staged changes — version and changelog already up to date.", "de": "No staged changes — version and changelog already up to date.", "en": "No staged changes — version and changelog already up to date.", + "pl": "Brak zmian w staging — wersja i changelog są już aktualne.", "ru": "No staged changes — version and changelog already up to date.", "zh": "No staged changes — version and changelog already up to date." }, @@ -717,6 +819,7 @@ "bg": "No tags found — treating all changes as user-facing.", "de": "No tags found — treating all changes as user-facing.", "en": "No tags found — treating all changes as user-facing.", + "pl": "Nie znaleziono tagów — traktowanie wszystkich zmian jako widocznych dla użytkownika.", "ru": "No tags found — treating all changes as user-facing.", "zh": "No tags found — treating all changes as user-facing." }, @@ -724,6 +827,7 @@ "bg": "No task ID ({prefix}-N) found in commit message: {msg}. Every non-infrastructure commit must have a task ID.", "de": "No task ID ({prefix}-N) found in commit message: {msg}. Every non-infrastructure commit must have a task ID.", "en": "No task ID ({prefix}-N) found in commit message: {msg}. Every non-infrastructure commit must have a task ID.", + "pl": "Nie znaleziono ID zadania ({prefix}-N) w wiadomości commit: {msg}. Każdy commit nie-infrastrukturalny musi mieć ID zadania.", "ru": "No task ID ({prefix}-N) found in commit message: {msg}. Every non-infrastructure commit must have a task ID.", "zh": "No task ID ({prefix}-N) found in commit message: {msg}. Every non-infrastructure commit must have a task ID." }, @@ -731,6 +835,7 @@ "bg": "No unreleased changes found. Nothing to release.", "de": "No unreleased changes found. Nothing to release.", "en": "No unreleased changes found. Nothing to release.", + "pl": "Nie znaleziono nieopublikowanych zmian. Nic do wydania.", "ru": "No unreleased changes found. Nothing to release.", "zh": "No unreleased changes found. Nothing to release." }, @@ -738,6 +843,7 @@ "bg": "No user-facing changes since {tag} — only workflow/infrastructure files changed. Skipping release.", "de": "No user-facing changes since {tag} — only workflow/infrastructure files changed. Skipping release.", "en": "No user-facing changes since {tag} — only workflow/infrastructure files changed. Skipping release.", + "pl": "Brak zmian widocznych dla użytkownika od {tag} — tylko pliki workflow/infrastruktury uległy zmianie. Pomijanie wydania.", "ru": "No user-facing changes since {tag} — only workflow/infrastructure files changed. Skipping release.", "zh": "No user-facing changes since {tag} — only workflow/infrastructure files changed. Skipping release." }, @@ -745,6 +851,7 @@ "bg": "Note: Self-approval not allowed. Posting COMMENT instead.", "de": "Note: Self-approval not allowed. Posting COMMENT instead.", "en": "Note: Self-approval not allowed. Posting COMMENT instead.", + "pl": "Uwaga: Samo-zatwierdzenie niedozwolone. Publikowanie COMMENT zamiast tego.", "ru": "Note: Self-approval not allowed. Posting COMMENT instead.", "zh": "Note: Self-approval not allowed. Posting COMMENT instead." }, @@ -752,6 +859,7 @@ "bg": "Опа! Съобщението за commit трябва да следва конвенционален формат.\n Очаква се: : \n Получено: {subject}\n Разрешени типове: feat, fix, chore, docs, style, refactor,\n perf, test, ci, build, revert, BREAKING CHANGE", "de": "Ups! Commit-Nachricht muss dem konventionellen Commit-Format folgen.\n Erwartet: : \n Erhalten: {subject}\n Erlaubte Typen: feat, fix, chore, docs, style, refactor,\n perf, test, ci, build, revert, BREAKING CHANGE", "en": "Oops! Commit message must follow conventional commit format.\n Expected: : \n Got: {subject}\n Allowed types: feat, fix, chore, docs, style, refactor,\n perf, test, ci, build, revert, BREAKING CHANGE", + "pl": "Ups! Wiadomość commit musi być w formacie conventional commit.\n Oczekiwano: : \n Otrzymano: {subject}\n Dozwolone typy: feat, fix, chore, docs, style, refactor,\n perf, test, ci, build, revert, BREAKING CHANGE", "ru": "Ой! Сообщение коммита должно соответствовать формату conventional commit.\n Ожидается: : \n Получено: {subject}\n Допустимые типы: feat, fix, chore, docs, style, refactor,\n perf, test, ci, build, revert, BREAKING CHANGE", "zh": "哎呀!提交消息必须遵循 conventional commit 格式。\n 预期格式: : \n 实际: {subject}\n 允许的类型: feat, fix, chore, docs, style, refactor,\n perf, test, ci, build, revert, BREAKING CHANGE" }, @@ -759,6 +867,7 @@ "bg": "Oops! Do not include task ID ({prefix}-N) in feature branch commits.\n The task ID will be added automatically on merge via CI.", "de": "Oops! Do not include task ID ({prefix}-N) in feature branch commits.\n The task ID will be added automatically on merge via CI.", "en": "Oops! Do not include task ID ({prefix}-N) in feature branch commits.\n The task ID will be added automatically on merge via CI.", + "pl": "Ups! Nie dołączaj ID zadania ({prefix}-N) w commitach gałęzi feature.\n ID zadania zostanie dodane automatycznie przy scaleniu przez CI.", "ru": "Oops! Do not include task ID ({prefix}-N) in feature branch commits.\n The task ID will be added automatically on merge via CI.", "zh": "Oops! Do not include task ID ({prefix}-N) in feature branch commits.\n The task ID will be added automatically on merge via CI." }, @@ -766,6 +875,7 @@ "bg": "Опа! Публикуването в Gitea PyPI registry неуспешно:\n{stderr}", "de": "Ups! Veröffentlichung in der Gitea PyPI-Registry fehlgeschlagen:\n{stderr}", "en": "Oops! Gitea PyPI registry publish failed:\n{stderr}", + "pl": "Ups! Publikacja w rejestrze Gitea PyPI nie powiodła się:\n{stderr}", "ru": "Ой! Публикация в Gitea PyPI registry не удалась:\n{stderr}", "zh": "哎呀!Gitea PyPI registry 发布失败:\n{stderr}" }, @@ -773,6 +883,7 @@ "bg": "Oops! Master branch commit must follow conventional format after task ID.\n Expected: {prefix}-N: : \n Got: {subject}", "de": "Oops! Master branch commit must follow conventional format after task ID.\n Expected: {prefix}-N: : \n Got: {subject}", "en": "Oops! Master branch commit must follow conventional format after task ID.\n Expected: {prefix}-N: : \n Got: {subject}", + "pl": "Ups! Commit gałęzi master musi być w formacie conventional po ID zadania.\n Oczekiwano: {prefix}-N: : \n Otrzymano: {subject}", "ru": "Oops! Master branch commit must follow conventional format after task ID.\n Expected: {prefix}-N: : \n Got: {subject}", "zh": "Oops! Master branch commit must follow conventional format after task ID.\n Expected: {prefix}-N: : \n Got: {subject}" }, @@ -780,13 +891,23 @@ "bg": "Oops! Master branch commits must start with a task ID.\n Expected: {prefix}-N: \n Got: {subject}", "de": "Oops! Master branch commits must start with a task ID.\n Expected: {prefix}-N: \n Got: {subject}", "en": "Oops! Master branch commits must start with a task ID.\n Expected: {prefix}-N: \n Got: {subject}", + "pl": "Ups! Commity gałęzi master muszą zaczynać się od ID zadania.\n Oczekiwano: {prefix}-N: \n Otrzymano: {subject}", "ru": "Oops! Master branch commits must start with a task ID.\n Expected: {prefix}-N: \n Got: {subject}", "zh": "Oops! Master branch commits must start with a task ID.\n Expected: {prefix}-N: \n Got: {subject}" }, + "Oops! No task ID found in branch name '{branch}'. Branch names must include the task ID prefix (e.g., DEVX-31-fix-bug).": { + "bg": "Ой! Не е намерен ID на задача в името на клона '{branch}'. Имената на клонове трябва да включват префикса за ID на задача (напр. DEVX-31-fix-bug).", + "de": "Hoppla! Keine Task-ID im Branch-Namen '{branch}' gefunden. Branch-Namen müssen das Task-ID-Präfix enthalten (z.B. DEVX-31-fix-bug).", + "en": "Oops! No task ID found in branch name '{branch}'. Branch names must include the task ID prefix (e.g., DEVX-31-fix-bug).", + "pl": "Ups! Nie znaleziono ID zadania w nazwie gałęzi '{branch}'. Nazwy gałęzi muszą zawierać prefiks ID zadania (np., DEVX-31-fix-bug).", + "ru": "Ой! ID задачи не найден в имени ветки '{branch}'. Имена веток должны включать префикс ID задачи (например, DEVX-31-fix-bug).", + "zh": "哎呀!在分支名称 '{branch}' 中未找到任务 ID。分支名称必须包含任务 ID 前缀(例如 DEVX-31-fix-bug)。" + }, "Oops! PR title must follow format '{prefix}-N: '.\n Expected: {task_id}: \n Got: {pr_title}": { "bg": "Oops! PR title must follow format '{prefix}-N: '.\n Expected: {task_id}: \n Got: {pr_title}", "de": "Oops! PR title must follow format '{prefix}-N: '.\n Expected: {task_id}: \n Got: {pr_title}", "en": "Oops! PR title must follow format '{prefix}-N: '.\n Expected: {task_id}: \n Got: {pr_title}", + "pl": "Ups! Tytuł PR musi być w formacie '{prefix}-N: '.\n Oczekiwano: {task_id}: \n Otrzymano: {pr_title}", "ru": "Oops! PR title must follow format '{prefix}-N: '.\n Expected: {task_id}: \n Got: {pr_title}", "zh": "Oops! PR title must follow format '{prefix}-N: '.\n Expected: {task_id}: \n Got: {pr_title}" }, @@ -794,6 +915,7 @@ "bg": "Oops! PR title task ID mismatch.\n Branch task ID: {task_id}\n PR title: {pr_title}", "de": "Oops! PR title task ID mismatch.\n Branch task ID: {task_id}\n PR title: {pr_title}", "en": "Oops! PR title task ID mismatch.\n Branch task ID: {task_id}\n PR title: {pr_title}", + "pl": "Ups! Niezgodność ID zadania w tytule PR.\n ID zadania z gałęzi: {task_id}\n Tytuł PR: {pr_title}", "ru": "Oops! PR title task ID mismatch.\n Branch task ID: {task_id}\n PR title: {pr_title}", "zh": "Oops! PR title task ID mismatch.\n Branch task ID: {task_id}\n PR title: {pr_title}" }, @@ -801,6 +923,7 @@ "bg": "Опа! Сборката на пакета неуспешна:\n{stderr}", "de": "Ups! Paket-Build fehlgeschlagen:\n{stderr}", "en": "Oops! Package build failed:\n{stderr}", + "pl": "Ups! Budowanie pakietu nie powiodło się:\n{stderr}", "ru": "Ой! Сборка пакета не удалась:\n{stderr}", "zh": "哎呀!包构建失败:\n{stderr}" }, @@ -808,20 +931,15 @@ "bg": "Опа! Публикуването в PyPI неуспешно:\n{stderr}", "de": "Ups! PyPI-Veröffentlichung fehlgeschlagen:\n{stderr}", "en": "Oops! PyPI publish failed:\n{stderr}", + "pl": "Ups! Publikacja PyPI nie powiodła się:\n{stderr}", "ru": "Ой! Публикация в PyPI не удалась:\n{stderr}", "zh": "哎呀!PyPI 发布失败:\n{stderr}" }, - "Parsed owner={owner}, repo={repo} from DEVX_REPO_NAME": { - "bg": "Разбор на owner={owner}, repo={repo} от DEVX_REPO_NAME", - "de": "Owner={owner}, repo={repo} aus DEVX_REPO_NAME analysiert", - "en": "Parsed owner={owner}, repo={repo} from DEVX_REPO_NAME", - "ru": "Извлечён owner={owner}, repo={repo} из DEVX_REPO_NAME", - "zh": "从 DEVX_REPO_NAME 解析 owner={owner}, repo={repo}" - }, "PASSED: {pair}": { "bg": "PASSED: {pair}", "de": "PASSED: {pair}", "en": "PASSED: {pair}", + "pl": "UDANE: {pair}", "ru": "PASSED: {pair}", "zh": "PASSED: {pair}" }, @@ -829,6 +947,7 @@ "bg": "PR number must be an integer, got: {pr_number}", "de": "PR number must be an integer, got: {pr_number}", "en": "PR number must be an integer, got: {pr_number}", + "pl": "Numer PR musi być liczbą całkowitą, otrzymano: {pr_number}", "ru": "PR number must be an integer, got: {pr_number}", "zh": "PR number must be an integer, got: {pr_number}" }, @@ -836,6 +955,7 @@ "bg": "PR title does not match Vikunja task title.\n Expected: {expected}\n Got: {pr_title}", "de": "PR title does not match Vikunja task title.\n Expected: {expected}\n Got: {pr_title}", "en": "PR title does not match Vikunja task title.\n Expected: {expected}\n Got: {pr_title}", + "pl": "Tytuł PR nie pasuje do tytułu zadania Vikunja.\n Oczekiwano: {expected}\n Otrzymano: {pr_title}", "ru": "PR title does not match Vikunja task title.\n Expected: {expected}\n Got: {pr_title}", "zh": "PR title does not match Vikunja task title.\n Expected: {expected}\n Got: {pr_title}" }, @@ -843,13 +963,23 @@ "bg": "PYPI_TOKEN не е зададен и няма конфигуриран URL на registry — пропускаме публикуването в PyPI. Без притеснения, просто ще създадем Gitea release.", "de": "PYPI_TOKEN nicht gesetzt und keine Registry-URL konfiguriert — PyPI-Veröffentlichung wird übersprungen. Keine Sorge, wir erstellen einfach das Gitea-Release.", "en": "PYPI_TOKEN not set and no registry URL configured — skipping PyPI publish. No worries, we'll just create the Gitea release.", + "pl": "PYPI_TOKEN nie ustawiony i brak URL rejestru — pomijanie publikacji PyPI. Bez obaw, utworzymy tylko wydanie Gitea.", "ru": "PYPI_TOKEN не задан и URL registry не настроен — пропускаем публикацию в PyPI. Не беспокойтесь, мы просто создадим Gitea release.", "zh": "未设置 PYPI_TOKEN 且未配置 registry URL — 跳过 PyPI 发布。别担心,我们直接创建 Gitea release。" }, + "Parsed owner={owner}, repo={repo} from DEVX_REPO_NAME": { + "bg": "Разбор на owner={owner}, repo={repo} от DEVX_REPO_NAME", + "de": "Owner={owner}, repo={repo} aus DEVX_REPO_NAME analysiert", + "en": "Parsed owner={owner}, repo={repo} from DEVX_REPO_NAME", + "pl": "Przeanalizowano owner={owner}, repo={repo} z DEVX_REPO_NAME", + "ru": "Извлечён owner={owner}, repo={repo} из DEVX_REPO_NAME", + "zh": "从 DEVX_REPO_NAME 解析 owner={owner}, repo={repo}" + }, "Per-test speed check FAILED: {count} test(s) exceed {limit}s limit.": { "bg": "Per-test speed check FAILED: {count} test(s) exceed {limit}s limit.", "de": "Per-test speed check FAILED: {count} test(s) exceed {limit}s limit.", "en": "Per-test speed check FAILED: {count} test(s) exceed {limit}s limit.", + "pl": "Kontrola szybkości pojedynczego testu NIEUDANA: {count} test(ów) przekracza limit {limit}s.", "ru": "Per-test speed check FAILED: {count} test(s) exceed {limit}s limit.", "zh": "Per-test speed check FAILED: {count} test(s) exceed {limit}s limit." }, @@ -857,6 +987,7 @@ "bg": "Публикувано в Gitea PyPI registry.", "de": "In der Gitea PyPI-Registry veröffentlicht.", "en": "Published to Gitea PyPI registry.", + "pl": "Opublikowano w rejestrze Gitea PyPI.", "ru": "Опубликовано в Gitea PyPI registry.", "zh": "已发布到 Gitea PyPI registry。" }, @@ -864,6 +995,7 @@ "bg": "Публикувано в PyPI.", "de": "In PyPI veröffentlicht.", "en": "Published to PyPI.", + "pl": "Opublikowano w PyPI.", "ru": "Опубликовано в PyPI.", "zh": "已发布到 PyPI。" }, @@ -871,6 +1003,7 @@ "bg": "Pushed release commit to master.", "de": "Pushed release commit to master.", "en": "Pushed release commit to master.", + "pl": "Wypchnięto commit wydania do master.", "ru": "Pushed release commit to master.", "zh": "Pushed release commit to master." }, @@ -878,6 +1011,7 @@ "bg": "Rebased and pushed. Retrying merge...", "de": "Rebased and pushed. Retrying merge...", "en": "Rebased and pushed. Retrying merge...", + "pl": "Rebase i wypchnięto. Ponowna próba scalenia...", "ru": "Rebased and pushed. Retrying merge...", "zh": "Rebased and pushed. Retrying merge..." }, @@ -885,6 +1019,7 @@ "bg": "Release creation failed: {error}", "de": "Release creation failed: {error}", "en": "Release creation failed: {error}", + "pl": "Tworzenie wydania nie powiodło się: {error}", "ru": "Release creation failed: {error}", "zh": "Release creation failed: {error}" }, @@ -892,6 +1027,7 @@ "bg": "Release must be run on master, currently on '{branch}'.", "de": "Release must be run on master, currently on '{branch}'.", "en": "Release must be run on master, currently on '{branch}'.", + "pl": "Wydanie musi być uruchomione na master, obecnie na '{branch}'.", "ru": "Release must be run on master, currently on '{branch}'.", "zh": "Release must be run on master, currently on '{branch}'." }, @@ -899,6 +1035,7 @@ "bg": "Repo must be in 'owner/name' format, got: {repo}", "de": "Repo must be in 'owner/name' format, got: {repo}", "en": "Repo must be in 'owner/name' format, got: {repo}", + "pl": "Repo musi być w formacie 'owner/name', otrzymano: {repo}", "ru": "Repo must be in 'owner/name' format, got: {repo}", "zh": "Repo must be in 'owner/name' format, got: {repo}" }, @@ -906,6 +1043,7 @@ "bg": "Конфигурирането на хранилището е завършено.", "de": "Repository-Konfiguration abgeschlossen.", "en": "Repository configuration complete.", + "pl": "Konfiguracja repozytorium zakończona.", "ru": "Конфигурация репозитория завершена.", "zh": "仓库配置完成。" }, @@ -913,6 +1051,7 @@ "bg": "Roles directory not found: {path}", "de": "Roles directory not found: {path}", "en": "Roles directory not found: {path}", + "pl": "Katalog ról nie znaleziony: {path}", "ru": "Roles directory not found: {path}", "zh": "Roles directory not found: {path}" }, @@ -920,6 +1059,7 @@ "bg": "Индексът на runner {index} е извън диапазона (0..{max})", "de": "Runner-Index {index} außerhalb des Bereichs (0..{max})", "en": "Runner index {index} out of range (0..{max})", + "pl": "Indeks runnera {index} poza zakresem (0..{max})", "ru": "Индекс runner {index} вне диапазона (0..{max})", "zh": "Runner 索引 {index} 超出范围 (0..{max})" }, @@ -927,6 +1067,7 @@ "bg": "Running lint checks...", "de": "Running lint checks...", "en": "Running lint checks...", + "pl": "Uruchamianie kontroli lint...", "ru": "Running lint checks...", "zh": "Running lint checks..." }, @@ -934,6 +1075,7 @@ "bg": "Running tests...", "de": "Running tests...", "en": "Running tests...", + "pl": "Uruchamianie testów...", "ru": "Running tests...", "zh": "Running tests..." }, @@ -941,6 +1083,7 @@ "bg": "Running: {scenario} on {platform}", "de": "Running: {scenario} on {platform}", "en": "Running: {scenario} on {platform}", + "pl": "Uruchamianie: {scenario} na {platform}", "ru": "Running: {scenario} on {platform}", "zh": "Running: {scenario} on {platform}" }, @@ -948,6 +1091,7 @@ "bg": "Skipping commit push — no staged changes.", "de": "Skipping commit push — no staged changes.", "en": "Skipping commit push — no staged changes.", + "pl": "Pomijanie wypchnięcia commit — brak zmian w staging.", "ru": "Skipping commit push — no staged changes.", "zh": "Skipping commit push — no staged changes." }, @@ -955,6 +1099,7 @@ "bg": "Syncing {count} documentation pages to wiki...", "de": "Syncing {count} documentation pages to wiki...", "en": "Syncing {count} documentation pages to wiki...", + "pl": "Synchronizowanie {count} stron dokumentacji do wiki...", "ru": "Syncing {count} documentation pages to wiki...", "zh": "Syncing {count} documentation pages to wiki..." }, @@ -962,6 +1107,7 @@ "bg": "Tag consistency check failed.", "de": "Tag consistency check failed.", "en": "Tag consistency check failed.", + "pl": "Kontrola zgodności tagów nie powiodła się.", "ru": "Tag consistency check failed.", "zh": "Tag consistency check failed." }, @@ -969,6 +1115,7 @@ "bg": "Tag v{version} already existed. Publish workflow should already have been triggered.", "de": "Tag v{version} already existed. Publish workflow should already have been triggered.", "en": "Tag v{version} already existed. Publish workflow should already have been triggered.", + "pl": "Tag v{version} już istniał. Workflow publikacji powinien już być uruchomiony.", "ru": "Tag v{version} already existed. Publish workflow should already have been triggered.", "zh": "Tag v{version} already existed. Publish workflow should already have been triggered." }, @@ -976,6 +1123,7 @@ "bg": "Tag {tag} already exists and points to HEAD. Skipping creation.", "de": "Tag {tag} already exists and points to HEAD. Skipping creation.", "en": "Tag {tag} already exists and points to HEAD. Skipping creation.", + "pl": "Tag {tag} już istnieje i wskazuje na HEAD. Pomijanie tworzenia.", "ru": "Tag {tag} already exists and points to HEAD. Skipping creation.", "zh": "Tag {tag} already exists and points to HEAD. Skipping creation." }, @@ -983,6 +1131,7 @@ "bg": "Tag {tag} already exists but points to {tag_commit} (expected HEAD {head_commit}). This indicates a tag/commit misalignment. Run 'python3 -m devx.ci.release --verify' for details.", "de": "Tag {tag} already exists but points to {tag_commit} (expected HEAD {head_commit}). This indicates a tag/commit misalignment. Run 'python3 -m devx.ci.release --verify' for details.", "en": "Tag {tag} already exists but points to {tag_commit} (expected HEAD {head_commit}). This indicates a tag/commit misalignment. Run 'python3 -m devx.ci.release --verify' for details.", + "pl": "Tag {tag} już istnieje ale wskazuje na {tag_commit} (oczekiwano HEAD {head_commit}). Wskazuje to na niezgodność tag/commit. Uruchom 'python3 -m devx.ci.release --verify', aby uzyskać szczegóły.", "ru": "Tag {tag} already exists but points to {tag_commit} (expected HEAD {head_commit}). This indicates a tag/commit misalignment. Run 'python3 -m devx.ci.release --verify' for details.", "zh": "Tag {tag} already exists but points to {tag_commit} (expected HEAD {head_commit}). This indicates a tag/commit misalignment. Run 'python3 -m devx.ci.release --verify' for details." }, @@ -990,6 +1139,7 @@ "bg": "Task ID: {task_id}", "de": "Task ID: {task_id}", "en": "Task ID: {task_id}", + "pl": "ID zadania: {task_id}", "ru": "Task ID: {task_id}", "zh": "Task ID: {task_id}" }, @@ -997,6 +1147,7 @@ "bg": "Test '{name}' took {elapsed:.2f}s (limit: {limit}s). Optimise: use lighter fixtures, reduce I/O, or mock external calls.", "de": "Test '{name}' took {elapsed:.2f}s (limit: {limit}s). Optimise: use lighter fixtures, reduce I/O, or mock external calls.", "en": "Test '{name}' took {elapsed:.2f}s (limit: {limit}s). Optimise: use lighter fixtures, reduce I/O, or mock external calls.", + "pl": "Test '{name}' trwał {elapsed:.2f}s (limit: {limit}s). Optymalizuj: użyj lżejszych fixtures, zmniejsz I/O, lub mockuj zewnętrzne wywołania.", "ru": "Test '{name}' took {elapsed:.2f}s (limit: {limit}s). Optimise: use lighter fixtures, reduce I/O, or mock external calls.", "zh": "Test '{name}' took {elapsed:.2f}s (limit: {limit}s). Optimise: use lighter fixtures, reduce I/O, or mock external calls." }, @@ -1004,6 +1155,7 @@ "bg": "Tests failed — refusing to release. Fix test failures first.\n{stderr}", "de": "Tests failed — refusing to release. Fix test failures first.\n{stderr}", "en": "Tests failed — refusing to release. Fix test failures first.\n{stderr}", + "pl": "Testy nie powiodły się — odmowa wydania. Najpierw napraw niepowodzenia testów.\n{stderr}", "ru": "Tests failed — refusing to release. Fix test failures first.\n{stderr}", "zh": "Tests failed — refusing to release. Fix test failures first.\n{stderr}" }, @@ -1011,6 +1163,7 @@ "bg": "Tests passed.", "de": "Tests passed.", "en": "Tests passed.", + "pl": "Testy zakończone pomyślnie.", "ru": "Tests passed.", "zh": "Tests passed." }, @@ -1018,6 +1171,7 @@ "bg": "Unit tests passed in {duration:.2f}s (under {max}s limit, all tests under {single}s per-test limit).", "de": "Unit tests passed in {duration:.2f}s (under {max}s limit, all tests under {single}s per-test limit).", "en": "Unit tests passed in {duration:.2f}s (under {max}s limit, all tests under {single}s per-test limit).", + "pl": "Testy jednostkowe zakończone pomyślnie w {duration:.2f}s (poniżej limitu {max}s, wszystkie testy poniżej limitu {single}s na test).", "ru": "Unit tests passed in {duration:.2f}s (under {max}s limit, all tests under {single}s per-test limit).", "zh": "Unit tests passed in {duration:.2f}s (under {max}s limit, all tests under {single}s per-test limit)." }, @@ -1025,6 +1179,7 @@ "bg": "Unit tests too slow: {duration:.2f}s (max allowed: {max}s).\n Fix: run 'make pytest-cov' to profile, then optimise slow tests.\n Hint: avoid unnecessary imports, use lighter mocks, or cache fixtures.", "de": "Unit tests too slow: {duration:.2f}s (max allowed: {max}s).\n Fix: run 'make pytest-cov' to profile, then optimise slow tests.\n Hint: avoid unnecessary imports, use lighter mocks, or cache fixtures.", "en": "Unit tests too slow: {duration:.2f}s (max allowed: {max}s).\n Fix: run 'make pytest-cov' to profile, then optimise slow tests.\n Hint: avoid unnecessary imports, use lighter mocks, or cache fixtures.", + "pl": "Testy jednostkowe zbyt wolne: {duration:.2f}s (maks. dozwolone: {max}s).\n Naprawa: uruchom 'make pytest-cov' do profilowania, następnie zoptymalizuj wolne testy.\n Wskazówka: unikaj niepotrzebnych importów, użyj lżejszych mocków, lub buforuj fixtures.", "ru": "Unit tests too slow: {duration:.2f}s (max allowed: {max}s).\n Fix: run 'make pytest-cov' to profile, then optimise slow tests.\n Hint: avoid unnecessary imports, use lighter mocks, or cache fixtures.", "zh": "Unit tests too slow: {duration:.2f}s (max allowed: {max}s).\n Fix: run 'make pytest-cov' to profile, then optimise slow tests.\n Hint: avoid unnecessary imports, use lighter mocks, or cache fixtures." }, @@ -1032,6 +1187,7 @@ "bg": "Unknown check category '{check}'. Available: all, user-facing{tags}", "de": "Unknown check category '{check}'. Available: all, user-facing{tags}", "en": "Unknown check category '{check}'. Available: all, user-facing{tags}", + "pl": "Nieznana kategoria kontroli '{check}'. Dostępne: all, user-facing{tags}", "ru": "Unknown check category '{check}'. Available: all, user-facing{tags}", "zh": "Unknown check category '{check}'. Available: all, user-facing{tags}" }, @@ -1039,6 +1195,7 @@ "bg": "Updated version in {init}", "de": "Updated version in {init}", "en": "Updated version in {init}", + "pl": "Zaktualizowano wersję w {init}", "ru": "Updated version in {init}", "zh": "Updated version in {init}" }, @@ -1046,6 +1203,7 @@ "bg": "Updated {changelog_file}", "de": "Updated {changelog_file}", "en": "Updated {changelog_file}", + "pl": "Zaktualizowano {changelog_file}", "ru": "Updated {changelog_file}", "zh": "Updated {changelog_file}" }, @@ -1053,6 +1211,7 @@ "bg": "VIKUNJA_TOKEN is not set. This is required in CI to validate PR titles.", "de": "VIKUNJA_TOKEN is not set. This is required in CI to validate PR titles.", "en": "VIKUNJA_TOKEN is not set. This is required in CI to validate PR titles.", + "pl": "VIKUNJA_TOKEN nie jest ustawiony. Jest to wymagane w CI do walidacji tytułów PR.", "ru": "VIKUNJA_TOKEN is not set. This is required in CI to validate PR titles.", "zh": "VIKUNJA_TOKEN is not set. This is required in CI to validate PR titles." }, @@ -1060,6 +1219,7 @@ "bg": "Version file: {file}", "de": "Version file: {file}", "en": "Version file: {file}", + "pl": "Plik wersji: {file}", "ru": "Version file: {file}", "zh": "Version file: {file}" }, @@ -1067,6 +1227,7 @@ "bg": "Vikunja API error (HTTP {status}): {message}. Task {task_id} was NOT updated. The merge succeeded but the Vikunja task needs manual update.", "de": "Vikunja API error (HTTP {status}): {message}. Task {task_id} was NOT updated. The merge succeeded but the Vikunja task needs manual update.", "en": "Vikunja API error (HTTP {status}): {message}. Task {task_id} was NOT updated. The merge succeeded but the Vikunja task needs manual update.", + "pl": "Błąd API Vikunja (HTTP {status}): {message}. Zadanie {task_id} NIE zostało zaktualizowane. Scalenie powiodło się ale zadanie Vikunja wymaga ręcznej aktualizacji.", "ru": "Vikunja API error (HTTP {status}): {message}. Task {task_id} was NOT updated. The merge succeeded but the Vikunja task needs manual update.", "zh": "Vikunja API error (HTTP {status}): {message}. Task {task_id} was NOT updated. The merge succeeded but the Vikunja task needs manual update." }, @@ -1074,13 +1235,23 @@ "bg": "WARNING: --skip-tests passed — skipping test verification.", "de": "WARNING: --skip-tests passed — skipping test verification.", "en": "WARNING: --skip-tests passed — skipping test verification.", + "pl": "OSTRZEŻENIE: --skip-tests przekazane — pomijanie weryfikacji testów.", "ru": "WARNING: --skip-tests passed — skipping test verification.", "zh": "WARNING: --skip-tests passed — skipping test verification." }, + "WARNING: .taskid file ({file_id}) is deprecated and disagrees with branch name ({branch_id}). Delete .taskid from the repo — branch name is the sole source of truth.": { + "bg": "ВНИМАНИЕ: Файлът .taskid ({file_id}) е остарял и не съвпада с името на клона ({branch_id}). Изтрийте .taskid от хранилището — името на клона е единственият източник на истината.", + "de": "WARNUNG: Die Datei .taskid ({file_id}) ist veraltet und stimmt nicht mit dem Branch-Namen ({branch_id}) überein. Löschen Sie .taskid aus dem Repo — der Branch-Name ist die einzige Wahrheitsquelle.", + "en": "WARNING: .taskid file ({file_id}) is deprecated and disagrees with branch name ({branch_id}). Delete .taskid from the repo — branch name is the sole source of truth.", + "pl": "OSTRZEŻENIE: plik .taskid ({file_id}) jest przestarzały i niezgodny z nazwą gałęzi ({branch_id}). Usuń .taskid z repozytorium — nazwa gałęzi jest jedynym źródłem prawdy.", + "ru": "ВНИМАНИЕ: Файл .taskid ({file_id}) устарел и не совпадает с именем ветки ({branch_id}). Удалите .taskid из репозитория — имя ветки — единственный источник истины.", + "zh": "警告:.taskid 文件 ({file_id}) 已弃用,与分支名称 ({branch_id}) 不一致。请从仓库中删除 .taskid — 分支名称是唯一的真实来源。" + }, "Warning: could not fetch tags from origin.": { "bg": "Warning: could not fetch tags from origin.", "de": "Warning: could not fetch tags from origin.", "en": "Warning: could not fetch tags from origin.", + "pl": "Ostrzeżenie: nie udało się pobrać tagów z origin.", "ru": "Warning: could not fetch tags from origin.", "zh": "Warning: could not fetch tags from origin." }, @@ -1088,6 +1259,7 @@ "bg": "Wiki integrity check failed — {count} issue(s)", "de": "Wiki integrity check failed — {count} issue(s)", "en": "Wiki integrity check failed — {count} issue(s)", + "pl": "Kontrola integralności wiki nie powiodła się — {count} problem(ów)", "ru": "Wiki integrity check failed — {count} issue(s)", "zh": "Wiki integrity check failed — {count} issue(s)" }, @@ -1095,6 +1267,7 @@ "bg": "Wiki verification failed — {failures} page(s) empty or mismatched", "de": "Wiki verification failed — {failures} page(s) empty or mismatched", "en": "Wiki verification failed — {failures} page(s) empty or mismatched", + "pl": "Weryfikacja wiki nie powiodła się — {failures} strona(y) pusta lub niezgodna", "ru": "Wiki verification failed — {failures} page(s) empty or mismatched", "zh": "Wiki verification failed — {failures} page(s) empty or mismatched" }, @@ -1102,6 +1275,7 @@ "bg": "[dry-run] Would commit: release: v{version}", "de": "[dry-run] Would commit: release: v{version}", "en": "[dry-run] Would commit: release: v{version}", + "pl": "[dry-run] Utworzono by commit: release: v{version}", "ru": "[dry-run] Would commit: release: v{version}", "zh": "[dry-run] Would commit: release: v{version}" }, @@ -1109,6 +1283,7 @@ "bg": "[dry-run] Would create tag: v{version}", "de": "[dry-run] Would create tag: v{version}", "en": "[dry-run] Would create tag: v{version}", + "pl": "[dry-run] Utworzono by tag: v{version}", "ru": "[dry-run] Would create tag: v{version}", "zh": "[dry-run] Would create tag: v{version}" }, @@ -1116,6 +1291,7 @@ "bg": "[dry-run] Would create tag: {tag}", "de": "[dry-run] Would create tag: {tag}", "en": "[dry-run] Would create tag: {tag}", + "pl": "[dry-run] Utworzono by tag: {tag}", "ru": "[dry-run] Would create tag: {tag}", "zh": "[dry-run] Would create tag: {tag}" }, @@ -1123,6 +1299,7 @@ "bg": "[dry-run] Would push commit to master", "de": "[dry-run] Would push commit to master", "en": "[dry-run] Would push commit to master", + "pl": "[dry-run] Wypchnięto by commit do master", "ru": "[dry-run] Would push commit to master", "zh": "[dry-run] Would push commit to master" }, @@ -1130,6 +1307,7 @@ "bg": "[dry-run] Would sync page: {title} ({chars} chars)", "de": "[dry-run] Would sync page: {title} ({chars} chars)", "en": "[dry-run] Would sync page: {title} ({chars} chars)", + "pl": "[dry-run] Zsynchronizowano by stronę: {title} ({chars} znaków)", "ru": "[dry-run] Would sync page: {title} ({chars} chars)", "zh": "[dry-run] Would sync page: {title} ({chars} chars)" }, @@ -1137,6 +1315,7 @@ "bg": "[dry-run] Would update {changelog_file}", "de": "[dry-run] Would update {changelog_file}", "en": "[dry-run] Would update {changelog_file}", + "pl": "[dry-run] Zaktualizowano by {changelog_file}", "ru": "[dry-run] Would update {changelog_file}", "zh": "[dry-run] Would update {changelog_file}" }, @@ -1144,6 +1323,7 @@ "bg": "[dry-run] Would update {init}", "de": "[dry-run] Would update {init}", "en": "[dry-run] Would update {init}", + "pl": "[dry-run] Zaktualizowano by {init}", "ru": "[dry-run] Would update {init}", "zh": "[dry-run] Would update {init}" }, @@ -1151,6 +1331,7 @@ "bg": "активен", "de": "aktiv", "en": "active", + "pl": "aktywny", "ru": "активен", "zh": "活跃" }, @@ -1158,6 +1339,7 @@ "bg": "завършен", "de": "abgeschlossen", "en": "completed", + "pl": "ukończony", "ru": "завершён", "zh": "已完成" }, @@ -1165,6 +1347,7 @@ "bg": "неуспешен", "de": "fehlgeschlagen", "en": "failed", + "pl": "nieudany", "ru": "неудачный", "zh": "失败" }, @@ -1172,6 +1355,7 @@ "bg": "git command failed ({cmd}): {stderr}", "de": "git command failed ({cmd}): {stderr}", "en": "git command failed ({cmd}): {stderr}", + "pl": "polecenie git nie powiodło się ({cmd}): {stderr}", "ru": "git command failed ({cmd}): {stderr}", "zh": "git command failed ({cmd}): {stderr}" }, @@ -1179,6 +1363,7 @@ "bg": "git-cliff generated empty changelog for v{version}. Check cliff.toml and commit history.", "de": "git-cliff generated empty changelog for v{version}. Check cliff.toml and commit history.", "en": "git-cliff generated empty changelog for v{version}. Check cliff.toml and commit history.", + "pl": "git-cliff wygenerował pusty changelog dla v{version}. Sprawdź cliff.toml i historię commitów.", "ru": "git-cliff generated empty changelog for v{version}. Check cliff.toml and commit history.", "zh": "git-cliff generated empty changelog for v{version}. Check cliff.toml and commit history." }, @@ -1186,6 +1371,7 @@ "bg": "git-cliff returned empty version.", "de": "git-cliff returned empty version.", "en": "git-cliff returned empty version.", + "pl": "git-cliff zwrócił pustą wersję.", "ru": "git-cliff returned empty version.", "zh": "git-cliff returned empty version." }, @@ -1193,6 +1379,7 @@ "bg": "git-cliff returned invalid version format: {version}. Expected semver (e.g., 0.4.1).", "de": "git-cliff returned invalid version format: {version}. Expected semver (e.g., 0.4.1).", "en": "git-cliff returned invalid version format: {version}. Expected semver (e.g., 0.4.1).", + "pl": "git-cliff zwrócił nieprawidłowy format wersji: {version}. Oczekiwano semver (np., 0.4.1).", "ru": "git-cliff returned invalid version format: {version}. Expected semver (e.g., 0.4.1).", "zh": "git-cliff returned invalid version format: {version}. Expected semver (e.g., 0.4.1)." }, @@ -1200,6 +1387,7 @@ "bg": "в процес", "de": "in Bearbeitung", "en": "in progress", + "pl": "w toku", "ru": "в процессе", "zh": "进行中" }, @@ -1207,6 +1395,7 @@ "bg": "неактивен", "de": "inaktiv", "en": "inactive", + "pl": "nieaktywny", "ru": "неактивен", "zh": "未激活" }, @@ -1214,6 +1403,7 @@ "bg": "mapping.json keys and values must be strings, got {k}={v}", "de": "mapping.json keys and values must be strings, got {k}={v}", "en": "mapping.json keys and values must be strings, got {k}={v}", + "pl": "klucze i wartości mapping.json muszą być ciągami znaków, otrzymano {k}={v}", "ru": "mapping.json keys and values must be strings, got {k}={v}", "zh": "mapping.json keys and values must be strings, got {k}={v}" }, @@ -1221,6 +1411,7 @@ "bg": "mapping.json must be a dict of file-path -> page-title, got {type}", "de": "mapping.json must be a dict of file-path -> page-title, got {type}", "en": "mapping.json must be a dict of file-path -> page-title, got {type}", + "pl": "mapping.json musi być słownikiem ścieżka-pliku -> tytuł-strony, otrzymano {type}", "ru": "mapping.json must be a dict of file-path -> page-title, got {type}", "zh": "mapping.json must be a dict of file-path -> page-title, got {type}" }, @@ -1228,6 +1419,7 @@ "bg": "в очакване", "de": "ausstehend", "en": "pending", + "pl": "oczekujący", "ru": "ожидает", "zh": "待处理" }, @@ -1235,6 +1427,7 @@ "bg": "неизвестен", "de": "unbekannt", "en": "unknown", + "pl": "nieznany", "ru": "неизвестно", "zh": "未知" }, @@ -1242,21 +1435,8 @@ "bg": "{file} already exists. Use --force to overwrite.", "de": "{file} already exists. Use --force to overwrite.", "en": "{file} already exists. Use --force to overwrite.", + "pl": "{file} już istnieje. Użyj --force, aby nadpisać.", "ru": "{file} already exists. Use --force to overwrite.", "zh": "{file} already exists. Use --force to overwrite." - }, - "Oops! No task ID found in branch name '{branch}'. Branch names must include the task ID prefix (e.g., DEVX-31-fix-bug).": { - "en": "Oops! No task ID found in branch name '{branch}'. Branch names must include the task ID prefix (e.g., DEVX-31-fix-bug).", - "bg": "Ой! Не е намерен ID на задача в името на клона '{branch}'. Имената на клонове трябва да включват префикса за ID на задача (напр. DEVX-31-fix-bug).", - "de": "Hoppla! Keine Task-ID im Branch-Namen '{branch}' gefunden. Branch-Namen müssen das Task-ID-Präfix enthalten (z.B. DEVX-31-fix-bug).", - "ru": "Ой! ID задачи не найден в имени ветки '{branch}'. Имена веток должны включать префикс ID задачи (например, DEVX-31-fix-bug).", - "zh": "哎呀!在分支名称 '{branch}' 中未找到任务 ID。分支名称必须包含任务 ID 前缀(例如 DEVX-31-fix-bug)。" - }, - "WARNING: .taskid file ({file_id}) is deprecated and disagrees with branch name ({branch_id}). Delete .taskid from the repo — branch name is the sole source of truth.": { - "en": "WARNING: .taskid file ({file_id}) is deprecated and disagrees with branch name ({branch_id}). Delete .taskid from the repo — branch name is the sole source of truth.", - "bg": "ВНИМАНИЕ: Файлът .taskid ({file_id}) е остарял и не съвпада с името на клона ({branch_id}). Изтрийте .taskid от хранилището — името на клона е единственият източник на истината.", - "de": "WARNUNG: Die Datei .taskid ({file_id}) ist veraltet und stimmt nicht mit dem Branch-Namen ({branch_id}) überein. Löschen Sie .taskid aus dem Repo — der Branch-Name ist die einzige Wahrheitsquelle.", - "ru": "ВНИМАНИЕ: Файл .taskid ({file_id}) устарел и не совпадает с именем ветки ({branch_id}). Удалите .taskid из репозитория — имя ветки — единственный источник истины.", - "zh": "警告:.taskid 文件 ({file_id}) 已弃用,与分支名称 ({branch_id}) 不一致。请从仓库中删除 .taskid — 分支名称是唯一的真实来源。" } } diff --git a/tests/unit/test_check_translations.py b/tests/unit/test_check_translations.py index 181f016..863d12d 100644 --- a/tests/unit/test_check_translations.py +++ b/tests/unit/test_check_translations.py @@ -41,9 +41,12 @@ class TestCheckTranslationSet: src_dir.mkdir() (src_dir / "mod.py").write_text('_("Hello")\n') trans_file = tmp_path / "translations.json" - trans_file.write_text( - json.dumps({"Hello": {"en": "Hello", "bg": "Здравей", "de": "Hallo", "ru": "Привет", "zh": "你好"}}) - ) + all_langs = {"en": "Hello", "bg": "Здравей", "de": "Hallo", "ru": "Привет", "zh": "你好", "pl": "Cześć"} + # Include dynamic keys since collect_keys now adds them for all dirs + data = {"Hello": all_langs} + for dk in check_translations.DYNAMIC_KEYS: + data[dk] = all_langs + trans_file.write_text(json.dumps(data)) result = check_translations.check_translation_set("test", src_dir, trans_file) assert not result.errors @@ -170,9 +173,11 @@ class TestMain: def test_translations_flag(self, tmp_path: Path) -> None: """--translations flag should check a specific file.""" trans_file = tmp_path / "translations.json" - trans_file.write_text( - json.dumps({"Hello": {"en": "Hello", "bg": "Здравей", "de": "Hallo", "ru": "Привет", "zh": "你好"}}) - ) + all_langs = {"en": "Hello", "bg": "Здравей", "de": "Hallo", "ru": "Привет", "zh": "你好", "pl": "Cześć"} + data = {"Hello": all_langs} + for dk in check_translations.DYNAMIC_KEYS: + data[dk] = all_langs + trans_file.write_text(json.dumps(data)) (tmp_path / "mod.py").write_text('_("Hello")\n') runner = CliRunner() @@ -251,6 +256,19 @@ class TestDevxI18n: monkeypatch.delenv("DEVX_LANG", raising=False) importlib.reload(devx.i18n) + def test_polish_translation(self, monkeypatch: pytest.MonkeyPatch) -> None: + import importlib + + monkeypatch.setenv("DEVX_LANG", "pl") + import devx.i18n + + importlib.reload(devx.i18n) + result = devx.i18n._("Running tests...") + assert "Uruchamianie testów" in result + + monkeypatch.delenv("DEVX_LANG", raising=False) + importlib.reload(devx.i18n) + def test_unsupported_lang_fallback(self, monkeypatch: pytest.MonkeyPatch) -> None: import importlib @@ -290,14 +308,14 @@ class TestCollectKeys: assert "should_appear" in keys assert "should_not_appear" not in keys - def test_non_default_dir_no_dynamic_keys(self, tmp_path: Path) -> None: - """Non-default source dirs should not include DYNAMIC_KEYS.""" + def test_non_default_dir_includes_dynamic_keys(self, tmp_path: Path) -> None: + """Non-default source dirs should also include DYNAMIC_KEYS.""" (tmp_path / "mod.py").write_text('_("mykey")\n') keys = check_translations.collect_keys(tmp_path) assert "mykey" in keys - # Dynamic keys should NOT be present for non-default dirs - assert "completed" not in keys - assert "pending" not in keys + # Dynamic keys should be present for all dirs + assert "completed" in keys + assert "pending" in keys def test_default_dir_includes_dynamic_keys(self) -> None: """The default source dir should include DYNAMIC_KEYS."""