Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion aegis/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def main(
lang: str | None = typer.Option(
None,
"--lang",
help="Output language (de, en, fr, ja, ko, ru, zh, zh_Hant). Default: auto-detect from AEGIS_LANG or system locale",
help="Output language (de, en, es, fr, ja, ko, ru, zh, zh_Hant). Default: auto-detect from AEGIS_LANG or system locale",
envvar="AEGIS_LANG",
),
) -> None:
Expand Down
12 changes: 11 additions & 1 deletion aegis/i18n/locales/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
"""Available locales for Aegis Stack CLI."""

AVAILABLE_LOCALES: set[str] = {"de", "en", "fr", "ja", "ko", "ru", "zh", "zh_Hant"}
AVAILABLE_LOCALES: set[str] = {
"de",
"en",
"es",
"fr",
"ja",
"ko",
"ru",
"zh",
"zh_Hant",
}
757 changes: 757 additions & 0 deletions aegis/i18n/locales/es.py

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions aegis/i18n/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ def _load_locale(locale: str) -> None:
from .locales.de import MESSAGES

_messages["de"] = MESSAGES
elif locale == "es":
from .locales.es import MESSAGES

_messages["es"] = MESSAGES
elif locale == "fr":
from .locales.fr import MESSAGES

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
"""Available locales for the project CLI."""

AVAILABLE_LOCALES: set[str] = {"de", "en", "fr", "ja", "ko", "ru", "zh", "zh_Hant"}
AVAILABLE_LOCALES: set[str] = {
"de",
"en",
"es",
"fr",
"ja",
"ko",
"ru",
"zh",
"zh_Hant",
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"main.unsupported_lang": "Sprache '{lang}' nicht unterstützt. Verfügbar: {available}",
# Help text
"main.help": "Projekt-Management-CLI",
"main.opt_lang": "Ausgabesprache (de, en, fr, ja, ko, ru, zh, zh_Hant). Standard: automatisch",
"main.opt_lang": "Ausgabesprache (de, en, es, fr, ja, ko, ru, zh, zh_Hant). Standard: automatisch",
# ── Health ────────────────────────────────────────────────────────
"health.count_healthy": "{count} gesund",
"health.count_warning": "{count} Warnung",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"main.unsupported_lang": "Unsupported language '{lang}'. Available: {available}",
# Help text
"main.help": "Project management CLI",
"main.opt_lang": "Output language (de, en, fr, ja, ko, ru, zh, zh_Hant). Default: auto-detect",
"main.opt_lang": "Output language (de, en, es, fr, ja, ko, ru, zh, zh_Hant). Default: auto-detect",
# ── Health ────────────────────────────────────────────────────────
"health.count_healthy": "{count} healthy",
"health.count_warning": "{count} warning",
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"main.unsupported_lang": "Langue non prise en charge « {lang} ». Disponibles : {available}",
# Texte d'aide
"main.help": "CLI de gestion de projet",
"main.opt_lang": "Langue de sortie (de, en, fr, ja, ko, ru, zh, zh_Hant). Par défaut : détection auto",
"main.opt_lang": "Langue de sortie (de, en, es, fr, ja, ko, ru, zh, zh_Hant). Par défaut : détection auto",
# ── Santé ────────────────────────────────────────────────────────
"health.count_healthy": "{count} sain(s)",
"health.count_warning": "{count} avertissement",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"main.unsupported_lang": "未対応の言語 '{lang}'。利用可能:{available}",
# ヘルプ
"main.help": "プロジェクト管理CLI",
"main.opt_lang": "出力言語(de、en、fr、ja、ko、ru、zh、zh_Hant)。デフォルト:自動検出",
"main.opt_lang": "出力言語(de、en、es、fr、ja、ko、ru、zh、zh_Hant)。デフォルト:自動検出",
# ── ヘルスチェック ─────────────────────────────────────────────────
"health.count_healthy": "{count} 件正常",
"health.count_warning": "{count} 件警告",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"main.unsupported_lang": "지원하지 않는 언어입니다: '{lang}'. 사용 가능: {available}",
# Help text
"main.help": "프로젝트 관리 CLI",
"main.opt_lang": "출력 언어 (de, en, fr, ja, ko, ru, zh, zh_Hant). 기본값: 자동 감지",
"main.opt_lang": "출력 언어 (de, en, es, fr, ja, ko, ru, zh, zh_Hant). 기본값: 자동 감지",
# ── Health ────────────────────────────────────────────────────────
"health.count_healthy": "{count}개 정상",
"health.count_warning": "{count}개 경고",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"main.unsupported_lang": "Язык '{lang}' не поддерживается. Доступные: {available}",
# Справка
"main.help": "CLI управления проектом",
"main.opt_lang": "Язык вывода (de, en, fr, ja, ko, ru, zh, zh_Hant). По умолчанию: автоопределение",
"main.opt_lang": "Язык вывода (de, en, es, fr, ja, ko, ru, zh, zh_Hant). По умолчанию: автоопределение",
# ── Здоровье ─────────────────────────────────────────────────────
"health.count_healthy": "{count} в норме",
"health.count_warning": "{count} предупреждение",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"main.unsupported_lang": "不支持的语言 '{lang}'。可用语言:{available}",
# 帮助文本
"main.help": "项目命令行工具",
"main.opt_lang": "输出语言(de、en、fr、ja、ko、ru、zh、zh_Hant),默认自动检测系统语言",
"main.opt_lang": "输出语言(de、en、es、fr、ja、ko、ru、zh、zh_Hant),默认自动检测系统语言",
# ── 健康检查 ──────────────────────────────────────────────────────
"health.count_healthy": "{count} 个正常",
"health.count_warning": "{count} 个警告",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"main.unsupported_lang": "不支援的语言 '{lang}'。可用語言:{available}",
# 幫助文本
"main.help": "項目命令行工具",
"main.opt_lang": "輸出語言(de、en、fr、ja、ko、ru、zh、zh_Hant),默認自動檢測系統語言",
"main.opt_lang": "輸出語言(de、en、es、fr、ja、ko、ru、zh、zh_Hant),默認自動檢測系統語言",
# ── 健康檢查 ──────────────────────────────────────────────────────
"health.count_healthy": "{count} 個正常",
"health.count_warning": "{count} 個警告",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ def _ensure_loaded(locale: str) -> None:
from .locales.de import MESSAGES

_messages["de"] = MESSAGES
elif locale == "es":
from .locales.es import MESSAGES

_messages["es"] = MESSAGES
elif locale == "fr":
from .locales.fr import MESSAGES

Expand Down
22 changes: 21 additions & 1 deletion tests/core/test_i18n.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ def test_korean_variants(self) -> None:
assert _normalize_locale("ko_KR.UTF-8") == "ko"
assert _normalize_locale("ko-KR") == "ko"

def test_spanish_variants(self) -> None:
"""Spanish locale variants normalize to 'es'."""
assert _normalize_locale("es") == "es"
assert _normalize_locale("es_ES") == "es"
assert _normalize_locale("es-MX") == "es"
assert _normalize_locale("es_AR") == "es"
assert _normalize_locale("es_ES.UTF-8") == "es"

def test_german_variants(self) -> None:
"""German locale variants normalize to 'de'."""
assert _normalize_locale("de") == "de"
Expand All @@ -70,8 +78,8 @@ def test_russian_variants(self) -> None:
def test_unsupported_falls_back_to_english(self) -> None:
"""Unsupported locales fall back to 'en'."""
assert _normalize_locale("xx") == "en"
assert _normalize_locale("es_MX.UTF-8") == "en"
assert _normalize_locale("pt_BR") == "en"
assert _normalize_locale("sv_SE") == "en"

def test_encoding_and_modifier_stripped(self) -> None:
"""Encoding suffixes and modifiers are stripped."""
Expand All @@ -97,13 +105,23 @@ def test_all_locales_registered(self) -> None:
"""All expected locales are in AVAILABLE_LOCALES."""
assert "de" in AVAILABLE_LOCALES
assert "en" in AVAILABLE_LOCALES
assert "es" in AVAILABLE_LOCALES
assert "fr" in AVAILABLE_LOCALES
assert "ja" in AVAILABLE_LOCALES
assert "ko" in AVAILABLE_LOCALES
assert "ru" in AVAILABLE_LOCALES
assert "zh" in AVAILABLE_LOCALES
assert "zh_Hant" in AVAILABLE_LOCALES

def test_es_has_all_keys(self) -> None:
"""Spanish has all English keys."""
Comment thread
lbedner marked this conversation as resolved.
from aegis.i18n.locales.es import MESSAGES as ES

missing = set(EN_MESSAGES) - set(ES)
extra = set(ES) - set(EN_MESSAGES)
assert not missing, f"Keys in en but not es: {missing}"
assert not extra, f"Keys in es but not en: {extra}"

def test_de_has_all_keys(self) -> None:
"""German has all English keys."""
from aegis.i18n.locales.de import MESSAGES as DE
Expand Down Expand Up @@ -170,6 +188,7 @@ def test_ko_has_all_keys(self) -> None:
def test_no_empty_values(self) -> None:
"""No locale has empty string values."""
from aegis.i18n.locales.de import MESSAGES as DE
from aegis.i18n.locales.es import MESSAGES as ES
from aegis.i18n.locales.fr import MESSAGES as FR
from aegis.i18n.locales.ja import MESSAGES as JA
from aegis.i18n.locales.ko import MESSAGES as KO
Expand All @@ -179,6 +198,7 @@ def test_no_empty_values(self) -> None:

for name, messages in [
("de", DE),
("es", ES),
("fr", FR),
("ja", JA),
("ko", KO),
Expand Down
Loading