From 0cf0802a2f9273cbf7c634825a79acc730382e2b Mon Sep 17 00:00:00 2001 From: nikk gitanes Date: Fri, 4 Jun 2021 19:32:37 +0300 Subject: [PATCH 01/19] add RU locale --- web/package.json | 4 ++ web/public/index.html | 2 +- web/src/App/Sidebar.jsx | 13 +++-- web/src/components/About.jsx | 20 ++++--- web/src/components/Add/index.jsx | 7 ++- web/src/components/Donate/DonateDialog.jsx | 5 +- web/src/components/RemoveAll.jsx | 14 +++-- web/src/components/Settings.jsx | 67 +++++++++++----------- web/src/components/TorrentCard/index.jsx | 23 ++++---- web/src/components/Upload.jsx | 8 ++- web/src/index.jsx | 32 ++++++++++- web/src/locales/en/translation.json | 52 +++++++++++++++++ web/src/locales/ru/translation.json | 52 +++++++++++++++++ 13 files changed, 228 insertions(+), 71 deletions(-) create mode 100644 web/src/locales/en/translation.json create mode 100644 web/src/locales/ru/translation.json diff --git a/web/package.json b/web/package.json index 958db46..70e37dd 100644 --- a/web/package.json +++ b/web/package.json @@ -8,6 +8,9 @@ "axios": "^0.21.1", "clsx": "^1.1.1", "fontsource-roboto": "^4.0.0", + "i18next": "^20.3.1", + "i18next-browser-languagedetector": "^6.1.1", + "i18next-xhr-backend": "^3.2.2", "konva": "^8.0.1", "lodash": "^4.17.21", "material-ui-image": "^3.3.2", @@ -16,6 +19,7 @@ "react-copy-to-clipboard": "^5.0.3", "react-div-100vh": "^0.6.0", "react-dom": "^17.0.2", + "react-i18next": "^11.10.0", "react-konva": "^17.0.2-4", "react-measure": "^2.5.2", "react-scripts": "4.0.3", diff --git a/web/public/index.html b/web/public/index.html index 1fe47d0..41b4208 100644 --- a/web/public/index.html +++ b/web/public/index.html @@ -2,7 +2,7 @@ - + diff --git a/web/src/App/Sidebar.jsx b/web/src/App/Sidebar.jsx index 5d6edac..1d792e0 100644 --- a/web/src/App/Sidebar.jsx +++ b/web/src/App/Sidebar.jsx @@ -14,21 +14,24 @@ import { PowerSettingsNew as PowerSettingsNewIcon, } from '@material-ui/icons' import List from '@material-ui/core/List' +import { useTranslation } from 'react-i18next' import { AppSidebarStyle } from './style' export default function Sidebar({ isDrawerOpen, setIsDonationDialogOpen }) { + // eslint-disable-next-line no-unused-vars + const { t, i18n } = useTranslation('translations') return ( - + - + @@ -37,11 +40,11 @@ export default function Sidebar({ isDrawerOpen, setIsDonationDialogOpen }) { - fetch(shutdownHost())}> + fetch(shutdownHost())}> - + @@ -52,7 +55,7 @@ export default function Sidebar({ isDrawerOpen, setIsDonationDialogOpen }) { - + diff --git a/web/src/components/About.jsx b/web/src/components/About.jsx index a241eee..cfc5894 100644 --- a/web/src/components/About.jsx +++ b/web/src/components/About.jsx @@ -8,36 +8,38 @@ import InfoIcon from '@material-ui/icons/Info' import ListItem from '@material-ui/core/ListItem' import ListItemIcon from '@material-ui/core/ListItemIcon' import ListItemText from '@material-ui/core/ListItemText' +import { useTranslation } from 'react-i18next' export default function AboutDialog() { const [open, setOpen] = useState(false) - + // eslint-disable-next-line no-unused-vars + const { t, i18n } = useTranslation('translations') return (
setOpen(true)}> - + setOpen(false)} aria-labelledby='form-dialog-title' fullWidth maxWidth='lg'> - About + {t('About')}
-

Thanks to everyone who tested and helped.

+

{t('ThanksToEveryone')}


-

Special thanks:

- Anacrolix Matt Joiner github.com/anacrolix +

{t('SpecialThanks')}

+ anacrolix Matt Joiner github.com/anacrolix
- tsynik nikk Никита github.com/tsynik + nikk github.com/tsynik
dancheskus github.com/dancheskus
- Tw1cker Руслан Пахнев github.com/Nemiroff + tw1cker Руслан Пахнев github.com/Nemiroff
SpAwN_LMG
@@ -46,7 +48,7 @@ export default function AboutDialog() {
diff --git a/web/src/components/Add/index.jsx b/web/src/components/Add/index.jsx index b798785..7e27629 100644 --- a/web/src/components/Add/index.jsx +++ b/web/src/components/Add/index.jsx @@ -3,22 +3,23 @@ import ListItemIcon from '@material-ui/core/ListItemIcon' import LibraryAddIcon from '@material-ui/icons/LibraryAdd' import ListItemText from '@material-ui/core/ListItemText' import ListItem from '@material-ui/core/ListItem' +import { useTranslation } from 'react-i18next' import AddDialog from './AddDialog' export default function AddDialogButton() { const [isDialogOpen, setIsDialogOpen] = useState(false) - const handleClickOpen = () => setIsDialogOpen(true) const handleClose = () => setIsDialogOpen(false) - + // eslint-disable-next-line no-unused-vars + const { t, i18n } = useTranslation('translations') return (
- + {isDialogOpen && } diff --git a/web/src/components/Donate/DonateDialog.jsx b/web/src/components/Donate/DonateDialog.jsx index 40a0b75..5d0a113 100644 --- a/web/src/components/Donate/DonateDialog.jsx +++ b/web/src/components/Donate/DonateDialog.jsx @@ -6,14 +6,17 @@ import DialogActions from '@material-ui/core/DialogActions' import List from '@material-ui/core/List' import ButtonGroup from '@material-ui/core/ButtonGroup' import Button from '@material-ui/core/Button' +import { useTranslation } from 'react-i18next' const donateFrame = '' export default function DonateDialog({ onClose }) { + // eslint-disable-next-line no-unused-vars + const { t, i18n } = useTranslation('translations') return ( - Donate + {t('Donate')} diff --git a/web/src/components/RemoveAll.jsx b/web/src/components/RemoveAll.jsx index aac5c0f..53705fe 100644 --- a/web/src/components/RemoveAll.jsx +++ b/web/src/components/RemoveAll.jsx @@ -5,6 +5,7 @@ import ListItemText from '@material-ui/core/ListItemText' import DeleteIcon from '@material-ui/icons/Delete' import { useState } from 'react' import { torrentsHost } from 'utils/Hosts' +import { useTranslation } from 'react-i18next' const fnRemoveAll = () => { fetch(torrentsHost(), { @@ -34,22 +35,23 @@ export default function RemoveAll() { const [open, setOpen] = useState(false) const closeDialog = () => setOpen(false) const openDialog = () => setOpen(true) - + // eslint-disable-next-line no-unused-vars + const { t, i18n } = useTranslation('translations') return ( <> - + - + - Delete Torrent? + {t('DeleteTorrents?')} diff --git a/web/src/components/Settings.jsx b/web/src/components/Settings.jsx index b670c69..c6af72e 100644 --- a/web/src/components/Settings.jsx +++ b/web/src/components/Settings.jsx @@ -12,6 +12,7 @@ import Button from '@material-ui/core/Button' import { FormControlLabel, InputLabel, Select, Switch } from '@material-ui/core' import { settingsHost, setTorrServerHost, getTorrServerHost } from 'utils/Hosts' import axios from 'axios' +import { useTranslation } from 'react-i18next' export default function SettingsDialog() { const [open, setOpen] = useState(false) @@ -27,6 +28,8 @@ export default function SettingsDialog() { sets.CacheSize *= 1024 * 1024 axios.post(settingsHost(), { action: 'set', sets }) } + // eslint-disable-next-line no-unused-vars + const { t, i18n } = useTranslation('translations') useEffect(() => { axios @@ -82,21 +85,21 @@ export default function SettingsDialog() { return (
- + - + - Settings + {t('Settings')} } - label='Preload buffer' + label={t('PreloadBuffer')} />

- Retracker mode + {t('RetrackersMode')} } - label='Enable IPv6' + label={t('EnableIPv6')} />
} - label='Force encrypt' + label={t('ForceEncrypt')} />
} - label='Disable TCP' + label={t('DisableTCP')} />
} - label='Disable UTP' + label={t('DisableUTP')} />
} - label='Disable UPNP' + label={t('DisableUPNP')} />
} - label='Disable DHT' + label={t('DisableDHT')} />
} - label='Disable PEX' + label={t('DisablePEX')} />
} - label='Disable upload' + label={t('DisableUpload')} />
} - label='Use disk' + label={t('UseDisk')} />
} - label='Remove cache from disk on drop torrent' + label={t('RemoveCacheOnDrop')} />
- If disabled, remove cache on delete torrent + {t('RemoveCacheOnDropDesc')}
diff --git a/web/src/components/TorrentCard/index.jsx b/web/src/components/TorrentCard/index.jsx index d8c94f1..0580d88 100644 --- a/web/src/components/TorrentCard/index.jsx +++ b/web/src/components/TorrentCard/index.jsx @@ -10,12 +10,15 @@ import Slide from '@material-ui/core/Slide' import { Button, DialogActions, DialogTitle, useMediaQuery, useTheme } from '@material-ui/core' import axios from 'axios' import ptt from 'parse-torrent-title' +import { useTranslation } from 'react-i18next' import { StyledButton, TorrentCard, TorrentCardButtons, TorrentCardDescription, TorrentCardPoster } from './style' const Transition = forwardRef((props, ref) => ) export default function Torrent({ torrent }) { + // eslint-disable-next-line no-unused-vars + const { t, i18n } = useTranslation('translations') const [isDetailedInfoOpened, setIsDetailedInfoOpened] = useState(false) const [isDeleteTorrentOpened, setIsDeleteTorrentOpened] = useState(false) @@ -44,41 +47,41 @@ export default function Torrent({ torrent }) { - Details + {t('Details')} dropTorrent(torrent)}> - Drop + {t('Drop')} - Delete + {t('Delete')}
-
Name
+
{t('Name')}
{shortenText(parsedTitle, 100)}
-
Size
+
{t('Size')}
{torrentSize > 0 && humanizeSize(torrentSize)}
-
Speed
+
{t('Speed')}
{downloadSpeed > 0 ? humanizeSize(downloadSpeed) : '---'}
-
Peers
+
{t('Peers')}
{getPeerString(torrent) || '---'}
@@ -97,10 +100,10 @@ export default function Torrent({ torrent }) {
- Delete Torrent? + {t('DeleteTorrent?')} diff --git a/web/src/components/Upload.jsx b/web/src/components/Upload.jsx index 8b1d7ab..e1dcfdc 100644 --- a/web/src/components/Upload.jsx +++ b/web/src/components/Upload.jsx @@ -4,6 +4,7 @@ import ListItem from '@material-ui/core/ListItem' import PublishIcon from '@material-ui/icons/Publish' import { torrentUploadHost } from 'utils/Hosts' import axios from 'axios' +import { useTranslation } from 'react-i18next' export default function UploadDialog() { const handleCapture = ({ target: { files } }) => { @@ -13,18 +14,19 @@ export default function UploadDialog() { data.append('file', file) axios.post(torrentUploadHost(), data) } - + // eslint-disable-next-line no-unused-vars + const { t, i18n } = useTranslation('translations') return (
diff --git a/web/src/index.jsx b/web/src/index.jsx index 52bdd23..692b8f8 100644 --- a/web/src/index.jsx +++ b/web/src/index.jsx @@ -1,12 +1,42 @@ import { StrictMode } from 'react' import ReactDOM from 'react-dom' +import { I18nextProvider } from 'react-i18next' +import i18n from 'i18next' +import LanguageDetector from 'i18next-browser-languagedetector' +import XHR from 'i18next-xhr-backend' import './index.css' import App from './App' +import translationEng from './locales/en/translation.json' +import translationRus from './locales/ru/translation.json' + +i18n + .use(XHR) + .use(LanguageDetector) + .init({ + lng: 'ru', // default + fallbackLng: 'en', // use en if detected lng is not available + keySeparator: false, // we do not use keys in form messages.welcome + interpolation: { + escapeValue: false, // react already safes from xss + }, + resources: { + en: { + translations: translationEng, + }, + ru: { + translations: translationRus, + }, + }, + ns: ['translations'], + defaultNS: 'translations', + }) ReactDOM.render( - + + + , document.getElementById('root'), ) diff --git a/web/src/locales/en/translation.json b/web/src/locales/en/translation.json new file mode 100644 index 0000000..b788b7b --- /dev/null +++ b/web/src/locales/en/translation.json @@ -0,0 +1,52 @@ +{ + "About": "About", + "AddFromLink": "Add from Link", + "CacheSize": "Cache Size (Megabytes)", + "Cancel": "Cancel", + "Close": "Close", + "CloseServer": "Close Server", + "ConnectionsLimit": "Connections Limit", + "Delete": "Delete", + "DeleteTorrent?": "Delete Torrent?", + "DeleteTorrents?": "Delete All Torrents?", + "Details": "Details", + "DhtConnectionLimit": "DHT Connection Limit", + "DisableDHT": "Disable DHT", + "DisablePEX": "Disable PEX", + "DisableTCP": "Disable TCP", + "DisableUpload": "Disable Upload", + "DisableUPNP": "Disable UPNP", + "DisableUTP": "Disable UTP", + "Donate": "Donate", + "DownloadRateLimit": "Download Rate Limit", + "Drop": "Drop", + "EnableIPv6": "Enable IPv6", + "ForceEncrypt": "Force Encrypt Headers", + "Host": "Host", + "Name": "Name", + "OK": "OK", + "Peers": "Peers", + "PeersListenPort": "Peers Listen Port", + "PlaylistAll": "Playlist All", + "PreloadBuffer": "Preload Buffer", + "ReaderReadAHead": "Reader Read Ahead (5-100%)", + "RemoveAll": "Remove All", + "RemoveCacheOnDrop": "Remove Cache from Disk on Drop Torrent", + "RemoveCacheOnDropDesc": "If disabled, remove cache on delete torrent.", + "RetrackersMode": "Retrackers Mode", + "DontAddRetrackers": "Don't add retrackers", + "AddRetrackers": "Add retrackers", + "RemoveRetrackers": "Remove retrackers", + "ReplaceRetrackers": "Replace retrackers", + "Save": "Save", + "Settings": "Settings", + "Size": "Size", + "SpecialThanks": "Special Thanks:", + "Speed": "Speed", + "ThanksToEveryone": "Thanks to everyone who tested and helped.", + "TorrentDisconnectTimeout": "Torrent Disconnect Timeout", + "TorrentsSavePath": "Torrents Save Path", + "UploadFile": "Upload File", + "UploadRateLimit": "Upload Rate Limit", + "UseDisk": "Use Disk" +} \ No newline at end of file diff --git a/web/src/locales/ru/translation.json b/web/src/locales/ru/translation.json new file mode 100644 index 0000000..2620d5c --- /dev/null +++ b/web/src/locales/ru/translation.json @@ -0,0 +1,52 @@ +{ + "About": "О сервере", + "AddFromLink": "Добавить", + "CacheSize": "Размер кеша (Мегабайты)", + "Cancel": "Отмена", + "Close": "Закрыть", + "CloseServer": "Выкл. сервер", + "ConnectionsLimit": "Торрент-соединения", + "Delete": "Удалить", + "DeleteTorrent?": "Удалить торрент?", + "DeleteTorrents?": "Удалить все торренты?", + "Details": "Информация", + "DhtConnectionLimit": "Лимит подключений DHT", + "DisableDHT": "Откл. DHT", + "DisablePEX": "Откл. PEX", + "DisableTCP": "Откл. TCP", + "DisableUpload": "Откл. отдачу", + "DisableUPNP": "Откл. UPNP", + "DisableUTP": "Откл. UTP", + "Donate": "Поддержка", + "DownloadRateLimit": "Ограничение скорости загрузки", + "Drop": "Отключить", + "EnableIPv6": "Вкл. IPv6", + "ForceEncrypt": "Принудительное шифрование заголовков", + "Host": "Хост", + "Name": "Имя", + "OK": "OK", + "Peers": "Подключения", + "PeersListenPort": "Порт для входящих подключений", + "PlaylistAll": "Плейлист всех", + "PreloadBuffer": "Наполнять кеш перед началом воспроизведения", + "ReaderReadAHead": "Кеш предзагрузки (5-100%, рек.95%)", + "RemoveAll": "Удалить все", + "RemoveCacheOnDrop": "Очищать кеш на диске при отключении торрента", + "RemoveCacheOnDropDesc": "Если отключено, кеш очищается при удалении торрента.", + "RetrackersMode": "Ретрекеры", + "DontAddRetrackers": "Ничего не делать", + "AddRetrackers": "Добавлять", + "RemoveRetrackers": "Удалять", + "ReplaceRetrackers": "Заменять", + "Save": "Сохранить", + "Settings": "Настройки", + "Size": "Размер", + "SpecialThanks": "Отдельное спасибо:", + "Speed": "Скорость", + "ThanksToEveryone": "Спасибо всем, кто тестировал и помогал!", + "TorrentDisconnectTimeout": "Тайм-аут отключения торрента (секунды)", + "TorrentsSavePath": "Путь хранения кеша", + "UploadFile": "Загрузить файл", + "UploadRateLimit": "Ограничение скорости отдачи", + "UseDisk": "Использовать кеш на диске" +} \ No newline at end of file From ecb2403bf6e7f26dcb2b88bab02810e90a1d5bd2 Mon Sep 17 00:00:00 2001 From: nikk gitanes Date: Sat, 5 Jun 2021 16:40:07 +0300 Subject: [PATCH 02/19] fix fresh web build --- build-all.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/build-all.sh b/build-all.sh index 4ea903f..e977862 100755 --- a/build-all.sh +++ b/build-all.sh @@ -34,6 +34,7 @@ OUTPUT="${ROOT}/dist/TorrServer" #### Build web echo "Build web" cd "${ROOT}/web" || exit 1 +npm install --silent npm run --silent build-js cp "${ROOT}/web/dest/index.html" "${ROOT}/server/web/pages/template/pages/" From aea6ac2bf6f8f474568bdfdd085ae427957be749 Mon Sep 17 00:00:00 2001 From: nikk gitanes Date: Sat, 5 Jun 2021 17:32:26 +0300 Subject: [PATCH 03/19] simplify i18n --- web/src/App/Sidebar.jsx | 2 +- web/src/components/About.jsx | 2 +- web/src/components/Add/index.jsx | 2 +- web/src/components/Donate/DonateDialog.jsx | 2 +- web/src/components/RemoveAll.jsx | 2 +- web/src/components/Settings.jsx | 2 +- web/src/components/TorrentCard/index.jsx | 2 +- web/src/components/Upload.jsx | 2 +- web/src/index.jsx | 42 +++++++++++----------- 9 files changed, 28 insertions(+), 30 deletions(-) diff --git a/web/src/App/Sidebar.jsx b/web/src/App/Sidebar.jsx index 1d792e0..577539b 100644 --- a/web/src/App/Sidebar.jsx +++ b/web/src/App/Sidebar.jsx @@ -20,7 +20,7 @@ import { AppSidebarStyle } from './style' export default function Sidebar({ isDrawerOpen, setIsDonationDialogOpen }) { // eslint-disable-next-line no-unused-vars - const { t, i18n } = useTranslation('translations') + const { t } = useTranslation() return ( diff --git a/web/src/components/About.jsx b/web/src/components/About.jsx index cfc5894..d4535a9 100644 --- a/web/src/components/About.jsx +++ b/web/src/components/About.jsx @@ -13,7 +13,7 @@ import { useTranslation } from 'react-i18next' export default function AboutDialog() { const [open, setOpen] = useState(false) // eslint-disable-next-line no-unused-vars - const { t, i18n } = useTranslation('translations') + const { t } = useTranslation() return (
setOpen(true)}> diff --git a/web/src/components/Add/index.jsx b/web/src/components/Add/index.jsx index 7e27629..e3f5eaa 100644 --- a/web/src/components/Add/index.jsx +++ b/web/src/components/Add/index.jsx @@ -12,7 +12,7 @@ export default function AddDialogButton() { const handleClickOpen = () => setIsDialogOpen(true) const handleClose = () => setIsDialogOpen(false) // eslint-disable-next-line no-unused-vars - const { t, i18n } = useTranslation('translations') + const { t } = useTranslation() return (
diff --git a/web/src/components/Donate/DonateDialog.jsx b/web/src/components/Donate/DonateDialog.jsx index 5d0a113..d5cf2c9 100644 --- a/web/src/components/Donate/DonateDialog.jsx +++ b/web/src/components/Donate/DonateDialog.jsx @@ -13,7 +13,7 @@ const donateFrame = export default function DonateDialog({ onClose }) { // eslint-disable-next-line no-unused-vars - const { t, i18n } = useTranslation('translations') + const { t } = useTranslation() return ( {t('Donate')} diff --git a/web/src/components/RemoveAll.jsx b/web/src/components/RemoveAll.jsx index 53705fe..08a0445 100644 --- a/web/src/components/RemoveAll.jsx +++ b/web/src/components/RemoveAll.jsx @@ -36,7 +36,7 @@ export default function RemoveAll() { const closeDialog = () => setOpen(false) const openDialog = () => setOpen(true) // eslint-disable-next-line no-unused-vars - const { t, i18n } = useTranslation('translations') + const { t } = useTranslation() return ( <> diff --git a/web/src/components/Settings.jsx b/web/src/components/Settings.jsx index c6af72e..b6a84a0 100644 --- a/web/src/components/Settings.jsx +++ b/web/src/components/Settings.jsx @@ -29,7 +29,7 @@ export default function SettingsDialog() { axios.post(settingsHost(), { action: 'set', sets }) } // eslint-disable-next-line no-unused-vars - const { t, i18n } = useTranslation('translations') + const { t } = useTranslation() useEffect(() => { axios diff --git a/web/src/components/TorrentCard/index.jsx b/web/src/components/TorrentCard/index.jsx index 0580d88..67b88ac 100644 --- a/web/src/components/TorrentCard/index.jsx +++ b/web/src/components/TorrentCard/index.jsx @@ -18,7 +18,7 @@ const Transition = forwardRef((props, ref) => diff --git a/web/src/components/DialogTorrentDetailsContent/DialogHeader.jsx b/web/src/components/DialogTorrentDetailsContent/DialogHeader.jsx index 520ed60..e79569a 100644 --- a/web/src/components/DialogTorrentDetailsContent/DialogHeader.jsx +++ b/web/src/components/DialogTorrentDetailsContent/DialogHeader.jsx @@ -2,6 +2,7 @@ import Button from '@material-ui/core/Button' import { AppBar, IconButton, makeStyles, Toolbar, Typography } from '@material-ui/core' import CloseIcon from '@material-ui/icons/Close' import { ArrowBack } from '@material-ui/icons' +import { useTranslation } from 'react-i18next' const useStyles = makeStyles(theme => ({ appBar: { position: 'relative' }, @@ -10,6 +11,8 @@ const useStyles = makeStyles(theme => ({ export default function DialogHeader({ title, onClose, onBack }) { const classes = useStyles() + // eslint-disable-next-line no-unused-vars + const { t } = useTranslation() return ( @@ -24,7 +27,7 @@ export default function DialogHeader({ title, onClose, onBack }) { {onBack && ( )} diff --git a/web/src/components/TorrentList.jsx b/web/src/components/TorrentList.jsx index c75c9d2..0639375 100644 --- a/web/src/components/TorrentList.jsx +++ b/web/src/components/TorrentList.jsx @@ -5,12 +5,15 @@ import TorrentCard from 'components/TorrentCard' import axios from 'axios' import CircularProgress from '@material-ui/core/CircularProgress' import { TorrentListWrapper, CenteredGrid } from 'App/style' +import { useTranslation } from 'react-i18next' export default function TorrentList() { const [torrents, setTorrents] = useState([]) const [isLoading, setIsLoading] = useState(true) const [isOffline, setIsOffline] = useState(true) const timerID = useRef(-1) + // eslint-disable-next-line no-unused-vars + const { t } = useTranslation() useEffect(() => { timerID.current = setInterval(() => { @@ -39,9 +42,9 @@ export default function TorrentList() { {isLoading ? ( ) : isOffline ? ( - Offline + {t('Offline')} ) : ( - !torrents.length && No torrents added + !torrents.length && {t('NoTorrentsAdded')} )} ) diff --git a/web/src/locales/en/translation.json b/web/src/locales/en/translation.json index 594a538..fe7e4c1 100644 --- a/web/src/locales/en/translation.json +++ b/web/src/locales/en/translation.json @@ -1,6 +1,8 @@ { "About": "About", + "Add": "Add", "AddFromLink": "Add from Link", + "AddMagnetOrLink": "Add magnet or link to torrent file", "AddRetrackers": "Add retrackers", "Buffer": "Buffer", "CacheSize": "Cache Size (Megabytes)", @@ -30,12 +32,16 @@ "Host": "Host", "Info": "Info", "LatestFilePlayed": "Latest file played:", + "MagnetOrTorrentFileLink": "Magnet or torrent file link", "Name": "Name", + "NoTorrentsAdded": "No torrents added", + "Offline": "Offline", "OK": "OK", "Peers": "Peers", "PeersListenPort": "Peers Listen Port", "PEX": "PEX (Peer Exchange)", "PlaylistAll": "Playlist All", + "Poster": "Poster", "PreloadBuffer": "Preload Buffer", "ReaderReadAHead": "Reader Read Ahead (5-100%)", "RemoveAll": "Remove All", @@ -54,6 +60,7 @@ "Speed": "Speed", "TCP": "TCP (Transmission Control Protocol)", "ThanksToEveryone": "Thanks to everyone who tested and helped.", + "Title": "Title", "TorrentContent": "Torrent Content", "TorrentDetails": "Torrent Details", "TorrentDisconnectTimeout": "Torrent Disconnect Timeout", diff --git a/web/src/locales/ru/translation.json b/web/src/locales/ru/translation.json index 9509739..d0c8d36 100644 --- a/web/src/locales/ru/translation.json +++ b/web/src/locales/ru/translation.json @@ -1,6 +1,8 @@ { "About": "О сервере", + "Add": "Добавить", "AddFromLink": "Добавить", + "AddMagnetOrLink": "Добавьте magnet или ссылку на торрент", "AddRetrackers": "Добавлять", "Buffer": "Буфер", "CacheSize": "Размер кеша (Мегабайты)", @@ -30,12 +32,16 @@ "Host": "Хост", "Info": "Инфо", "LatestFilePlayed": "Последний воспроизведенный файл:", + "MagnetOrTorrentFileLink": "Ссылка на файл торрента или magnet-ссылка", "Name": "Имя", + "NoTorrentsAdded": "Нет торрентов", + "Offline": "Сервер не доступен", "OK": "OK", "Peers": "Подкл./Пиры", "PeersListenPort": "Порт для входящих подключений", "PEX": "PEX (Peer Exchange)", "PlaylistAll": "Плейлист всех", + "Poster": "Постер", "PreloadBuffer": "Наполнять кеш перед началом воспроизведения", "ReaderReadAHead": "Кеш предзагрузки (5-100%, рек. 95%)", "RemoveAll": "Удалить все", @@ -54,11 +60,12 @@ "Speed": "Скорость", "TCP": "TCP (Transmission Control Protocol)", "ThanksToEveryone": "Спасибо всем, кто тестировал и помогал!", + "Title": "Название", "TorrentContent": "Содержимое торрента", "TorrentDetails": "Информация о торренте", "TorrentDisconnectTimeout": "Тайм-аут отключения торрента (секунды)", "TorrentsSavePath": "Путь хранения кеша", - "TorrentState": "Состояние", + "TorrentState": "Данные торрента", "Upload": "Отдача (не рекомендуется отключать)", "UploadFile": "Загрузить файл", "UploadRateLimit": "Ограничение скорости отдачи (Килобайты)", From b3389e033e5e998e9cbd81ec553a9f66fd179a78 Mon Sep 17 00:00:00 2001 From: nikk gitanes Date: Sun, 6 Jun 2021 00:03:53 +0300 Subject: [PATCH 09/19] sync settings with client --- web/src/components/Settings.jsx | 50 ++++++++++++++++----------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/web/src/components/Settings.jsx b/web/src/components/Settings.jsx index fa5adfa..414e46b 100644 --- a/web/src/components/Settings.jsx +++ b/web/src/components/Settings.jsx @@ -140,16 +140,6 @@ export default function SettingsDialog() { label={t('PreloadBuffer')} />
- -
} label={t('UseDisk')} @@ -199,6 +189,16 @@ export default function SettingsDialog() { label={t('ForceEncrypt')} />
+ +

+ } + label={t('DHT')} + /> +
+ +

- } - label={t('DHT')} - /> -
- -
Date: Sun, 6 Jun 2021 01:12:56 +0300 Subject: [PATCH 10/19] rework green color (beter buttons text) --- web/src/App/index.jsx | 2 +- web/src/App/style.js | 2 +- .../DialogTorrentDetailsContent/TorrentCache/colors.js | 4 ++-- web/src/components/TorrentCard/style.js | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/web/src/App/index.jsx b/web/src/App/index.jsx index ce7164a..3cfe795 100644 --- a/web/src/App/index.jsx +++ b/web/src/App/index.jsx @@ -16,7 +16,7 @@ import Sidebar from './Sidebar' const baseTheme = createMuiTheme({ overrides: { MuiCssBaseline: { '@global': { html: { WebkitFontSmoothing: 'auto' } } } }, - palette: { primary: { main: '#3fb57a' }, secondary: { main: '#FFA724' }, tonalOffset: 0.2 }, + palette: { primary: { main: '#00a572' }, secondary: { main: '#ffa724' }, tonalOffset: 0.2 }, }) export default function App() { diff --git a/web/src/App/style.js b/web/src/App/style.js index bebad80..36bb8b8 100644 --- a/web/src/App/style.js +++ b/web/src/App/style.js @@ -17,7 +17,7 @@ export const CenteredGrid = styled.div` ` export const AppHeader = styled.div` - background: #3fb57a; + background: #00a572; color: rgba(0, 0, 0, 0.87); grid-area: head; display: flex; diff --git a/web/src/components/DialogTorrentDetailsContent/TorrentCache/colors.js b/web/src/components/DialogTorrentDetailsContent/TorrentCache/colors.js index 50e3d3b..235be1d 100644 --- a/web/src/components/DialogTorrentDetailsContent/TorrentCache/colors.js +++ b/web/src/components/DialogTorrentDetailsContent/TorrentCache/colors.js @@ -1,7 +1,7 @@ export const defaultBorderColor = '#eef2f4' export const defaultBackgroundColor = '#fff' -export const completeColor = '#3fb57a' -export const progressColor = '#00d0d0' +export const completeColor = '#00a572' +export const progressColor = '#ffa724' export const activeColor = '#000' export const rangeColor = '#9a9aff' diff --git a/web/src/components/TorrentCard/style.js b/web/src/components/TorrentCard/style.js index e9da211..7695aba 100644 --- a/web/src/components/TorrentCard/style.js +++ b/web/src/components/TorrentCard/style.js @@ -8,7 +8,7 @@ export const TorrentCard = styled.div` grid-template-areas: 'poster description buttons'; gap: 10px; padding: 10px; - background: #3fb57a; + background: #00a572; box-shadow: 0px 2px 4px -1px rgb(0 0 0 / 20%), 0px 4px 5px 0px rgb(0 0 0 / 14%), 0px 1px 10px 0px rgb(0 0 0 / 12%); @media (max-width: 1260px), (max-height: 500px) { From 645c6fc4dcadb91622ca29fdba86419374288a3b Mon Sep 17 00:00:00 2001 From: nikk gitanes Date: Sun, 6 Jun 2021 02:35:05 +0300 Subject: [PATCH 11/19] translate buffer note in details --- web/src/components/DialogTorrentDetailsContent/index.jsx | 5 ++--- web/src/locales/en/translation.json | 3 ++- web/src/locales/ru/translation.json | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/web/src/components/DialogTorrentDetailsContent/index.jsx b/web/src/components/DialogTorrentDetailsContent/index.jsx index 9eec5ae..c1aaa98 100644 --- a/web/src/components/DialogTorrentDetailsContent/index.jsx +++ b/web/src/components/DialogTorrentDetailsContent/index.jsx @@ -103,6 +103,7 @@ export default function DialogTorrentDetailsContent({ closeDialog, torrent }) { }, [hash]) const bufferSize = settings?.PreloadBuffer ? Capacity : 33554432 // Default is 32mb if PreloadBuffer is false + // const bufferSize = Capacity const getTitle = value => { const torrentParsedName = value && ptt.parse(value) @@ -176,9 +177,7 @@ export default function DialogTorrentDetailsContent({ closeDialog, torrent }) { {t('Buffer')} - {!settings?.PreloadBuffer && ( - Enable "Preload Buffer" in settings to change buffer size - )} + {!settings?.PreloadBuffer && ({t('BufferNote')})} Date: Sun, 6 Jun 2021 03:39:00 +0300 Subject: [PATCH 12/19] add colors to main UI and fix donate iframe --- web/src/App/style.js | 3 ++- web/src/components/Donate/DonateDialog.jsx | 6 ++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/web/src/App/style.js b/web/src/App/style.js index 36bb8b8..436b758 100644 --- a/web/src/App/style.js +++ b/web/src/App/style.js @@ -2,6 +2,7 @@ import styled, { css } from 'styled-components' export const AppWrapper = styled.div` height: 100%; + background: #cbe8d9; display: grid; grid-template-columns: 60px 1fr; grid-template-rows: 60px 1fr; @@ -34,7 +35,7 @@ export const AppSidebarStyle = styled.div` overflow-x: hidden; transition: width 195ms cubic-bezier(0.4, 0, 0.6, 1) 0ms; border-right: 1px solid rgba(0, 0, 0, 0.12); - background: #fff; + background: #eee; white-space: nowrap; `} ` diff --git a/web/src/components/Donate/DonateDialog.jsx b/web/src/components/Donate/DonateDialog.jsx index d5cf2c9..e01b04c 100644 --- a/web/src/components/Donate/DonateDialog.jsx +++ b/web/src/components/Donate/DonateDialog.jsx @@ -9,7 +9,7 @@ import Button from '@material-ui/core/Button' import { useTranslation } from 'react-i18next' const donateFrame = - '' + '' export default function DonateDialog({ onClose }) { // eslint-disable-next-line no-unused-vars @@ -22,9 +22,7 @@ export default function DonateDialog({ onClose }) { - + From e961903eb6f9c5a5044e293d64fd226dd135a1ef Mon Sep 17 00:00:00 2001 From: nikk gitanes Date: Sun, 6 Jun 2021 03:47:16 +0300 Subject: [PATCH 13/19] Update translation.json --- web/src/locales/ru/translation.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/locales/ru/translation.json b/web/src/locales/ru/translation.json index c61fab5..145f0e7 100644 --- a/web/src/locales/ru/translation.json +++ b/web/src/locales/ru/translation.json @@ -49,7 +49,7 @@ "RemoveCacheOnDrop": "Очищать кеш на диске при отключении торрента", "RemoveCacheOnDropDesc": "Если отключено, кэш очищается при удалении торрента.", "RemoveRetrackers": "Удалять", - "RemoveViews": "Удалить отметки просмотра", + "RemoveViews": "Очистить просмотры", "ReplaceRetrackers": "Заменять", "RetrackersMode": "Ретрекеры", "Save": "Сохранить", From 651e88e34fce706ffdff69d3cb9d7f16b5ef97ae Mon Sep 17 00:00:00 2001 From: nikk gitanes Date: Sun, 6 Jun 2021 12:13:27 +0300 Subject: [PATCH 14/19] translate tables --- .../Table/index.jsx | 39 ++++++++++--------- .../DialogTorrentDetailsContent/index.jsx | 2 +- web/src/locales/en/translation.json | 8 +++- web/src/locales/ru/translation.json | 10 ++++- 4 files changed, 37 insertions(+), 22 deletions(-) diff --git a/web/src/components/DialogTorrentDetailsContent/Table/index.jsx b/web/src/components/DialogTorrentDetailsContent/Table/index.jsx index 11e56b7..e2434b0 100644 --- a/web/src/components/DialogTorrentDetailsContent/Table/index.jsx +++ b/web/src/components/DialogTorrentDetailsContent/Table/index.jsx @@ -4,6 +4,7 @@ import { humanizeSize } from 'utils/Utils' import ptt from 'parse-torrent-title' import { Button } from '@material-ui/core' import CopyToClipboard from 'react-copy-to-clipboard' +import { useTranslation } from 'react-i18next' import { TableStyle, ShortTableWrapper, ShortTable } from './style' @@ -17,6 +18,8 @@ const Table = memo( const fileHasEpisodeText = !!playableFileList?.find(({ path }) => ptt.parse(path).episode) const fileHasSeasonText = !!playableFileList?.find(({ path }) => ptt.parse(path).season) const fileHasResolutionText = !!playableFileList?.find(({ path }) => ptt.parse(path).resolution) + // eslint-disable-next-line no-unused-vars + const { t } = useTranslation() return !playableFileList?.length ? ( 'No playable files in this torrent' @@ -25,13 +28,13 @@ const Table = memo( - viewed - name - {fileHasSeasonText && seasonAmount?.length === 1 && season} - {fileHasEpisodeText && episode} - {fileHasResolutionText && resolution} - size - actions + {t('Viewed')} + {t('Name')} + {fileHasSeasonText && seasonAmount?.length === 1 && {t('Season')}} + {fileHasEpisodeText && {t('Episode')}} + {fileHasResolutionText && {t('Resolution')}} + {t('Size')} + {t('Actions')} @@ -52,18 +55,18 @@ const Table = memo( {humanizeSize(length)} @@ -87,7 +90,7 @@ const Table = memo(
{isViewed && (
-
viewed
+
{t('Viewed')}
@@ -95,41 +98,41 @@ const Table = memo( )} {fileHasSeasonText && seasonAmount?.length === 1 && (
-
season
+
{t('Season')}
{season}
)} {fileHasEpisodeText && (
-
epoisode
+
{t('Episode')}
{episode}
)} {fileHasResolutionText && (
-
resolution
+
{t('Resolution')}
{resolution}
)}
-
size
+
{t('Size')}
{humanizeSize(length)}
diff --git a/web/src/components/DialogTorrentDetailsContent/index.jsx b/web/src/components/DialogTorrentDetailsContent/index.jsx index c1aaa98..7c78ed6 100644 --- a/web/src/components/DialogTorrentDetailsContent/index.jsx +++ b/web/src/components/DialogTorrentDetailsContent/index.jsx @@ -177,7 +177,7 @@ export default function DialogTorrentDetailsContent({ closeDialog, torrent }) { {t('Buffer')} - {!settings?.PreloadBuffer && ({t('BufferNote')})} + {!settings?.PreloadBuffer && {t('BufferNote')}} Date: Sun, 6 Jun 2021 14:11:40 +0300 Subject: [PATCH 15/19] translate widgets --- .../DialogTorrentDetailsContent/widgets.jsx | 122 ++++++++++-------- web/src/locales/en/translation.json | 6 + web/src/locales/ru/translation.json | 6 + 3 files changed, 83 insertions(+), 51 deletions(-) diff --git a/web/src/components/DialogTorrentDetailsContent/widgets.jsx b/web/src/components/DialogTorrentDetailsContent/widgets.jsx index 991b0a5..f9571ff 100644 --- a/web/src/components/DialogTorrentDetailsContent/widgets.jsx +++ b/web/src/components/DialogTorrentDetailsContent/widgets.jsx @@ -8,61 +8,81 @@ import { Build as BuildIcon, } from '@material-ui/icons' import { getPeerString, humanizeSize } from 'utils/Utils' +import { useTranslation } from 'react-i18next' import StatisticsField from './StatisticsField' -export const DownlodSpeedWidget = ({ data }) => ( - -) +export const DownlodSpeedWidget = ({ data }) => { + const { t } = useTranslation() + return ( + + ) +} -export const UploadSpeedWidget = ({ data }) => ( - -) +export const UploadSpeedWidget = ({ data }) => { + const { t } = useTranslation() + return ( + + ) +} -export const PeersWidget = ({ data }) => ( - -) +export const PeersWidget = ({ data }) => { + const { t } = useTranslation() + return ( + + ) +} -export const PiecesCountWidget = ({ data }) => ( - -) -export const PiecesLengthWidget = ({ data }) => ( - -) -export const StatusWidget = ({ data }) => ( - -) +export const PiecesCountWidget = ({ data }) => { + const { t } = useTranslation() + return +} -export const SizeWidget = ({ data }) => ( - -) +export const PiecesLengthWidget = ({ data }) => { + const { t } = useTranslation() + return ( + + ) +} + +export const StatusWidget = ({ data }) => { + const { t } = useTranslation() + return +} + +export const SizeWidget = ({ data }) => { + const { t } = useTranslation() + return ( + + ) +} diff --git a/web/src/locales/en/translation.json b/web/src/locales/en/translation.json index 2e671df..30c58c4 100644 --- a/web/src/locales/en/translation.json +++ b/web/src/locales/en/translation.json @@ -25,6 +25,7 @@ "DontAddRetrackers": "Don't add retrackers", "DownloadPlaylist": "Download Playlist", "DownloadRateLimit": "Download Rate Limit (Kilobytes)", + "DownloadSpeed": "Download speed", "Drop": "Drop", "DropTorrent": "Reset Torrent", "EnableIPv6": "IPv6", @@ -44,6 +45,8 @@ "Peers": "Peers", "PeersListenPort": "Peers Listen Port", "PEX": "PEX (Peer Exchange)", + "PiecesCount": "Pieces count", + "PiecesLength": "Pieces length", "PlaylistAll": "Playlist All", "Poster": "Poster", "Preload": "Preload", @@ -70,11 +73,14 @@ "TorrentContent": "Torrent Content", "TorrentDetails": "Torrent Details", "TorrentDisconnectTimeout": "Torrent Disconnect Timeout", + "TorrentSize": "Torrent size", "TorrentsSavePath": "Torrents Save Path", "TorrentState": "Torrent State", + "TorrentStatus": "Torrent Status", "Upload": "Upload (not recommended to disable)", "UploadFile": "Upload File", "UploadRateLimit": "Upload Rate Limit (Kilobytes)", + "UploadSpeed": "Upload speed", "UPNP": "UPnP (Universal Plug and Play)", "UseDisk": "Use Disk", "UTP": "μTP (Micro Transport Protocol)", diff --git a/web/src/locales/ru/translation.json b/web/src/locales/ru/translation.json index c5e71ab..7810343 100644 --- a/web/src/locales/ru/translation.json +++ b/web/src/locales/ru/translation.json @@ -25,6 +25,7 @@ "DontAddRetrackers": "Ничего не делать", "DownloadPlaylist": "Скачать плейлист", "DownloadRateLimit": "Ограничение скорости загрузки (Килобайты)", + "DownloadSpeed": "Скорость загрузки", "Drop": "Сброс", "DropTorrent": "Сбросить торрент", "EnableIPv6": "IPv6", @@ -44,6 +45,8 @@ "Peers": "Подкл./Пиры", "PeersListenPort": "Порт для входящих подключений", "PEX": "PEX (Peer Exchange)", + "PiecesCount": "Кол-во блоков", + "PiecesLength": "Размер блока", "PlaylistAll": "Плейлист всех", "Poster": "Постер", "Preload": "Предзагр.", @@ -70,11 +73,14 @@ "TorrentContent": "Содержимое торрента", "TorrentDetails": "Информация о торренте", "TorrentDisconnectTimeout": "Тайм-аут отключения торрента (секунды)", + "TorrentSize": "Размер торрента", "TorrentsSavePath": "Путь хранения кеша", "TorrentState": "Данные торрента", + "TorrentStatus": "Состояние", "Upload": "Отдача (не рекомендуется отключать)", "UploadFile": "Загрузить файл", "UploadRateLimit": "Ограничение скорости отдачи (Килобайты)", + "UploadSpeed": "Скорость отдачи", "UPNP": "UPnP (Universal Plug and Play)", "UseDisk": "Использовать кеш на диске", "UTP": "μTP (Micro Transport Protocol)", From c03123fdc5a0cb1d7600576517ef81c2c02cfcf0 Mon Sep 17 00:00:00 2001 From: nikk gitanes Date: Sun, 6 Jun 2021 20:27:09 +0300 Subject: [PATCH 16/19] remove unneded no-unused-vars --- web/src/App/Sidebar.jsx | 1 - web/src/components/About.jsx | 3 +-- web/src/components/Add/AddDialog.jsx | 4 +--- web/src/components/Add/index.jsx | 3 +-- web/src/components/TorrentList.jsx | 3 +-- web/src/components/Upload.jsx | 3 +-- 6 files changed, 5 insertions(+), 12 deletions(-) diff --git a/web/src/App/Sidebar.jsx b/web/src/App/Sidebar.jsx index 577539b..1ecec1b 100644 --- a/web/src/App/Sidebar.jsx +++ b/web/src/App/Sidebar.jsx @@ -19,7 +19,6 @@ import { useTranslation } from 'react-i18next' import { AppSidebarStyle } from './style' export default function Sidebar({ isDrawerOpen, setIsDonationDialogOpen }) { - // eslint-disable-next-line no-unused-vars const { t } = useTranslation() return ( diff --git a/web/src/components/About.jsx b/web/src/components/About.jsx index 9327ee9..58cae8a 100644 --- a/web/src/components/About.jsx +++ b/web/src/components/About.jsx @@ -13,9 +13,8 @@ import { useTranslation } from 'react-i18next' import { echoHost } from 'utils/Hosts' export default function AboutDialog() { - const [open, setOpen] = useState(false) - // eslint-disable-next-line no-unused-vars const { t } = useTranslation() + const [open, setOpen] = useState(false) const [torrServerVersion, setTorrServerVersion] = useState('') useEffect(() => { axios.get(echoHost()).then(({ data }) => setTorrServerVersion(data)) diff --git a/web/src/components/Add/AddDialog.jsx b/web/src/components/Add/AddDialog.jsx index 174ec2d..a1dd0c2 100644 --- a/web/src/components/Add/AddDialog.jsx +++ b/web/src/components/Add/AddDialog.jsx @@ -10,6 +10,7 @@ import axios from 'axios' import { useTranslation } from 'react-i18next' export default function AddDialog({ handleClose }) { + const { t } = useTranslation() const [link, setLink] = useState('') const [title, setTitle] = useState('') const [poster, setPoster] = useState('') @@ -18,9 +19,6 @@ export default function AddDialog({ handleClose }) { const inputTitle = ({ target: { value } }) => setTitle(value) const inputPoster = ({ target: { value } }) => setPoster(value) - // eslint-disable-next-line no-unused-vars - const { t } = useTranslation() - const handleSave = () => { axios.post(torrentsHost(), { action: 'add', link, title, poster, save_to_db: true }).finally(() => handleClose()) } diff --git a/web/src/components/Add/index.jsx b/web/src/components/Add/index.jsx index e3f5eaa..5a92c86 100644 --- a/web/src/components/Add/index.jsx +++ b/web/src/components/Add/index.jsx @@ -8,11 +8,10 @@ import { useTranslation } from 'react-i18next' import AddDialog from './AddDialog' export default function AddDialogButton() { + const { t } = useTranslation() const [isDialogOpen, setIsDialogOpen] = useState(false) const handleClickOpen = () => setIsDialogOpen(true) const handleClose = () => setIsDialogOpen(false) - // eslint-disable-next-line no-unused-vars - const { t } = useTranslation() return (
diff --git a/web/src/components/TorrentList.jsx b/web/src/components/TorrentList.jsx index 0639375..4168b22 100644 --- a/web/src/components/TorrentList.jsx +++ b/web/src/components/TorrentList.jsx @@ -8,12 +8,11 @@ import { TorrentListWrapper, CenteredGrid } from 'App/style' import { useTranslation } from 'react-i18next' export default function TorrentList() { + const { t } = useTranslation() const [torrents, setTorrents] = useState([]) const [isLoading, setIsLoading] = useState(true) const [isOffline, setIsOffline] = useState(true) const timerID = useRef(-1) - // eslint-disable-next-line no-unused-vars - const { t } = useTranslation() useEffect(() => { timerID.current = setInterval(() => { diff --git a/web/src/components/Upload.jsx b/web/src/components/Upload.jsx index 14707d4..8f460d8 100644 --- a/web/src/components/Upload.jsx +++ b/web/src/components/Upload.jsx @@ -7,6 +7,7 @@ import axios from 'axios' import { useTranslation } from 'react-i18next' export default function UploadDialog() { + const { t } = useTranslation() const handleCapture = ({ target: { files } }) => { const [file] = files const data = new FormData() @@ -14,8 +15,6 @@ export default function UploadDialog() { data.append('file', file) axios.post(torrentUploadHost(), data) } - // eslint-disable-next-line no-unused-vars - const { t } = useTranslation() return (