mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-11 16:05:47 +01:00
✨ Add translation to user settings
This commit is contained in:
@@ -1,2 +1,4 @@
|
||||
export const REPO_URL = 'ajnart/homarr';
|
||||
export const ICON_PICKER_SLICE_LIMIT = 36;
|
||||
export const COOKIE_LOCALE_KEY = 'config-locale';
|
||||
export const COOKIE_COLOR_SCHEME_KEY = 'color-scheme';
|
||||
|
||||
@@ -1,20 +1,25 @@
|
||||
import { Group, Select, Stack, Text } from '@mantine/core';
|
||||
import { showNotification } from '@mantine/notifications';
|
||||
import { getCookie, setCookie } from 'cookies-next';
|
||||
import { useSession } from 'next-auth/react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useRouter } from 'next/router';
|
||||
import { forwardRef, useState } from 'react';
|
||||
import { api } from '~/utils/api';
|
||||
|
||||
import { COOKIE_LOCALE_KEY } from '../../../../../data/constants';
|
||||
import { Language, getLanguageByCode } from '../../../../tools/language';
|
||||
|
||||
export default function LanguageSelect() {
|
||||
const { data: sessionData } = useSession();
|
||||
const { t, i18n } = useTranslation('settings/general/internationalization');
|
||||
const { changeLanguage } = i18n;
|
||||
const configLocale = getCookie('config-locale');
|
||||
const configLocale = getCookie(COOKIE_LOCALE_KEY);
|
||||
const { locale, locales, pathname, query, asPath, push } = useRouter();
|
||||
const [selectedLanguage, setSelectedLanguage] = useState<string>(
|
||||
(configLocale as string) ?? locale ?? 'en'
|
||||
sessionData?.user.language ?? (configLocale as string) ?? locale ?? 'en'
|
||||
);
|
||||
const { mutateAsync } = api.user.changeLanguage.useMutation();
|
||||
|
||||
const data = locales
|
||||
? locales.map((localeItem) => ({
|
||||
@@ -30,12 +35,18 @@ export default function LanguageSelect() {
|
||||
|
||||
const newLanguage = getLanguageByCode(value);
|
||||
changeLanguage(value)
|
||||
.then(() => {
|
||||
setCookie('config-locale', value, {
|
||||
.then(async () => {
|
||||
setCookie(COOKIE_LOCALE_KEY, value, {
|
||||
maxAge: 60 * 60 * 24 * 30,
|
||||
sameSite: 'strict',
|
||||
});
|
||||
|
||||
if (sessionData?.user && new Date(sessionData.expires) > new Date()) {
|
||||
await mutateAsync({
|
||||
language: value,
|
||||
});
|
||||
}
|
||||
|
||||
push(
|
||||
{
|
||||
pathname,
|
||||
|
||||
@@ -5,6 +5,8 @@ import { Session } from 'next-auth';
|
||||
import { useState } from 'react';
|
||||
import { api } from '~/utils/api';
|
||||
|
||||
import { COOKIE_COLOR_SCHEME_KEY } from '../../data/constants';
|
||||
|
||||
export const useColorScheme = (defaultValue: ColorScheme, session: Session) => {
|
||||
const [colorScheme, setColorScheme] = useState(defaultValue);
|
||||
const { mutateAsync } = api.user.changeColorScheme.useMutation();
|
||||
@@ -12,7 +14,7 @@ export const useColorScheme = (defaultValue: ColorScheme, session: Session) => {
|
||||
const toggleColorScheme = async () => {
|
||||
const newColorScheme = colorScheme === 'dark' ? 'light' : 'dark';
|
||||
setColorScheme(newColorScheme);
|
||||
setCookie('color-scheme', newColorScheme);
|
||||
setCookie(COOKIE_COLOR_SCHEME_KEY, newColorScheme);
|
||||
if (session && new Date(session.expires) > new Date()) {
|
||||
await mutateAsync({ colorScheme: newColorScheme });
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import { ConfigType } from '~/types/config';
|
||||
import { api } from '~/utils/api';
|
||||
import { colorSchemeParser } from '~/validations/user';
|
||||
|
||||
import { COOKIE_COLOR_SCHEME_KEY, COOKIE_LOCALE_KEY } from '../../data/constants';
|
||||
import nextI18nextConfig from '../../next-i18next.config.js';
|
||||
import { ChangeAppPositionModal } from '../components/Dashboard/Modals/ChangePosition/ChangeAppPositionModal';
|
||||
import { ChangeWidgetPositionModal } from '../components/Dashboard/Modals/ChangePosition/ChangeWidgetPositionModal';
|
||||
@@ -162,6 +163,12 @@ App.getInitialProps = async ({ ctx }: { ctx: GetServerSidePropsContext }) => {
|
||||
|
||||
const session = await getSession(ctx);
|
||||
|
||||
// Set the cookie language to the user language if it is not set correctly
|
||||
const cookieLanguage = getCookie(COOKIE_LOCALE_KEY, ctx);
|
||||
if (session?.user && session.user.language != cookieLanguage) {
|
||||
setCookie(COOKIE_LOCALE_KEY, session.user.language, ctx);
|
||||
}
|
||||
|
||||
return {
|
||||
pageProps: {
|
||||
colorScheme: getActiveColorScheme(session, ctx),
|
||||
@@ -175,13 +182,13 @@ export default appWithTranslation<any>(api.withTRPC(App), nextI18nextConfig as a
|
||||
|
||||
const getActiveColorScheme = (session: Session | null, ctx: GetServerSidePropsContext) => {
|
||||
const environmentColorScheme = env.DEFAULT_COLOR_SCHEME ?? 'light';
|
||||
const cookieValue = getCookie('color-scheme', ctx);
|
||||
const cookieColorScheme = getCookie(COOKIE_COLOR_SCHEME_KEY, ctx);
|
||||
const activeColorScheme = colorSchemeParser.parse(
|
||||
session?.user?.colorScheme ?? cookieValue ?? environmentColorScheme
|
||||
session?.user?.colorScheme ?? cookieColorScheme ?? environmentColorScheme
|
||||
);
|
||||
|
||||
if (cookieValue !== activeColorScheme) {
|
||||
setCookie('color-scheme', activeColorScheme, ctx);
|
||||
if (cookieColorScheme !== activeColorScheme) {
|
||||
setCookie(COOKIE_COLOR_SCHEME_KEY, activeColorScheme, ctx);
|
||||
}
|
||||
|
||||
return activeColorScheme === 'environment' ? environmentColorScheme : activeColorScheme;
|
||||
|
||||
@@ -4,6 +4,7 @@ import { z } from 'zod';
|
||||
import { hashPassword } from '~/utils/security';
|
||||
import { colorSchemeParser, signUpFormSchema } from '~/validations/user';
|
||||
|
||||
import { COOKIE_COLOR_SCHEME_KEY, COOKIE_LOCALE_KEY } from '../../../../data/constants';
|
||||
import { createTRPCRouter, protectedProcedure, publicProcedure } from '../trpc';
|
||||
|
||||
export const userRouter = createTRPCRouter({
|
||||
@@ -52,8 +53,8 @@ export const userRouter = createTRPCRouter({
|
||||
salt: salt,
|
||||
settings: {
|
||||
create: {
|
||||
colorScheme: colorSchemeParser.parse(ctx.cookies['color-scheme']),
|
||||
language: ctx.cookies['config-locale'] ?? 'en',
|
||||
colorScheme: colorSchemeParser.parse(ctx.cookies[COOKIE_COLOR_SCHEME_KEY]),
|
||||
language: ctx.cookies[COOKIE_LOCALE_KEY] ?? 'en',
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -89,4 +90,24 @@ export const userRouter = createTRPCRouter({
|
||||
},
|
||||
});
|
||||
}),
|
||||
changeLanguage: protectedProcedure
|
||||
.input(
|
||||
z.object({
|
||||
language: z.string(),
|
||||
})
|
||||
)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
await ctx.prisma.user.update({
|
||||
where: {
|
||||
id: ctx.session?.user?.id,
|
||||
},
|
||||
data: {
|
||||
settings: {
|
||||
update: {
|
||||
language: input.language,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -2,6 +2,8 @@ import { getCookie } from 'cookies-next';
|
||||
import { IncomingMessage, ServerResponse } from 'http';
|
||||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
|
||||
|
||||
import { COOKIE_LOCALE_KEY } from '../../../data/constants';
|
||||
|
||||
export const getServerSideTranslations = async (
|
||||
namespaces: string[],
|
||||
requestLocale?: string,
|
||||
@@ -12,7 +14,7 @@ export const getServerSideTranslations = async (
|
||||
return serverSideTranslations(requestLocale ?? 'en', namespaces);
|
||||
}
|
||||
|
||||
const configLocale = getCookie('config-locale', { req, res });
|
||||
const configLocale = getCookie(COOKIE_LOCALE_KEY, { req, res });
|
||||
|
||||
return serverSideTranslations((configLocale ?? requestLocale ?? 'en') as string, namespaces);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user