feat: 🙊 support user language settings
This commit is contained in:
parent
d11fd5f68f
commit
b50665a62c
9 changed files with 102 additions and 4 deletions
|
|
@ -35,6 +35,7 @@ MIDDLEWARE = [
|
|||
"django.middleware.common.CommonMiddleware",
|
||||
"django.middleware.csrf.CsrfViewMiddleware",
|
||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||
"moku.middleware.MokuLanguageMiddleware",
|
||||
"django.contrib.messages.middleware.MessageMiddleware",
|
||||
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ from django.urls import include, path
|
|||
|
||||
from moku.views.auth import LoginView, LogoutView
|
||||
from moku.views.post import FeedView
|
||||
from moku.views.user import EditProfileView, ProfileView, SignupView
|
||||
from moku.views.user import EditProfileView, EditSettingsView, ProfileView, SignupView
|
||||
|
||||
urlpatterns = [
|
||||
path("admin/", admin.site.urls),
|
||||
|
|
@ -30,6 +30,7 @@ urlpatterns = [
|
|||
path("logout", LogoutView.as_view(), name="logout"),
|
||||
path("signup", SignupView.as_view(), name="signup"),
|
||||
path("profile", EditProfileView.as_view(), name="profile.edit"),
|
||||
path("settings", EditSettingsView.as_view(), name="settings"),
|
||||
path("user/<str:username>", ProfileView.as_view(), name="profile"),
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from django.utils.translation import gettext_lazy as _
|
|||
|
||||
from django_recaptcha.fields import ReCaptchaField
|
||||
|
||||
from moku.models.user import User
|
||||
from moku.models.user import User, UserSettings
|
||||
|
||||
|
||||
class UserForm(UserCreationForm):
|
||||
|
|
@ -31,6 +31,15 @@ class UserForm(UserCreationForm):
|
|||
self.fields["captcha"].error_messages = {"required": _("make sure you've ticked the captcha.")}
|
||||
|
||||
|
||||
class UserSettingsForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = UserSettings
|
||||
fields = ("language",)
|
||||
labels = {
|
||||
"language": _("language"),
|
||||
}
|
||||
|
||||
|
||||
class ProfileForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = User
|
||||
|
|
|
|||
11
moku/middleware.py
Normal file
11
moku/middleware.py
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
from django.utils import translation
|
||||
|
||||
|
||||
class MokuLanguageMiddleware:
|
||||
def __init__(self, get_response):
|
||||
self.get_response = get_response
|
||||
|
||||
def __call__(self, request):
|
||||
if request.user.is_authenticated and hasattr(request.user, "settings"):
|
||||
translation.activate(request.user.settings.language)
|
||||
return self.get_response(request)
|
||||
23
moku/migrations/0005_usersettings.py
Normal file
23
moku/migrations/0005_usersettings.py
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 5.0.3 on 2024-03-25 17:02
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('moku', '0004_alter_post_verb'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='UserSettings',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('language', models.CharField(choices=[('af', 'Afrikaans'), ('ar', 'Arabic'), ('ar-dz', 'Algerian Arabic'), ('ast', 'Asturian'), ('az', 'Azerbaijani'), ('bg', 'Bulgarian'), ('be', 'Belarusian'), ('bn', 'Bengali'), ('br', 'Breton'), ('bs', 'Bosnian'), ('ca', 'Catalan'), ('ckb', 'Central Kurdish (Sorani)'), ('cs', 'Czech'), ('cy', 'Welsh'), ('da', 'Danish'), ('de', 'German'), ('dsb', 'Lower Sorbian'), ('el', 'Greek'), ('en', 'English'), ('en-au', 'Australian English'), ('en-gb', 'British English'), ('eo', 'Esperanto'), ('es', 'Spanish'), ('es-ar', 'Argentinian Spanish'), ('es-co', 'Colombian Spanish'), ('es-mx', 'Mexican Spanish'), ('es-ni', 'Nicaraguan Spanish'), ('es-ve', 'Venezuelan Spanish'), ('et', 'Estonian'), ('eu', 'Basque'), ('fa', 'Persian'), ('fi', 'Finnish'), ('fr', 'French'), ('fy', 'Frisian'), ('ga', 'Irish'), ('gd', 'Scottish Gaelic'), ('gl', 'Galician'), ('he', 'Hebrew'), ('hi', 'Hindi'), ('hr', 'Croatian'), ('hsb', 'Upper Sorbian'), ('hu', 'Hungarian'), ('hy', 'Armenian'), ('ia', 'Interlingua'), ('id', 'Indonesian'), ('ig', 'Igbo'), ('io', 'Ido'), ('is', 'Icelandic'), ('it', 'Italian'), ('ja', 'Japanese'), ('ka', 'Georgian'), ('kab', 'Kabyle'), ('kk', 'Kazakh'), ('km', 'Khmer'), ('kn', 'Kannada'), ('ko', 'Korean'), ('ky', 'Kyrgyz'), ('lb', 'Luxembourgish'), ('lt', 'Lithuanian'), ('lv', 'Latvian'), ('mk', 'Macedonian'), ('ml', 'Malayalam'), ('mn', 'Mongolian'), ('mr', 'Marathi'), ('ms', 'Malay'), ('my', 'Burmese'), ('nb', 'Norwegian Bokmål'), ('ne', 'Nepali'), ('nl', 'Dutch'), ('nn', 'Norwegian Nynorsk'), ('os', 'Ossetic'), ('pa', 'Punjabi'), ('pl', 'Polish'), ('pt', 'Portuguese'), ('pt-br', 'Brazilian Portuguese'), ('ro', 'Romanian'), ('ru', 'Russian'), ('sk', 'Slovak'), ('sl', 'Slovenian'), ('sq', 'Albanian'), ('sr', 'Serbian'), ('sr-latn', 'Serbian Latin'), ('sv', 'Swedish'), ('sw', 'Swahili'), ('ta', 'Tamil'), ('te', 'Telugu'), ('tg', 'Tajik'), ('th', 'Thai'), ('tk', 'Turkmen'), ('tr', 'Turkish'), ('tt', 'Tatar'), ('udm', 'Udmurt'), ('ug', 'Uyghur'), ('uk', 'Ukrainian'), ('ur', 'Urdu'), ('uz', 'Uzbek'), ('vi', 'Vietnamese'), ('zh-hans', 'Simplified Chinese'), ('zh-hant', 'Traditional Chinese')], default='en', help_text='what language do you want to use moku.blog in?', max_length=16, verbose_name='language')),
|
||||
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='settings', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
from django.contrib.auth.models import AbstractUser, BaseUserManager
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import AbstractUser
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.urls import reverse
|
||||
|
|
@ -77,3 +78,18 @@ class User(AbstractUser):
|
|||
@property
|
||||
def email_confirmed(self):
|
||||
return self.email_confirmed_at is not None
|
||||
|
||||
|
||||
class UserSettings(models.Model):
|
||||
user = models.OneToOneField(
|
||||
"User",
|
||||
related_name="settings",
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
language = models.CharField(
|
||||
verbose_name=_("language"),
|
||||
max_length=16,
|
||||
choices=settings.LANGUAGES,
|
||||
default="en",
|
||||
help_text=_("what language do you want to use moku.blog in?"),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
{% if request.user.is_authenticated %}
|
||||
<li><a href="{{ url('feed') }}">{% trans %}feed{% endtrans %}</a></li>
|
||||
<li><a href="{{ url('profile', username=request.user.username) }}">{% trans %}my profile{% endtrans %}</a></li>
|
||||
<li><a href="{{ url('settings') }}">{% trans %}settings{% endtrans %}</a></li>
|
||||
<li>
|
||||
<form action="{{ url('logout') }}" method="POST" class="logout">
|
||||
{% csrf_token %}
|
||||
|
|
|
|||
15
moku/templates/moku/settings.jinja
Normal file
15
moku/templates/moku/settings.jinja
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{% extends "moku/base.jinja" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="content">
|
||||
<form action="" method="POST" class="auth">
|
||||
{% csrf_token %}
|
||||
<div class="field">
|
||||
<label for="id_language">{{ form.language.label }}</label>
|
||||
{{ form.language }}
|
||||
<span class="help">{{ form.language.help_text }}</span>
|
||||
</div>
|
||||
<button type="submit">{% trans %}update!{% endtrans %}</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
|
@ -1,11 +1,12 @@
|
|||
from django.contrib import messages
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.db import IntegrityError
|
||||
from django.shortcuts import redirect
|
||||
from django.utils.translation import gettext as _
|
||||
from django.views.generic import FormView, TemplateView
|
||||
|
||||
from moku.images import process_avatar_image
|
||||
from moku.forms.user import ProfileForm, UserForm
|
||||
from moku.forms.user import ProfileForm, UserForm, UserSettingsForm
|
||||
from moku.models.user import User
|
||||
|
||||
|
||||
|
|
@ -24,6 +25,26 @@ class EditProfileView(LoginRequiredMixin, FormView):
|
|||
return self.form_class(instance=self.request.user, **self.get_form_kwargs())
|
||||
|
||||
|
||||
class EditSettingsView(LoginRequiredMixin, FormView):
|
||||
template_name = "moku/settings.jinja"
|
||||
form_class = UserSettingsForm
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.user = self.request.user
|
||||
try:
|
||||
form.save()
|
||||
except IntegrityError:
|
||||
messages.error(self.request, _("uh oh. i think something went a little bit oopsie."))
|
||||
return self.form_invalid(form)
|
||||
messages.success(self.request, _("settings updated!"))
|
||||
return redirect("settings")
|
||||
|
||||
def get_form(self):
|
||||
if hasattr(self.request.user, "settings"):
|
||||
return self.form_class(instance=self.request.user.settings, **self.get_form_kwargs())
|
||||
return super().get_form()
|
||||
|
||||
|
||||
class ProfileView(TemplateView):
|
||||
template_name = "moku/profile/show.jinja"
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue