Add language field and API
This commit is contained in:
parent
b5e4c30d40
commit
b667140d3e
|
|
@ -1,13 +1,15 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { loadLocaleMessages, setI18nLanguage } from "@/i18n";
|
import type { availableLanguages } from "@/stores/user";
|
||||||
|
import { useUserStore } from "@/stores/user";
|
||||||
import * as log from "loglevel";
|
import * as log from "loglevel";
|
||||||
|
|
||||||
log.debug("AppFooter created");
|
log.debug("AppFooter created");
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
async function changeLocale(event: Event) {
|
async function changeLocale(event: Event) {
|
||||||
const target = event.target as HTMLSelectElement;
|
const target = event.target as HTMLSelectElement;
|
||||||
await loadLocaleMessages(target.value);
|
userStore.setUserLanguages(target.value as availableLanguages);
|
||||||
setI18nLanguage(target.value);
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -22,9 +24,16 @@ async function changeLocale(event: Event) {
|
||||||
<div class="lg:ml-8">Deutsch</div>
|
<div class="lg:ml-8">Deutsch</div>
|
||||||
<!--div class="locale-changer">
|
<!--div class="locale-changer">
|
||||||
<select @change="changeLocale($event)">
|
<select @change="changeLocale($event)">
|
||||||
<option v-for="locale in ['de', 'fr']" :key="`locale-${locale}`" :value="locale">{{ locale }}</option>
|
<option
|
||||||
|
v-for="locale in ['de', 'fr']"
|
||||||
|
:key="`locale-${locale}`"
|
||||||
|
:value="locale"
|
||||||
|
:selected="locale === userStore.language"
|
||||||
|
>
|
||||||
|
{{ locale }}
|
||||||
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div-->
|
</div -->
|
||||||
<div class="lg:ml-8">{{ $t("footer.contact") }}</div>
|
<div class="lg:ml-8">{{ $t("footer.contact") }}</div>
|
||||||
</footer>
|
</footer>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,9 @@ import { createI18n } from "vue-i18n";
|
||||||
export const SUPPORT_LOCALES = ["de", "fr", "it"];
|
export const SUPPORT_LOCALES = ["de", "fr", "it"];
|
||||||
let i18n: any = null;
|
let i18n: any = null;
|
||||||
|
|
||||||
export function setupI18n(options = { locale: "de", legacy: false }) {
|
export function setupI18n(
|
||||||
|
options = { locale: "de", legacy: false, fallbackLocale: "de" }
|
||||||
|
) {
|
||||||
i18n = createI18n(options);
|
i18n = createI18n(options);
|
||||||
setI18nLanguage(options.locale);
|
setI18nLanguage(options.locale);
|
||||||
dayjs.locale(options.locale);
|
dayjs.locale(options.locale);
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,15 @@
|
||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
|
|
||||||
import { bustItGetCache, itGetCached, itPost } from "@/fetchHelpers";
|
import { bustItGetCache, itGetCached, itPost } from "@/fetchHelpers";
|
||||||
|
import { loadLocaleMessages, setI18nLanguage } from "@/i18n";
|
||||||
import { useAppStore } from "@/stores/app";
|
import { useAppStore } from "@/stores/app";
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
|
|
||||||
const logoutRedirectUrl = import.meta.env.VITE_LOGOUT_REDIRECT;
|
const logoutRedirectUrl = import.meta.env.VITE_LOGOUT_REDIRECT;
|
||||||
// typed state https://stackoverflow.com/questions/71012513/when-using-pinia-and-typescript-how-do-you-use-an-action-to-set-the-state
|
// typed state https://stackoverflow.com/questions/71012513/when-using-pinia-and-typescript-how-do-you-use-an-action-to-set-the-state
|
||||||
|
|
||||||
|
export type availableLanguages = "de" | "fr" | "it";
|
||||||
|
|
||||||
export type UserState = {
|
export type UserState = {
|
||||||
id: number;
|
id: number;
|
||||||
first_name: string;
|
first_name: string;
|
||||||
|
|
@ -17,6 +20,7 @@ export type UserState = {
|
||||||
is_superuser: boolean;
|
is_superuser: boolean;
|
||||||
course_session_experts: number[];
|
course_session_experts: number[];
|
||||||
loggedIn: boolean;
|
loggedIn: boolean;
|
||||||
|
language: availableLanguages;
|
||||||
};
|
};
|
||||||
|
|
||||||
const initialUserState: UserState = {
|
const initialUserState: UserState = {
|
||||||
|
|
@ -29,8 +33,14 @@ const initialUserState: UserState = {
|
||||||
is_superuser: false,
|
is_superuser: false,
|
||||||
course_session_experts: [],
|
course_session_experts: [],
|
||||||
loggedIn: false,
|
loggedIn: false,
|
||||||
|
language: "de",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
async function setLocale(language: availableLanguages) {
|
||||||
|
await loadLocaleMessages(language);
|
||||||
|
setI18nLanguage(language);
|
||||||
|
}
|
||||||
|
|
||||||
export const useUserStore = defineStore({
|
export const useUserStore = defineStore({
|
||||||
id: "user",
|
id: "user",
|
||||||
state: () => initialUserState as UserState,
|
state: () => initialUserState as UserState,
|
||||||
|
|
@ -80,6 +90,12 @@ export const useUserStore = defineStore({
|
||||||
this.$state = data;
|
this.$state = data;
|
||||||
this.loggedIn = true;
|
this.loggedIn = true;
|
||||||
appStore.userLoaded = true;
|
appStore.userLoaded = true;
|
||||||
|
await setLocale(data.language);
|
||||||
|
},
|
||||||
|
async setUserLanguages(language: availableLanguages) {
|
||||||
|
await setLocale(language);
|
||||||
|
this.$state.language = language;
|
||||||
|
await itPost("/api/core/me/", { language }, { method: "PUT" });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
("core", "0001_initial"),
|
("core", "0001_initial"),
|
||||||
]
|
]
|
||||||
|
|
@ -22,4 +21,13 @@ class Migration(migrations.Migration):
|
||||||
max_length=254, unique=True, verbose_name="email address"
|
max_length=254, unique=True, verbose_name="email address"
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="user",
|
||||||
|
name="language",
|
||||||
|
field=models.CharField(
|
||||||
|
choices=[("de", "Deutsch"), ("fr", "Français"), ("it", "Italiano")],
|
||||||
|
default="de",
|
||||||
|
max_length=2,
|
||||||
|
),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,12 @@ class User(AbstractUser):
|
||||||
If adding fields that need to be filled at user signup,
|
If adding fields that need to be filled at user signup,
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
LANGUAGE_CHOICES = (
|
||||||
|
("de", "Deutsch"),
|
||||||
|
("fr", "Français"),
|
||||||
|
("it", "Italiano"),
|
||||||
|
)
|
||||||
|
|
||||||
# FIXME: look into it...
|
# FIXME: look into it...
|
||||||
# objects = UserManager()
|
# objects = UserManager()
|
||||||
avatar_url = models.CharField(max_length=254, blank=True, default="")
|
avatar_url = models.CharField(max_length=254, blank=True, default="")
|
||||||
|
|
@ -19,6 +25,7 @@ class User(AbstractUser):
|
||||||
"SSO subscriber ID", unique=True, null=True, blank=True, default=None
|
"SSO subscriber ID", unique=True, null=True, blank=True, default=None
|
||||||
)
|
)
|
||||||
additional_json_data = JSONField(default=dict, blank=True)
|
additional_json_data = JSONField(default=dict, blank=True)
|
||||||
|
language = models.CharField(max_length=2, choices=LANGUAGE_CHOICES, default="de")
|
||||||
|
|
||||||
objects = UserManager()
|
objects = UserManager()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,15 @@ class UserSerializer(serializers.ModelSerializer):
|
||||||
"avatar_url",
|
"avatar_url",
|
||||||
"is_superuser",
|
"is_superuser",
|
||||||
"course_session_experts",
|
"course_session_experts",
|
||||||
|
"language",
|
||||||
|
]
|
||||||
|
read_only_fields = [
|
||||||
|
"id",
|
||||||
|
"is_superuser",
|
||||||
|
"first_name",
|
||||||
|
"last_name",
|
||||||
|
"email",
|
||||||
|
"username",
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_course_session_experts(self, obj):
|
def get_course_session_experts(self, obj):
|
||||||
|
|
|
||||||
|
|
@ -82,11 +82,25 @@ def vue_login(request):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@api_view(["GET"])
|
@api_view(["GET", "PUT"])
|
||||||
def me_user_view(request):
|
def me_user_view(request):
|
||||||
if request.user.is_authenticated:
|
if not request.user.is_authenticated:
|
||||||
|
return Response(status=403)
|
||||||
|
|
||||||
|
if request.method == "GET":
|
||||||
return Response(UserSerializer(request.user).data)
|
return Response(UserSerializer(request.user).data)
|
||||||
return Response(status=403)
|
|
||||||
|
if request.method == "PUT":
|
||||||
|
serializer = UserSerializer(
|
||||||
|
request.user,
|
||||||
|
data={"language": request.data.get("language", "de")},
|
||||||
|
partial=True,
|
||||||
|
)
|
||||||
|
if serializer.is_valid():
|
||||||
|
serializer.save()
|
||||||
|
return Response(UserSerializer(request.user).data)
|
||||||
|
|
||||||
|
return Response(status=400)
|
||||||
|
|
||||||
|
|
||||||
@api_view(["POST"])
|
@api_view(["POST"])
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue