i18n: complete OCI catalogue and wizard Slovak wording

This commit is contained in:
VAIO73
2026-10-21 07:06:04 +00:00
parent 092a62e2dd
commit 37a6c02111
6 changed files with 655 additions and 477 deletions
+6 -6
View File
@@ -15,7 +15,7 @@ from . import console, images
from .catalog import Catalog
from .converter import ConversionError
from .github_source import SourceError
from .i18n import N_, source_text, translate
from .i18n import N_, diagnostic, source_text, translate
from .installer import (
ADDRESS_SHOWN,
ADVANCED_MODE,
@@ -38,7 +38,7 @@ PUBLISHERS = {"linuxserver.io": "LinuxServer", "official": N_("Official image")}
STACK_LABELS = {
"server": N_("Server"),
"application": N_("Application"),
"machine_learning": "Machine learning",
"machine_learning": N_("Machine learning"),
"database": "PostgreSQL",
"valkey": "Valkey",
"cache": "Redis",
@@ -133,7 +133,7 @@ def _service_kind(service: dict[str, Any]) -> str:
if service.get("is_main"):
return translate("Application")
if "machine-learning" in name or "machine-learning" in image:
return "Machine learning"
return translate("Machine learning")
for key, label in SERVICE_KINDS:
if key in image:
return label
@@ -267,7 +267,7 @@ def _deployment_summary_text(template: dict[str, Any], deployment: dict[str, Any
target = (f"{mount['size_gb']} GB {on} {mount['source']}"
if mount["type"] == "managed-volume" else mount["source"])
lines.append(f" {mount['container_path']} → {target}")
for key, label in (("media", "Library"), ("application", "Application data"), ("transfer", "Consume/export")):
for key, label in (("media", N_("Library")), ("application", N_("Application data")), ("transfer", N_("Consume/export"))):
storage = plan.get(key)
if isinstance(storage, dict) and "mode" in storage:
if storage["mode"] == "host-bind":
@@ -614,7 +614,7 @@ def interactive(catalog: Catalog) -> int:
continue
except (ConversionError, InstallError, OSError, ValueError) as exc:
console.stop_spinner()
ui.message(f"{translate('The operation could not be completed')}:\n\n{exc}")
ui.message(f"{translate('The operation could not be completed')}:\n\n{diagnostic(exc)}")
# ---------------------------------------------------------------- maintenance CLI
@@ -773,7 +773,7 @@ def main(argv: list[str] | None = None) -> int:
return 130
except (ConversionError, SourceError, InstallError, OSError, ValueError) as exc:
console.stop_spinner()
print(f"ERROR: {exc}", file=sys.stderr)
print(f"ERROR: {diagnostic(exc)}", file=sys.stderr)
return 1
+18
View File
@@ -7,6 +7,7 @@ is the source language: a missing translation returns the English text.
from __future__ import annotations
import json
import re
from pathlib import Path
from typing import Any
@@ -46,6 +47,23 @@ def translate(text: str) -> str:
return _cache.get(text) or text
def diagnostic(error: Any) -> str:
"""Translate legacy diagnostics only when presenting them to a person.
The catalog's exception types and original messages remain stable for
internal callers; identifiers are inserted after the translation lookup.
"""
text = str(error)
for pattern, source in (
(r"No template is available for '(.*)'", N_("No template is available for '{app_id}'")),
(r"The application '(.*)' is not in the index", N_("The application '{app_id}' is not in the index")),
):
match = re.fullmatch(pattern, text)
if match:
return translate(source).format(app_id=match[1])
return text
def source_text(value: Any) -> str:
"""The English a catalog field was written in.
+3 -3
View File
@@ -365,13 +365,13 @@ def build_stack(template, ui, mode='advanced'):
service_name = group['service']
if service_name not in envs:
raise StackError(f"{translate('Unknown credential service:')} {service_name}")
if not quiet.confirm(f"{translate('Configure')} {group['label']} ({translate('optional')})", False):
if not quiet.confirm(f"{translate('Configure')} {translate(group['label'])} ({translate('optional')})", False):
continue
for field in group['fields']:
if field['name'] not in envs[service_name] or envs[service_name][field['name']] != '':
raise StackError(f"{translate('External field not reserved:')} {field['name']}")
value = (ui.password(field['label'], required=True) if field.get('sensitive',True)
else ui.ask(field['label'], required=True))
value = (ui.password(translate(field['label']), required=True) if field.get('sensitive',True)
else ui.ask(translate(field['label']), required=True))
if not value or any(c in value for c in '\r\n'):
raise StackError(translate('External credential is empty or spans multiple lines'))
envs[service_name][field['name']] = value
+10 -1
View File
@@ -3,6 +3,7 @@ transcoding and its recognition: the CPU, or each usable GPU of the host for
both or for only one of them."""
from pathlib import Path
import json
import sys
import unittest
from unittest.mock import patch
@@ -165,7 +166,15 @@ class ImmichAccelerationTests(unittest.TestCase):
def test_the_name_of_the_machine_learning_container_is_not_translated(self, *_):
script = (ROOT / "remote/install_immich_stack.sh").read_text()
self.assertNotIn('translate "Machine learning"', script)
self.assertNotIn('translate("Machine learning")', (ROOT / "src/proxmenux_oci/cli.py").read_text())
from proxmenux_oci.cli import _service_kind
from proxmenux_oci import i18n
service = {'name': 'immich-machine-learning', 'image': 'ghcr.io/immich-app/immich-machine-learning:release'}
original = dict(service)
with patch.object(i18n, 'language', return_value='sk'), patch.object(i18n, '_cache', json.loads((ROOT.parent / 'lang/sk.json').read_text())):
self.assertEqual(_service_kind(service), 'Strojové učenie')
_, _, plan = self.plan(NOTHING, DEFAULT_MODE)
self.assertIn('machine_learning', plan)
self.assertEqual(service, original)
if __name__ == "__main__":