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 = [
"activitypub_federation",
"actix-web",
"anyhow",
"chrono",
"encoding",
"enum-map",
@ -2645,6 +2646,7 @@ dependencies = [
"lemmy_db_views_moderator",
"lemmy_utils",
"mime",
"moka",
"once_cell",
"pretty_assertions",
"regex",

View file

@ -139,3 +139,23 @@ test("Create user with Arabic name", async () => {
let alphaPerson = (await resolvePerson(alpha, apShortname)).person;
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::{
aggregates::structs::PersonAggregates,
source::{
actor_language::LocalUserLanguage,
captcha_answer::{CaptchaAnswer, CheckCaptchaAnswer},
language::Language,
local_user::{LocalUser, LocalUserInsertForm},
local_user_vote_display_mode::LocalUserVoteDisplayMode,
person::{Person, PersonInsertForm},
@ -36,6 +38,7 @@ use lemmy_utils::{
validation::is_valid_actor_name,
},
};
use std::collections::HashSet;
#[tracing::instrument(skip(context))]
pub async fn register(
@ -128,12 +131,15 @@ pub async fn register(
let accepted_application = Some(!require_registration_application);
// Get the user's preferred language using the Accept-Language header
let language_tag = req.headers().get("Accept-Language").and_then(|hdr| {
accept_language::parse(hdr.to_str().unwrap_or_default())
.first()
// Remove the optional region code
.map(|lang_str| lang_str.split('-').next().unwrap_or_default().to_string())
});
let language_tags: Vec<String> = req
.headers()
.get("Accept-Language")
.map(|hdr| accept_language::parse(hdr.to_str().unwrap_or_default()))
.iter()
.flatten()
// Remove the optional region code
.map(|lang_str| lang_str.split('-').next().unwrap_or_default().to_string())
.collect();
// Create the local user
let local_user_form = LocalUserInsertForm::builder()
@ -144,13 +150,24 @@ pub async fn register(
.accepted_application(accepted_application)
.default_listing_type(Some(local_site.default_post_listing_type))
.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
.admin(Some(!local_site.site_setup))
.build();
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 {
// Create the registration application
let form = RegistrationApplicationInsertForm {