feat: 🙊 support user language settings

This commit is contained in:
m5ka 2024-03-25 17:12:36 +00:00
parent d11fd5f68f
commit b50665a62c
9 changed files with 102 additions and 4 deletions

View file

@ -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",
]

View file

@ -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"),
]

View file

@ -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
View 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)

View 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)),
],
),
]

View file

@ -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?"),
)

View file

@ -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 %}

View 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 %}

View file

@ -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"