The line-by-line web translator reordered words inside `**bold**` spans and
misplaced/dropped the markers, producing `**LB` or `****` (empty bold). Mask
each `**...**` as ONE atomic sentinel: translate the inner text on its own,
then store the whole balanced `**inner**` — the engine never sees the markers
and cannot reorder or collapse them. Also harden the anthropic prompt to keep
emphasis balanced.
Auto-prune: after translating, delete generated docs/ru files whose docs/en
source no longer exists (renamed/removed) and drop now-empty dirs, so the tree
mirrors docs/en 1:1 (removes the stale development/modules.md and
guides/geoip-and-device-detection.md).
Bump PROMPT_VERSION to 6 to invalidate the contaminated cache and regenerate
docs/ru (0 broken bold spans remaining, aside from pre-existing multi-line
bold that spans a soft line break).
Fix Markdown-mangling artifacts the free web engine (yandex) produced in the
committed docs/ru, and regenerate the whole tree cleanly (0 fallbacks):
- Sentinel format @@N@@ -> {N}. MT engines are trained to preserve curly
format-string placeholders, so {N} survives code-heavy lines where @@N@@ (and
ZZZ…ZZZ, which also duplicated its Z) were split/moved — e.g. the stray
"@0@@" in the FAQ and "load balancerZ" in the README are gone.
- Possessive: a trailing English `'s` is consumed INTO the masked span and
dropped on restore. Every sentinel format breaks when a bare `'s` sits right
after it, and Russian has no possessive `'s`.
- Validate + retry: after restore, any leftover brace fragment triggers a retry
(the engine is non-deterministic); after a few failures the line stays English
so a broken token is never emitted.
- Glossary += KeyDB, yt-dlp, Ubuntu, iptables, MAGSCAN.
Regenerated docs/ru (37 files, translators/yandex): no residual sentinels,
mkdocs build --strict clean.
CI translation was slow, so move it out of GitHub Actions: docs/ru is now a
committed, generated tree refreshed LOCALLY before a release; CI only builds it.
- pages.yml: drop the setup-python/cache/translate steps — the workflow now just
installs the build toolchain and runs `mkdocs build --strict` on the committed
en+ru trees.
- .gitignore: stop ignoring docs/ru (now committed); keep site/ + .docs-cache/.
- Split deps: docs/requirements.txt = build only (mkdocs-material, static-i18n,
used by CI); tools/docs/requirements.txt = translators (local-only).
- Makefile: docs-venv installs both; docs-build/docs-serve no longer translate
(translation is the deliberate `make docs-translate` release step).
- updates_checklist.md: new "Regenerate translated documentation" step
(make docs-translate + docs-build, commit docs/ru with the release commit).
- Commit the generated docs/ru (37 files, translators/yandex).
Rule: edit ONLY docs/en; docs/ru is generated — never hand-edit it.
Replace the hand-maintained Docsify site (parallel docs/en + docs/ru trees
that had already drifted) with a MkDocs Material build where English is the
single source of truth and Russian is generated at build time.
Engine & structure
- mkdocs.yml: Material theme, site_url for the /XC_VM/ Pages subpath, and a
two-tab information architecture — User Guide (administration, API/Swagger,
UI translations, diagnostics, info/FAQ) vs Developer Guide (architecture,
workflow, security, integrations, build). Files are NOT moved — the split is
nav-only, so URLs and cross-links stay stable.
- mkdocs-static-i18n (folder mode): English at root, Russian under /ru/, with a
language switcher. `mkdocs build --strict` validates every link/anchor.
Translation pipeline (tools/docs/translate.py)
- Engine-agnostic via DOCS_TRANSLATE_PROVIDER: translators (free, no API key —
default), anthropic, deepl, or noop. Per-file sha256 cache so only changed
English files are re-translated. Markdown-safe: code, URLs, HTML tags and
glossary terms (XC_VM, FFmpeg, HLS, ...) are masked and never translated.
A file whose translation fails falls back to English so the build never breaks.
- docs/ru is generated and gitignored — never committed. It is produced locally
(`make docs-serve` / `docs-build`) and in CI.
CI & tooling
- pages.yml: build-then-upload (setup-python -> install -> restore .docs-cache
with restore-keys -> translate -> mkdocs build --strict -> deploy), replacing
the verbatim docs/ upload.
- Makefile: docs-venv / docs-translate / docs-build / docs-serve.
- docs/requirements.txt; .gitignore for docs/ru, site/, .docs-cache.
Migration details
- Removed Docsify control files (index.html, _navbar.md, _sidebar.md, .nojekyll)
and de-Docsify-ed body links in 6 English files (en-us/ aliases -> relative,
swagger _media paths, stripped ':ignore' link syntax).
- Preserved the two Russian-only planning docs (no English source) by moving
them into docs/adr/ as *.ru.md (repo-internal, excluded from the site).
Drop the two ministra restoration working-notes now that the work is
done: ministra-unused-modules.md (dead-module audit complete) and
ministra-5.6.10-lost-customizations.md (all items resolved). Also drop
the now-dangling doc reference from the get_modules debug comment.
The ministra-browser-emulation.md integration guide is kept.
Review of the remaining 5.6.10 lost-customization items:
- player.js: multi-audio (titles/infoCurtitle) kept and improved by
5.6.10; xc_vm PVR branch intact; parental flow lives in tv.js, not
here. No changes needed.
- account.js: keep the full 5.6.10 account screen (decision) instead of
restoring the minimal Phone+message fork screen.
- xpcom.common.js: allowed_stb_types/aurahd richer in 5.6.10;
outdated_firmware (player<1382) only gates non-whitelisted types and
is more permissive, not a regression; check_image_version is a no-op
(backend sends no autoupdate); load_channels parental left to 5.6.10 +
tv.js guards to avoid a double password prompt.
Re-apply two xc_vm customizations that the 5.6.10 client drop wiped out:
- Channel logos (tv.js handling_block + player.js preview): on xc_vm the
backend sends a ready-to-use logo URL, but 5.6.10 rebuilt a classic
stalker misc/logos/<size>/ path, breaking the image. Use the URL
directly; keep the 5.6.10 timeshift_mode class on the player logo.
- TV color buttons (tv.js): in the xc_vm theme the 4th button is channel
search (search_menu_switcher) instead of the fav-manage "move" mode.
Hybrid with the new 5.6.10 quality-filter button — quality wins when
the profile enables tv_quality_filter, otherwise search.
Also drop the obsolete snumber/sortIDs note: the backend now numbers
channels sequentially, so 5.6.10 sortBy("number") is correct.
- Add ministra-5.6.10-lost-customizations.md: what our fork's clean
5.6.10 drop wiped out and how to restore it (get_types_list, tv.js
parental control, channel logos, account screen, DVR .ts format, ...).
- Update ministra-browser-emulation.md for the ?debug_key gate.
Drop portal JS modules that the loader never pulls in (not in
base_modules/all_modules, no dynamic loader, no live references) and
their theme assets:
- infoportal branch: infoportal, anecdote, cityinfo, horoscope,
weather.current, weather.day, course.cbr, course.nbu, game.mastermind
(root module dead + crashes main menu when force-enabled)
- magiccast (leaked proxy creds to an external Infomir service)
- youtube (web wrapper dir absent from repo)
- demo, service_management (stub features, no server handlers)
- karaoke (no backend; "radio only")
- pvr.js (legacy Pvr, never instantiated; live local PVR is
pvr_local/records)
- JsHttpRequest-debug.js (core loads JsHttpRequest.js)
Removes 15 per-theme CSS variants + menu icons per module. The dead-code
audit is tracked in docs/ru/guides/ministra-unused-modules.md.
The heartbeat is written by the watchdog daemon (which now waits out DB
outages), not by cron:servers; the babysitter section documents the
crontab/cron-service/hung-lock sub-checks, and the cheat-sheet covers
the 'all nodes drop at the same moment' scenario. cli-tools blurbs
updated to match (en/ru).
Overhaul the Docsify documentation (English + Russian) so it matches the current
codebase and follows one consistent pattern.
Content accuracy (post-migration):
- Rewrite development/autoloader.md to PSR-4 / Composer (the old XC_Autoloader
scanner, igbinary tmp/cache/autoload_map and registerDirectories are gone).
- PascalCase every source path (src/core -> src/Core, domain/Stream, cli/Commands,
public/Controllers, Infrastructure/Redis, ...) across all docs.
- Replace the removed autoload.php references with vendor/autoload.php
(build_system, bootstrap-contexts, error-handling, modules).
- ssl-generation: note that the installer now auto-generates a unique self-signed
certificate before Nginx starts.
Common pattern (Clean & uniform):
- Strip emoji from headings; remove the in-page Navigation blocks (the Docsify
sidebar already provides navigation).
- One H1 + intro per doc; uniform "Related files" / "Связанные файлы" section,
added to the code-centric docs that lacked it.
Structure:
- Remove the empty stray docs/api/; move updates_checklist.md into builds/;
link the previously-orphaned ucs-integration.md.
- Regroup the sidebars (split the oversized guides group into Developer Guides /
Security & Access / Integrations; fold builds into Build & Release).
Augment:
- dev-workflow: Local Setup (make dev-tools) + Quality Checks (phpstan, cs, gates).
- build_system: Composer Dependencies section (committed prod-only vendor,
committed lock, dev tools via composer install, no build-time vendor step).
en/ru parity:
- Apply the same structure, fixes and pattern to docs/ru/ (translated), including
a new Russian ucs-integration.md. The en and ru file sets are now identical.