mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-10 07:25:48 +01:00
✨ i18n translation for modules
This commit is contained in:
11
public/locales/de/modules/calendar-module.json
Normal file
11
public/locales/de/modules/calendar-module.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Kalender",
|
||||
"description": "Ein Kalender Modul welches bevorstehende Shows anzeigt. Es interagiert mit der API von Sonarr, Radarr, Readarr und Lidarr.",
|
||||
"settings": {
|
||||
"sundayStart": {
|
||||
"label": "Wochenstart am Sonntag"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,8 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Ping Services",
|
||||
"description": "Pings your services and shows their status as an indicator"
|
||||
},
|
||||
"states": {
|
||||
"online": "Online {{response}}",
|
||||
"offline": "Offline {{response}}",
|
||||
|
||||
11
public/locales/en/modules/calendar-module.json
Normal file
11
public/locales/en/modules/calendar-module.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Calendar",
|
||||
"description": "A calendar module for displaying upcoming releases. It interacts with the Sonarr and Radarr API.",
|
||||
"settings": {
|
||||
"sundayStart": {
|
||||
"label": "Start the week on Sunday"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
5
public/locales/en/modules/common.json
Normal file
5
public/locales/en/modules/common.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"settings": {
|
||||
"label": "Settings"
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,32 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Dash.",
|
||||
"description": "A module for displaying the graphs of your running Dash. instance.",
|
||||
"settings": {
|
||||
"cpuMultiView": {
|
||||
"label": "CPU Multi-Core View"
|
||||
},
|
||||
"storageMultiView": {
|
||||
"label": "Storage Multi-Drive View"
|
||||
},
|
||||
"useCompactView": {
|
||||
"label": "Use Compact View"
|
||||
},
|
||||
"graphs": {
|
||||
"label": "Graphs",
|
||||
"options": {
|
||||
"cpu": "CPU",
|
||||
"ram": "RAM",
|
||||
"storage": "Storage",
|
||||
"network": "Network",
|
||||
"gpu": "GPU"
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"label": "Dash. URL"
|
||||
}
|
||||
}
|
||||
},
|
||||
"card": {
|
||||
"title": "Dash.",
|
||||
"errors": {
|
||||
|
||||
11
public/locales/en/modules/date-module.json
Normal file
11
public/locales/en/modules/date-module.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Date",
|
||||
"description": "Show the current time and date in a card",
|
||||
"settings": {
|
||||
"display24HourFormat": {
|
||||
"label": "Display full time (24-hour)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,8 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Docker",
|
||||
"description": "Allows you to easily manage your torrents"
|
||||
},
|
||||
"search": {
|
||||
"placeholder": "Search by container or image name"
|
||||
},
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Torrent",
|
||||
"description": "Show the current download speed of supported services",
|
||||
"settings": {
|
||||
"hideComplete": {
|
||||
"label": "Hide completed torrents"
|
||||
}
|
||||
}
|
||||
},
|
||||
"card": {
|
||||
"table": {
|
||||
"header": {
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Overseerr",
|
||||
"description": "Allows you to search and add media from Overseerr/Jellyseerr"
|
||||
},
|
||||
"popup": {
|
||||
"item": {
|
||||
"buttons": {
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Search Bar",
|
||||
"description": "Search bar to search the web, youtube, torrents or overseerr"
|
||||
},
|
||||
"input": {
|
||||
"placeholder": "Search the web..."
|
||||
}
|
||||
|
||||
6
public/locales/en/modules/total-downloads-module.json
Normal file
6
public/locales/en/modules/total-downloads-module.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Download Speed",
|
||||
"description": "Show the current download speed of supported services"
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,16 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Weather",
|
||||
"description": "Look up the current weather in your location",
|
||||
"settings": {
|
||||
"displayInFahrenheit": {
|
||||
"label": "Display in Fahrenheit"
|
||||
},
|
||||
"location": {
|
||||
"label": "Weather location"
|
||||
}
|
||||
}
|
||||
},
|
||||
"card": {
|
||||
"weatherDescriptions": {
|
||||
"clear": "Clear",
|
||||
|
||||
@@ -11,26 +11,31 @@ export default function ModuleEnabler(props: any) {
|
||||
<Stack>
|
||||
<Title order={4}>{t('title')}</Title>
|
||||
<SimpleGrid cols={3} spacing="xs">
|
||||
{modules.map((module) => (
|
||||
<Checkbox
|
||||
key={module.title}
|
||||
size="md"
|
||||
checked={config.modules?.[module.title]?.enabled ?? false}
|
||||
label={`${module.title}`}
|
||||
onChange={(e) => {
|
||||
setConfig({
|
||||
...config,
|
||||
modules: {
|
||||
...config.modules,
|
||||
[module.title]: {
|
||||
...config.modules?.[module.title],
|
||||
enabled: e.currentTarget.checked,
|
||||
{modules.map((module) => {
|
||||
const { t: translationModules } = useTranslation(module.translationNamespace);
|
||||
return (
|
||||
<Checkbox
|
||||
key={module.title}
|
||||
size="md"
|
||||
checked={config.modules?.[module.title]?.enabled ?? false}
|
||||
label={translationModules(module.title, {
|
||||
defaultValue: 'UNKNOWN MODULE NAME',
|
||||
})}
|
||||
onChange={(e) => {
|
||||
setConfig({
|
||||
...config,
|
||||
modules: {
|
||||
...config.modules,
|
||||
[module.title]: {
|
||||
...config.modules?.[module.title],
|
||||
enabled: e.currentTarget.checked,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
});
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</SimpleGrid>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
1
src/modules/ModuleTypes.d.ts
vendored
1
src/modules/ModuleTypes.d.ts
vendored
@@ -11,6 +11,7 @@ export interface IModule {
|
||||
icon: TablerIcon;
|
||||
component: React.ComponentType;
|
||||
options?: Option;
|
||||
translationNamespace: string;
|
||||
}
|
||||
|
||||
interface Option {
|
||||
|
||||
@@ -25,17 +25,17 @@ import { serviceItem } from '../../tools/types';
|
||||
import { useColorTheme } from '../../tools/color';
|
||||
|
||||
export const CalendarModule: IModule = {
|
||||
title: 'Calendar',
|
||||
description:
|
||||
'A calendar module for displaying upcoming releases. It interacts with the Sonarr and Radarr API.',
|
||||
title: 'descriptor.name',
|
||||
description: 'descriptor.description',
|
||||
icon: CalendarIcon,
|
||||
component: CalendarComponent,
|
||||
options: {
|
||||
sundaystart: {
|
||||
name: 'Start the week on Sunday',
|
||||
name: 'descriptor.settings.sundayStart.label',
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
translationNamespace: 'modules/calendar-module',
|
||||
};
|
||||
|
||||
export default function CalendarComponent(props: any) {
|
||||
|
||||
@@ -9,33 +9,40 @@ import { IModule } from '../ModuleTypes';
|
||||
|
||||
const asModule = <T extends IModule>(t: T) => t;
|
||||
export const DashdotModule = asModule({
|
||||
title: 'Dash.',
|
||||
description: 'A module for displaying the graphs of your running Dash. instance.',
|
||||
title: 'descriptor.name',
|
||||
description: 'descriptor.description',
|
||||
icon: CalendarIcon,
|
||||
component: DashdotComponent,
|
||||
options: {
|
||||
cpuMultiView: {
|
||||
name: 'CPU Multi-Core View',
|
||||
name: 'descriptor.settings.cpuMultiView.label',
|
||||
value: false,
|
||||
},
|
||||
storageMultiView: {
|
||||
name: 'Storage Multi-Drive View',
|
||||
name: 'descriptor.settings.storageMultiView.label',
|
||||
value: false,
|
||||
},
|
||||
useCompactView: {
|
||||
name: 'Use Compact View',
|
||||
name: 'descriptor.settings.useCompactView.label',
|
||||
value: false,
|
||||
},
|
||||
graphs: {
|
||||
name: 'Graphs',
|
||||
name: 'descriptor.settings.graphs.label',
|
||||
value: ['CPU', 'RAM', 'Storage', 'Network'],
|
||||
options: ['CPU', 'RAM', 'Storage', 'Network', 'GPU'],
|
||||
options: [
|
||||
'descriptor.settings.graphs.options.cpu',
|
||||
'descriptor.settings.graphs.options.ram',
|
||||
'descriptor.settings.graphs.options.storage',
|
||||
'descriptor.settings.graphs.options.network',
|
||||
'descriptor.settings.graphs.options.GPU',
|
||||
],
|
||||
},
|
||||
url: {
|
||||
name: 'Dash. URL',
|
||||
name: 'descriptor.settings.url.label',
|
||||
value: '',
|
||||
},
|
||||
},
|
||||
translationNamespace: 'modules/dashdot-module',
|
||||
});
|
||||
|
||||
const useStyles = createStyles((theme, _params) => ({
|
||||
|
||||
@@ -7,16 +7,17 @@ import { IModule } from '../ModuleTypes';
|
||||
import { useSetSafeInterval } from '../../tools/hooks/useSetSafeInterval';
|
||||
|
||||
export const DateModule: IModule = {
|
||||
title: 'Date',
|
||||
description: 'Show the current time and date in a card',
|
||||
title: 'descriptor.name',
|
||||
description: 'descriptor.description',
|
||||
icon: Clock,
|
||||
component: DateComponent,
|
||||
options: {
|
||||
full: {
|
||||
name: 'Display full time (24-hour)',
|
||||
name: 'descriptor.settings.display24HourFormat.label',
|
||||
value: true,
|
||||
},
|
||||
},
|
||||
translationNamespace: 'modules/date-module',
|
||||
};
|
||||
|
||||
export default function DateComponent(props: any) {
|
||||
|
||||
@@ -12,10 +12,11 @@ import { useConfig } from '../../tools/state';
|
||||
import { IModule } from '../ModuleTypes';
|
||||
|
||||
export const DockerModule: IModule = {
|
||||
title: 'Docker',
|
||||
description: 'Allows you to easily manage your torrents',
|
||||
title: 'descriptor.name',
|
||||
description: 'descriptor.description',
|
||||
icon: IconBrandDocker,
|
||||
component: DockerMenuButton,
|
||||
translationNamespace: 'modules/docker-module',
|
||||
};
|
||||
|
||||
export default function DockerMenuButton(props: any) {
|
||||
|
||||
@@ -15,24 +15,25 @@ import axios from 'axios';
|
||||
import { NormalizedTorrent } from '@ctrl/shared-torrent';
|
||||
import { useViewportSize } from '@mantine/hooks';
|
||||
import { showNotification } from '@mantine/notifications';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { IModule } from '../ModuleTypes';
|
||||
import { useConfig } from '../../tools/state';
|
||||
import { AddItemShelfButton } from '../../components/AppShelf/AddAppShelfItem';
|
||||
import { useSetSafeInterval } from '../../tools/hooks/useSetSafeInterval';
|
||||
import { humanFileSize } from '../../tools/humanFileSize';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
export const DownloadsModule: IModule = {
|
||||
title: 'Torrent',
|
||||
description: 'Show the current download speed of supported services',
|
||||
title: 'descriptor.name',
|
||||
description: 'descriptor.description',
|
||||
icon: Download,
|
||||
component: DownloadComponent,
|
||||
options: {
|
||||
hidecomplete: {
|
||||
name: 'Hide completed torrents',
|
||||
name: 'descriptor.settings.hideComplete',
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
translationNamespace: 'modules/downloads-module',
|
||||
};
|
||||
|
||||
export default function DownloadComponent() {
|
||||
|
||||
@@ -15,10 +15,11 @@ import { IModule } from '../ModuleTypes';
|
||||
import { useSetSafeInterval } from '../../tools/hooks/useSetSafeInterval';
|
||||
|
||||
export const TotalDownloadsModule: IModule = {
|
||||
title: 'Download Speed',
|
||||
description: 'Show the current download speed of supported services',
|
||||
title: 'descriptor.name',
|
||||
description: 'descriptor.description',
|
||||
icon: Download,
|
||||
component: TotalDownloadsComponent,
|
||||
translationNamespace: 'modules/total-downloads-module',
|
||||
};
|
||||
|
||||
interface torrentHistory {
|
||||
|
||||
@@ -11,12 +11,15 @@ import {
|
||||
} from '@mantine/core';
|
||||
import { IconAdjustments } from '@tabler/icons';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useState } from 'react';
|
||||
import { useConfig } from '../tools/state';
|
||||
import { IModule } from './ModuleTypes';
|
||||
|
||||
function getItems(module: IModule) {
|
||||
const { config, setConfig } = useConfig();
|
||||
const { t } = useTranslation(module.translationNamespace);
|
||||
|
||||
const items: JSX.Element[] = [];
|
||||
if (module.options) {
|
||||
const keys = Object.keys(module.options);
|
||||
@@ -130,7 +133,7 @@ function getItems(module: IModule) {
|
||||
},
|
||||
});
|
||||
}}
|
||||
label={values[index].name}
|
||||
label={t(values[index].name)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -148,6 +151,7 @@ export function ModuleWrapper(props: any) {
|
||||
const isShown = enabledModules[module.title]?.enabled ?? false;
|
||||
//TODO: fix the hover problem
|
||||
const [hovering, setHovering] = useState(false);
|
||||
const { t } = useTranslation('modules');
|
||||
|
||||
if (!isShown) {
|
||||
return null;
|
||||
@@ -186,6 +190,7 @@ export function ModuleWrapper(props: any) {
|
||||
export function ModuleMenu(props: any) {
|
||||
const { module, styles, hovered } = props;
|
||||
const items: JSX.Element[] = getItems(module);
|
||||
const { t } = useTranslation('modules/common');
|
||||
return (
|
||||
<>
|
||||
{module.options && (
|
||||
@@ -217,7 +222,7 @@ export function ModuleMenu(props: any) {
|
||||
</motion.div>
|
||||
</Menu.Target>
|
||||
<Menu.Dropdown>
|
||||
<Menu.Label>Settings</Menu.Label>
|
||||
<Menu.Label>{t('settings.label')}</Menu.Label>
|
||||
{items.map((item) => (
|
||||
<Menu.Item key={item.key}>{item}</Menu.Item>
|
||||
))}
|
||||
|
||||
@@ -3,10 +3,11 @@ import { OverseerrMediaDisplay } from '../common';
|
||||
import { IModule } from '../ModuleTypes';
|
||||
|
||||
export const OverseerrModule: IModule = {
|
||||
title: 'Overseerr',
|
||||
description: 'Allows you to search and add media from Overseerr/Jellyseerr',
|
||||
title: 'descriptor.name',
|
||||
description: 'descriptor.description',
|
||||
icon: IconEyeglass,
|
||||
component: OverseerrMediaDisplay,
|
||||
translationNamespace: 'modules/overseerr-module',
|
||||
};
|
||||
|
||||
export interface OverseerSearchProps {
|
||||
|
||||
@@ -3,15 +3,16 @@ import axios, { AxiosResponse } from 'axios';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { IconPlug as Plug } from '@tabler/icons';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useConfig } from '../../tools/state';
|
||||
import { IModule } from '../ModuleTypes';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
export const PingModule: IModule = {
|
||||
title: 'Ping Services',
|
||||
description: 'Pings your services and shows their status as an indicator',
|
||||
title: 'descriptor.name',
|
||||
description: 'descriptor.description',
|
||||
icon: Plug,
|
||||
component: PingComponent,
|
||||
translationNamespace: 'modules/ping-module',
|
||||
};
|
||||
|
||||
export default function PingComponent(props: any) {
|
||||
|
||||
@@ -27,10 +27,11 @@ const useStyles = createStyles((theme) => ({
|
||||
}));
|
||||
|
||||
export const SearchModule: IModule = {
|
||||
title: 'Search Bar',
|
||||
description: 'Search bar to search the web, youtube, torrents or overseerr',
|
||||
title: 'descriptor.name',
|
||||
description: 'descriptor.description',
|
||||
icon: Search,
|
||||
component: SearchBar,
|
||||
translationNamespace: 'modules/search-module',
|
||||
};
|
||||
|
||||
export default function SearchBar(props: any) {
|
||||
|
||||
@@ -19,20 +19,21 @@ import { IModule } from '../ModuleTypes';
|
||||
import { WeatherResponse } from './WeatherInterface';
|
||||
|
||||
export const WeatherModule: IModule = {
|
||||
title: 'Weather',
|
||||
description: 'Look up the current weather in your location',
|
||||
title: 'descriptor.name',
|
||||
description: 'descriptor.description',
|
||||
icon: Sun,
|
||||
component: WeatherComponent,
|
||||
options: {
|
||||
freedomunit: {
|
||||
name: 'Display in Fahrenheit',
|
||||
name: 'descriptor.settings.displayInFahrenheit.label',
|
||||
value: false,
|
||||
},
|
||||
location: {
|
||||
name: 'Current location',
|
||||
name: 'descriptor.settings.location.label',
|
||||
value: 'Paris',
|
||||
},
|
||||
},
|
||||
translationNamespace: 'modules/weather-module',
|
||||
};
|
||||
|
||||
// 0 Clear sky
|
||||
|
||||
@@ -45,6 +45,10 @@ export async function getServerSideProps({
|
||||
'settings/customization/shade-selector',
|
||||
'settings/customization/app-width',
|
||||
'settings/customization/opacity-selector',
|
||||
'modules/common',
|
||||
'modules/date-module',
|
||||
'modules/calendar-module',
|
||||
'modules/total-downloads-module',
|
||||
'modules/search-module',
|
||||
'modules/downloads-module',
|
||||
'modules/weather-module',
|
||||
|
||||
Reference in New Issue
Block a user