Break monolithic modules >400 lines into focused sub-modules while preserving backward-compatible imports and all test coverage: Backend (Python): - TranslationExecutor: 1974→241 lines, split into 9 sub-modules - Translate plugin: orchestrator (1137→148), preview (1303→244), service (1052→275), dictionary (1007→68) - ProfileService: 857→172 with 4 extracted sub-modules - TaskManager: 708→322 with graph/event_bus/lifecycle extracted - Test dictionary: 1199→split into 6 focused test files Frontend (Svelte): - SettingsPage: 1451→291 with 6 extracted tab components - GitManager: 1220→228 with 5 extracted panels - DatasetReviewWorkspace: 1202→314 - translate.js API: 664→28 barrel with 6 domain modules Protocol: - Remove single-contract 150-line limit from INV_7 (keep CC≤10) - Fix unclosed #endregion tags across 11 files - Fix 19 test regressions from stale mock paths - All 294 tests passing
18 lines
705 B
Python
18 lines
705 B
Python
# #region _validate_bcp47 [C:2] [TYPE Function] [SEMANTICS validation, bcp47, language]
|
|
# @BRIEF Validate that a language tag is a non-empty BCP-47 string.
|
|
|
|
import re as _re
|
|
|
|
|
|
def _validate_bcp47(tag: str, field_name: str) -> None:
|
|
"""Validate that tag is a non-empty BCP-47 string (basic check)."""
|
|
if not tag or not tag.strip():
|
|
raise ValueError(f"{field_name} must be a non-empty BCP-47 language tag")
|
|
tag = tag.strip()
|
|
if not _re.match(r'^[a-zA-Z]{2,8}(-[a-zA-Z0-9]{1,8})*$', tag):
|
|
raise ValueError(
|
|
f"{field_name} is not a valid BCP-47 tag: '{tag}'. "
|
|
"Expected format like 'en', 'ru', 'zh-CN', 'pt-BR'."
|
|
)
|
|
# #endregion _validate_bcp47
|