form: add translating method

This commit is contained in:
axolotle 2023-04-17 19:51:16 +02:00
parent 3ff6e6ed96
commit 582b1ed311
2 changed files with 33 additions and 18 deletions

View file

@ -447,7 +447,7 @@ class BaseTest:
assert isinstance(option, OPTIONS[raw_option["type"]])
assert option.type == raw_option["type"]
assert option.id == id_
assert option.ask == {"en": id_}
assert option.ask == id_
assert option.readonly is (True if is_special_readonly_option else False)
assert option.visible is True
# assert option.bind is None
@ -493,7 +493,7 @@ class BaseTest:
)
option, value = _fill_or_prompt_one_option(raw_option, None)
expected_message = option.ask["en"]
expected_message = option.ask
choices = []
if isinstance(option, BaseChoicesOption):
@ -510,7 +510,7 @@ class BaseTest:
prefill=prefill,
is_multiline=option.type == "text",
autocomplete=choices,
help=option.help["en"],
help=option.help,
)
def test_scenarios(self, intake, expected_output, raw_option, data):
@ -558,7 +558,7 @@ class TestDisplayText(BaseTest):
options, form = ask_questions_and_parse_answers(
{_id: raw_option}, answers
)
assert stdout.getvalue() == f"{options[0].ask['en']}\n"
assert stdout.getvalue() == f"{options[0].ask}\n"
# ╭───────────────────────────────────────────────────────╮
@ -609,7 +609,7 @@ class TestAlert(TestDisplayText):
options, form = ask_questions_and_parse_answers(
{"display_text_id": raw_option}, answers
)
ask = options[0].ask["en"]
ask = options[0].ask
if style in colors:
color = colors[style]
title = style.title() + (":" if style != "success" else "!")

View file

@ -297,15 +297,6 @@ class BaseOption(BaseModel):
del schema["description"]
schema["additionalProperties"] = False
@validator("ask", always=True)
def parse_or_set_default_ask(
cls, value: Union[Translation, None], values: Values
) -> Translation:
if value is None:
return {"en": values["id"]}
if isinstance(value, str):
return {"en": value}
return value
@validator("readonly", pre=True)
def can_be_readonly(cls, value: bool, values: Values) -> bool:
@ -327,7 +318,9 @@ class BaseOption(BaseModel):
return evaluate_simple_js_expression(self.visible, context=context)
def _get_prompt_message(self, value: None) -> str:
return _value_for_locale(self.ask)
# force type to str
# `OptionsModel.translate_options()` should have been called before calling this method
return cast(str, self.ask)
# ╭───────────────────────────────────────────────────────╮
@ -367,7 +360,7 @@ class AlertOption(BaseReadonlyOption):
State.danger: "red",
}
message = m18n.g(self.style) if self.style != State.danger else m18n.n("danger")
return f"{colorize(message, colors[self.style])} {_value_for_locale(self.ask)}"
return f"{colorize(message, colors[self.style])} {self.ask}"
class ButtonOption(BaseReadonlyOption):
@ -624,6 +617,7 @@ class NumberOption(BaseInputOption):
max: Union[int, None] = None
step: Union[int, None] = None
_annotation = int
_none_as_empty_str = False
@staticmethod
def normalize(value, option={}):
@ -1274,6 +1268,26 @@ class OptionsModel(BaseModel):
def __init__(self, **kwargs) -> None:
super().__init__(options=self.options_dict_to_list(kwargs))
def translate_options(self, i18n_key: Union[str, None] = None):
"""
Mutate in place translatable attributes of options to their translations
"""
for option in self.options:
for key in ("ask", "help"):
if not hasattr(option, key):
continue
value = getattr(option, key)
if value:
setattr(option, key, _value_for_locale(value))
elif key == "ask" and m18n.key_exists(f"{i18n_key}_{option.id}"):
setattr(option, key, m18n.n(f"{i18n_key}_{option.id}"))
elif key == "help" and m18n.key_exists(f"{i18n_key}_{option.id}_help"):
setattr(option, key, m18n.n(f"{i18n_key}_{option.id}_help"))
elif key == "ask":
# FIXME warn?
option.ask = option.id
class FormModel(BaseModel):
"""
@ -1384,7 +1398,7 @@ def prompt_or_validate_form(
raise YunohostValidationError(
"config_action_disabled",
action=option.id,
help=_value_for_locale(option.help),
help=option.help,
)
if not option.is_visible(context):
@ -1433,7 +1447,7 @@ def prompt_or_validate_form(
prefill=value,
is_multiline=isinstance(option, TextOption),
autocomplete=choices,
help=_value_for_locale(option.help),
help=option.help,
)
# Apply default value if none
@ -1512,6 +1526,7 @@ def ask_questions_and_parse_answers(
# FIXME use YunohostError instead since it is not really a user mistake?
raise YunohostValidationError(error, raw_msg=True)
model.translate_options()
# Build the form from those questions and instantiate it without
# parsing/validation (construct) since it may contains required questions.
form = build_form(model.options).construct()