Language choices: not in User.model

Having this as a model field is "annoying" because each added language
will trigger a (potentially costly) migration even though no real database
work is actually done for it.

Also implements a selector that shows languages in both their own language
and the currently activated language.

Correct spelling to "zh-hans" (lowercase); see https://stackoverflow.com/a/7729311

See #161
This commit is contained in:
Klaas van Schelven
2025-08-28 12:45:09 +02:00
parent a7abde68a2
commit ef126814bf
4 changed files with 24 additions and 16 deletions

View File

@@ -250,7 +250,7 @@ USE_L10N = True
LOCALE_PATHS = [BASE_DIR / "locale"] LOCALE_PATHS = [BASE_DIR / "locale"]
LANGUAGES = ( LANGUAGES = (
("en", "English"), ("en", "English"),
("zh-Hans", "简体中文"), ("zh-hans", "简体中文"),
) )
USE_TZ = True USE_TZ = True

View File

@@ -9,7 +9,9 @@ from django.core.exceptions import ValidationError
from django.contrib.auth import password_validation from django.contrib.auth import password_validation
from django.forms import ModelForm from django.forms import ModelForm
from django.utils.html import escape, mark_safe from django.utils.html import escape, mark_safe
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _, get_language_info
from django.conf import settings
TRUE_FALSE_CHOICES = ( TRUE_FALSE_CHOICES = (
(True, _("Yes")), (True, _("Yes")),
@@ -131,6 +133,18 @@ class SetPasswordForm(BaseSetPasswordForm):
self.fields['new_password2'].help_text = None # "Confirm password" is descriptive enough self.fields['new_password2'].help_text = None # "Confirm password" is descriptive enough
def language_choices():
items = [("auto", _("Auto (browser preference)"))]
for code, _label in settings.LANGUAGES:
info = get_language_info(code)
label = info["name_local"] \
if info["name_local"] == info["name_translated"] \
else f"{info['name_local']} ({info['name_translated']})"
items.append((code, label))
return items
class PreferencesForm(ModelForm): class PreferencesForm(ModelForm):
# I haven't gotten a decent display for checkboxes in forms yet; the quickest hack around this is a ChoiceField # I haven't gotten a decent display for checkboxes in forms yet; the quickest hack around this is a ChoiceField
send_email_alerts = forms.ChoiceField( send_email_alerts = forms.ChoiceField(
@@ -143,7 +157,7 @@ class PreferencesForm(ModelForm):
) )
language = forms.ChoiceField( language = forms.ChoiceField(
label=_("Language"), label=_("Language"),
choices=User.LANGUAGE_CHOICES, choices=language_choices,
required=True, required=True,
widget=forms.Select(), widget=forms.Select(),
) )

View File

@@ -1,18 +1,16 @@
# Generated by Django 4.2.23 on 2025-07-28 09:27
from django.db import migrations, models from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('users', '0002_user_theme_preference'), ("users", "0002_user_theme_preference"),
] ]
operations = [ operations = [
migrations.AddField( migrations.AddField(
model_name='user', model_name="user",
name='language', name="language",
field=models.CharField(choices=[('auto', 'Auto'), ('en', 'English'), ('zh-Hans', 'Simplified Chinese')], default='auto', max_length=10), field=models.CharField(default="auto", max_length=10),
), ),
] ]

View File

@@ -28,15 +28,11 @@ class User(AbstractUser):
default="system", default="system",
blank=False, blank=False,
) )
LANGUAGE_CHOICES = [
("auto", _("Auto")),
("en", _("English")),
("zh-Hans", _("Simplified Chinese")),
]
language = models.CharField( language = models.CharField(
max_length=10, max_length=10,
choices=LANGUAGE_CHOICES, # choices intentionally not set, we don't want changes to trigger migrations; the actual choices are set in
# forms.py; in Django 5.0 and up we can instead used a callable here
# choices=...
default="auto", default="auto",
blank=False, blank=False,
) )