diff --git a/src/authentic2/attribute_kinds.py b/src/authentic2/attribute_kinds.py index ee101d698..ded475816 100644 --- a/src/authentic2/attribute_kinds.py +++ b/src/authentic2/attribute_kinds.py @@ -33,6 +33,7 @@ from django.core.validators import RegexValidator from django.urls import reverse, reverse_lazy from django.utils import html from django.utils.functional import keep_lazy +from django.utils.translation import get_supported_language_variant from django.utils.translation import gettext_lazy as _ from django.utils.translation import pgettext_lazy from gadjo.templatetags.gadjo import xstatic @@ -286,6 +287,21 @@ class Base64ImageField(serializers.ImageField): return super().to_internal_value(data) +def language_choices(): + return settings.LANGUAGES + + +def language_default(): + return get_supported_language_variant(settings.LANGUAGE_CODE) + + +def language_html_value(attribute, value): + for key, label in language_choices(): + if value == key: + return label + return '' + + DEFAULT_ALLOW_BLANK = True DEFAULT_MAX_LENGTH = 256 @@ -371,6 +387,17 @@ DEFAULT_ATTRIBUTE_KINDS = [ 'attributes_ng_serialize': profile_attributes_ng_serialize, 'csv_importable': False, }, + { + 'label': _('language'), + 'name': 'language', + 'default': language_default, + 'field_class': forms.ChoiceField, + 'html_value': language_html_value, + 'kwargs': { + 'choices': language_choices, + 'widget': forms.Select, + }, + }, ] diff --git a/src/authentic2/forms/profile.py b/src/authentic2/forms/profile.py index fcec00e8d..d2dde102d 100644 --- a/src/authentic2/forms/profile.py +++ b/src/authentic2/forms/profile.py @@ -68,6 +68,13 @@ class BaseUserForm(LockedFieldFormMixin, forms.ModelForm): self.atvs = [] self.locked_fields = set() if instance: + for attribute in self.attributes: + kind = attribute.get_kind() + if kind.get('default'): + if attribute.name in self.declared_fields: + initial[attribute.name] = ( + kind['default']() if callable(kind['default']) else kind['default'] + ) self.atvs = models.AttributeValue.objects.select_related('attribute').with_owner(instance) for atv in self.atvs: name = atv.attribute.name diff --git a/tests/test_profile.py b/tests/test_profile.py index 8e0179cad..594bc148b 100644 --- a/tests/test_profile.py +++ b/tests/test_profile.py @@ -41,18 +41,25 @@ def test_account_edit_view(app, simple_user): agreement = Attribute.objects.create( name='agreement', label='agreement', kind='boolean', user_visible=True, user_editable=True ) + language = Attribute.objects.create( + name='language', label='language', kind='language', user_visible=True, user_editable=True + ) resp = old_resp = app.get(url, status=200) resp.form['phone'] = '1234' assert resp.form['phone'].attrs['type'] == 'tel' resp.form['title'] = 'Mrs' resp.form['agreement'] = False + assert resp.form['language'].tag == 'select' + assert resp.form['language'].value == 'en' + resp.form['language'] = 'fr' resp = resp.form.submit() # verify that missing next_url in POST is ok assert resp['Location'].endswith(reverse('account_management')) assert phone.get_value(simple_user) == '1234' assert title.get_value(simple_user) == 'Mrs' assert agreement.get_value(simple_user) is False + assert language.get_value(simple_user) == 'fr' resp = resp.follow() profile = [ @@ -65,6 +72,7 @@ def test_account_edit_view(app, simple_user): ('Email address', 'user@example.net'), ('Phone', '1234'), ('Title', 'Mrs'), + ('Language', 'French'), ] resp = app.get(url, status=200)