On registration, automatically set content languages from accept header

This commit is contained in:
Felix Ableitner 2024-03-18 12:40:49 +01:00
parent 0f77951e05
commit 074e675651
3 changed files with 46 additions and 7 deletions

2
Cargo.lock generated
View file

@ -2633,6 +2633,7 @@ version = "0.19.3"
dependencies = [ dependencies = [
"activitypub_federation", "activitypub_federation",
"actix-web", "actix-web",
"anyhow",
"chrono", "chrono",
"encoding", "encoding",
"enum-map", "enum-map",
@ -2645,6 +2646,7 @@ dependencies = [
"lemmy_db_views_moderator", "lemmy_db_views_moderator",
"lemmy_utils", "lemmy_utils",
"mime", "mime",
"moka",
"once_cell", "once_cell",
"pretty_assertions", "pretty_assertions",
"regex", "regex",

View file

@ -139,3 +139,23 @@ test("Create user with Arabic name", async () => {
let alphaPerson = (await resolvePerson(alpha, apShortname)).person; let alphaPerson = (await resolvePerson(alpha, apShortname)).person;
expect(alphaPerson).toBeDefined(); expect(alphaPerson).toBeDefined();
}); });
test("Create user with accept-language", async () => {
let lemmy_http = new LemmyHttp(alphaUrl, {
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language#syntax
headers: { "Accept-Language": "fr-CH, en;q=0.8, de;q=0.7, *;q=0.5" },
});
let user = await registerUser(lemmy_http, alphaUrl);
let site = await getSite(user);
expect(site.my_user).toBeDefined();
expect(site.my_user?.local_user_view.local_user.interface_language).toBe(
"fr",
);
let langs = site.all_languages
.filter(a => site.my_user?.discussion_languages.includes(a.id))
.map(l => l.code);
// should have languages from accept header, as well as "undetermined"
// which is automatically enabled by backend
expect(langs).toStrictEqual(["und", "de", "en", "fr"]);
});

View file

@ -19,7 +19,9 @@ use lemmy_api_common::{
use lemmy_db_schema::{ use lemmy_db_schema::{
aggregates::structs::PersonAggregates, aggregates::structs::PersonAggregates,
source::{ source::{
actor_language::LocalUserLanguage,
captcha_answer::{CaptchaAnswer, CheckCaptchaAnswer}, captcha_answer::{CaptchaAnswer, CheckCaptchaAnswer},
language::Language,
local_user::{LocalUser, LocalUserInsertForm}, local_user::{LocalUser, LocalUserInsertForm},
local_user_vote_display_mode::LocalUserVoteDisplayMode, local_user_vote_display_mode::LocalUserVoteDisplayMode,
person::{Person, PersonInsertForm}, person::{Person, PersonInsertForm},
@ -36,6 +38,7 @@ use lemmy_utils::{
validation::is_valid_actor_name, validation::is_valid_actor_name,
}, },
}; };
use std::collections::HashSet;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
pub async fn register( pub async fn register(
@ -128,12 +131,15 @@ pub async fn register(
let accepted_application = Some(!require_registration_application); let accepted_application = Some(!require_registration_application);
// Get the user's preferred language using the Accept-Language header // Get the user's preferred language using the Accept-Language header
let language_tag = req.headers().get("Accept-Language").and_then(|hdr| { let language_tags: Vec<String> = req
accept_language::parse(hdr.to_str().unwrap_or_default()) .headers()
.first() .get("Accept-Language")
// Remove the optional region code .map(|hdr| accept_language::parse(hdr.to_str().unwrap_or_default()))
.map(|lang_str| lang_str.split('-').next().unwrap_or_default().to_string()) .iter()
}); .flatten()
// Remove the optional region code
.map(|lang_str| lang_str.split('-').next().unwrap_or_default().to_string())
.collect();
// Create the local user // Create the local user
let local_user_form = LocalUserInsertForm::builder() let local_user_form = LocalUserInsertForm::builder()
@ -144,13 +150,24 @@ pub async fn register(
.accepted_application(accepted_application) .accepted_application(accepted_application)
.default_listing_type(Some(local_site.default_post_listing_type)) .default_listing_type(Some(local_site.default_post_listing_type))
.post_listing_mode(Some(local_site.default_post_listing_mode)) .post_listing_mode(Some(local_site.default_post_listing_mode))
.interface_language(language_tag) .interface_language(language_tags.first().cloned())
// If its the initial site setup, they are an admin // If its the initial site setup, they are an admin
.admin(Some(!local_site.site_setup)) .admin(Some(!local_site.site_setup))
.build(); .build();
let inserted_local_user = LocalUser::create(&mut context.pool(), &local_user_form).await?; let inserted_local_user = LocalUser::create(&mut context.pool(), &local_user_form).await?;
let all_languages = Language::read_all(&mut context.pool()).await?;
// use hashset to avoid duplicates
let mut language_ids = HashSet::new();
for l in language_tags {
if let Some(found) = all_languages.iter().find(|all| all.code == l) {
language_ids.insert(found.id);
}
}
let language_ids = language_ids.into_iter().collect();
LocalUserLanguage::update(&mut context.pool(), language_ids, inserted_local_user.id).await?;
if local_site.site_setup && require_registration_application { if local_site.site_setup && require_registration_application {
// Create the registration application // Create the registration application
let form = RegistrationApplicationInsertForm { let form = RegistrationApplicationInsertForm {