♻️ Add translations for board customize page

This commit is contained in:
Meier Lukas
2023-08-05 17:18:05 +02:00
parent 6aff6dbedc
commit 73589623d4
15 changed files with 87 additions and 57 deletions

View File

@@ -0,0 +1,5 @@
{
"header": {
"customize": "Customize board"
}
}

View File

@@ -0,0 +1,26 @@
{
"metaTitle": "Customize {{name}} Board",
"pageTitle": "Customization for {{name}} Board",
"backToBoard": "Back to board",
"settings": {
"appearance": {
"primaryColor": "Primary color",
"secondaryColor": "Secondary color"
}
},
"save": "Save changes",
"notifications": {
"pending": {
"title": "Saving customization",
"message": "Please wait while we save your customization"
},
"success": {
"title": "Customization saved",
"message": "Your customization has been saved successfully"
},
"error": {
"title": "Error",
"message": "Unable to save changes"
}
}
}

View File

@@ -1,3 +0,0 @@
{
"label": "App Width"
}

View File

@@ -1,4 +0,0 @@
{
"colors": "Colors",
"suffix": "{{color}} color"
}

View File

@@ -23,8 +23,5 @@
"description": "Further, customize your dashboard using CSS, only recommended for experienced users", "description": "Further, customize your dashboard using CSS, only recommended for experienced users",
"placeholder": "Custom CSS will be applied last", "placeholder": "Custom CSS will be applied last",
"applying": "Applying CSS..." "applying": "Applying CSS..."
},
"buttons": {
"submit": "Submit"
} }
} }

View File

@@ -1,3 +0,0 @@
{
"label": "Switch to {{scheme}} mode"
}

View File

@@ -1,3 +0,0 @@
{
"label": "Switch to {{theme}} mode"
}

View File

@@ -18,11 +18,7 @@ import Editor from 'react-simple-code-editor';
import { useBoardCustomizationFormContext } from '../form'; import { useBoardCustomizationFormContext } from '../form';
export const AppearanceCustomization = () => { export const AppearanceCustomization = () => {
const { t } = useTranslation([ const { t } = useTranslation('settings/customization/page-appearance');
'settings/customization/page-appearance',
'settings/customization/color-selector',
]);
const theme = useMantineTheme();
const form = useBoardCustomizationFormContext(); const form = useBoardCustomizationFormContext();
return ( return (
@@ -45,7 +41,7 @@ type ColorSelectorProps = {
type: 'primaryColor' | 'secondaryColor'; type: 'primaryColor' | 'secondaryColor';
}; };
const ColorSelector = ({ type }: ColorSelectorProps) => { const ColorSelector = ({ type }: ColorSelectorProps) => {
const { t } = useTranslation('settings/customization/color-selector'); const { t } = useTranslation('boards/customize');
const theme = useMantineTheme(); const theme = useMantineTheme();
const form = useBoardCustomizationFormContext(); const form = useBoardCustomizationFormContext();
@@ -55,7 +51,7 @@ const ColorSelector = ({ type }: ColorSelectorProps) => {
})); }));
return ( return (
<Input.Wrapper label={type}> <Input.Wrapper label={t(`settings.appearance.${type}`)}>
<Group> <Group>
{colors.map(({ color, swatch }) => ( {colors.map(({ color, swatch }) => (
<ColorSwatch <ColorSwatch

View File

@@ -1,5 +1,4 @@
import { Button, Checkbox, Grid, Stack } from '@mantine/core'; import { Checkbox, Grid, Stack } from '@mantine/core';
import { IconDeviceFloppy } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { useBoardCustomizationFormContext } from '../form'; import { useBoardCustomizationFormContext } from '../form';

View File

@@ -15,12 +15,12 @@ import { Trans, useTranslation } from 'next-i18next';
import Link from 'next/link'; import Link from 'next/link';
import { useEditModeStore } from '~/components/Dashboard/Views/useEditModeStore'; import { useEditModeStore } from '~/components/Dashboard/Views/useEditModeStore';
import { useNamedWrapperColumnCount } from '~/components/Dashboard/Wrappers/gridstack/store'; import { useNamedWrapperColumnCount } from '~/components/Dashboard/Wrappers/gridstack/store';
import { BoardHeadOverride } from '~/components/layout/Meta/BoardHeadOverride';
import { HeaderActionButton } from '~/components/layout/header/ActionButton';
import { useConfigContext } from '~/config/provider'; import { useConfigContext } from '~/config/provider';
import { env } from '~/env'; import { env } from '~/env';
import { api } from '~/utils/api'; import { api } from '~/utils/api';
import { HeaderActionButton } from '~/components/layout/header/ActionButton';
import { BoardHeadOverride } from '~/components/layout/Meta/BoardHeadOverride';
import { MainLayout } from './MainLayout'; import { MainLayout } from './MainLayout';
type BoardLayoutProps = { type BoardLayoutProps = {
@@ -68,10 +68,10 @@ const DockerButton = () => {
const CustomizeBoardButton = () => { const CustomizeBoardButton = () => {
const { name } = useConfigContext(); const { name } = useConfigContext();
console.log('name', name); const { t } = useTranslation('boards/common');
return ( return (
<Tooltip label="Customize board"> <Tooltip label={t('header.customize')}>
<HeaderActionButton component={Link} href={`/board/${name}/customize`}> <HeaderActionButton component={Link} href={`/board/${name}/customize`}>
<IconSettings size={20} stroke={1.5} /> <IconSettings size={20} stroke={1.5} />
</HeaderActionButton> </HeaderActionButton>
@@ -158,7 +158,7 @@ const ToggleEditModeButton = () => {
if (enabled) { if (enabled) {
return ( return (
<Button.Group> <Button.Group>
<Tooltip label={t('button.disabled')}> <Tooltip label={t('button.enabled')}>
<HeaderActionButton onClick={save}> <HeaderActionButton onClick={save}>
<IconEditCircleOff size={20} stroke={1.5} /> <IconEditCircleOff size={20} stroke={1.5} />
</HeaderActionButton> </HeaderActionButton>

View File

@@ -7,7 +7,7 @@ import { useInitConfig } from '~/config/init';
import { configExists } from '~/tools/config/configExists'; import { configExists } from '~/tools/config/configExists';
import { getFrontendConfig } from '~/tools/config/getFrontendConfig'; import { getFrontendConfig } from '~/tools/config/getFrontendConfig';
import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations'; import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations';
import { dashboardNamespaces } from '~/tools/server/translation-namespaces'; import { boardNamespaces } from '~/tools/server/translation-namespaces';
import { ConfigType } from '~/types/config'; import { ConfigType } from '~/types/config';
export default function BoardPage({ export default function BoardPage({
@@ -52,7 +52,7 @@ export const getServerSideProps: GetServerSideProps<BoardGetServerSideProps> = a
} }
const config = await getFrontendConfig(routeParams.data.slug); const config = await getFrontendConfig(routeParams.data.slug);
const translations = await getServerSideTranslations(dashboardNamespaces, locale, req, res); const translations = await getServerSideTranslations(boardNamespaces, locale, req, res);
return { return {
props: { props: {

View File

@@ -12,6 +12,7 @@ import {
} from '@tabler/icons-react'; } from '@tabler/icons-react';
import { GetServerSideProps } from 'next'; import { GetServerSideProps } from 'next';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import Head from 'next/head';
import Link from 'next/link'; import Link from 'next/link';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { ReactNode } from 'react'; import { ReactNode } from 'react';
@@ -28,7 +29,8 @@ import { MainLayout } from '~/components/layout/Templates/MainLayout';
import { createTrpcServersideHelpers } from '~/server/api/helper'; import { createTrpcServersideHelpers } from '~/server/api/helper';
import { getServerAuthSession } from '~/server/auth'; import { getServerAuthSession } from '~/server/auth';
import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations'; import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations';
import { dashboardNamespaces } from '~/tools/server/translation-namespaces'; import { boardNamespaces } from '~/tools/server/translation-namespaces';
import { firstUpperCase } from '~/tools/shared/strings';
import { api } from '~/utils/api'; import { api } from '~/utils/api';
import { useI18nZodResolver } from '~/utils/i18n-zod-resolver'; import { useI18nZodResolver } from '~/utils/i18n-zod-resolver';
import { boardCustomizationSchema } from '~/validations/dashboards'; import { boardCustomizationSchema } from '~/validations/dashboards';
@@ -41,6 +43,7 @@ export default function CustomizationPage() {
const { data: config } = api.config.byName.useQuery({ name: query.slug }); const { data: config } = api.config.byName.useQuery({ name: query.slug });
const { mutateAsync: saveCusomization, isLoading } = api.config.saveCusomization.useMutation(); const { mutateAsync: saveCusomization, isLoading } = api.config.saveCusomization.useMutation();
const { i18nZodResolver } = useI18nZodResolver(); const { i18nZodResolver } = useI18nZodResolver();
const { t } = useTranslation('boards/customize');
const form = useBoardCustomizationForm({ const form = useBoardCustomizationForm({
initialValues: { initialValues: {
layout: { layout: {
@@ -75,8 +78,8 @@ export default function CustomizationPage() {
if (isLoading) return; if (isLoading) return;
showNotification({ showNotification({
id: notificationId, id: notificationId,
title: 'Saving customization', title: t('notifications.pending.title'),
message: 'Please wait while we save your customization', message: t('notifications.pending.message'),
loading: true, loading: true,
}); });
await saveCusomization( await saveCusomization(
@@ -91,8 +94,8 @@ export default function CustomizationPage() {
onSuccess() { onSuccess() {
updateNotification({ updateNotification({
id: notificationId, id: notificationId,
title: 'Customization saved', title: t('notifications.success.title'),
message: 'Your customization has been saved', message: t('notifications.success.message'),
color: 'green', color: 'green',
icon: <IconCheck />, icon: <IconCheck />,
}); });
@@ -100,8 +103,8 @@ export default function CustomizationPage() {
onError() { onError() {
updateNotification({ updateNotification({
id: notificationId, id: notificationId,
title: 'Error', title: t('notifications.error.title'),
message: 'Unable to save customization', message: t('notifications.error.message'),
color: 'red', color: 'red',
icon: <IconX />, icon: <IconX />,
}); });
@@ -110,20 +113,31 @@ export default function CustomizationPage() {
); );
}; };
const metaTitle = `${t('metaTitle', {
name: firstUpperCase(query.slug),
})} • Homarr`;
return ( return (
<MainLayout> <MainLayout>
<Head>
<title>{metaTitle}</title>
</Head>
<Container> <Container>
<Paper p="xl" py="sm" mih="100%" withBorder> <Paper p="xl" py="sm" mih="100%" withBorder>
<Stack> <Stack>
<Group position="apart"> <Group position="apart">
<Title order={2}>Customization for {query.slug} Board</Title> <Title order={2}>
{t('pageTitle', {
name: firstUpperCase(query.slug),
})}
</Title>
<Button <Button
component={Link} component={Link}
href={`/board/${query.slug}`} href={`/board/${query.slug}`}
variant="light" variant="light"
leftIcon={<IconArrowLeft size={16} />} leftIcon={<IconArrowLeft size={16} />}
> >
Back to Board {t('backToBoard')}
</Button> </Button>
</Group> </Group>
<BoardCustomizationFormProvider form={form}> <BoardCustomizationFormProvider form={form}>
@@ -146,7 +160,7 @@ export default function CustomizationPage() {
<AppearanceCustomization /> <AppearanceCustomization />
</Stack> </Stack>
<Button type="submit" loading={isLoading}> <Button type="submit" loading={isLoading}>
Save changes {t('save')}
</Button> </Button>
</Stack> </Stack>
</form> </form>
@@ -200,7 +214,20 @@ export const getServerSideProps: GetServerSideProps = async ({ req, res, locale,
helpers.config.byName.prefetch({ name: routeParams.data.slug }); helpers.config.byName.prefetch({ name: routeParams.data.slug });
const translations = await getServerSideTranslations(dashboardNamespaces, locale, req, res); const translations = await getServerSideTranslations(
[
'boards/customize',
'settings/common',
'settings/customization/general',
'settings/customization/page-appearance',
'settings/customization/shade-selector',
'settings/customization/opacity-selector',
'settings/customization/gridstack',
],
locale,
req,
res
);
return { return {
props: { props: {

View File

@@ -7,7 +7,7 @@ import { getServerAuthSession } from '~/server/auth';
import { prisma } from '~/server/db'; import { prisma } from '~/server/db';
import { getFrontendConfig } from '~/tools/config/getFrontendConfig'; import { getFrontendConfig } from '~/tools/config/getFrontendConfig';
import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations'; import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations';
import { dashboardNamespaces } from '~/tools/server/translation-namespaces'; import { boardNamespaces } from '~/tools/server/translation-namespaces';
import { ConfigType } from '~/types/config'; import { ConfigType } from '~/types/config';
export default function BoardPage({ export default function BoardPage({
@@ -36,7 +36,7 @@ export const getServerSideProps: GetServerSideProps<BoardGetServerSideProps> = a
}); });
const translations = await getServerSideTranslations( const translations = await getServerSideTranslations(
dashboardNamespaces, boardNamespaces,
ctx.locale, ctx.locale,
ctx.req, ctx.req,
ctx.res ctx.res

View File

@@ -8,7 +8,7 @@ import ContainerActionBar from '~/modules/Docker/ContainerActionBar';
import DockerTable from '~/modules/Docker/DockerTable'; import DockerTable from '~/modules/Docker/DockerTable';
import { getServerAuthSession } from '~/server/auth'; import { getServerAuthSession } from '~/server/auth';
import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations'; import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations';
import { dashboardNamespaces } from '~/tools/server/translation-namespaces'; import { boardNamespaces } from '~/tools/server/translation-namespaces';
import { api } from '~/utils/api'; import { api } from '~/utils/api';
export default function DockerPage() { export default function DockerPage() {
@@ -42,7 +42,7 @@ export const getServerSideProps: GetServerSideProps = async ({ locale, req, res
}; };
} }
const translations = await getServerSideTranslations(dashboardNamespaces, locale, req, res); const translations = await getServerSideTranslations(boardNamespaces, locale, req, res);
return { return {
props: { props: {
...translations, ...translations,

View File

@@ -1,4 +1,4 @@
export const dashboardNamespaces = [ export const boardNamespaces = [
'common', 'common',
'zod', 'zod',
'layout/element-selector/selector', 'layout/element-selector/selector',
@@ -9,18 +9,10 @@ export const dashboardNamespaces = [
'layout/header/actions/toggle-edit-mode', 'layout/header/actions/toggle-edit-mode',
'layout/mobile/drawer', 'layout/mobile/drawer',
'settings/common', 'settings/common',
'settings/general/theme-selector',
'settings/general/config-changer', 'settings/general/config-changer',
'settings/general/internationalization', 'settings/general/internationalization',
'settings/general/search-engine', 'settings/general/search-engine',
'settings/general/widget-positions', 'settings/general/widget-positions',
'settings/customization/general',
'settings/customization/color-selector',
'settings/customization/page-appearance',
'settings/customization/shade-selector',
'settings/customization/app-width',
'settings/customization/opacity-selector',
'settings/customization/gridstack',
'modules/common', 'modules/common',
'modules/date', 'modules/date',
'modules/calendar', 'modules/calendar',
@@ -46,6 +38,7 @@ export const dashboardNamespaces = [
'widgets/error-boundary', 'widgets/error-boundary',
'widgets/draggable-list', 'widgets/draggable-list',
'widgets/location', 'widgets/location',
'boards/common',
]; ];
export const manageNamespaces = ['user/preferences', 'zod']; export const manageNamespaces = ['user/preferences', 'zod'];