mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-09 15:05:48 +01:00
Translations and styling
This commit is contained in:
@@ -1,14 +1,14 @@
|
|||||||
{
|
{
|
||||||
"actions": {
|
|
||||||
"save": "Save",
|
"save": "Save",
|
||||||
|
"about": "About",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"close": "Close",
|
"close": "Close",
|
||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
"ok": "Okay",
|
"ok": "Okay",
|
||||||
"edit": "Edit",
|
"edit": "Edit",
|
||||||
|
"version": "Version",
|
||||||
"changePosition": "Change position",
|
"changePosition": "Change position",
|
||||||
"remove": "Remove"
|
"remove": "Remove",
|
||||||
},
|
|
||||||
"sections": {
|
"sections": {
|
||||||
"settings": "Settings",
|
"settings": "Settings",
|
||||||
"dangerZone": "Danger zone"
|
"dangerZone": "Danger zone"
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
"title": "Add a new tile",
|
"title": "Add a new tile",
|
||||||
"text": "Tiles are the main element of homarr. They allow you to configure the dashboard and display the information you want."
|
"text": "Tiles are the main element of homarr. They allow you to configure the dashboard and display the information you want."
|
||||||
},
|
},
|
||||||
|
"widgetDescription": "Widgets interact with your apps, to provide you with more control over your applications. They usually require a few configurations before use.",
|
||||||
"actionIcon": {
|
"actionIcon": {
|
||||||
"tooltip": "Add a tile"
|
"tooltip": "Add a tile"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,6 @@
|
|||||||
},
|
},
|
||||||
"popover": {
|
"popover": {
|
||||||
"title": "Edit mode is enabled",
|
"title": "Edit mode is enabled",
|
||||||
"text": "You can adjust and configure your apps now. Changes are not saved until you exit edit mode"
|
"text": "You can adjust and configure your apps now. Changes are <strong>not saved</strong> until you exit edit mode"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
7
public/locales/en/layout/modals/about.json
Normal file
7
public/locales/en/layout/modals/about.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"description": "Homarr is a <strong>simple</strong> and <strong>modern</strong> homepage for your server that helps you access all of your apps in one place. It integrates with the apps you use to display useful information or control them. It's easy to install and supports many different devices.",
|
||||||
|
"i18n": "Loaded I18n translation namespaces",
|
||||||
|
"locales": "Configured I18n locales",
|
||||||
|
"contact": "Having trouble or questions? Connect with us!",
|
||||||
|
"addToDashboard": "Add to Dashboard"
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
Badge,
|
Badge,
|
||||||
Button,
|
Button,
|
||||||
createStyles,
|
createStyles,
|
||||||
|
Divider,
|
||||||
Group,
|
Group,
|
||||||
HoverCard,
|
HoverCard,
|
||||||
Modal,
|
Modal,
|
||||||
@@ -21,7 +22,7 @@ import {
|
|||||||
} from '@tabler/icons';
|
} from '@tabler/icons';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
import { InitOptions } from 'i18next';
|
import { InitOptions } from 'i18next';
|
||||||
import { i18n } from 'next-i18next';
|
import { i18n, Trans, useTranslation } from 'next-i18next';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
import { CURRENT_VERSION } from '../../../data/constants';
|
import { CURRENT_VERSION } from '../../../data/constants';
|
||||||
@@ -37,6 +38,7 @@ export const AboutModal = ({ opened, closeModal, newVersionAvailable }: AboutMod
|
|||||||
const { classes } = useStyles();
|
const { classes } = useStyles();
|
||||||
const colorGradiant = usePrimaryGradient();
|
const colorGradiant = usePrimaryGradient();
|
||||||
const informations = useInformationTableItems(newVersionAvailable);
|
const informations = useInformationTableItems(newVersionAvailable);
|
||||||
|
const { t } = useTranslation(['common', 'layout/modals/about']);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
@@ -46,22 +48,16 @@ export const AboutModal = ({ opened, closeModal, newVersionAvailable }: AboutMod
|
|||||||
<Group spacing="sm">
|
<Group spacing="sm">
|
||||||
<Image src="/imgs/logo/logo.png" width={30} height={30} objectFit="contain" />
|
<Image src="/imgs/logo/logo.png" width={30} height={30} objectFit="contain" />
|
||||||
<Title order={3} variant="gradient" gradient={colorGradiant}>
|
<Title order={3} variant="gradient" gradient={colorGradiant}>
|
||||||
About Homarr
|
{t('about')} Homarr
|
||||||
</Title>
|
</Title>
|
||||||
</Group>
|
</Group>
|
||||||
}
|
}
|
||||||
size="xl"
|
size="xl"
|
||||||
>
|
>
|
||||||
<Text mb="lg">
|
<Text mb="lg">
|
||||||
Homarr is a simple and modern homepage for your server that helps you access all of your
|
<Trans i18nKey="layout/modals/about:description" />
|
||||||
apps in one place. It integrates with the apps you use to display useful information or
|
|
||||||
control them. It's easy to install and supports many different devices.
|
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<Title order={6} mb="xs" align="center">
|
|
||||||
Version information:
|
|
||||||
</Title>
|
|
||||||
|
|
||||||
<Table mb="lg" striped highlightOnHover withBorder>
|
<Table mb="lg" striped highlightOnHover withBorder>
|
||||||
<tbody>
|
<tbody>
|
||||||
{informations.map((item, index) => (
|
{informations.map((item, index) => (
|
||||||
@@ -71,7 +67,7 @@ export const AboutModal = ({ opened, closeModal, newVersionAvailable }: AboutMod
|
|||||||
<ActionIcon className={classes.informationIcon} variant="default">
|
<ActionIcon className={classes.informationIcon} variant="default">
|
||||||
{item.icon}
|
{item.icon}
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
{item.label}
|
{t(item.label)}
|
||||||
</Group>
|
</Group>
|
||||||
</td>
|
</td>
|
||||||
<td className={classes.informationTableColumn}>{item.content}</td>
|
<td className={classes.informationTableColumn}>{item.content}</td>
|
||||||
@@ -79,9 +75,9 @@ export const AboutModal = ({ opened, closeModal, newVersionAvailable }: AboutMod
|
|||||||
))}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
</Table>
|
</Table>
|
||||||
|
<Divider variant="dashed" mb="md" />
|
||||||
<Title order={6} mb="xs" align="center">
|
<Title order={6} mb="xs" align="center">
|
||||||
Having trouble or questions? Connect with us!
|
{t('layout/modals/about:contact')}
|
||||||
</Title>
|
</Title>
|
||||||
|
|
||||||
<Group grow>
|
<Group grow>
|
||||||
@@ -101,7 +97,7 @@ export const AboutModal = ({ opened, closeModal, newVersionAvailable }: AboutMod
|
|||||||
leftIcon={<IconWorldWww size={20} />}
|
leftIcon={<IconWorldWww size={20} />}
|
||||||
variant="default"
|
variant="default"
|
||||||
>
|
>
|
||||||
Website
|
Documentation
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
component="a"
|
component="a"
|
||||||
@@ -141,7 +137,7 @@ const useInformationTableItems = (newVersionAvailable?: string): InformationTabl
|
|||||||
...items,
|
...items,
|
||||||
{
|
{
|
||||||
icon: <IconLanguage size={20} />,
|
icon: <IconLanguage size={20} />,
|
||||||
label: 'Loaded I18n translation namespaces',
|
label: 'layout/modals/about:i18n',
|
||||||
content: (
|
content: (
|
||||||
<Badge variant="gradient" gradient={colorGradiant}>
|
<Badge variant="gradient" gradient={colorGradiant}>
|
||||||
{usedI18nNamespaces.length}
|
{usedI18nNamespaces.length}
|
||||||
@@ -150,7 +146,7 @@ const useInformationTableItems = (newVersionAvailable?: string): InformationTabl
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: <IconVocabulary size={20} />,
|
icon: <IconVocabulary size={20} />,
|
||||||
label: 'Configured I18n locales',
|
label: 'layout/modals/about:locales',
|
||||||
content: (
|
content: (
|
||||||
<Badge variant="gradient" gradient={colorGradiant}>
|
<Badge variant="gradient" gradient={colorGradiant}>
|
||||||
{initOptions.locales.length}
|
{initOptions.locales.length}
|
||||||
@@ -164,7 +160,7 @@ const useInformationTableItems = (newVersionAvailable?: string): InformationTabl
|
|||||||
...items,
|
...items,
|
||||||
{
|
{
|
||||||
icon: <IconVersions size={20} />,
|
icon: <IconVersions size={20} />,
|
||||||
label: 'Homarr version',
|
label: 'version',
|
||||||
content: (
|
content: (
|
||||||
<Group position="right">
|
<Group position="right">
|
||||||
<Badge variant="gradient" gradient={colorGradiant}>
|
<Badge variant="gradient" gradient={colorGradiant}>
|
||||||
@@ -176,7 +172,7 @@ const useInformationTableItems = (newVersionAvailable?: string): InformationTabl
|
|||||||
<motion.div
|
<motion.div
|
||||||
initial={{ scale: 1.2 }}
|
initial={{ scale: 1.2 }}
|
||||||
animate={{
|
animate={{
|
||||||
scale: [0.8, 1.10, 1],
|
scale: [0.8, 1.1, 1],
|
||||||
rotate: [0, 10, 0],
|
rotate: [0, 10, 0],
|
||||||
}}
|
}}
|
||||||
transition={{ duration: 0.8, ease: 'easeInOut' }}
|
transition={{ duration: 0.8, ease: 'easeInOut' }}
|
||||||
|
|||||||
@@ -200,10 +200,10 @@ export const EditAppModal = ({
|
|||||||
|
|
||||||
<Group position="right" mt="md">
|
<Group position="right" mt="md">
|
||||||
<Button onClick={closeModal} px={50} variant="light" color="gray">
|
<Button onClick={closeModal} px={50} variant="light" color="gray">
|
||||||
{t('common:actions.cancel')}
|
{t('common:cancel')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button disabled={!form.isValid()} px={50} type="submit">
|
<Button disabled={!form.isValid()} px={50} type="submit">
|
||||||
{t('common:actions.save')}
|
{t('common:save')}
|
||||||
</Button>
|
</Button>
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Button, Card, Center, Grid, Stack, Text } from '@mantine/core';
|
import { Button, Card, Center, Grid, ScrollArea, Stack, Text } from '@mantine/core';
|
||||||
import { TablerIcon } from '@tabler/icons';
|
import { TablerIcon } from '@tabler/icons';
|
||||||
|
import { useTranslation } from 'next-i18next';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useStyles } from './styles';
|
import { useStyles } from './styles';
|
||||||
@@ -20,6 +21,7 @@ export const GenericAvailableElementType = ({
|
|||||||
handleAddition,
|
handleAddition,
|
||||||
}: GenericAvailableElementTypeProps) => {
|
}: GenericAvailableElementTypeProps) => {
|
||||||
const { classes } = useStyles();
|
const { classes } = useStyles();
|
||||||
|
const { t } = useTranslation('layout/modals/about');
|
||||||
|
|
||||||
const Icon =
|
const Icon =
|
||||||
typeof image === 'string' ? () => <Image src={image} width={24} height={24} /> : image;
|
typeof image === 'string' ? () => <Image src={image} width={24} height={24} /> : image;
|
||||||
@@ -50,7 +52,7 @@ export const GenericAvailableElementType = ({
|
|||||||
radius="md"
|
radius="md"
|
||||||
fullWidth
|
fullWidth
|
||||||
>
|
>
|
||||||
Add to Dashboard
|
{t('addToDashboard')}
|
||||||
</Button>
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -19,8 +19,7 @@ export const AvailableIntegrationElements = ({
|
|||||||
<SelectorBackArrow onClickBack={onClickBack} />
|
<SelectorBackArrow onClickBack={onClickBack} />
|
||||||
|
|
||||||
<Text mb="md" color="dimmed">
|
<Text mb="md" color="dimmed">
|
||||||
Widgets interact with your apps, to provide you with more control over your applications.
|
{t('widgetDescription')}
|
||||||
They usually require a few configurations before use.
|
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export const GenericTileMenu = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Menu withinPortal>
|
<Menu withinPortal withArrow position="right-start">
|
||||||
<Menu.Target>
|
<Menu.Target>
|
||||||
<ActionIcon pos="absolute" top={4} right={4}>
|
<ActionIcon pos="absolute" top={4} right={4}>
|
||||||
<IconDots />
|
<IconDots />
|
||||||
@@ -34,14 +34,14 @@ export const GenericTileMenu = ({
|
|||||||
<Menu.Label>{t('sections.settings')}</Menu.Label>
|
<Menu.Label>{t('sections.settings')}</Menu.Label>
|
||||||
{displayEdit && (
|
{displayEdit && (
|
||||||
<Menu.Item icon={<IconPencil size={16} stroke={1.5} />} onClick={handleClickEdit}>
|
<Menu.Item icon={<IconPencil size={16} stroke={1.5} />} onClick={handleClickEdit}>
|
||||||
{t('actions.edit')}
|
{t('edit')}
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
)}
|
)}
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
icon={<IconLayoutKanban size={16} stroke={1.5} />}
|
icon={<IconLayoutKanban size={16} stroke={1.5} />}
|
||||||
onClick={handleClickChangePosition}
|
onClick={handleClickChangePosition}
|
||||||
>
|
>
|
||||||
{t('actions.changePosition')}
|
{t('changePosition')}
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<Menu.Label>{t('sections.dangerZone')}</Menu.Label>
|
<Menu.Label>{t('sections.dangerZone')}</Menu.Label>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
@@ -49,7 +49,7 @@ export const GenericTileMenu = ({
|
|||||||
icon={<IconTrash size={16} stroke={1.5} color="red" />}
|
icon={<IconTrash size={16} stroke={1.5} color="red" />}
|
||||||
onClick={handleClickDelete}
|
onClick={handleClickDelete}
|
||||||
>
|
>
|
||||||
{t('actions.remove')}
|
{t('remove')}
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
</Menu.Dropdown>
|
</Menu.Dropdown>
|
||||||
</Menu>
|
</Menu>
|
||||||
|
|||||||
@@ -92,9 +92,9 @@ export const WidgetsEditModal = ({
|
|||||||
|
|
||||||
<Group position="right">
|
<Group position="right">
|
||||||
<Button onClick={() => context.closeModal(id)} variant="light">
|
<Button onClick={() => context.closeModal(id)} variant="light">
|
||||||
{t('common:actions.cancel')}
|
{t('common:cancel')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={handleSave}>{t('common:actions.save')}</Button>
|
<Button onClick={handleSave}>{t('common:save')}</Button>
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ export const WidgetsRemoveModal = ({
|
|||||||
<Text>{t('descriptor.remove.confirm')}</Text>
|
<Text>{t('descriptor.remove.confirm')}</Text>
|
||||||
<Group position="right">
|
<Group position="right">
|
||||||
<Button onClick={() => context.closeModal(id)} variant="light">
|
<Button onClick={() => context.closeModal(id)} variant="light">
|
||||||
{t('common:actions.cancel')}
|
{t('common:cancel')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={() => handleDeletion()}>{t('common:actions.ok')}</Button>
|
<Button onClick={() => handleDeletion()}>{t('common:ok')}</Button>
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import { ActionIcon, Button, Text, Tooltip } from '@mantine/core';
|
import { ActionIcon, Button, Text, Tooltip } from '@mantine/core';
|
||||||
import { IconEdit, IconEditOff } from '@tabler/icons';
|
import { IconEdit, IconEditOff } from '@tabler/icons';
|
||||||
|
import { useTranslation } from 'next-i18next';
|
||||||
import { useScreenLargerThan } from '../../../tools/hooks/useScreenLargerThan';
|
import { useScreenLargerThan } from '../../../tools/hooks/useScreenLargerThan';
|
||||||
import { useEditModeStore } from './useEditModeStore';
|
import { useEditModeStore } from './useEditModeStore';
|
||||||
|
|
||||||
export const ViewToggleButton = () => {
|
export const ViewToggleButton = () => {
|
||||||
const screenLargerThanMd = useScreenLargerThan('md');
|
const screenLargerThanMd = useScreenLargerThan('md');
|
||||||
const { enabled: isEditMode, toggleEditMode } = useEditModeStore();
|
const { enabled: isEditMode, toggleEditMode } = useEditModeStore();
|
||||||
|
const { t } = useTranslation('layout/header/actions/toggle-edit-mode');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
@@ -27,7 +29,7 @@ export const ViewToggleButton = () => {
|
|||||||
color={isEditMode ? 'red' : undefined}
|
color={isEditMode ? 'red' : undefined}
|
||||||
radius="md"
|
radius="md"
|
||||||
>
|
>
|
||||||
<Text>{isEditMode ? 'Exit Edit Mode' : 'Enter Edit Mode'}</Text>
|
<Text>{isEditMode ? t('button.enabled') : t('button.disabled')}</Text>
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { ActionIcon, Button, Popover, Text, Tooltip } from '@mantine/core';
|
import { ActionIcon, Button, Popover, Text, Tooltip } from '@mantine/core';
|
||||||
import { IconEditCircle, IconEditCircleOff, IconX } from '@tabler/icons';
|
import { IconEditCircle, IconEditCircleOff, IconX } from '@tabler/icons';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { Trans, useTranslation } from 'next-i18next';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useScreenSmallerThan } from '../../../../../tools/hooks/useScreenSmallerThan';
|
import { useScreenSmallerThan } from '../../../../../tools/hooks/useScreenSmallerThan';
|
||||||
|
|
||||||
@@ -54,7 +54,9 @@ export const ToggleEditModeAction = () => {
|
|||||||
</div>
|
</div>
|
||||||
<Text align="center" size="sm">
|
<Text align="center" size="sm">
|
||||||
<Text weight="bold">{t('popover.title')}</Text>
|
<Text weight="bold">{t('popover.title')}</Text>
|
||||||
{t('popover.text')}
|
<Text>
|
||||||
|
<Trans i18nKey="layout/header/actions/toggle-edit-mode:popover.text" />
|
||||||
|
</Text>
|
||||||
</Text>
|
</Text>
|
||||||
</Popover.Dropdown>
|
</Popover.Dropdown>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export function SettingsMenu({ newVersionAvailable }: { newVersionAvailable: str
|
|||||||
}
|
}
|
||||||
onClick={() => aboutModal.open()}
|
onClick={() => aboutModal.open()}
|
||||||
>
|
>
|
||||||
About
|
{t('about')}
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
</Menu.Dropdown>
|
</Menu.Dropdown>
|
||||||
</Menu>
|
</Menu>
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ function getItems(module: IModule) {
|
|||||||
onChange={(e) => {}}
|
onChange={(e) => {}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button type="submit">{t('actions.save', { ns: 'common' })}</Button>
|
<Button type="submit">{t('save', { ns: 'common' })}</Button>
|
||||||
</Group>
|
</Group>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ export const dashboardNamespaces = [
|
|||||||
'layout/tools',
|
'layout/tools',
|
||||||
'layout/element-selector/selector',
|
'layout/element-selector/selector',
|
||||||
'layout/modals/add-app',
|
'layout/modals/add-app',
|
||||||
|
'layout/modals/about',
|
||||||
'layout/header/actions/toggle-edit-mode',
|
'layout/header/actions/toggle-edit-mode',
|
||||||
'settings/common',
|
'settings/common',
|
||||||
'settings/general/theme-selector',
|
'settings/general/theme-selector',
|
||||||
|
|||||||
Reference in New Issue
Block a user