mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-01-23 19:36:56 -08:00
let user choose interface language #51
This commit is contained in:
parent
3bc30ec99c
commit
29c2a05d38
8 changed files with 62 additions and 7 deletions
|
@ -4,7 +4,7 @@
|
||||||
import logging
|
import logging
|
||||||
from logging.handlers import SMTPHandler, RotatingFileHandler
|
from logging.handlers import SMTPHandler, RotatingFileHandler
|
||||||
import os
|
import os
|
||||||
from flask import Flask, request, current_app
|
from flask import Flask, request, current_app, session
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
from flask_migrate import Migrate
|
from flask_migrate import Migrate
|
||||||
from flask_login import LoginManager
|
from flask_login import LoginManager
|
||||||
|
@ -20,6 +20,9 @@ from config import Config
|
||||||
|
|
||||||
|
|
||||||
def get_locale():
|
def get_locale():
|
||||||
|
if session.get('ui_language', None):
|
||||||
|
return session['ui_language']
|
||||||
|
else:
|
||||||
try:
|
try:
|
||||||
return request.accept_languages.best_match(current_app.config['LANGUAGES'])
|
return request.accept_languages.best_match(current_app.config['LANGUAGES'])
|
||||||
except:
|
except:
|
||||||
|
|
|
@ -56,6 +56,7 @@ def login():
|
||||||
if user.waiting_for_approval():
|
if user.waiting_for_approval():
|
||||||
return redirect(url_for('auth.please_wait'))
|
return redirect(url_for('auth.please_wait'))
|
||||||
login_user(user, remember=True)
|
login_user(user, remember=True)
|
||||||
|
session['ui_language'] = user.interface_language
|
||||||
current_user.last_seen = utcnow()
|
current_user.last_seen = utcnow()
|
||||||
current_user.ip_address = ip_address()
|
current_user.ip_address = ip_address()
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
|
@ -606,6 +606,8 @@ class User(UserMixin, db.Model):
|
||||||
theme = db.Column(db.String(20), default='')
|
theme = db.Column(db.String(20), default='')
|
||||||
referrer = db.Column(db.String(256))
|
referrer = db.Column(db.String(256))
|
||||||
markdown_editor = db.Column(db.Boolean, default=False)
|
markdown_editor = db.Column(db.Boolean, default=False)
|
||||||
|
interface_language = db.Column(db.String(10)) # a locale that the translation system understands e.g. 'en' or 'en-us'. If empty, use browser default
|
||||||
|
language_id = db.Column(db.Integer, db.ForeignKey('language.id')) # the default choice in the language dropdown when composing posts & comments
|
||||||
|
|
||||||
avatar = db.relationship('File', lazy='joined', foreign_keys=[avatar_id], single_parent=True, cascade="all, delete-orphan")
|
avatar = db.relationship('File', lazy='joined', foreign_keys=[avatar_id], single_parent=True, cascade="all, delete-orphan")
|
||||||
cover = db.relationship('File', lazy='joined', foreign_keys=[cover_id], single_parent=True, cascade="all, delete-orphan")
|
cover = db.relationship('File', lazy='joined', foreign_keys=[cover_id], single_parent=True, cascade="all, delete-orphan")
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
{{ render_field(form.searchable) }}
|
{{ render_field(form.searchable) }}
|
||||||
{{ render_field(form.indexable) }}
|
{{ render_field(form.indexable) }}
|
||||||
<h5> Preferences </h5>
|
<h5> Preferences </h5>
|
||||||
|
{{ render_field(form.interface_language) }}
|
||||||
{{ render_field(form.markdown_editor) }}
|
{{ render_field(form.markdown_editor) }}
|
||||||
{{ render_field(form.default_sort) }}
|
{{ render_field(form.default_sort) }}
|
||||||
{{ render_field(form.theme) }}
|
{{ render_field(form.theme) }}
|
||||||
|
|
|
@ -3,6 +3,7 @@ from flask_login import current_user
|
||||||
from flask_wtf import FlaskForm
|
from flask_wtf import FlaskForm
|
||||||
from wtforms import StringField, SubmitField, PasswordField, BooleanField, EmailField, TextAreaField, FileField, \
|
from wtforms import StringField, SubmitField, PasswordField, BooleanField, EmailField, TextAreaField, FileField, \
|
||||||
RadioField, DateField, SelectField
|
RadioField, DateField, SelectField
|
||||||
|
from wtforms.fields.choices import SelectMultipleField
|
||||||
from wtforms.validators import ValidationError, DataRequired, Email, EqualTo, Length, Optional
|
from wtforms.validators import ValidationError, DataRequired, Email, EqualTo, Length, Optional
|
||||||
from flask_babel import _, lazy_gettext as _l
|
from flask_babel import _, lazy_gettext as _l
|
||||||
|
|
||||||
|
@ -31,6 +32,7 @@ class ProfileForm(FlaskForm):
|
||||||
|
|
||||||
|
|
||||||
class SettingsForm(FlaskForm):
|
class SettingsForm(FlaskForm):
|
||||||
|
interface_language = SelectField(_l('Interface language'), coerce=str, validators=[Optional()], render_kw={'class': 'form-select'})
|
||||||
newsletter = BooleanField(_l('Subscribe to email newsletter'))
|
newsletter = BooleanField(_l('Subscribe to email newsletter'))
|
||||||
email_unread = BooleanField(_l('Receive email about missed notifications'))
|
email_unread = BooleanField(_l('Receive email about missed notifications'))
|
||||||
ignore_bots = BooleanField(_l('Hide posts by bots'))
|
ignore_bots = BooleanField(_l('Hide posts by bots'))
|
||||||
|
|
|
@ -3,7 +3,7 @@ from time import sleep
|
||||||
|
|
||||||
from flask import redirect, url_for, flash, request, make_response, session, Markup, current_app, abort, json
|
from flask import redirect, url_for, flash, request, make_response, session, Markup, current_app, abort, json
|
||||||
from flask_login import login_user, logout_user, current_user, login_required
|
from flask_login import login_user, logout_user, current_user, login_required
|
||||||
from flask_babel import _
|
from flask_babel import _, lazy_gettext as _l
|
||||||
|
|
||||||
from app import db, cache, celery
|
from app import db, cache, celery
|
||||||
from app.activitypub.signature import post_request, default_context
|
from app.activitypub.signature import post_request, default_context
|
||||||
|
@ -164,6 +164,13 @@ def change_settings():
|
||||||
abort(404)
|
abort(404)
|
||||||
form = SettingsForm()
|
form = SettingsForm()
|
||||||
form.theme.choices = theme_list()
|
form.theme.choices = theme_list()
|
||||||
|
form.interface_language.choices = [
|
||||||
|
('', _l('Auto-detect')),
|
||||||
|
('ca', _l('Catalan')),
|
||||||
|
('en', _l('English')),
|
||||||
|
('fr', _l('French')),
|
||||||
|
('de', _l('German')),
|
||||||
|
]
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
propagate_indexable = form.indexable.data != current_user.indexable
|
propagate_indexable = form.indexable.data != current_user.indexable
|
||||||
current_user.newsletter = form.newsletter.data
|
current_user.newsletter = form.newsletter.data
|
||||||
|
@ -176,6 +183,8 @@ def change_settings():
|
||||||
current_user.theme = form.theme.data
|
current_user.theme = form.theme.data
|
||||||
current_user.email_unread = form.email_unread.data
|
current_user.email_unread = form.email_unread.data
|
||||||
current_user.markdown_editor = form.markdown_editor.data
|
current_user.markdown_editor = form.markdown_editor.data
|
||||||
|
current_user.interface_language = form.interface_language.data
|
||||||
|
session['ui_language'] = form.interface_language.data
|
||||||
import_file = request.files['import_file']
|
import_file = request.files['import_file']
|
||||||
if propagate_indexable:
|
if propagate_indexable:
|
||||||
db.session.execute(text('UPDATE "post" set indexable = :indexable WHERE user_id = :user_id'),
|
db.session.execute(text('UPDATE "post" set indexable = :indexable WHERE user_id = :user_id'),
|
||||||
|
@ -213,6 +222,7 @@ def change_settings():
|
||||||
form.default_sort.data = current_user.default_sort
|
form.default_sort.data = current_user.default_sort
|
||||||
form.theme.data = current_user.theme
|
form.theme.data = current_user.theme
|
||||||
form.markdown_editor.data = current_user.markdown_editor
|
form.markdown_editor.data = current_user.markdown_editor
|
||||||
|
form.interface_language.data = current_user.interface_language
|
||||||
|
|
||||||
return render_template('user/edit_settings.html', title=_('Edit profile'), form=form, user=current_user,
|
return render_template('user/edit_settings.html', title=_('Edit profile'), form=form, user=current_user,
|
||||||
moderating_communities=moderating_communities(current_user.get_id()),
|
moderating_communities=moderating_communities(current_user.get_id()),
|
||||||
|
|
|
@ -22,7 +22,7 @@ class Config(object):
|
||||||
RECAPTCHA_PUBLIC_KEY = os.environ.get("RECAPTCHA_PUBLIC_KEY") or None
|
RECAPTCHA_PUBLIC_KEY = os.environ.get("RECAPTCHA_PUBLIC_KEY") or None
|
||||||
RECAPTCHA_PRIVATE_KEY = os.environ.get("RECAPTCHA_PRIVATE_KEY") or None
|
RECAPTCHA_PRIVATE_KEY = os.environ.get("RECAPTCHA_PRIVATE_KEY") or None
|
||||||
MODE = os.environ.get('MODE') or 'development'
|
MODE = os.environ.get('MODE') or 'development'
|
||||||
LANGUAGES = ['de', 'en']
|
LANGUAGES = ['de', 'en', 'fr']
|
||||||
FULL_AP_CONTEXT = bool(int(os.environ.get('FULL_AP_CONTEXT', 0)))
|
FULL_AP_CONTEXT = bool(int(os.environ.get('FULL_AP_CONTEXT', 0)))
|
||||||
CACHE_TYPE = os.environ.get('CACHE_TYPE') or 'FileSystemCache'
|
CACHE_TYPE = os.environ.get('CACHE_TYPE') or 'FileSystemCache'
|
||||||
CACHE_REDIS_URL = os.environ.get('CACHE_REDIS_URL') or 'redis://localhost:6379/1'
|
CACHE_REDIS_URL = os.environ.get('CACHE_REDIS_URL') or 'redis://localhost:6379/1'
|
||||||
|
|
36
migrations/versions/e73996747d7e_user_language.py
Normal file
36
migrations/versions/e73996747d7e_user_language.py
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
"""user language
|
||||||
|
|
||||||
|
Revision ID: e73996747d7e
|
||||||
|
Revises: 94828ddc7c63
|
||||||
|
Create Date: 2024-05-09 13:37:17.010724
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'e73996747d7e'
|
||||||
|
down_revision = '94828ddc7c63'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('user', schema=None) as batch_op:
|
||||||
|
batch_op.add_column(sa.Column('interface_language', sa.String(length=10), nullable=True))
|
||||||
|
batch_op.add_column(sa.Column('language_id', sa.Integer(), nullable=True))
|
||||||
|
batch_op.create_foreign_key(None, 'language', ['language_id'], ['id'])
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('user', schema=None) as batch_op:
|
||||||
|
batch_op.drop_constraint(None, type_='foreignkey')
|
||||||
|
batch_op.drop_column('language_id')
|
||||||
|
batch_op.drop_column('interface_language')
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
Loading…
Add table
Reference in a new issue