🌐 Replaced hardcoded text to use translation

This commit is contained in:
Tagaishi
2023-08-09 22:16:57 +02:00
parent ffa850b081
commit 9b2fecdfcb
24 changed files with 148 additions and 81 deletions

View File

@@ -12,7 +12,12 @@
"label": "Items" "label": "Items"
}, },
"layout": { "layout": {
"label": "Layout" "label": "Layout",
"data":{
"autoGrid": "Auto Grid",
"horizontal": "Horizontal",
"vertical": "Vertical"
}
} }
} }
}, },
@@ -21,5 +26,21 @@
"title": "Bookmark list empty", "title": "Bookmark list empty",
"text": "Add new items to this list in the edit mode" "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"
} }
} }

View File

@@ -11,13 +11,25 @@
"label": "Start the week on Sunday" "label": "Start the week on Sunday"
}, },
"radarrReleaseType": { "radarrReleaseType": {
"label": "Radarr release type" "label": "Radarr release type",
"data":{
"inCinemas": "In Cinemas",
"physicalRelease": "Physical",
"digitalRelease": "Digital"
}
}, },
"hideWeekDays": { "hideWeekDays": {
"label": "Hide week days" "label": "Hide week days"
}, },
"fontSize": { "fontSize": {
"label": "Font Size" "label": "Font Size",
"data":{
"xs": "Extra Small",
"sm": "Small",
"md": "Medium",
"lg": "Large",
"xl": "Extra Large"
}
} }
} }
} }

View File

@@ -38,7 +38,8 @@
"noUrl": { "noUrl": {
"title": "Invalid URL", "title": "Invalid URL",
"text": "Ensure that you've entered a valid address in the configuration of your widget" "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."
} }
} }
} }

View File

@@ -19,6 +19,37 @@
}, },
"tooltips": { "tooltips": {
"approve": "Approve requests", "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"
}
} }
} }

View File

@@ -5,7 +5,11 @@
"settings": { "settings": {
"title": "Media requests stats", "title": "Media requests stats",
"direction": { "direction": {
"label": "Direction of the layout." "label": "Direction of the layout.",
"data":{
"row": "Horizontal",
"column": "Vertical"
}
} }
} }
}, },

View File

@@ -6,6 +6,7 @@
"title": "Settings for media server widget" "title": "Settings for media server widget"
} }
}, },
"loading": "Homarr is loading streams...",
"card": { "card": {
"table": { "table": {
"header": { "header": {

View File

@@ -12,7 +12,8 @@
"label": "Refresh interval (in minutes)" "label": "Refresh interval (in minutes)"
}, },
"dangerousAllowSanitizedItemContent": { "dangerousAllowSanitizedItemContent": {
"label": "" "label": "Allow HTML formatting (Dangerous)",
"info": "Allowing HTML formatting from outside could be dangerous.<br/>Please make sure that the feed is from a trusted source."
}, },
"textLinesClamp": { "textLinesClamp": {
"label": "Text lines clamp" "label": "Text lines clamp"

View File

@@ -63,7 +63,8 @@
} }
}, },
"loading": { "loading": {
"title": "Loading..." "title": "Loading...",
"description": "Homarr is establishing a connection..."
}, },
"popover": { "popover": {
"introductionPrefix": "Managed by", "introductionPrefix": "Managed by",

View File

@@ -31,7 +31,8 @@
"title": "Error", "title": "Error",
"message": "An error has occurred" "message": "An error has occurred"
}, },
"paused": "Paused" "paused": "Paused",
"notImplemented": "NOT IMPLEMENTED"
}, },
"history": { "history": {
"header": { "header": {

View File

@@ -32,5 +32,6 @@
"thunderstormWithHail": "Thunderstorm with hail", "thunderstormWithHail": "Thunderstorm with hail",
"unknown": "Unknown" "unknown": "Unknown"
} }
} },
"error": "An error occured"
} }

View File

@@ -49,6 +49,6 @@ export async function getStaticProps({ req, res, locale }: GetServerSidePropsCon
const useStyles = createStyles(() => ({ const useStyles = createStyles(() => ({
image: { image: {
margin: '0 auto', margin: '0 auto',
display: 'blcok', display: 'block',
}, },
})); }));

View File

@@ -74,6 +74,7 @@ const definition = defineWidget({
}; };
}, },
itemComponent({ data, onChange, delete: deleteData }) { itemComponent({ data, onChange, delete: deleteData }) {
const { t } = useTranslation('modules/bookmark');
const form = useForm({ const form = useForm({
initialValues: data, initialValues: data,
validate: { validate: {
@@ -83,15 +84,15 @@ const definition = defineWidget({
return undefined; return undefined;
} }
return 'Length must be between 1 and 100'; return t('item.validation.length100');
}, },
href: (value) => { href: (value) => {
if (!z.string().min(1).max(200).safeParse(value).success) { 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) { if (!z.string().url().safeParse(value).success) {
return 'Not a valid link'; return t('item.validation.invalidLink');
} }
return undefined; return undefined;
@@ -101,7 +102,7 @@ const definition = defineWidget({
return undefined; return undefined;
} }
return 'Length must be between 1 and 100'; return t('item.validation.length400');
}, },
}, },
validateInputOnChange: true, validateInputOnChange: true,
@@ -122,13 +123,13 @@ const definition = defineWidget({
<TextInput <TextInput
icon={<IconTypography size="1rem" />} icon={<IconTypography size="1rem" />}
{...form.getInputProps('name')} {...form.getInputProps('name')}
label="Name" label={t('item.name')}
withAsterisk withAsterisk
/> />
<TextInput <TextInput
icon={<IconLink size="1rem" />} icon={<IconLink size="1rem" />}
{...form.getInputProps('href')} {...form.getInputProps('href')}
label="URL" label={t('item.url')}
withAsterisk withAsterisk
/> />
<IconSelector <IconSelector
@@ -140,17 +141,17 @@ const definition = defineWidget({
/> />
<Switch <Switch
{...form.getInputProps('openNewTab')} {...form.getInputProps('openNewTab')}
label="Open in new tab" label={t('item.newTab')}
checked={form.values.openNewTab} checked={form.values.openNewTab}
/> />
<Switch <Switch
{...form.getInputProps('hideHostname')} {...form.getInputProps('hideHostname')}
label="Hide Hostname" label={t('item.hideHostname')}
checked={form.values.hideHostname} checked={form.values.hideHostname}
/> />
<Switch <Switch
{...form.getInputProps('hideIcon')} {...form.getInputProps('hideIcon')}
label="Hide Icon" label={t('item.hideIcon')}
checked={form.values.hideIcon} checked={form.values.hideIcon}
/> />
<Button <Button
@@ -159,11 +160,11 @@ const definition = defineWidget({
variant="light" variant="light"
type="button" type="button"
> >
Delete {t('item.delete')}
</Button> </Button>
{!form.isValid() && ( {!form.isValid() && (
<Alert color="red" icon={<IconAlertTriangle size="1rem" />}> <Alert color="red" icon={<IconAlertTriangle size="1rem" />}>
Did not save, because there were validation errors. Please adust your inputs {t('item.validation.errorMsg')}
</Alert> </Alert>
)} )}
</Stack> </Stack>
@@ -174,18 +175,9 @@ const definition = defineWidget({
layout: { layout: {
type: 'select', type: 'select',
data: [ data: [
{ { value: 'autoGrid', },
label: 'Auto Grid', { value: 'horizontal', },
value: 'autoGrid', { value: 'vertical', },
},
{
label: 'Horizontal',
value: 'horizontal',
},
{
label: 'Vertical',
value: 'vertical',
},
], ],
defaultValue: 'autoGrid', defaultValue: 'autoGrid',
}, },
@@ -206,10 +198,10 @@ interface BookmarkWidgetTileProps {
} }
function BookmarkWidgetTile({ widget }: BookmarkWidgetTileProps) { function BookmarkWidgetTile({ widget }: BookmarkWidgetTileProps) {
const { t } = useTranslation('modules/bookmark');
const { classes } = useStyles(); const { classes } = useStyles();
const { enabled: isEditModeEnabled } = useEditModeStore(); const { enabled: isEditModeEnabled } = useEditModeStore();
const { fn, colors, colorScheme } = useMantineTheme(); const { fn, colors, colorScheme } = useMantineTheme();
const { t } = useTranslation('modules/bookmark');
if (widget.properties.items.length === 0) { if (widget.properties.items.length === 0) {
return ( return (

View File

@@ -33,20 +33,20 @@ const definition = defineWidget({
type: 'select', type: 'select',
defaultValue: 'inCinemas', defaultValue: 'inCinemas',
data: [ data: [
{ label: 'In Cinemas', value: 'inCinemas' }, { value: 'inCinemas' },
{ label: 'Physical', value: 'physicalRelease' }, { value: 'physicalRelease' },
{ label: 'Digital', value: 'digitalRelease' }, { value: 'digitalRelease' },
], ],
}, },
fontSize: { fontSize: {
type: 'select', type: 'select',
defaultValue: 'xs', defaultValue: 'xs',
data: [ data: [
{ label: 'Extra Small', value: 'xs' }, { value: 'xs' },
{ label: 'Small', value: 'sm' }, { value: 'sm' },
{ label: 'Medium', value: 'md' }, { value: 'md' },
{ label: 'Large', value: 'lg' }, { value: 'lg' },
{ label: 'Extra Large', value: 'xl' }, { value: 'xl' },
], ],
}, },
}, },

View File

@@ -121,7 +121,7 @@ function IFrameTile({ widget }: IFrameTileProps) {
title="widget iframe" title="widget iframe"
allow={allowedPermissions.join(' ')} allow={allowedPermissions.join(' ')}
> >
<Text>Your Browser does not support iframes. Please update your browser.</Text> <Text>{t('card.errors.browserSupport')}</Text>
</iframe> </iframe>
</Container> </Container>
); );

View File

@@ -58,12 +58,13 @@ const useMediaRequestDecisionMutation = () => {
utils.mediaRequest.all.invalidate(); utils.mediaRequest.all.invalidate();
}, },
}); });
const { t } = useTranslation('modules/media-requests-list');
return async (variables: MediaRequestDecisionVariables) => { return async (variables: MediaRequestDecisionVariables) => {
const action = variables.isApproved ? 'Approving' : 'Declining'; const action = variables.isApproved ? t('mutation.approving') : t('mutation.declining');
notifications.show({ notifications.show({
id: `decide-${variables.request.id}`, id: `decide-${variables.request.id}`,
color: 'yellow', color: 'yellow',
title: `${action} request...`, title: `${action} ${t('mutation.request')}`,
message: undefined, message: undefined,
loading: true, loading: true,
}); });
@@ -75,7 +76,7 @@ const useMediaRequestDecisionMutation = () => {
}, },
{ {
onSuccess(_data, variables) { 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({ notifications.update({
id: `decide-${variables.id}`, id: `decide-${variables.id}`,
color: 'teal', color: 'teal',
@@ -187,7 +188,7 @@ function MediaRequestListTile({ widget }: MediaRequestListWidgetProps) {
notifications.show({ notifications.show({
id: `approve ${item.id}`, id: `approve ${item.id}`,
color: 'yellow', color: 'yellow',
title: 'Approving request...', title: t('tooltips.approving'),
message: undefined, message: undefined,
loading: true, loading: true,
}); });

View File

@@ -16,8 +16,8 @@ const definition = defineWidget({
type: 'select', type: 'select',
defaultValue: 'row' as 'row' | 'column', defaultValue: 'row' as 'row' | 'column',
data: [ data: [
{ label: 'Horizontal', value: 'row' }, { value: 'row' },
{ label: 'Vertical', value: 'column' }, { value: 'column' },
], ],
}, },
}, },

View File

@@ -2,27 +2,29 @@ import { Card, Divider, Flex, Grid, Group, Text } from '@mantine/core';
import { IconDeviceMobile, IconId } from '@tabler/icons-react'; import { IconDeviceMobile, IconId } from '@tabler/icons-react';
import { GenericSessionInfo } from '../../types/api/media-server/session-info'; import { GenericSessionInfo } from '../../types/api/media-server/session-info';
import { useTranslation } from 'react-i18next';
export const DetailCollapseable = ({ session }: { session: GenericSessionInfo }) => { export const DetailCollapseable = ({ session }: { session: GenericSessionInfo }) => {
let details: { title: string; metrics: { name: string; value: string | undefined }[] }[] = []; let details: { title: string; metrics: { name: string; value: string | undefined }[] }[] = [];
const { t } = useTranslation('modules/media-server-list');
if (session.currentlyPlaying) { if (session.currentlyPlaying) {
if (session.currentlyPlaying.metadata.video) { if (session.currentlyPlaying.metadata.video) {
details = [ details = [
...details, ...details,
{ {
title: 'Video', title: t('detail.video.'),
metrics: [ metrics: [
{ {
name: 'Resolution', name: t('detail.video.resolution'),
value: `${session.currentlyPlaying.metadata.video.width}x${session.currentlyPlaying.metadata.video.height}`, 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, value: session.currentlyPlaying.metadata.video.videoFrameRate,
}, },
{ {
name: 'Codec', name: t('detail.video.codec'),
value: session.currentlyPlaying.metadata.video.videoCodec, value: session.currentlyPlaying.metadata.video.videoCodec,
}, },
{ {
@@ -39,14 +41,14 @@ export const DetailCollapseable = ({ session }: { session: GenericSessionInfo })
details = [ details = [
...details, ...details,
{ {
title: 'Audio', title: t('detail.audio.audio'),
metrics: [ metrics: [
{ {
name: 'Audio channels', name: t('detail.audio.channels'),
value: `${session.currentlyPlaying.metadata.audio.audioChannels}`, value: `${session.currentlyPlaying.metadata.audio.audioChannels}`,
}, },
{ {
name: 'Audio codec', name: t('detail.audio.codec'),
value: session.currentlyPlaying.metadata.audio.audioCodec, value: session.currentlyPlaying.metadata.audio.audioCodec,
}, },
], ],
@@ -58,24 +60,24 @@ export const DetailCollapseable = ({ session }: { session: GenericSessionInfo })
details = [ details = [
...details, ...details,
{ {
title: 'Transcoding', title: t('detail.transcoding.transcoding'),
metrics: [ metrics: [
{ {
name: 'Resolution', name: t('detail.video.resolution'),
value: `${session.currentlyPlaying.metadata.transcoding.width}x${session.currentlyPlaying.metadata.transcoding.height}`, 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, value: session.currentlyPlaying.metadata.transcoding.context,
}, },
{ {
name: 'Hardware encoding requested', name: t('detail.transcoding.requested'),
value: session.currentlyPlaying.metadata.transcoding.transcodeHwRequested value: session.currentlyPlaying.metadata.transcoding.transcodeHwRequested
? 'yes' ? 'yes'
: 'no', : 'no',
}, },
{ {
name: 'Source codec', name: t('detail.transcoding.source'),
value: value:
session.currentlyPlaying.metadata.transcoding.sourceAudioCodec || session.currentlyPlaying.metadata.transcoding.sourceAudioCodec ||
session.currentlyPlaying.metadata.transcoding.sourceVideoCodec session.currentlyPlaying.metadata.transcoding.sourceVideoCodec
@@ -83,7 +85,7 @@ export const DetailCollapseable = ({ session }: { session: GenericSessionInfo })
: undefined, : undefined,
}, },
{ {
name: 'Target codec', name: t('detail.transcoding.target'),
value: `${session.currentlyPlaying.metadata.transcoding.videoCodec} ${session.currentlyPlaying.metadata.transcoding.audioCodec}`, value: `${session.currentlyPlaying.metadata.transcoding.videoCodec} ${session.currentlyPlaying.metadata.transcoding.audioCodec}`,
}, },
], ],
@@ -97,19 +99,19 @@ export const DetailCollapseable = ({ session }: { session: GenericSessionInfo })
<Flex justify="space-between" mb="xs"> <Flex justify="space-between" mb="xs">
<Group> <Group>
<IconId size={16} /> <IconId size={16} />
<Text>ID</Text> <Text>{t('detail.id')}</Text>
</Group> </Group>
<Text>{session.id}</Text> <Text>{session.id}</Text>
</Flex> </Flex>
<Flex justify="space-between" mb="md"> <Flex justify="space-between" mb="md">
<Group> <Group>
<IconDeviceMobile size={16} /> <IconDeviceMobile size={16} />
<Text>Device</Text> <Text>{t('detail.device')}</Text>
</Group> </Group>
<Text>{session.sessionName}</Text> <Text>{session.sessionName}</Text>
</Flex> </Flex>
{details.length > 0 && ( {details.length > 0 && (
<Divider label="Stats for nerds" labelPosition="center" mt="lg" mb="sm" /> <Divider label={t('detail.label')} labelPosition="center" mt="lg" mb="sm" />
)} )}
<Grid> <Grid>
{details.map((detail, index) => ( {details.map((detail, index) => (

View File

@@ -42,7 +42,6 @@ interface MediaServerWidgetProps {
function MediaServerTile({ widget }: MediaServerWidgetProps) { function MediaServerTile({ widget }: MediaServerWidgetProps) {
const { t } = useTranslation('modules/media-server'); const { t } = useTranslation('modules/media-server');
const { config } = useConfigContext(); const { config } = useConfigContext();
const isEditMode = useEditModeStore((x) => x.enabled);
const { data, isError, isFetching, isInitialLoading } = useGetMediaServers({ const { data, isError, isFetching, isInitialLoading } = useGetMediaServers({
enabled: config !== undefined, enabled: config !== undefined,
@@ -72,7 +71,7 @@ function MediaServerTile({ widget }: MediaServerWidgetProps) {
<Loader /> <Loader />
<Stack align="center" spacing={0}> <Stack align="center" spacing={0}>
<Text>{t('descriptor.name')}</Text> <Text>{t('descriptor.name')}</Text>
<Text color="dimmed">Homarr is loading streams...</Text> <Text color="dimmed">{t('descriptor.loading')}</Text>
</Stack> </Stack>
</Stack> </Stack>
); );

View File

@@ -42,6 +42,7 @@ const definition = defineWidget({
dangerousAllowSanitizedItemContent: { dangerousAllowSanitizedItemContent: {
type: 'switch', type: 'switch',
defaultValue: false, defaultValue: false,
info: true,
}, },
textLinesClamp: { textLinesClamp: {
type: 'slider', type: 'slider',

View File

@@ -13,7 +13,7 @@ import {
createStyles, createStyles,
useMantineTheme, useMantineTheme,
} from '@mantine/core'; } from '@mantine/core';
import { useDisclosure, useElementSize } from '@mantine/hooks'; import { useDisclosure } from '@mantine/hooks';
import { import {
IconAffiliate, IconAffiliate,
IconDatabase, IconDatabase,
@@ -37,9 +37,8 @@ interface TorrentQueueItemProps {
width: number; 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 [popoverOpened, { open: openPopover, close: closePopover }] = useDisclosure(false);
const theme = useMantineTheme();
const { classes } = useStyles(); const { classes } = useStyles();
const { t } = useTranslation('modules/torrents-status'); const { t } = useTranslation('modules/torrents-status');

View File

@@ -25,7 +25,7 @@ import { AppIntegrationType } from '../../types/app';
import { useGetDownloadClientsQueue } from '../download-speed/useGetNetworkSpeed'; import { useGetDownloadClientsQueue } from '../download-speed/useGetNetworkSpeed';
import { defineWidget } from '../helper'; import { defineWidget } from '../helper';
import { IWidget } from '../widgets'; import { IWidget } from '../widgets';
import { BitTorrrentQueueItem } from './TorrentQueueItem'; import { BitTorrentQueueItem } from './TorrentQueueItem';
dayjs.extend(duration); dayjs.extend(duration);
dayjs.extend(relativeTime); dayjs.extend(relativeTime);
@@ -108,7 +108,7 @@ function TorrentTile({ widget }: TorrentTileProps) {
<Loader /> <Loader />
<Stack align="center" spacing={0}> <Stack align="center" spacing={0}>
<Text>{t('card.loading.title')}</Text> <Text>{t('card.loading.title')}</Text>
<Text color="dimmed">Homarr is establishing a connection...</Text> <Text color="dimmed">{t('card.loading.description')}</Text>
</Stack> </Stack>
</Stack> </Stack>
); );
@@ -156,7 +156,7 @@ function TorrentTile({ widget }: TorrentTileProps) {
</thead> </thead>
<tbody> <tbody>
{filteredTorrents.map((torrent, index) => ( {filteredTorrents.map((torrent, index) => (
<BitTorrrentQueueItem key={index} torrent={torrent} width={width} app={undefined} /> <BitTorrentQueueItem key={index} torrent={torrent} width={width} app={undefined} />
))} ))}
{filteredTorrents.length !== torrents.length && ( {filteredTorrents.length !== torrents.length && (

View File

@@ -109,13 +109,13 @@ export const UsenetQueueList: FunctionComponent<UsenetQueueListProps> = ({ appId
<tr key={nzb.id}> <tr key={nzb.id}>
<td> <td>
{nzb.state === 'paused' ? ( {nzb.state === 'paused' ? (
<Tooltip label="NOT IMPLEMENTED"> <Tooltip label={t('queue.notImplemented')}>
<ActionIcon color="gray" variant="subtle" radius="xl" size="sm"> <ActionIcon color="gray" variant="subtle" radius="xl" size="sm">
<IconPlayerPlay size="16" /> <IconPlayerPlay size="16" />
</ActionIcon> </ActionIcon>
</Tooltip> </Tooltip>
) : ( ) : (
<Tooltip label="NOT IMPLEMENTED"> <Tooltip label={t('queue.notImplemented')}>
<ActionIcon color="primary" variant="subtle" radius="xl" size="sm"> <ActionIcon color="primary" variant="subtle" radius="xl" size="sm">
<IconPlayerPause size="16" /> <IconPlayerPause size="16" />
</ActionIcon> </ActionIcon>

View File

@@ -11,7 +11,6 @@ import {
IconSun, IconSun,
} from '@tabler/icons-react'; } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { useElementSize } from '@mantine/hooks';
interface WeatherIconProps { interface WeatherIconProps {
code: number; code: number;
@@ -25,8 +24,7 @@ interface WeatherIconProps {
*/ */
export const WeatherIcon = ({ code, size=50 }: WeatherIconProps) => { export const WeatherIcon = ({ code, size=50 }: WeatherIconProps) => {
const { t } = useTranslation('modules/weather'); const { t } = useTranslation('modules/weather');
const { width, ref } = useElementSize();
const { icon: Icon, name } = const { icon: Icon, name } =
weatherDefinitions.find((wd) => wd.codes.includes(code)) ?? unknownWeather; weatherDefinitions.find((wd) => wd.codes.includes(code)) ?? unknownWeather;

View File

@@ -4,7 +4,6 @@ import {
IconArrowDownRight, IconArrowDownRight,
IconArrowUpRight, IconArrowUpRight,
IconCloudRain, IconCloudRain,
IconCurrentLocation,
IconMapPin, IconMapPin,
} from '@tabler/icons-react'; } from '@tabler/icons-react';
import { api } from '~/utils/api'; import { api } from '~/utils/api';
@@ -12,6 +11,7 @@ import { api } from '~/utils/api';
import { defineWidget } from '../helper'; import { defineWidget } from '../helper';
import { IWidget } from '../widgets'; import { IWidget } from '../widgets';
import { WeatherIcon } from './WeatherIcon'; import { WeatherIcon } from './WeatherIcon';
import { useTranslation } from 'react-i18next';
const definition = defineWidget({ const definition = defineWidget({
id: 'weather', id: 'weather',
@@ -52,6 +52,7 @@ interface WeatherTileProps {
function WeatherTile({ widget }: WeatherTileProps) { function WeatherTile({ widget }: WeatherTileProps) {
const { data: weather, isLoading, isError } = api.weather.at.useQuery(widget.properties.location); const { data: weather, isLoading, isError } = api.weather.at.useQuery(widget.properties.location);
const { width, ref } = useElementSize(); const { width, ref } = useElementSize();
const { t } = useTranslation('modules/weather');
if (isLoading) { if (isLoading) {
return ( return (
@@ -77,7 +78,7 @@ function WeatherTile({ widget }: WeatherTileProps) {
if (isError) { if (isError) {
return ( return (
<Center> <Center>
<Text weight={500}>An error occured</Text> <Text weight={500}>{t('error')}</Text>
</Center> </Center>
); );
} }