1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-11 12:46:49 +00:00

feat(vrtManager): the libvirt layer's messages show in the reader's language

vrtManager's errors (some 140: a disk that does not move, a network
address outside its subnet, a host device given to another VM, the
disks a migration cannot copy) were English f-strings, so no catalog
could translate them, on pages or in jobs.

They are marked texts with their values now; a variant that differs by
a word (internal or external, running or persistent, with a subnet or
without) is a whole message of its own, and a list of problems is a
list of messages. OperationError reads in the active language, so the
pages that show one translate it as they are; its args stay English, and
so do the logs and the audit log. Host device problems and the Migrate
tab's reasons a disk is not copied are messages too.
This commit is contained in:
catborise 2026-11-03 00:05:34 +03:00
parent 1e66367bb4
commit 491819ed64
21 changed files with 2371 additions and 420 deletions

View file

@ -19,7 +19,7 @@ from libvirt import libvirtError
from accounts.models import UserInstance
from appsettings.models import AppSettings
from instances.models import Instance
from vrtManager.util import ConnectionFailed, OperationError
from vrtManager.util import ConnectionFailed, OperationError, render
from . import jobs
@ -66,7 +66,18 @@ def safe_text(text):
# words() puts them in the language of whoever reads them. A text that is not
# ours (libvirt's) is a message without values and stays as it is.
def say(text, **values):
return [{"text": safe_text(text), "values": {key: safe_text(value) for key, value in values.items()}}]
return [{"text": safe_text(text), "values": {key: _stored(value) for key, value in values.items()}}]
def _stored(value):
"""A value as a job keeps it: messages stay messages (vrtManager.util.message)."""
if isinstance(value, list):
return [say(m["text"], **m["values"])[0] for m in value]
if isinstance(value, OperationError):
return [say(value.text, **value.values)[0]]
if isinstance(value, (int, float)) and not isinstance(value, bool):
return value # for %(x).1f and the like
return safe_text(value)
def said(exception):
@ -78,7 +89,7 @@ def said(exception):
def words(messages):
"""messages in the active language, each a sentence of its own."""
parts = [_(m["text"]) % m["values"] if m["values"] else _(m["text"]) for m in messages]
parts = [render(m["text"], m["values"], _) for m in messages]
return " ".join(part if last or part.endswith((".", "。", "!", "?")) else part + "."
for last, part in ((i == len(parts) - 1, part) for i, part in enumerate(parts)))