Working with forms¶
Fields and Widgets¶
If you use a ModelForm
, you will automatically get an I18nFormField
field
for your internationalized fields with the default widget being either an I18nTextInput
or an I18nTextarea
being the default widget. But of course you can also use these
fields manually as you would use any other field, even completely without touching models.
-
class
i18nfield.forms.
I18nFormField
(*args, **kwargs)¶ The form field that is used by I18nCharField and I18nTextField. It makes use of Django’s MultiValueField mechanism to create one sub-field per available language.
It contains special treatment to make sure that a field marked as “required” is validated as “filled out correctly” if at least one translation is filled it. It is never required to fill in all of them. This has the drawback that the HTML property
required
is set on none of the fields as this would lead to irritating behaviour.Parameters: - locales – An iterable of locale codes that the widget should render a field for. If
omitted, fields will be rendered for all languages configured in
settings.LANGUAGES
. - require_all_fields – A boolean, if set to True field requires all translations to be given.
- locales – An iterable of locale codes that the widget should render a field for. If
omitted, fields will be rendered for all languages configured in
-
class
i18nfield.forms.
I18nTextInput
(locales: List[str], field: django.forms.fields.Field, attrs=None)¶ The default form widget for I18nCharField. It makes use of Django’s MultiWidget mechanism and does some magic to save you time.
-
class
i18nfield.forms.
I18nTextarea
(locales: List[str], field: django.forms.fields.Field, attrs=None)¶ The default form widget for I18nTextField. It makes use of Django’s MultiWidget mechanism and does some magic to save you time.
Widget styling¶
The form widget will output something similar to the following HTML sample:
<div class="i18n-form-group">
<input class="form-control" id="id_name_0" lang="en"
maxlength="200" name="name_0" placeholder="Name" title="en"
type="text" value="">
<input class="form-control" id="id_name_1" lang="de"
maxlength="200" name="name_1" placeholder="Name" title="de"
type="text" value="">
</div>
This alone provides no good indication to your user on which field resembles which language (except the title attribute that is visible on mouseover in most browsers). Also, it will render the input forms in a row by default, why we find it more understandable if they are arranged vertically.
You can achieve all this with a little bit of CSS. We can’t give you the full details, as we don’t know how you style form widgets in general in your project.
To indicate the language, we use the following CSS to draw a little flag at the beginning of the input field:
input[lang] {
background: no-repeat 10px center;
padding-left: 34px;
}
textarea[lang] {
background: no-repeat 10px 10px;
padding-left: 34px;
}
input[lang=de], textarea[lang=de] {
background-image: url('/static/img/flags/de.png');
}
input[lang=en], textarea[lang=en] {
background-image: url('/static/img/flags/en.png');
}
In pretix, this looks like this:
Advanced usage: Restrict the visible languages¶
Sometimes, you do not want to display fields for all languages every time. If you build a shopping platform, your platform might support tens or hundreds of languages, while a single shop only supports a few of them. In this case, the shop owner should not see input fields for languages that they don’t want to support.
As you can see above, I18nFormField
has a constructor argument locales
that takes a
list of locales for this exact purpose. However, most of the time, your I18nFormField
is defined in a way that does not allow you to pass a dynamic list there. Therefore, we provide
a form base class that you can use for your ModelForm
that also takes a locales
constructor
argument and passes it through to all its fields.
For the same reason, we provide formset base classes that add the locales
argument to your
formset class and pass it through to all fields.
-
class
i18nfield.forms.
I18nForm
(*args, **kwargs)¶ This is a modified version of Django’s Form which differs from Form in only one way: The constructor takes one additional optional argument
locales
expecting a list of language codes. If given, this instance is used to select the visible languages in all I18nFormFields of the form. If not given, all languages fromsettings.LANGUAGES
will be displayed.Parameters: locales – A list of locales that should be displayed.
-
class
i18nfield.forms.
I18nModelForm
(*args, **kwargs)¶ This is a modified version of Django’s ModelForm which differs from ModelForm in only one way: The constructor takes one additional optional argument
locales
expecting a list of language codes. If given, this instance is used to select the visible languages in all I18nFormFields of the form. If not given, all languages fromsettings.LANGUAGES
will be displayed.Parameters: locales – A list of locales that should be displayed.
-
class
i18nfield.forms.
I18nModelFormSet
(*args, **kwargs)¶ This is equivalent to a normal BaseModelFormset, but cares for the special needs of I18nForms (see there for more information).
Parameters: locales – A list of locales that should be displayed.
-
class
i18nfield.forms.
I18nInlineFormSet
(*args, **kwargs)¶ This is equivalent to a normal BaseInlineFormset, but cares for the special needs of I18nForms (see there for more information).
Parameters: locales – A list of locales that should be displayed.
Note
As I18nFormField
tries to pass this information down to the widget, this might
fail if you use a custom widget class that does not inherit from our default widgets.