perf: Language settings in personal settings

pull/15501/head
wangruidong 2025-05-12 10:10:54 +08:00 committed by w940853815
parent 8a3acb649e
commit 5e0babdba8
9 changed files with 62 additions and 17 deletions

View File

@ -375,6 +375,7 @@ class ConnectionTokenViewSet(AuthFaceMixin, ExtraActionApiMixin, RootOrgViewMixi
for name in default_name_opts.keys(): for name in default_name_opts.keys():
value = preferences.get(name, default_name_opts[name]) value = preferences.get(name, default_name_opts[name])
connect_options[name] = value connect_options[name] = value
connect_options['lang'] = getattr(user, 'lang', settings.LANGUAGE_CODE)
data['connect_options'] = connect_options data['connect_options'] = connect_options
@staticmethod @staticmethod

View File

@ -75,6 +75,7 @@ class SuperConnectionTokenSerializer(ConnectionTokenSerializer):
def get_user(self, attrs): def get_user(self, attrs):
return attrs.get('user') return attrs.get('user')
class AdminConnectionTokenSerializer(ConnectionTokenSerializer): class AdminConnectionTokenSerializer(ConnectionTokenSerializer):
class Meta(ConnectionTokenSerializer.Meta): class Meta(ConnectionTokenSerializer.Meta):
model = AdminConnectionToken model = AdminConnectionToken

View File

@ -37,7 +37,7 @@ def on_user_auth_login_success(sender, user, request, **kwargs):
cache.set(lock_key, request.session.session_key, None) cache.set(lock_key, request.session.session_key, None)
lang = request.COOKIES.get('django_language') lang = request.COOKIES.get('django_language')
if lang: if not user.lang and lang:
user.lang = lang user.lang = lang

View File

@ -10,7 +10,7 @@ from django.conf import settings
from django.core.exceptions import MiddlewareNotUsed from django.core.exceptions import MiddlewareNotUsed
from django.http.response import HttpResponseForbidden from django.http.response import HttpResponseForbidden
from django.shortcuts import HttpResponse from django.shortcuts import HttpResponse
from django.utils import timezone from django.utils import timezone, translation
from .utils import set_current_request from .utils import set_current_request
@ -137,3 +137,30 @@ class EndMiddleware:
response = self.get_response(request) response = self.get_response(request)
request._e_time_end = time.time() request._e_time_end = time.time()
return response return response
class LocaleMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
lang = None
if request.user.is_authenticated:
lang = getattr(request.user, 'lang', None)
if not lang:
lang = translation.get_language_from_request(request, check_path=False)
lang = lang or settings.LANGUAGE_CODE
try:
translation.activate(lang)
request.LANGUAGE_CODE = lang
response.set_cookie(
settings.LANGUAGE_COOKIE_NAME,
lang,
expires=timezone.now() + timezone.timedelta(days=365)
)
except Exception:
pass
return response

View File

@ -165,6 +165,7 @@ MIDDLEWARE = [
'jumpserver.middleware.RequestMiddleware', 'jumpserver.middleware.RequestMiddleware',
'jumpserver.middleware.RefererCheckMiddleware', 'jumpserver.middleware.RefererCheckMiddleware',
'jumpserver.middleware.SQLCountMiddleware', 'jumpserver.middleware.SQLCountMiddleware',
'jumpserver.middleware.LocaleMiddleware',
'orgs.middleware.OrgMiddleware', 'orgs.middleware.OrgMiddleware',
'authentication.backends.oidc.middleware.OIDCRefreshIDTokenMiddleware', 'authentication.backends.oidc.middleware.OIDCRefreshIDTokenMiddleware',
'authentication.backends.cas.middleware.CASMiddleware', 'authentication.backends.cas.middleware.CASMiddleware',

View File

@ -11,6 +11,7 @@ from common.utils.timezone import local_now
from notifications.backends import BACKEND from notifications.backends import BACKEND
from settings.utils import get_login_title from settings.utils import get_login_title
from users.models import User from users.models import User
from users.utils import activate_user_language
from .models import SystemMsgSubscription, UserMsgSubscription from .models import SystemMsgSubscription, UserMsgSubscription
__all__ = ('SystemMessage', 'UserMessage', 'system_msgs', 'Message') __all__ = ('SystemMessage', 'UserMessage', 'system_msgs', 'Message')
@ -267,13 +268,13 @@ class SystemMessage(Message):
*subscription.users.all(), *subscription.users.all(),
*chain(*[g.users.all() for g in subscription.groups.all()]) *chain(*[g.users.all() for g in subscription.groups.all()])
] ]
for user in users:
receive_user_ids = [u.id for u in users] with activate_user_language(user):
backends_msg_mapper = self.get_backend_msg_mapper(receive_backends) backends_msg_mapper = self.get_backend_msg_mapper(receive_backends)
if is_async: if is_async:
publish_task.delay(receive_user_ids, backends_msg_mapper) publish_task.delay([user.id], backends_msg_mapper)
else: else:
self.send_msg(receive_user_ids, backends_msg_mapper) self.send_msg([user.id], backends_msg_mapper)
@classmethod @classmethod
def post_insert_to_db(cls, subscription: SystemMsgSubscription): def post_insert_to_db(cls, subscription: SystemMsgSubscription):
@ -295,12 +296,13 @@ class UserMessage(Message):
发送消息到每个用户配置的接收方式上 发送消息到每个用户配置的接收方式上
""" """
sub = UserMsgSubscription.objects.get(user=self.user) sub = UserMsgSubscription.objects.get(user=self.user)
backends_msg_mapper = self.get_backend_msg_mapper(sub.receive_backends) with activate_user_language(self.user):
receive_user_ids = [self.user.id] backends_msg_mapper = self.get_backend_msg_mapper(sub.receive_backends)
if is_async: receive_user_ids = [self.user.id]
publish_task.delay(receive_user_ids, backends_msg_mapper) if is_async:
else: publish_task.delay(receive_user_ids, backends_msg_mapper)
self.send_msg(receive_user_ids, backends_msg_mapper) else:
self.send_msg(receive_user_ids, backends_msg_mapper)
@classmethod @classmethod
def get_test_user(cls): def get_test_user(cls):

View File

@ -48,5 +48,5 @@ class BasicSerializer(serializers.Serializer):
class LinaSerializer(serializers.Serializer): class LinaSerializer(serializers.Serializer):
# basic = BasicSerializer(required=False, label=_('Basic')) basic = BasicSerializer(required=False, label=_('Basic'))
file = FileEncryptSerializer(required=False, label=_('File Encryption')) file = FileEncryptSerializer(required=False, label=_('File Encryption'))

View File

@ -63,6 +63,7 @@ class UserProfileSerializer(UserSerializer):
mfa_level = LabeledChoiceField(choices=MFAMixin.MFA_LEVEL_CHOICES, label=_("MFA"), required=False) mfa_level = LabeledChoiceField(choices=MFAMixin.MFA_LEVEL_CHOICES, label=_("MFA"), required=False)
guide_url = serializers.SerializerMethodField() guide_url = serializers.SerializerMethodField()
receive_backends = serializers.ListField(child=serializers.CharField(), read_only=True) receive_backends = serializers.ListField(child=serializers.CharField(), read_only=True)
lang = serializers.SerializerMethodField(label=_("Language"))
class Meta(UserSerializer.Meta): class Meta(UserSerializer.Meta):
read_only_fields = [ read_only_fields = [
@ -74,7 +75,7 @@ class UserProfileSerializer(UserSerializer):
] ]
fields = UserSerializer.Meta.fields + [ fields = UserSerializer.Meta.fields + [
'public_key_comment', 'public_key_hash_md5', 'guide_url', 'public_key_comment', 'public_key_hash_md5', 'guide_url',
"wecom_id", "dingtalk_id", "feishu_id", "slack_id", "wecom_id", "dingtalk_id", "feishu_id", "slack_id", 'lang'
] + read_only_fields ] + read_only_fields
extra_kwargs = dict(UserSerializer.Meta.extra_kwargs) extra_kwargs = dict(UserSerializer.Meta.extra_kwargs)
@ -144,6 +145,9 @@ class UserProfileSerializer(UserSerializer):
raise serializers.ValidationError(msg) raise serializers.ValidationError(msg)
return password return password
def get_lang(self, obj):
return getattr(self.instance, 'lang', settings.LANGUAGE_CODE)
class UserPKUpdateSerializer(serializers.ModelSerializer): class UserPKUpdateSerializer(serializers.ModelSerializer):
class Meta: class Meta:

View File

@ -6,10 +6,12 @@ import logging
import os import os
import re import re
import time import time
from contextlib import contextmanager
import pyotp import pyotp
from django.conf import settings from django.conf import settings
from django.core.cache import cache from django.core.cache import cache
from django.utils import translation
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from common.tasks import send_mail_async from common.tasks import send_mail_async
@ -336,3 +338,10 @@ def is_confirm_time_valid(session, key):
def is_auth_confirm_time_valid(session): def is_auth_confirm_time_valid(session):
return is_confirm_time_valid(session, 'MFA_VERIFY_TIME') return is_confirm_time_valid(session, 'MFA_VERIFY_TIME')
@contextmanager
def activate_user_language(user):
language = getattr(user, 'lang', settings.LANGUAGE_CODE)
with translation.override(language):
yield