diff --git a/public/locales/en/modules/bookmark.json b/public/locales/en/modules/bookmark.json index 183ee3130..43ede12c2 100644 --- a/public/locales/en/modules/bookmark.json +++ b/public/locales/en/modules/bookmark.json @@ -12,7 +12,12 @@ "label": "Items" }, "layout": { - "label": "Layout" + "label": "Layout", + "data":{ + "autoGrid": "Auto Grid", + "horizontal": "Horizontal", + "vertical": "Vertical" + } } } }, @@ -21,5 +26,21 @@ "title": "Bookmark list empty", "text": "Add new items to this list in the edit mode" } + }, + "item": { + "validation": { + "length100": "Length must be between 1 and 100", + "length200": "Length must be between 1 and 200", + "length400": "Length must be between 1 and 400", + "invalidLink": "Not a valid link", + "errorMsg": "Did not save, because there were validation errors. Please adust your inputs" + }, + "name": "Name", + "url": "URL", + "newTab": "Open in new tab", + "hideHostname": "Hide Hostname", + "hideIcon": "Hide Icon", + "delete": "Delete" + } } diff --git a/public/locales/en/modules/calendar.json b/public/locales/en/modules/calendar.json index 8fcfdf442..1f261ade0 100644 --- a/public/locales/en/modules/calendar.json +++ b/public/locales/en/modules/calendar.json @@ -11,13 +11,25 @@ "label": "Start the week on Sunday" }, "radarrReleaseType": { - "label": "Radarr release type" + "label": "Radarr release type", + "data":{ + "inCinemas": "In Cinemas", + "physicalRelease": "Physical", + "digitalRelease": "Digital" + } }, "hideWeekDays": { "label": "Hide week days" }, "fontSize": { - "label": "Font Size" + "label": "Font Size", + "data":{ + "xs": "Extra Small", + "sm": "Small", + "md": "Medium", + "lg": "Large", + "xl": "Extra Large" + } } } } diff --git a/public/locales/en/modules/iframe.json b/public/locales/en/modules/iframe.json index 067cda28a..baa55e498 100644 --- a/public/locales/en/modules/iframe.json +++ b/public/locales/en/modules/iframe.json @@ -38,7 +38,8 @@ "noUrl": { "title": "Invalid URL", "text": "Ensure that you've entered a valid address in the configuration of your widget" - } + }, + "browserSupport": "Your Browser does not support iframes. Please update your browser." } } } diff --git a/public/locales/en/modules/media-requests-list.json b/public/locales/en/modules/media-requests-list.json index a1a2b6ab2..9016a0f0f 100644 --- a/public/locales/en/modules/media-requests-list.json +++ b/public/locales/en/modules/media-requests-list.json @@ -19,6 +19,37 @@ }, "tooltips": { "approve": "Approve requests", - "decline": "Decline requests" + "decline": "Decline requests", + "approving": "Approving Request..." + }, + "mutation": { + "approving": "Approving", + "declining": "Declining", + "request": "request...", + "approved": "Request was approved!", + "declined": "Request was declined!" + }, + "detail": { + "label": "Stats for nerds", + "id": "ID", + "device": "Device", + "video": { + "video":"Video", + "resolution": "Resolution", + "framerate": "Framerate", + "codec": "Video Codec" + }, + "audio": { + "audio": "Audio", + "channels": "Audio Channels", + "codec": "Audio Codec" + }, + "transcoding": { + "transcoding": "Transcoding", + "context": "Context", + "requested": "Hardware Encoding Requested", + "source": "Source Codec", + "target": "Target Codec" + } } } diff --git a/public/locales/en/modules/media-requests-stats.json b/public/locales/en/modules/media-requests-stats.json index a06a52860..3027c8e1c 100644 --- a/public/locales/en/modules/media-requests-stats.json +++ b/public/locales/en/modules/media-requests-stats.json @@ -5,7 +5,11 @@ "settings": { "title": "Media requests stats", "direction": { - "label": "Direction of the layout." + "label": "Direction of the layout.", + "data":{ + "row": "Horizontal", + "column": "Vertical" + } } } }, diff --git a/public/locales/en/modules/media-server.json b/public/locales/en/modules/media-server.json index 1b93eb4c2..52e7d4b1f 100644 --- a/public/locales/en/modules/media-server.json +++ b/public/locales/en/modules/media-server.json @@ -6,6 +6,7 @@ "title": "Settings for media server widget" } }, + "loading": "Homarr is loading streams...", "card": { "table": { "header": { diff --git a/public/locales/en/modules/rss.json b/public/locales/en/modules/rss.json index fc6907fb7..ee73f375b 100644 --- a/public/locales/en/modules/rss.json +++ b/public/locales/en/modules/rss.json @@ -12,7 +12,8 @@ "label": "Refresh interval (in minutes)" }, "dangerousAllowSanitizedItemContent": { - "label": "" + "label": "Allow HTML formatting (Dangerous)", + "info": "Allowing HTML formatting from outside could be dangerous.
Please make sure that the feed is from a trusted source." }, "textLinesClamp": { "label": "Text lines clamp" diff --git a/public/locales/en/modules/torrents-status.json b/public/locales/en/modules/torrents-status.json index cd2674b4d..5901c0e5e 100644 --- a/public/locales/en/modules/torrents-status.json +++ b/public/locales/en/modules/torrents-status.json @@ -63,7 +63,8 @@ } }, "loading": { - "title": "Loading..." + "title": "Loading...", + "description": "Homarr is establishing a connection..." }, "popover": { "introductionPrefix": "Managed by", diff --git a/public/locales/en/modules/usenet.json b/public/locales/en/modules/usenet.json index d21c37ff4..19b292811 100644 --- a/public/locales/en/modules/usenet.json +++ b/public/locales/en/modules/usenet.json @@ -31,7 +31,8 @@ "title": "Error", "message": "An error has occurred" }, - "paused": "Paused" + "paused": "Paused", + "notImplemented": "NOT IMPLEMENTED" }, "history": { "header": { diff --git a/public/locales/en/modules/weather.json b/public/locales/en/modules/weather.json index 16b034320..a8e5cefcc 100644 --- a/public/locales/en/modules/weather.json +++ b/public/locales/en/modules/weather.json @@ -32,5 +32,6 @@ "thunderstormWithHail": "Thunderstorm with hail", "unknown": "Unknown" } - } + }, + "error": "An error occured" } diff --git a/src/pages/404.tsx b/src/pages/404.tsx index fc9cfda5a..e0afe4192 100644 --- a/src/pages/404.tsx +++ b/src/pages/404.tsx @@ -49,6 +49,6 @@ export async function getStaticProps({ req, res, locale }: GetServerSidePropsCon const useStyles = createStyles(() => ({ image: { margin: '0 auto', - display: 'blcok', + display: 'block', }, })); diff --git a/src/widgets/bookmark/BookmarkWidgetTile.tsx b/src/widgets/bookmark/BookmarkWidgetTile.tsx index dd04b87ae..6969bc18d 100644 --- a/src/widgets/bookmark/BookmarkWidgetTile.tsx +++ b/src/widgets/bookmark/BookmarkWidgetTile.tsx @@ -74,6 +74,7 @@ const definition = defineWidget({ }; }, itemComponent({ data, onChange, delete: deleteData }) { + const { t } = useTranslation('modules/bookmark'); const form = useForm({ initialValues: data, validate: { @@ -83,15 +84,15 @@ const definition = defineWidget({ return undefined; } - return 'Length must be between 1 and 100'; + return t('item.validation.length100'); }, href: (value) => { if (!z.string().min(1).max(200).safeParse(value).success) { - return 'Length must be between 1 and 200'; + return t('item.validation.length200'); } if (!z.string().url().safeParse(value).success) { - return 'Not a valid link'; + return t('item.validation.invalidLink'); } return undefined; @@ -101,7 +102,7 @@ const definition = defineWidget({ return undefined; } - return 'Length must be between 1 and 100'; + return t('item.validation.length400'); }, }, validateInputOnChange: true, @@ -122,13 +123,13 @@ const definition = defineWidget({ } {...form.getInputProps('name')} - label="Name" + label={t('item.name')} withAsterisk /> } {...form.getInputProps('href')} - label="URL" + label={t('item.url')} withAsterisk /> {!form.isValid() && ( }> - Did not save, because there were validation errors. Please adust your inputs + {t('item.validation.errorMsg')} )} @@ -174,18 +175,9 @@ const definition = defineWidget({ layout: { type: 'select', data: [ - { - label: 'Auto Grid', - value: 'autoGrid', - }, - { - label: 'Horizontal', - value: 'horizontal', - }, - { - label: 'Vertical', - value: 'vertical', - }, + { value: 'autoGrid', }, + { value: 'horizontal', }, + { value: 'vertical', }, ], defaultValue: 'autoGrid', }, @@ -206,10 +198,10 @@ interface BookmarkWidgetTileProps { } function BookmarkWidgetTile({ widget }: BookmarkWidgetTileProps) { - const { t } = useTranslation('modules/bookmark'); const { classes } = useStyles(); const { enabled: isEditModeEnabled } = useEditModeStore(); const { fn, colors, colorScheme } = useMantineTheme(); + const { t } = useTranslation('modules/bookmark'); if (widget.properties.items.length === 0) { return ( diff --git a/src/widgets/calendar/CalendarTile.tsx b/src/widgets/calendar/CalendarTile.tsx index 501f5a4cd..ec421e191 100644 --- a/src/widgets/calendar/CalendarTile.tsx +++ b/src/widgets/calendar/CalendarTile.tsx @@ -33,20 +33,20 @@ const definition = defineWidget({ type: 'select', defaultValue: 'inCinemas', data: [ - { label: 'In Cinemas', value: 'inCinemas' }, - { label: 'Physical', value: 'physicalRelease' }, - { label: 'Digital', value: 'digitalRelease' }, + { value: 'inCinemas' }, + { value: 'physicalRelease' }, + { value: 'digitalRelease' }, ], }, fontSize: { type: 'select', defaultValue: 'xs', data: [ - { label: 'Extra Small', value: 'xs' }, - { label: 'Small', value: 'sm' }, - { label: 'Medium', value: 'md' }, - { label: 'Large', value: 'lg' }, - { label: 'Extra Large', value: 'xl' }, + { value: 'xs' }, + { value: 'sm' }, + { value: 'md' }, + { value: 'lg' }, + { value: 'xl' }, ], }, }, diff --git a/src/widgets/iframe/IFrameTile.tsx b/src/widgets/iframe/IFrameTile.tsx index 07bb951b3..86b32c89c 100644 --- a/src/widgets/iframe/IFrameTile.tsx +++ b/src/widgets/iframe/IFrameTile.tsx @@ -121,7 +121,7 @@ function IFrameTile({ widget }: IFrameTileProps) { title="widget iframe" allow={allowedPermissions.join(' ')} > - Your Browser does not support iframes. Please update your browser. + {t('card.errors.browserSupport')} ); diff --git a/src/widgets/media-requests/MediaRequestListTile.tsx b/src/widgets/media-requests/MediaRequestListTile.tsx index 512dbe45d..83eccc7a8 100644 --- a/src/widgets/media-requests/MediaRequestListTile.tsx +++ b/src/widgets/media-requests/MediaRequestListTile.tsx @@ -58,12 +58,13 @@ const useMediaRequestDecisionMutation = () => { utils.mediaRequest.all.invalidate(); }, }); + const { t } = useTranslation('modules/media-requests-list'); return async (variables: MediaRequestDecisionVariables) => { - const action = variables.isApproved ? 'Approving' : 'Declining'; + const action = variables.isApproved ? t('mutation.approving') : t('mutation.declining'); notifications.show({ id: `decide-${variables.request.id}`, color: 'yellow', - title: `${action} request...`, + title: `${action} ${t('mutation.request')}`, message: undefined, loading: true, }); @@ -75,7 +76,7 @@ const useMediaRequestDecisionMutation = () => { }, { onSuccess(_data, variables) { - const title = variables.isApproved ? 'Request was approved!' : 'Request was declined!'; + const title = variables.isApproved ? t('mutation.approved') : t('mutation.declined'); notifications.update({ id: `decide-${variables.id}`, color: 'teal', @@ -187,7 +188,7 @@ function MediaRequestListTile({ widget }: MediaRequestListWidgetProps) { notifications.show({ id: `approve ${item.id}`, color: 'yellow', - title: 'Approving request...', + title: t('tooltips.approving'), message: undefined, loading: true, }); diff --git a/src/widgets/media-requests/MediaRequestStatsTile.tsx b/src/widgets/media-requests/MediaRequestStatsTile.tsx index 2af61d3e3..a46bbe542 100644 --- a/src/widgets/media-requests/MediaRequestStatsTile.tsx +++ b/src/widgets/media-requests/MediaRequestStatsTile.tsx @@ -16,8 +16,8 @@ const definition = defineWidget({ type: 'select', defaultValue: 'row' as 'row' | 'column', data: [ - { label: 'Horizontal', value: 'row' }, - { label: 'Vertical', value: 'column' }, + { value: 'row' }, + { value: 'column' }, ], }, }, diff --git a/src/widgets/media-server/DetailCollapseable.tsx b/src/widgets/media-server/DetailCollapseable.tsx index 6c0cea44d..85aa18531 100644 --- a/src/widgets/media-server/DetailCollapseable.tsx +++ b/src/widgets/media-server/DetailCollapseable.tsx @@ -2,27 +2,29 @@ import { Card, Divider, Flex, Grid, Group, Text } from '@mantine/core'; import { IconDeviceMobile, IconId } from '@tabler/icons-react'; import { GenericSessionInfo } from '../../types/api/media-server/session-info'; +import { useTranslation } from 'react-i18next'; export const DetailCollapseable = ({ session }: { session: GenericSessionInfo }) => { let details: { title: string; metrics: { name: string; value: string | undefined }[] }[] = []; + const { t } = useTranslation('modules/media-server-list'); if (session.currentlyPlaying) { if (session.currentlyPlaying.metadata.video) { details = [ ...details, { - title: 'Video', + title: t('detail.video.'), metrics: [ { - name: 'Resolution', + name: t('detail.video.resolution'), value: `${session.currentlyPlaying.metadata.video.width}x${session.currentlyPlaying.metadata.video.height}`, }, { - name: 'Framerate', + name: t('detail.video.framerate'), value: session.currentlyPlaying.metadata.video.videoFrameRate, }, { - name: 'Codec', + name: t('detail.video.codec'), value: session.currentlyPlaying.metadata.video.videoCodec, }, { @@ -39,14 +41,14 @@ export const DetailCollapseable = ({ session }: { session: GenericSessionInfo }) details = [ ...details, { - title: 'Audio', + title: t('detail.audio.audio'), metrics: [ { - name: 'Audio channels', + name: t('detail.audio.channels'), value: `${session.currentlyPlaying.metadata.audio.audioChannels}`, }, { - name: 'Audio codec', + name: t('detail.audio.codec'), value: session.currentlyPlaying.metadata.audio.audioCodec, }, ], @@ -58,24 +60,24 @@ export const DetailCollapseable = ({ session }: { session: GenericSessionInfo }) details = [ ...details, { - title: 'Transcoding', + title: t('detail.transcoding.transcoding'), metrics: [ { - name: 'Resolution', + name: t('detail.video.resolution'), value: `${session.currentlyPlaying.metadata.transcoding.width}x${session.currentlyPlaying.metadata.transcoding.height}`, }, { - name: 'Context', + name: t('detail.transcoding.context'), value: session.currentlyPlaying.metadata.transcoding.context, }, { - name: 'Hardware encoding requested', + name: t('detail.transcoding.requested'), value: session.currentlyPlaying.metadata.transcoding.transcodeHwRequested ? 'yes' : 'no', }, { - name: 'Source codec', + name: t('detail.transcoding.source'), value: session.currentlyPlaying.metadata.transcoding.sourceAudioCodec || session.currentlyPlaying.metadata.transcoding.sourceVideoCodec @@ -83,7 +85,7 @@ export const DetailCollapseable = ({ session }: { session: GenericSessionInfo }) : undefined, }, { - name: 'Target codec', + name: t('detail.transcoding.target'), value: `${session.currentlyPlaying.metadata.transcoding.videoCodec} ${session.currentlyPlaying.metadata.transcoding.audioCodec}`, }, ], @@ -97,19 +99,19 @@ export const DetailCollapseable = ({ session }: { session: GenericSessionInfo }) - ID + {t('detail.id')} {session.id} - Device + {t('detail.device')} {session.sessionName} {details.length > 0 && ( - + )} {details.map((detail, index) => ( diff --git a/src/widgets/media-server/MediaServerTile.tsx b/src/widgets/media-server/MediaServerTile.tsx index c66d2f2e7..c2257ee49 100644 --- a/src/widgets/media-server/MediaServerTile.tsx +++ b/src/widgets/media-server/MediaServerTile.tsx @@ -42,7 +42,6 @@ interface MediaServerWidgetProps { function MediaServerTile({ widget }: MediaServerWidgetProps) { const { t } = useTranslation('modules/media-server'); const { config } = useConfigContext(); - const isEditMode = useEditModeStore((x) => x.enabled); const { data, isError, isFetching, isInitialLoading } = useGetMediaServers({ enabled: config !== undefined, @@ -72,7 +71,7 @@ function MediaServerTile({ widget }: MediaServerWidgetProps) { {t('descriptor.name')} - Homarr is loading streams... + {t('descriptor.loading')} ); diff --git a/src/widgets/rss/RssWidgetTile.tsx b/src/widgets/rss/RssWidgetTile.tsx index e9c9beec1..233b04dbd 100644 --- a/src/widgets/rss/RssWidgetTile.tsx +++ b/src/widgets/rss/RssWidgetTile.tsx @@ -42,6 +42,7 @@ const definition = defineWidget({ dangerousAllowSanitizedItemContent: { type: 'switch', defaultValue: false, + info: true, }, textLinesClamp: { type: 'slider', diff --git a/src/widgets/torrent/TorrentQueueItem.tsx b/src/widgets/torrent/TorrentQueueItem.tsx index 48d73a1ee..74600ca87 100644 --- a/src/widgets/torrent/TorrentQueueItem.tsx +++ b/src/widgets/torrent/TorrentQueueItem.tsx @@ -13,7 +13,7 @@ import { createStyles, useMantineTheme, } from '@mantine/core'; -import { useDisclosure, useElementSize } from '@mantine/hooks'; +import { useDisclosure } from '@mantine/hooks'; import { IconAffiliate, IconDatabase, @@ -37,9 +37,8 @@ interface TorrentQueueItemProps { width: number; } -export const BitTorrrentQueueItem = ({ torrent, width, app }: TorrentQueueItemProps) => { +export const BitTorrentQueueItem = ({ torrent, width, app }: TorrentQueueItemProps) => { const [popoverOpened, { open: openPopover, close: closePopover }] = useDisclosure(false); - const theme = useMantineTheme(); const { classes } = useStyles(); const { t } = useTranslation('modules/torrents-status'); diff --git a/src/widgets/torrent/TorrentTile.tsx b/src/widgets/torrent/TorrentTile.tsx index d5fa11c9a..70df20529 100644 --- a/src/widgets/torrent/TorrentTile.tsx +++ b/src/widgets/torrent/TorrentTile.tsx @@ -25,7 +25,7 @@ import { AppIntegrationType } from '../../types/app'; import { useGetDownloadClientsQueue } from '../download-speed/useGetNetworkSpeed'; import { defineWidget } from '../helper'; import { IWidget } from '../widgets'; -import { BitTorrrentQueueItem } from './TorrentQueueItem'; +import { BitTorrentQueueItem } from './TorrentQueueItem'; dayjs.extend(duration); dayjs.extend(relativeTime); @@ -108,7 +108,7 @@ function TorrentTile({ widget }: TorrentTileProps) { {t('card.loading.title')} - Homarr is establishing a connection... + {t('card.loading.description')} ); @@ -156,7 +156,7 @@ function TorrentTile({ widget }: TorrentTileProps) { {filteredTorrents.map((torrent, index) => ( - + ))} {filteredTorrents.length !== torrents.length && ( diff --git a/src/widgets/useNet/UsenetQueueList.tsx b/src/widgets/useNet/UsenetQueueList.tsx index f034d818b..cf38b1aed 100644 --- a/src/widgets/useNet/UsenetQueueList.tsx +++ b/src/widgets/useNet/UsenetQueueList.tsx @@ -109,13 +109,13 @@ export const UsenetQueueList: FunctionComponent = ({ appId {nzb.state === 'paused' ? ( - + ) : ( - + diff --git a/src/widgets/weather/WeatherIcon.tsx b/src/widgets/weather/WeatherIcon.tsx index f74175867..0ee71f70c 100644 --- a/src/widgets/weather/WeatherIcon.tsx +++ b/src/widgets/weather/WeatherIcon.tsx @@ -11,7 +11,6 @@ import { IconSun, } from '@tabler/icons-react'; import { useTranslation } from 'next-i18next'; -import { useElementSize } from '@mantine/hooks'; interface WeatherIconProps { code: number; @@ -25,8 +24,7 @@ interface WeatherIconProps { */ export const WeatherIcon = ({ code, size=50 }: WeatherIconProps) => { const { t } = useTranslation('modules/weather'); - const { width, ref } = useElementSize(); - + const { icon: Icon, name } = weatherDefinitions.find((wd) => wd.codes.includes(code)) ?? unknownWeather; diff --git a/src/widgets/weather/WeatherTile.tsx b/src/widgets/weather/WeatherTile.tsx index a4443d7cd..8514bbcfc 100644 --- a/src/widgets/weather/WeatherTile.tsx +++ b/src/widgets/weather/WeatherTile.tsx @@ -4,7 +4,6 @@ import { IconArrowDownRight, IconArrowUpRight, IconCloudRain, - IconCurrentLocation, IconMapPin, } from '@tabler/icons-react'; import { api } from '~/utils/api'; @@ -12,6 +11,7 @@ import { api } from '~/utils/api'; import { defineWidget } from '../helper'; import { IWidget } from '../widgets'; import { WeatherIcon } from './WeatherIcon'; +import { useTranslation } from 'react-i18next'; const definition = defineWidget({ id: 'weather', @@ -52,6 +52,7 @@ interface WeatherTileProps { function WeatherTile({ widget }: WeatherTileProps) { const { data: weather, isLoading, isError } = api.weather.at.useQuery(widget.properties.location); const { width, ref } = useElementSize(); + const { t } = useTranslation('modules/weather'); if (isLoading) { return ( @@ -77,7 +78,7 @@ function WeatherTile({ widget }: WeatherTileProps) { if (isError) { return (
- An error occured + {t('error')}
); }