44@author: wf
55"""
66
7+ from dataclasses import dataclass
78from typing import Any , Dict , List , Optional , Union
89
910from basemkit .yamlable import lod_storable
1011
12+
1113# Type alias: a translatable string is either a plain str or a
1214# language-keyed dict, e.g. {"en": "Name", "de": "Name", "fr": "Nom"}.
1315I18nStr = Optional [Union [str , Dict [str , str ]]]
@@ -34,51 +36,36 @@ def resolve(value: I18nStr, lang: str = "en") -> str:
3436 Returns:
3537 str: the resolved string for the requested language
3638 """
37- if value is None :
38- return ""
39- if isinstance (value , dict ):
40- resolved = value .get (lang ) or value .get ("en" )
41- if resolved is None and value :
42- resolved = next (iter (value .values ()))
43- return resolved or ""
44- return value
39+ i18n = ""
40+ if value is not None :
41+ if isinstance (value , dict ):
42+ i18n = value .get (lang ) or value .get ("en" )
43+ if i18n is None and value :
44+ i18n = next (iter (value .values ()))
45+ i18n = i18n or ""
46+ return i18n
4547
4648
4749def resolve_i18n (value : I18nStr , lang : str = "en" ) -> str :
4850 """Backward compatible alias for I18n.resolve()"""
49- return I18n .resolve (value , lang )
50-
51+ i18n = I18n .resolve (value , lang )
52+ return i18n
5153
54+ @dataclass
5255class HtmlElement :
5356 """
5457 Base class for HTML elements with common attributes.
5558 """
56-
5759 css_class : str = "" # e.g. "form-control selectpicker"
5860 size : str = "" # xs, sm, md, lg
5961
6062
6163@lod_storable
62- class FormLabel :
64+ class FormLabel ( HtmlElement ) :
6365 """
6466 Label element with i18n support for form fields.
65-
66- Can be defined as a simple string/dict (backward compatible) or as an object:
67-
68- # Simple (backward compatible):
69- label: "Name" or label: {en: "Name", de: "Name"}
70-
71- # Object with CSS class:
72- label:
73- text:
74- en: "Name"
75- de: "Name"
76- css_class: "bitplanorange"
7767 """
78-
7968 text : I18nStr = "" # the label text
80- css_class : str = "" # additional CSS class (e.g., "bitplanorange")
81- size : str = "" # xs, sm, md, lg
8269
8370
8471@lod_storable
@@ -103,16 +90,15 @@ class FormField(HtmlElement):
10390 max: 100
10491 - type: Email
10592 """
106-
10793 name : str = "" # required but defaults to empty for compatibility
10894 field_type : str = "text" # text | textarea | select | hidden | email
109- label : Any = None # I18nStr or FormLabel object
110- placeholder : Any = None # I18nStr
95+ label : FormLabel = None
96+ placeholder : I18nStr = None # I18nStr
11197 glyphicon : Optional [str ] = None
11298 required : bool = False
113- error_msg : Any = None # I18nStr
99+ error_msg : I18nStr = None # I18nStr
114100 value : Optional [str ] = None # for hidden fields / pre-filled defaults
115- choices : Optional [List [str ]] = None # for select fields
101+ choices : Optional [List [I18nStr ]] = None # for select fields
116102 placeholder_choice : I18nStr = None # e.g. "Bitte wählen" for select fields
117103 validators : Optional [List [Dict [str , Any ]]] = None # WTForms validator descriptors
118104
@@ -130,9 +116,9 @@ class FormDefinition:
130116 legend : Any # I18nStr — required, no default
131117 fields : List [FormField ]
132118 action : str = ""
133- submit_label : Any = None # I18nStr; defaults to {"en": "Send", "de": "Absenden"}
119+ submit_label : I18nStr = None # I18nStr; defaults to {"en": "Send", "de": "Absenden"}
134120 submit_glyphicon : Optional [str ] = None
135- success_message : Any = None # I18nStr
121+ success_message : I18nStr = None # I18nStr
136122
137123 def resolved_submit_label (self , lang : str = "en" ) -> str :
138124 """
0 commit comments