From c312828c798f11250710bd07e7e0251d544a848b Mon Sep 17 00:00:00 2001 From: Meier Lukas Date: Sat, 29 Jul 2023 11:35:34 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20translation=20to=20user=20set?= =?UTF-8?q?tings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data/constants.ts | 2 ++ .../Common/Language/LanguageSelect.tsx | 19 +++++++++++--- src/hooks/use-colorscheme.ts | 4 ++- src/pages/_app.tsx | 15 ++++++++--- src/server/api/routers/user.ts | 25 +++++++++++++++++-- src/tools/server/getServerSideTranslations.ts | 4 ++- 6 files changed, 57 insertions(+), 12 deletions(-) diff --git a/data/constants.ts b/data/constants.ts index b10f63d7e..6c43f365d 100644 --- a/data/constants.ts +++ b/data/constants.ts @@ -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'; diff --git a/src/components/Settings/Common/Language/LanguageSelect.tsx b/src/components/Settings/Common/Language/LanguageSelect.tsx index 37dbdec9b..03f12e3d0 100644 --- a/src/components/Settings/Common/Language/LanguageSelect.tsx +++ b/src/components/Settings/Common/Language/LanguageSelect.tsx @@ -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( - (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, diff --git a/src/hooks/use-colorscheme.ts b/src/hooks/use-colorscheme.ts index 46aafa659..3f325111b 100644 --- a/src/hooks/use-colorscheme.ts +++ b/src/hooks/use-colorscheme.ts @@ -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 }); } diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index a42263082..4c9a4c0d1 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -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(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; diff --git a/src/server/api/routers/user.ts b/src/server/api/routers/user.ts index 638c4fb09..6ba36d93a 100644 --- a/src/server/api/routers/user.ts +++ b/src/server/api/routers/user.ts @@ -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, + }, + }, + }, + }); + }), }); diff --git a/src/tools/server/getServerSideTranslations.ts b/src/tools/server/getServerSideTranslations.ts index 5bf9388e8..3e803fc63 100644 --- a/src/tools/server/getServerSideTranslations.ts +++ b/src/tools/server/getServerSideTranslations.ts @@ -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); };