(false);
+ const { t } = useTranslation('modules/docker');
+
useEffect(() => {
setContainers(containers);
}, [containers]);
@@ -86,7 +89,9 @@ export default function DockerTable({
))}
{element.Ports.length > 3 && (
- {element.Ports.length - 3} more
+
+ {t('table.body.portCollapse', { ports: element.Ports.length - 3 })}
+
)}
@@ -95,7 +100,7 @@ export default function DockerTable({
-
+
setOpened(false)}
- title="Add service"
+ title={t('actionBar.addService.title')}
>
}
value={search}
@@ -149,11 +154,11 @@ export default function DockerTable({
disabled={usedContainers.length === 0}
/>
- | Name |
- Image |
- Ports |
- State |
- Action |
+ {t('table.header.name')} |
+ {t('table.header.image')} |
+ {t('table.header.ports')} |
+ {t('table.header.state')} |
+ {t('table.header.action')} |
{rows}
diff --git a/src/modules/downloads/DownloadsModule.tsx b/src/modules/downloads/DownloadsModule.tsx
index d81de9123..51afc5301 100644
--- a/src/modules/downloads/DownloadsModule.tsx
+++ b/src/modules/downloads/DownloadsModule.tsx
@@ -8,6 +8,7 @@ import {
Skeleton,
ScrollArea,
Center,
+ Stack,
} from '@mantine/core';
import { IconDownload as Download } from '@tabler/icons';
import { useEffect, useState } from 'react';
@@ -15,6 +16,7 @@ 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';
@@ -23,15 +25,15 @@ import { humanFileSize } from '../../tools/humanFileSize';
export const DownloadsModule: IModule = {
title: 'Torrent',
- description: 'Show the current download speed of supported services',
icon: Download,
component: DownloadComponent,
options: {
hidecomplete: {
- name: 'Hide completed torrents',
+ name: 'descriptor.settings.hideComplete',
value: false,
},
},
+ id: 'torrents-status',
};
export default function DownloadComponent() {
@@ -45,10 +47,13 @@ export default function DownloadComponent() {
service.type === 'Deluge'
) ?? [];
const hideComplete: boolean =
- (config?.modules?.[DownloadsModule.title]?.options?.hidecomplete?.value as boolean) ?? false;
+ (config?.modules?.[DownloadsModule.id]?.options?.hidecomplete?.value as boolean) ?? false;
const [torrents, setTorrents] = useState([]);
const setSafeInterval = useSetSafeInterval();
const [isLoading, setIsLoading] = useState(true);
+
+ const { t } = useTranslation(`modules/${DownloadsModule.id}`);
+
useEffect(() => {
setIsLoading(true);
if (downloadServices.length === 0) return;
@@ -81,13 +86,13 @@ export default function DownloadComponent() {
if (downloadServices.length === 0) {
return (
-
- No supported download clients found!
+
+ {t('card.errors.noDownloadClients.title')}
- Add a download service to view your current downloads
+ {t('card.errors.noDownloadClients.text')}
-
+
);
}
@@ -105,12 +110,12 @@ export default function DownloadComponent() {
const DEVICE_WIDTH = 576;
const ths = (
- | Name |
- Size |
- {width > 576 ? Down | : ''}
- {width > 576 ? Up | : ''}
- ETA |
- Progress |
+ {t('card.table.header.name')} |
+ {t('card.table.header.size')} |
+ {width > 576 ? {t('card.table.header.download')} | : ''}
+ {width > 576 ? {t('card.table.header.upload')} | : ''}
+ {t('card.table.header.estimatedTimeOfArrival')} |
+ {t('card.table.header.progress')} |
);
// Convert Seconds to readable format.
@@ -195,7 +200,7 @@ export default function DownloadComponent() {
) : (
- No torrents found
+ {t('card.table.body.nothingFound')}
)}
diff --git a/src/modules/downloads/TotalDownloadsModule.tsx b/src/modules/downloads/TotalDownloadsModule.tsx
index ccf7de7b3..0addfd712 100644
--- a/src/modules/downloads/TotalDownloadsModule.tsx
+++ b/src/modules/downloads/TotalDownloadsModule.tsx
@@ -4,6 +4,7 @@ import { useEffect, useState } from 'react';
import axios from 'axios';
import { NormalizedTorrent } from '@ctrl/shared-torrent';
import { linearGradientDef } from '@nivo/core';
+import { useTranslation } from 'next-i18next';
import { Datum, ResponsiveLine } from '@nivo/line';
import { useListState } from '@mantine/hooks';
import { showNotification } from '@mantine/notifications';
@@ -15,9 +16,9 @@ import { useSetSafeInterval } from '../../tools/hooks/useSetSafeInterval';
export const TotalDownloadsModule: IModule = {
title: 'Download Speed',
- description: 'Show the current download speed of supported services',
icon: Download,
component: TotalDownloadsComponent,
+ id: 'dlspeed',
};
interface torrentHistory {
@@ -36,6 +37,7 @@ export default function TotalDownloadsComponent() {
service.type === 'Transmission' ||
service.type === 'Deluge'
) ?? [];
+ const { t } = useTranslation(`modules/${TotalDownloadsModule.id}`);
const [torrentHistory, torrentHistoryHandlers] = useListState([]);
const [torrents, setTorrents] = useState([]);
@@ -80,14 +82,14 @@ export default function TotalDownloadsComponent() {
if (downloadServices.length === 0) {
return (
- No supported download clients found!
+ {t('card.errors.noDownloadClients.title')}
- Add a download service to view your current downloads
+ {t('card.errors.noDownloadClients.text')}
);
@@ -107,15 +109,19 @@ export default function TotalDownloadsComponent() {
return (
- Current download speed
+ {t('card.lineChart.title')}
- Download: {humanFileSize(totalDownloadSpeed)}/s
+
+ {t('card.lineChart.totalDownload', { download: humanFileSize(totalDownloadSpeed) })}
+
- Upload: {humanFileSize(totalUploadSpeed)}/s
+
+ {t('card.lineChart.totalUpload', { upload: humanFileSize(totalUploadSpeed) })}
+
- {roundedSeconds} seconds ago
+ {t('card.lineChart.timeSpan', { seconds: roundedSeconds })}
- Download: {humanFileSize(Download)}
+
+ {t('card.lineChart.download', { download: humanFileSize(Download) })}
+
- Upload: {humanFileSize(Upload)}
+
+ {t('card.lineChart.upload', { upload: humanFileSize(Upload) })}
+
diff --git a/src/modules/moduleWrapper.tsx b/src/modules/moduleWrapper.tsx
index 90e958f91..bebb928a1 100644
--- a/src/modules/moduleWrapper.tsx
+++ b/src/modules/moduleWrapper.tsx
@@ -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.id, 'common']);
+
const items: JSX.Element[] = [];
if (module.options) {
const keys = Object.keys(module.options);
@@ -25,8 +28,8 @@ function getItems(module: IModule) {
const types = values.map((v) => typeof v.value);
// Loop over all the types with a for each loop
types.forEach((type, index) => {
- const optionName = `${module.title}.${keys[index]}`;
- const moduleInConfig = config.modules?.[module.title];
+ const optionName = `${module.id}.${keys[index]}`;
+ const moduleInConfig = config.modules?.[module.id];
if (type === 'object') {
items.push(
{}}
/>
-
+
);
@@ -117,12 +120,12 @@ function getItems(module: IModule) {
...config,
modules: {
...config.modules,
- [module.title]: {
- ...config.modules[module.title],
+ [module.id]: {
+ ...config.modules[module.id],
options: {
- ...config.modules[module.title].options,
+ ...config.modules[module.id].options,
[keys[index]]: {
- ...config.modules[module.title].options?.[keys[index]],
+ ...config.modules[module.id].options?.[keys[index]],
value: e.currentTarget.checked,
},
},
@@ -130,7 +133,7 @@ function getItems(module: IModule) {
},
});
}}
- label={values[index].name}
+ label={t(values[index].name)}
/>
);
}
@@ -145,9 +148,10 @@ export function ModuleWrapper(props: any) {
const { config, setConfig } = useConfig();
const enabledModules = config.modules ?? {};
// Remove 'Module' from enabled modules titles
- const isShown = enabledModules[module.title]?.enabled ?? false;
+ const isShown = enabledModules[module.id]?.enabled ?? false;
//TODO: fix the hover problem
const [hovering, setHovering] = useState(false);
+ const { t } = useTranslation('modules');
if (!isShown) {
return null;
@@ -156,7 +160,7 @@ export function ModuleWrapper(props: any) {
return (
{module.options && (
|