i18n translation for modules

This commit is contained in:
Manuel Ruwe
2022-08-24 19:51:54 +02:00
parent 14924e4562
commit 4e7d3edb5f
26 changed files with 194 additions and 55 deletions

View 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"
}
}
}
}

View File

@@ -1,4 +1,8 @@
{ {
"descriptor": {
"name": "Ping Services",
"description": "Pings your services and shows their status as an indicator"
},
"states": { "states": {
"online": "Online {{response}}", "online": "Online {{response}}",
"offline": "Offline {{response}}", "offline": "Offline {{response}}",

View 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"
}
}
}
}

View File

@@ -0,0 +1,5 @@
{
"settings": {
"label": "Settings"
}
}

View File

@@ -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": { "card": {
"title": "Dash.", "title": "Dash.",
"errors": { "errors": {

View 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)"
}
}
}
}

View File

@@ -1,4 +1,8 @@
{ {
"descriptor": {
"name": "Docker",
"description": "Allows you to easily manage your torrents"
},
"search": { "search": {
"placeholder": "Search by container or image name" "placeholder": "Search by container or image name"
}, },

View File

@@ -1,4 +1,13 @@
{ {
"descriptor": {
"name": "Torrent",
"description": "Show the current download speed of supported services",
"settings": {
"hideComplete": {
"label": "Hide completed torrents"
}
}
},
"card": { "card": {
"table": { "table": {
"header": { "header": {

View File

@@ -1,4 +1,8 @@
{ {
"descriptor": {
"name": "Overseerr",
"description": "Allows you to search and add media from Overseerr/Jellyseerr"
},
"popup": { "popup": {
"item": { "item": {
"buttons": { "buttons": {

View File

@@ -1,4 +1,8 @@
{ {
"descriptor": {
"name": "Search Bar",
"description": "Search bar to search the web, youtube, torrents or overseerr"
},
"input": { "input": {
"placeholder": "Search the web..." "placeholder": "Search the web..."
} }

View File

@@ -0,0 +1,6 @@
{
"descriptor": {
"name": "Download Speed",
"description": "Show the current download speed of supported services"
}
}

View File

@@ -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": { "card": {
"weatherDescriptions": { "weatherDescriptions": {
"clear": "Clear", "clear": "Clear",

View File

@@ -11,26 +11,31 @@ export default function ModuleEnabler(props: any) {
<Stack> <Stack>
<Title order={4}>{t('title')}</Title> <Title order={4}>{t('title')}</Title>
<SimpleGrid cols={3} spacing="xs"> <SimpleGrid cols={3} spacing="xs">
{modules.map((module) => ( {modules.map((module) => {
<Checkbox const { t: translationModules } = useTranslation(module.translationNamespace);
key={module.title} return (
size="md" <Checkbox
checked={config.modules?.[module.title]?.enabled ?? false} key={module.title}
label={`${module.title}`} size="md"
onChange={(e) => { checked={config.modules?.[module.title]?.enabled ?? false}
setConfig({ label={translationModules(module.title, {
...config, defaultValue: 'UNKNOWN MODULE NAME',
modules: { })}
...config.modules, onChange={(e) => {
[module.title]: { setConfig({
...config.modules?.[module.title], ...config,
enabled: e.currentTarget.checked, modules: {
...config.modules,
[module.title]: {
...config.modules?.[module.title],
enabled: e.currentTarget.checked,
},
}, },
}, });
}); }}
}} />
/> );
))} })}
</SimpleGrid> </SimpleGrid>
</Stack> </Stack>
); );

View File

@@ -11,6 +11,7 @@ export interface IModule {
icon: TablerIcon; icon: TablerIcon;
component: React.ComponentType; component: React.ComponentType;
options?: Option; options?: Option;
translationNamespace: string;
} }
interface Option { interface Option {

View File

@@ -25,17 +25,17 @@ import { serviceItem } from '../../tools/types';
import { useColorTheme } from '../../tools/color'; import { useColorTheme } from '../../tools/color';
export const CalendarModule: IModule = { export const CalendarModule: IModule = {
title: 'Calendar', title: 'descriptor.name',
description: description: 'descriptor.description',
'A calendar module for displaying upcoming releases. It interacts with the Sonarr and Radarr API.',
icon: CalendarIcon, icon: CalendarIcon,
component: CalendarComponent, component: CalendarComponent,
options: { options: {
sundaystart: { sundaystart: {
name: 'Start the week on Sunday', name: 'descriptor.settings.sundayStart.label',
value: false, value: false,
}, },
}, },
translationNamespace: 'modules/calendar-module',
}; };
export default function CalendarComponent(props: any) { export default function CalendarComponent(props: any) {

View File

@@ -9,33 +9,40 @@ import { IModule } from '../ModuleTypes';
const asModule = <T extends IModule>(t: T) => t; const asModule = <T extends IModule>(t: T) => t;
export const DashdotModule = asModule({ export const DashdotModule = asModule({
title: 'Dash.', title: 'descriptor.name',
description: 'A module for displaying the graphs of your running Dash. instance.', description: 'descriptor.description',
icon: CalendarIcon, icon: CalendarIcon,
component: DashdotComponent, component: DashdotComponent,
options: { options: {
cpuMultiView: { cpuMultiView: {
name: 'CPU Multi-Core View', name: 'descriptor.settings.cpuMultiView.label',
value: false, value: false,
}, },
storageMultiView: { storageMultiView: {
name: 'Storage Multi-Drive View', name: 'descriptor.settings.storageMultiView.label',
value: false, value: false,
}, },
useCompactView: { useCompactView: {
name: 'Use Compact View', name: 'descriptor.settings.useCompactView.label',
value: false, value: false,
}, },
graphs: { graphs: {
name: 'Graphs', name: 'descriptor.settings.graphs.label',
value: ['CPU', 'RAM', 'Storage', 'Network'], 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: { url: {
name: 'Dash. URL', name: 'descriptor.settings.url.label',
value: '', value: '',
}, },
}, },
translationNamespace: 'modules/dashdot-module',
}); });
const useStyles = createStyles((theme, _params) => ({ const useStyles = createStyles((theme, _params) => ({

View File

@@ -7,16 +7,17 @@ import { IModule } from '../ModuleTypes';
import { useSetSafeInterval } from '../../tools/hooks/useSetSafeInterval'; import { useSetSafeInterval } from '../../tools/hooks/useSetSafeInterval';
export const DateModule: IModule = { export const DateModule: IModule = {
title: 'Date', title: 'descriptor.name',
description: 'Show the current time and date in a card', description: 'descriptor.description',
icon: Clock, icon: Clock,
component: DateComponent, component: DateComponent,
options: { options: {
full: { full: {
name: 'Display full time (24-hour)', name: 'descriptor.settings.display24HourFormat.label',
value: true, value: true,
}, },
}, },
translationNamespace: 'modules/date-module',
}; };
export default function DateComponent(props: any) { export default function DateComponent(props: any) {

View File

@@ -12,10 +12,11 @@ import { useConfig } from '../../tools/state';
import { IModule } from '../ModuleTypes'; import { IModule } from '../ModuleTypes';
export const DockerModule: IModule = { export const DockerModule: IModule = {
title: 'Docker', title: 'descriptor.name',
description: 'Allows you to easily manage your torrents', description: 'descriptor.description',
icon: IconBrandDocker, icon: IconBrandDocker,
component: DockerMenuButton, component: DockerMenuButton,
translationNamespace: 'modules/docker-module',
}; };
export default function DockerMenuButton(props: any) { export default function DockerMenuButton(props: any) {

View File

@@ -15,24 +15,25 @@ import axios from 'axios';
import { NormalizedTorrent } from '@ctrl/shared-torrent'; import { NormalizedTorrent } from '@ctrl/shared-torrent';
import { useViewportSize } from '@mantine/hooks'; import { useViewportSize } from '@mantine/hooks';
import { showNotification } from '@mantine/notifications'; import { showNotification } from '@mantine/notifications';
import { useTranslation } from 'next-i18next';
import { IModule } from '../ModuleTypes'; import { IModule } from '../ModuleTypes';
import { useConfig } from '../../tools/state'; import { useConfig } from '../../tools/state';
import { AddItemShelfButton } from '../../components/AppShelf/AddAppShelfItem'; import { AddItemShelfButton } from '../../components/AppShelf/AddAppShelfItem';
import { useSetSafeInterval } from '../../tools/hooks/useSetSafeInterval'; import { useSetSafeInterval } from '../../tools/hooks/useSetSafeInterval';
import { humanFileSize } from '../../tools/humanFileSize'; import { humanFileSize } from '../../tools/humanFileSize';
import { useTranslation } from 'next-i18next';
export const DownloadsModule: IModule = { export const DownloadsModule: IModule = {
title: 'Torrent', title: 'descriptor.name',
description: 'Show the current download speed of supported services', description: 'descriptor.description',
icon: Download, icon: Download,
component: DownloadComponent, component: DownloadComponent,
options: { options: {
hidecomplete: { hidecomplete: {
name: 'Hide completed torrents', name: 'descriptor.settings.hideComplete',
value: false, value: false,
}, },
}, },
translationNamespace: 'modules/downloads-module',
}; };
export default function DownloadComponent() { export default function DownloadComponent() {

View File

@@ -15,10 +15,11 @@ import { IModule } from '../ModuleTypes';
import { useSetSafeInterval } from '../../tools/hooks/useSetSafeInterval'; import { useSetSafeInterval } from '../../tools/hooks/useSetSafeInterval';
export const TotalDownloadsModule: IModule = { export const TotalDownloadsModule: IModule = {
title: 'Download Speed', title: 'descriptor.name',
description: 'Show the current download speed of supported services', description: 'descriptor.description',
icon: Download, icon: Download,
component: TotalDownloadsComponent, component: TotalDownloadsComponent,
translationNamespace: 'modules/total-downloads-module',
}; };
interface torrentHistory { interface torrentHistory {

View File

@@ -11,12 +11,15 @@ import {
} from '@mantine/core'; } from '@mantine/core';
import { IconAdjustments } from '@tabler/icons'; import { IconAdjustments } from '@tabler/icons';
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
import { useTranslation } from 'next-i18next';
import { useState } from 'react'; import { useState } from 'react';
import { useConfig } from '../tools/state'; import { useConfig } from '../tools/state';
import { IModule } from './ModuleTypes'; import { IModule } from './ModuleTypes';
function getItems(module: IModule) { function getItems(module: IModule) {
const { config, setConfig } = useConfig(); const { config, setConfig } = useConfig();
const { t } = useTranslation(module.translationNamespace);
const items: JSX.Element[] = []; const items: JSX.Element[] = [];
if (module.options) { if (module.options) {
const keys = Object.keys(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; const isShown = enabledModules[module.title]?.enabled ?? false;
//TODO: fix the hover problem //TODO: fix the hover problem
const [hovering, setHovering] = useState(false); const [hovering, setHovering] = useState(false);
const { t } = useTranslation('modules');
if (!isShown) { if (!isShown) {
return null; return null;
@@ -186,6 +190,7 @@ export function ModuleWrapper(props: any) {
export function ModuleMenu(props: any) { export function ModuleMenu(props: any) {
const { module, styles, hovered } = props; const { module, styles, hovered } = props;
const items: JSX.Element[] = getItems(module); const items: JSX.Element[] = getItems(module);
const { t } = useTranslation('modules/common');
return ( return (
<> <>
{module.options && ( {module.options && (
@@ -217,7 +222,7 @@ export function ModuleMenu(props: any) {
</motion.div> </motion.div>
</Menu.Target> </Menu.Target>
<Menu.Dropdown> <Menu.Dropdown>
<Menu.Label>Settings</Menu.Label> <Menu.Label>{t('settings.label')}</Menu.Label>
{items.map((item) => ( {items.map((item) => (
<Menu.Item key={item.key}>{item}</Menu.Item> <Menu.Item key={item.key}>{item}</Menu.Item>
))} ))}

View File

@@ -3,10 +3,11 @@ import { OverseerrMediaDisplay } from '../common';
import { IModule } from '../ModuleTypes'; import { IModule } from '../ModuleTypes';
export const OverseerrModule: IModule = { export const OverseerrModule: IModule = {
title: 'Overseerr', title: 'descriptor.name',
description: 'Allows you to search and add media from Overseerr/Jellyseerr', description: 'descriptor.description',
icon: IconEyeglass, icon: IconEyeglass,
component: OverseerrMediaDisplay, component: OverseerrMediaDisplay,
translationNamespace: 'modules/overseerr-module',
}; };
export interface OverseerSearchProps { export interface OverseerSearchProps {

View File

@@ -3,15 +3,16 @@ import axios, { AxiosResponse } from 'axios';
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { IconPlug as Plug } from '@tabler/icons'; import { IconPlug as Plug } from '@tabler/icons';
import { useTranslation } from 'next-i18next';
import { useConfig } from '../../tools/state'; import { useConfig } from '../../tools/state';
import { IModule } from '../ModuleTypes'; import { IModule } from '../ModuleTypes';
import { useTranslation } from 'next-i18next';
export const PingModule: IModule = { export const PingModule: IModule = {
title: 'Ping Services', title: 'descriptor.name',
description: 'Pings your services and shows their status as an indicator', description: 'descriptor.description',
icon: Plug, icon: Plug,
component: PingComponent, component: PingComponent,
translationNamespace: 'modules/ping-module',
}; };
export default function PingComponent(props: any) { export default function PingComponent(props: any) {

View File

@@ -27,10 +27,11 @@ const useStyles = createStyles((theme) => ({
})); }));
export const SearchModule: IModule = { export const SearchModule: IModule = {
title: 'Search Bar', title: 'descriptor.name',
description: 'Search bar to search the web, youtube, torrents or overseerr', description: 'descriptor.description',
icon: Search, icon: Search,
component: SearchBar, component: SearchBar,
translationNamespace: 'modules/search-module',
}; };
export default function SearchBar(props: any) { export default function SearchBar(props: any) {

View File

@@ -19,20 +19,21 @@ import { IModule } from '../ModuleTypes';
import { WeatherResponse } from './WeatherInterface'; import { WeatherResponse } from './WeatherInterface';
export const WeatherModule: IModule = { export const WeatherModule: IModule = {
title: 'Weather', title: 'descriptor.name',
description: 'Look up the current weather in your location', description: 'descriptor.description',
icon: Sun, icon: Sun,
component: WeatherComponent, component: WeatherComponent,
options: { options: {
freedomunit: { freedomunit: {
name: 'Display in Fahrenheit', name: 'descriptor.settings.displayInFahrenheit.label',
value: false, value: false,
}, },
location: { location: {
name: 'Current location', name: 'descriptor.settings.location.label',
value: 'Paris', value: 'Paris',
}, },
}, },
translationNamespace: 'modules/weather-module',
}; };
// 0 Clear sky // 0 Clear sky

View File

@@ -45,6 +45,10 @@ export async function getServerSideProps({
'settings/customization/shade-selector', 'settings/customization/shade-selector',
'settings/customization/app-width', 'settings/customization/app-width',
'settings/customization/opacity-selector', 'settings/customization/opacity-selector',
'modules/common',
'modules/date-module',
'modules/calendar-module',
'modules/total-downloads-module',
'modules/search-module', 'modules/search-module',
'modules/downloads-module', 'modules/downloads-module',
'modules/weather-module', 'modules/weather-module',