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:
parent
1e66367bb4
commit
491819ed64
21 changed files with 2371 additions and 420 deletions
|
|
@ -1,3 +1,4 @@
|
|||
from django.utils.translation import gettext_noop
|
||||
import ipaddress
|
||||
import random
|
||||
import secrets
|
||||
|
|
@ -8,23 +9,47 @@ import libvirt
|
|||
import lxml.etree as etree
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.translation import gettext
|
||||
|
||||
|
||||
|
||||
def message(text, **values):
|
||||
"""Our text, marked with gettext_noop, with %(name)s for each of values.
|
||||
A value may be a list of messages: they are put in its place one after
|
||||
another."""
|
||||
return {"text": str(text), "values": values}
|
||||
|
||||
|
||||
def render(text, values, translate):
|
||||
"""text with its values, through translate (gettext, or str for English)."""
|
||||
def shown(value):
|
||||
if isinstance(value, list):
|
||||
return "; ".join(render(m["text"], m["values"], translate) for m in value)
|
||||
if isinstance(value, OperationError):
|
||||
return render(value.text, value.values, translate)
|
||||
return value
|
||||
text = translate(text)
|
||||
return text % {key: shown(value) for key, value in values.items()} if values else text
|
||||
|
||||
|
||||
class OperationError(libvirt.libvirtError):
|
||||
"""An error with WebVirtCloud's own message: text, with %(name)s for each
|
||||
of values. str() is the English message; a page or a job shows text
|
||||
translated, with the values (operations.utils.said).
|
||||
"""An error with WebVirtCloud's own message (see message()). Its args are
|
||||
the English message, for logs and the audit log; str() is the message in
|
||||
the active language, English outside a request. A job keeps the text and
|
||||
values (operations.utils.said) and shows them in its reader's language.
|
||||
|
||||
libvirtError(msg) reports the thread's last libvirt error instead of msg
|
||||
when there is one, so an earlier, unrelated failure would be shown.
|
||||
"""
|
||||
|
||||
def __init__(self, text, **values):
|
||||
Exception.__init__(self, text % values if values else text)
|
||||
self.text, self.values = str(text), values
|
||||
Exception.__init__(self, render(self.text, values, str))
|
||||
self.err = None
|
||||
|
||||
def __str__(self):
|
||||
return render(self.text, self.values, gettext)
|
||||
|
||||
|
||||
class ConnectionFailed(OperationError):
|
||||
"""The host could not be connected to; the message may name it and how it
|
||||
|
|
@ -112,9 +137,9 @@ def parse_xml(xml):
|
|||
try:
|
||||
tree = etree.fromstring(xml.encode(), parser) # bytes: the XML may declare its encoding
|
||||
except etree.XMLSyntaxError as err:
|
||||
raise OperationError(f"The XML is not valid: {err}") from None
|
||||
raise OperationError(gettext_noop("The XML is not valid: %(err)s"), err=err) from None
|
||||
if tree.getroottree().docinfo.internalDTD is not None:
|
||||
raise OperationError("The XML may not declare a DTD")
|
||||
raise OperationError(gettext_noop("The XML may not declare a DTD"))
|
||||
return tree
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue