Merge remote-tracking branch 'overseerr/develop' into develop

This commit is contained in:
notfakie
2022-09-12 19:17:01 +12:00
19 changed files with 624 additions and 192 deletions

View File

@@ -1,6 +1,7 @@
import SearchInput from '@app/components/Layout/SearchInput';
import Sidebar from '@app/components/Layout/Sidebar';
import UserDropdown from '@app/components/Layout/UserDropdown';
import PullToRefresh from '@app/components/PullToRefresh';
import type { AvailableLocale } from '@app/context/LanguageContext';
import useLocale from '@app/hooks/useLocale';
import useSettings from '@app/hooks/useSettings';
@@ -58,6 +59,7 @@ const Layout = ({ children }: LayoutProps) => {
<Sidebar open={isSidebarOpen} setClosed={() => setSidebarOpen(false)} />
<div className="relative mb-16 flex w-0 min-w-0 flex-1 flex-col lg:ml-64">
<PullToRefresh />
<div
className={`searchbar fixed left-0 right-0 top-0 z-10 flex flex-shrink-0 bg-opacity-80 transition duration-300 ${
isScrolled ? 'bg-gray-700' : 'bg-transparent'

View File

@@ -11,6 +11,7 @@ import { ServerIcon, ViewListIcon } from '@heroicons/react/outline';
import { CheckCircleIcon, DocumentRemoveIcon } from '@heroicons/react/solid';
import { IssueStatus } from '@server/constants/issue';
import { MediaRequestStatus, MediaStatus } from '@server/constants/media';
import { MediaServerType } from '@server/constants/server';
import type { MediaWatchDataResponse } from '@server/interfaces/api/mediaInterfaces';
import type { MovieDetails } from '@server/models/Movie';
import type { TvDetails } from '@server/models/Tv';

View File

@@ -0,0 +1,36 @@
import { RefreshIcon } from '@heroicons/react/outline';
import Router from 'next/router';
import PR from 'pulltorefreshjs';
import { useEffect } from 'react';
import ReactDOMServer from 'react-dom/server';
const PullToRefresh: React.FC = () => {
useEffect(() => {
PR.init({
mainElement: '#pull-to-refresh',
onRefresh() {
Router.reload();
},
iconArrow: ReactDOMServer.renderToString(
<RefreshIcon className="z-50 m-auto h-9 w-9 rounded-full border-4 border-gray-800 bg-gray-800 text-indigo-500 ring-1 ring-gray-700" />
),
iconRefreshing: ReactDOMServer.renderToString(
<RefreshIcon
className="z-50 m-auto h-9 w-9 animate-spin rounded-full border-4 border-gray-800 bg-gray-800 text-indigo-500 ring-1 ring-gray-700"
style={{ animationDirection: 'reverse' }}
/>
),
instructionsPullToRefresh: ReactDOMServer.renderToString(<div />),
instructionsReleaseToRefresh: ReactDOMServer.renderToString(<div />),
instructionsRefreshing: ReactDOMServer.renderToString(<div />),
distReload: 55,
});
return () => {
PR.destroyAll();
};
}, []);
return <div id="pull-to-refresh"></div>;
};
export default PullToRefresh;

View File

@@ -5,6 +5,7 @@ import LoadingSpinner from '@app/components/Common/LoadingSpinner';
import Modal from '@app/components/Common/Modal';
import PageTitle from '@app/components/Common/PageTitle';
import Table from '@app/components/Common/Table';
import useLocale from '@app/hooks/useLocale';
import useSettings from '@app/hooks/useSettings';
import globalMessages from '@app/i18n/globalMessages';
import { formatBytes } from '@app/utils/numberHelpers';
@@ -15,7 +16,8 @@ import { MediaServerType } from '@server/constants/server';
import type { CacheItem } from '@server/interfaces/api/settingsInterfaces';
import type { JobId } from '@server/lib/settings';
import axios from 'axios';
import { Fragment, useState } from 'react';
import cronstrue from 'cronstrue/i18n';
import { Fragment, useReducer, useState } from 'react';
import type { MessageDescriptor } from 'react-intl';
import { defineMessages, FormattedRelativeTime, useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
@@ -59,7 +61,8 @@ const messages: { [messageName: string]: MessageDescriptor } = defineMessages({
editJobSchedule: 'Modify Job',
jobScheduleEditSaved: 'Job edited successfully!',
jobScheduleEditFailed: 'Something went wrong while saving the job.',
editJobSchedulePrompt: 'Frequency',
editJobScheduleCurrent: 'Current Frequency',
editJobSchedulePrompt: 'New Frequency',
editJobScheduleSelectorHours:
'Every {jobScheduleHours, plural, one {hour} other {{jobScheduleHours} hours}}',
editJobScheduleSelectorMinutes:
@@ -71,12 +74,56 @@ interface Job {
name: string;
type: 'process' | 'command';
interval: 'short' | 'long' | 'fixed';
cronSchedule: string;
nextExecutionTime: string;
running: boolean;
}
type JobModalState = {
isOpen?: boolean;
job?: Job;
scheduleHours: number;
scheduleMinutes: number;
};
type JobModalAction =
| { type: 'set'; hours?: number; minutes?: number }
| {
type: 'close';
}
| { type: 'open'; job?: Job };
const jobModalReducer = (
state: JobModalState,
action: JobModalAction
): JobModalState => {
switch (action.type) {
case 'close':
return {
...state,
isOpen: false,
};
case 'open':
return {
isOpen: true,
job: action.job,
scheduleHours: 1,
scheduleMinutes: 5,
};
case 'set':
return {
...state,
scheduleHours: action.hours ?? state.scheduleHours,
scheduleMinutes: action.minutes ?? state.scheduleMinutes,
};
}
};
const SettingsJobs = () => {
const intl = useIntl();
const { locale } = useLocale();
const { addToast } = useToasts();
const {
data,
@@ -92,15 +139,12 @@ const SettingsJobs = () => {
}
);
const [jobEditModal, setJobEditModal] = useState<{
isOpen: boolean;
job?: Job;
}>({
const [jobModalState, dispatch] = useReducer(jobModalReducer, {
isOpen: false,
scheduleHours: 1,
scheduleMinutes: 5,
});
const [isSaving, setIsSaving] = useState(false);
const [jobScheduleMinutes, setJobScheduleMinutes] = useState(5);
const [jobScheduleHours, setJobScheduleHours] = useState(1);
const settings = useSettings();
if (!data && !error) {
@@ -151,10 +195,10 @@ const SettingsJobs = () => {
const jobScheduleCron = ['0', '0', '*', '*', '*', '*'];
try {
if (jobEditModal.job?.interval === 'short') {
jobScheduleCron[1] = `*/${jobScheduleMinutes}`;
} else if (jobEditModal.job?.interval === 'long') {
jobScheduleCron[2] = `*/${jobScheduleHours}`;
if (jobModalState.job?.interval === 'short') {
jobScheduleCron[1] = `*/${jobModalState.scheduleMinutes}`;
} else if (jobModalState.job?.interval === 'long') {
jobScheduleCron[2] = `*/${jobModalState.scheduleHours}`;
} else {
// jobs with interval: fixed should not be editable
throw new Error();
@@ -162,16 +206,18 @@ const SettingsJobs = () => {
setIsSaving(true);
await axios.post(
`/api/v1/settings/jobs/${jobEditModal.job?.id}/schedule`,
`/api/v1/settings/jobs/${jobModalState.job.id}/schedule`,
{
schedule: jobScheduleCron.join(' '),
}
);
addToast(intl.formatMessage(messages.jobScheduleEditSaved), {
appearance: 'success',
autoDismiss: true,
});
setJobEditModal({ isOpen: false });
dispatch({ type: 'close' });
revalidate();
} catch (e) {
addToast(intl.formatMessage(messages.jobScheduleEditFailed), {
@@ -199,7 +245,7 @@ const SettingsJobs = () => {
leave="opacity-100 transition duration-300"
leaveFrom="opacity-100"
leaveTo="opacity-0"
show={jobEditModal.isOpen}
show={jobModalState.isOpen}
>
<Modal
title={intl.formatMessage(messages.editJobSchedule)}
@@ -208,24 +254,43 @@ const SettingsJobs = () => {
? intl.formatMessage(globalMessages.saving)
: intl.formatMessage(globalMessages.save)
}
onCancel={() => setJobEditModal({ isOpen: false })}
onCancel={() => dispatch({ type: 'close' })}
okDisabled={isSaving}
onOk={() => scheduleJob()}
>
<div className="section">
<form>
<div className="form-row pb-6">
<form className="mb-6">
<div className="form-row">
<label className="text-label">
{intl.formatMessage(messages.editJobScheduleCurrent)}
</label>
<div className="form-input-area mt-2 mb-1">
<div>
{jobModalState.job &&
cronstrue.toString(jobModalState.job.cronSchedule, {
locale,
})}
</div>
<div className="text-sm text-gray-500">
{jobModalState.job?.cronSchedule}
</div>
</div>
</div>
<div className="form-row">
<label htmlFor="jobSchedule" className="text-label">
{intl.formatMessage(messages.editJobSchedulePrompt)}
</label>
<div className="form-input-area">
{jobEditModal.job?.interval === 'short' ? (
{jobModalState.job?.interval === 'short' ? (
<select
name="jobScheduleMinutes"
className="inline"
value={jobScheduleMinutes}
value={jobModalState.scheduleMinutes}
onChange={(e) =>
setJobScheduleMinutes(Number(e.target.value))
dispatch({
type: 'set',
minutes: Number(e.target.value),
})
}
>
{[5, 10, 15, 20, 30, 60].map((v) => (
@@ -243,9 +308,12 @@ const SettingsJobs = () => {
<select
name="jobScheduleHours"
className="inline"
value={jobScheduleHours}
value={jobModalState.scheduleHours}
onChange={(e) =>
setJobScheduleHours(Number(e.target.value))
dispatch({
type: 'set',
hours: Number(e.target.value),
})
}
>
{[1, 2, 3, 4, 6, 8, 12, 24, 48, 72].map((v) => (
@@ -324,9 +392,7 @@ const SettingsJobs = () => {
<Button
className="mr-2"
buttonType="warning"
onClick={() =>
setJobEditModal({ isOpen: true, job: job })
}
onClick={() => dispatch({ type: 'open', job })}
>
<PencilIcon />
<span>{intl.formatMessage(globalMessages.edit)}</span>

View File

@@ -5,6 +5,7 @@ import Modal from '@app/components/Common/Modal';
import PageTitle from '@app/components/Common/PageTitle';
import Table from '@app/components/Common/Table';
import Tooltip from '@app/components/Common/Tooltip';
import useDebouncedState from '@app/hooks/useDebouncedState';
import { useUpdateQueryParams } from '@app/hooks/useUpdateQueryParams';
import globalMessages from '@app/i18n/globalMessages';
import Error from '@app/pages/_error';
@@ -17,6 +18,7 @@ import {
FilterIcon,
PauseIcon,
PlayIcon,
SearchIcon,
} from '@heroicons/react/solid';
import type {
LogMessage,
@@ -59,6 +61,8 @@ const SettingsLogs = () => {
const { addToast } = useToasts();
const [currentFilter, setCurrentFilter] = useState<Filter>('debug');
const [currentPageSize, setCurrentPageSize] = useState(25);
const [searchFilter, debouncedSearchFilter, setSearchFilter] =
useDebouncedState('');
const [refreshInterval, setRefreshInterval] = useState(5000);
const [activeLog, setActiveLog] = useState<{
isOpen: boolean;
@@ -76,7 +80,9 @@ const SettingsLogs = () => {
const { data, error } = useSWR<LogsResultsResponse>(
`/api/v1/settings/logs?take=${currentPageSize}&skip=${
pageIndex * currentPageSize
}&filter=${currentFilter}`,
}&filter=${currentFilter}${
debouncedSearchFilter ? `&search=${debouncedSearchFilter}` : ''
}`,
{
refreshInterval: refreshInterval,
revalidateOnFocus: false,
@@ -118,15 +124,13 @@ const SettingsLogs = () => {
});
};
if (!data && !error) {
return <LoadingSpinner />;
}
if (!data) {
// check if there's no data and no errors in the table
// so as to show a spinner inside the table and not refresh the whole component
if (!data && error) {
return <Error statusCode={500} />;
}
const hasNextPage = data.pageInfo.pages > pageIndex + 1;
const hasNextPage = data?.pageInfo.pages ?? 0 > pageIndex + 1;
const hasPrevPage = pageIndex > 0;
return (
@@ -245,10 +249,21 @@ const SettingsLogs = () => {
appDataPath: appData ? appData.appDataPath : '/app/config',
})}
</p>
<div className="mt-2 flex flex-grow flex-row sm:flex-grow-0 sm:justify-end">
<div className="mt-2 flex flex-grow flex-col sm:flex-grow-0 sm:flex-row sm:justify-end">
<div className="mb-2 flex flex-grow sm:mb-0 sm:mr-2 md:flex-grow-0">
<span className="inline-flex cursor-default items-center rounded-l-md border border-r-0 border-gray-500 bg-gray-800 px-3 text-sm text-gray-100">
<SearchIcon className="h-6 w-6" />
</span>
<input
type="text"
className="rounded-r-only"
value={searchFilter}
onChange={(e) => setSearchFilter(e.target.value as string)}
/>
</div>
<div className="mb-2 flex flex-1 flex-row justify-between sm:mb-0 sm:flex-none">
<Button
className="mr-2 w-full flex-grow"
className="mr-2 flex flex-grow"
buttonType={refreshInterval ? 'default' : 'primary'}
onClick={() => toggleLogs()}
>
@@ -259,34 +274,34 @@ const SettingsLogs = () => {
)}
</span>
</Button>
</div>
<div className="mb-2 flex flex-1 sm:mb-0 sm:flex-none">
<span className="inline-flex cursor-default items-center rounded-l-md border border-r-0 border-gray-500 bg-gray-800 px-3 text-sm text-gray-100">
<FilterIcon className="h-6 w-6" />
</span>
<select
id="filter"
name="filter"
onChange={(e) => {
setCurrentFilter(e.target.value as Filter);
router.push(router.pathname);
}}
value={currentFilter}
className="rounded-r-only"
>
<option value="debug">
{intl.formatMessage(messages.filterDebug)}
</option>
<option value="info">
{intl.formatMessage(messages.filterInfo)}
</option>
<option value="warn">
{intl.formatMessage(messages.filterWarn)}
</option>
<option value="error">
{intl.formatMessage(messages.filterError)}
</option>
</select>
<div className="flex flex-grow">
<span className="inline-flex cursor-default items-center rounded-l-md border border-r-0 border-gray-500 bg-gray-800 px-3 text-sm text-gray-100">
<FilterIcon className="h-6 w-6" />
</span>
<select
id="filter"
name="filter"
onChange={(e) => {
setCurrentFilter(e.target.value as Filter);
router.push(router.pathname);
}}
value={currentFilter}
className="rounded-r-only"
>
<option value="debug">
{intl.formatMessage(messages.filterDebug)}
</option>
<option value="info">
{intl.formatMessage(messages.filterInfo)}
</option>
<option value="warn">
{intl.formatMessage(messages.filterWarn)}
</option>
<option value="error">
{intl.formatMessage(messages.filterError)}
</option>
</select>
</div>
</div>
</div>
<Table>
@@ -300,73 +315,81 @@ const SettingsLogs = () => {
</tr>
</thead>
<Table.TBody>
{data.results.map((row: LogMessage, index: number) => {
return (
<tr key={`log-list-${index}`}>
<Table.TD className="text-gray-300">
{intl.formatDate(row.timestamp, {
year: 'numeric',
month: 'short',
day: '2-digit',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
})}
</Table.TD>
<Table.TD className="text-gray-300">
<Badge
badgeType={
row.level === 'error'
? 'danger'
: row.level === 'warn'
? 'warning'
: row.level === 'info'
? 'success'
: 'default'
}
>
{row.level.toUpperCase()}
</Badge>
</Table.TD>
<Table.TD className="text-gray-300">
{row.label ?? ''}
</Table.TD>
<Table.TD className="text-gray-300">{row.message}</Table.TD>
<Table.TD className="-m-1 flex flex-wrap items-center justify-end">
{row.data && (
{!data ? (
<tr>
<Table.TD colSpan={5} noPadding>
<LoadingSpinner />
</Table.TD>
</tr>
) : (
data.results.map((row: LogMessage, index: number) => {
return (
<tr key={`log-list-${index}`}>
<Table.TD className="text-gray-300">
{intl.formatDate(row.timestamp, {
year: 'numeric',
month: 'short',
day: '2-digit',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
})}
</Table.TD>
<Table.TD className="text-gray-300">
<Badge
badgeType={
row.level === 'error'
? 'danger'
: row.level === 'warn'
? 'warning'
: row.level === 'info'
? 'success'
: 'default'
}
>
{row.level.toUpperCase()}
</Badge>
</Table.TD>
<Table.TD className="text-gray-300">
{row.label ?? ''}
</Table.TD>
<Table.TD className="text-gray-300">{row.message}</Table.TD>
<Table.TD className="-m-1 flex flex-wrap items-center justify-end">
{row.data && (
<Tooltip
content={intl.formatMessage(messages.viewdetails)}
>
<Button
buttonSize="sm"
buttonType="primary"
onClick={() =>
setActiveLog({ log: row, isOpen: true })
}
className="m-1"
>
<DocumentSearchIcon className="icon-md" />
</Button>
</Tooltip>
)}
<Tooltip
content={intl.formatMessage(messages.viewdetails)}
content={intl.formatMessage(messages.copyToClipboard)}
>
<Button
buttonType="primary"
buttonSize="sm"
onClick={() =>
setActiveLog({ log: row, isOpen: true })
}
onClick={() => copyLogString(row)}
className="m-1"
>
<DocumentSearchIcon className="icon-md" />
<ClipboardCopyIcon className="icon-md" />
</Button>
</Tooltip>
)}
<Tooltip
content={intl.formatMessage(messages.copyToClipboard)}
>
<Button
buttonType="primary"
buttonSize="sm"
onClick={() => copyLogString(row)}
className="m-1"
>
<ClipboardCopyIcon className="icon-md" />
</Button>
</Tooltip>
</Table.TD>
</tr>
);
})}
</Table.TD>
</tr>
);
})
)}
{data.results.length === 0 && (
{data?.results.length === 0 && (
<tr className="relative h-24 p-2 text-white">
<Table.TD colSpan={5} noPadding>
<div className="flex w-screen flex-col items-center justify-center p-6 md:w-full">
@@ -396,15 +419,15 @@ const SettingsLogs = () => {
>
<div className="hidden lg:flex lg:flex-1">
<p className="text-sm">
{data.results.length > 0 &&
{(data?.results.length ?? 0) > 0 &&
intl.formatMessage(globalMessages.showingresults, {
from: pageIndex * currentPageSize + 1,
to:
data.results.length < currentPageSize
data?.results.length ?? 0 < currentPageSize
? pageIndex * currentPageSize +
data.results.length
(data?.results.length ?? 0)
: (pageIndex + 1) * currentPageSize,
total: data.pageInfo.results,
total: data?.pageInfo.results ?? 0,
strong: (msg: React.ReactNode) => (
<span className="font-medium">{msg}</span>
),

View File

@@ -26,9 +26,9 @@
"components.Settings.SettingsUsers.userSettings": "Uživatelské nastavení",
"components.Settings.SettingsUsers.defaultPermissions": "Výchozí oprávnění",
"components.Settings.SettingsJobsCache.unknownJob": "Neznámá úloha",
"components.Settings.SettingsJobsCache.sonarr-scan": "Sonarr Sken",
"components.Settings.SettingsJobsCache.sonarr-scan": "Sonarr sken",
"components.Settings.SettingsJobsCache.runnow": "Spustit nyní",
"components.Settings.SettingsJobsCache.radarr-scan": "Radarr Sken",
"components.Settings.SettingsJobsCache.radarr-scan": "Radarr sken",
"components.Settings.SettingsJobsCache.jobstarted": "{jobname} zahájeno.",
"components.Settings.SettingsJobsCache.jobname": "Název úlohy",
"components.Settings.SettingsJobsCache.jobcancelled": "{jobname} zrušeno.",
@@ -39,12 +39,12 @@
"components.Settings.SettingsAbout.totalrequests": "Celkový počet žádostí",
"components.Settings.SettingsAbout.totalmedia": "Celkový počet médií",
"components.Settings.SettingsAbout.timezone": "Časové pásmo",
"components.Settings.SettingsAbout.supportoverseerr": "Podpořte Jellyseerr",
"components.Settings.SettingsAbout.overseerrinformation": "Jellyseerr Informace",
"components.Settings.SettingsAbout.supportoverseerr": "Podpořte Overseerr",
"components.Settings.SettingsAbout.overseerrinformation": "O Jellyseerr",
"components.Settings.SettingsAbout.githubdiscussions": "Diskuze na GitHubu",
"components.Settings.SettingsAbout.Releases.viewchangelog": "Zobrazit seznam změn",
"components.Settings.SettingsAbout.Releases.versionChangelog": "Seznam změn",
"components.Settings.SettingsAbout.Releases.currentversion": "Aktuální verze",
"components.Settings.SettingsAbout.Releases.versionChangelog": "{version} Seznam změn",
"components.Settings.SettingsAbout.Releases.currentversion": "Aktuální",
"components.Settings.RadarrModal.syncEnabled": "Povolit skenování",
"components.Settings.RadarrModal.ssl": "Použít SSL",
"components.Settings.RadarrModal.servername": "Název serveru",
@@ -85,7 +85,7 @@
"components.Settings.Notifications.NotificationsLunaSea.webhookUrl": "Webhook URL",
"components.Settings.Notifications.NotificationsLunaSea.profileName": "Jméno profilu",
"components.Settings.Notifications.NotificationsLunaSea.agentenabled": "Povolit agenta",
"components.Search.searchresults": "Výsledek vyhledávání",
"components.Search.searchresults": "Výsledky vyhledávání",
"components.ResetPassword.passwordreset": "Obnovení hesla",
"components.ResetPassword.email": "E-mailová adresa",
"components.ResetPassword.confirmpassword": "Potvrďte heslo",
@@ -105,7 +105,7 @@
"components.RequestModal.AdvancedRequester.destinationserver": "Cílový server",
"components.RequestModal.AdvancedRequester.default": "{name} (výchozí)",
"components.RequestList.sortModified": "Naposledy změněno",
"components.RequestList.sortAdded": "Datum žádosti",
"components.RequestList.sortAdded": "Nejnovější",
"components.RequestList.RequestItem.editrequest": "Upravit žádost",
"components.RequestList.RequestItem.deleterequest": "Odstranit žádost",
"components.RequestList.RequestItem.cancelRequest": "Zrušit žádost",
@@ -128,8 +128,8 @@
"components.PermissionEdit.users": "Spravovat uživatele",
"components.PermissionEdit.settings": "Spravovat nastavení",
"components.PermissionEdit.requestTv": "Žádat seriály",
"components.PermissionEdit.requestMovies": "Žádat filmy",
"components.PermissionEdit.request4k": "Žádosti ve 4K",
"components.PermissionEdit.requestMovies": "Vyžádat filmy",
"components.PermissionEdit.request4k": "Vyžádat ve 4K",
"components.PermissionEdit.managerequests": "Spravovat žádosti",
"components.PermissionEdit.autoapproveSeries": "Automaticky schvalovat seriály",
"components.PermissionEdit.autoapproveMovies": "Automaticky schvalovat filmy",
@@ -234,7 +234,7 @@
"components.NotificationTypeSelector.usermediaapprovedDescription": "Získat upozornění na schválení vašich žádostí o média.",
"components.NotificationTypeSelector.usermediaAutoApprovedDescription": "Získat upozornění, když ostatní uživatelé zadají nové požadavky na média, která jsou automaticky schválena.",
"components.NotificationTypeSelector.mediarequestedDescription": "Odeslat oznámení, když uživatelé zažádají o média vyžadující schválení.",
"components.MovieDetails.streamingproviders": "Aktuálně streamovatelné zde",
"components.MovieDetails.streamingproviders": "Aktuálně streamovatelné na",
"pages.serviceunavailable": "Služba není k dispozici",
"pages.returnHome": "Vrátit se domů",
"pages.pagenotfound": "Stránka nebyla nalezena",
@@ -469,7 +469,7 @@
"components.IssueDetails.IssueComment.edit": "Upravit komentář",
"components.IssueDetails.allseasons": "Všechny série",
"components.IssueDetails.closeissue": "Uzavřít problém",
"components.ManageSlideOver.downloadstatus": "Stav stahování",
"components.ManageSlideOver.downloadstatus": "Stahování",
"components.NotificationTypeSelector.issueresolved": "Problém vyřešen",
"components.RequestList.RequestItem.modifieduserdate": "{date} od {user}",
"components.RequestList.showallrequests": "Zobrazit všechny žádosti",
@@ -710,7 +710,7 @@
"components.Settings.SonarrModal.toastSonarrTestSuccess": "Připojení Sonarr úspěšně navázáno!",
"components.Settings.SonarrModal.validationBaseUrlLeadingSlash": "Základní adresa URL musí mít na začátku lomítko",
"components.Settings.cacheImages": "Povolení ukládání obrázků do mezipaměti",
"components.Settings.cacheImagesTip": "Optimalizovat a ukládat všechny obrázky lokálně (spotřebovává značné množství místa na disku)",
"components.Settings.cacheImagesTip": "Ukládat do mezipaměti a poskytovat optimalizované obrazy (vyžaduje značné množství místa na disku)",
"components.Settings.manualscanDescription": "Obvykle se provádí pouze jednou za 24 hodin. Jellyseerr bude kontrolovat nedávno přidané položky vašeho serveru Plex agresivněji. Pokud Plex konfigurujete poprvé, doporučujeme provést jednorázovou úplnou ruční kontrolu knihovny!",
"components.Settings.originallanguageTip": "Filtrování obsahu podle původního jazyka",
"components.Settings.urlBase": "Základní adresa URL",
@@ -894,11 +894,11 @@
"components.Settings.Notifications.NotificationsPushover.userToken": "Klíč uživatele nebo skupiny",
"components.RequestCard.failedretry": "Při opakovaném pokusu o zadání požadavku se něco pokazilo.",
"components.Settings.Notifications.NotificationsLunaSea.profileNameTip": "Vyžaduje se pouze v případě, že nepoužíváte profil <code>default</code>",
"components.RequestCard.mediaerror": "Související titul pro tuto žádost již není k dispozici.",
"components.Settings.trustProxyTip": "Povolit Jellyseerr správně registrovat IP adresy klientů za proxy serverem (aby se změny projevily, musí být Jellyseerr znovu načten)",
"components.RequestList.RequestItem.mediaerror": "Související titul pro tuto žádost již není k dispozici.",
"components.RequestCard.mediaerror": "{mediaType} Nenalezeno",
"components.Settings.trustProxyTip": "Povolit Jellyseerr správně registrovat IP adresy klientů za proxy serverem",
"components.RequestList.RequestItem.mediaerror": "{mediaType} Nenalezeno",
"components.RequestModal.QuotaDisplay.allowedRequests": "Můžete požádat o <strong>{limit}</strong> {type} každé <strong>{days}</strong> dny.",
"components.RequestModal.SearchByNameModal.notvdbiddescription": "Váš požadavek jsme nemohli automaticky porovnat. Vyberte prosím správnou shodu ze seznamu níže.",
"components.RequestModal.SearchByNameModal.notvdbiddescription": "Tuto sérii jsme nemohli automaticky spárovat. Níže prosím vyberte správnou shodu.",
"components.Settings.RadarrModal.validationBaseUrlLeadingSlash": "Základ URL musí mít na začátku lomítko",
"components.Settings.SettingsJobsCache.plex-recently-added-scan": "Plex Nedávno přidané skenování",
"components.Settings.SettingsLogs.logsDescription": "Tyto protokoly můžete také zobrazit přímo prostřednictvím <code>stdout</code> nebo v <code>{appDataPath}/logs/overseerr.log</code>.",
@@ -1036,5 +1036,91 @@
"components.RequestButton.decline4krequests": "Odmítnout {requestCount, plural, one {4K žádost} other {{requestCount} 4K žádosti}}",
"components.RequestButton.declinerequests": "Odmítnout {requestCount, plural, one {Žádost} other {{requestCount} Žádosti}}",
"components.RequestModal.requestmovies": "Požádat {count} {count, plural, one {film} other {filmy}}",
"components.Settings.SettingsJobsCache.editJobScheduleSelectorMinutes": "{jobScheduleMinutes, plural, one {Každou minutu} few {Každé {jobScheduleMinutes} minuty} other {Každých {jobScheduleMinutes} minut}}"
"components.Settings.SettingsJobsCache.editJobScheduleSelectorMinutes": "{jobScheduleMinutes, plural, one {Každou minutu} few {Každé {jobScheduleMinutes} minuty} other {Každých {jobScheduleMinutes} minut}}",
"components.MovieDetails.digitalrelease": "Digitální vydání",
"components.Discover.DiscoverWatchlist.discoverwatchlist": "Váš Plex Watchlist",
"components.MovieDetails.physicalrelease": "Fyzické vydání",
"components.MovieDetails.managemovie": "Spravovat film",
"components.AirDateBadge.airsrelative": "Vysíla se {relativeTime}",
"components.Layout.UserDropdown.MiniQuotaDisplay.movierequests": "Žádosti o filmy",
"components.MovieDetails.rtaudiencescore": "Skóre publika Rotten Tomatoes",
"components.MovieDetails.rtcriticsscore": "Rotten Tomatoes Tomatometer",
"components.Layout.UserDropdown.MiniQuotaDisplay.seriesrequests": "Žádosti o seriály",
"components.AirDateBadge.airedrelative": "Odvysílano {relativeTime}",
"components.Layout.UserDropdown.requests": "Žádosti",
"components.MovieDetails.reportissue": "Nahlásit problém",
"components.StatusChecker.restartRequired": "Je vyžadován restart serveru",
"components.PermissionEdit.viewrecent": "Zobrazit naposledy přidané",
"components.StatusChecker.appUpdated": "{applicationTitle} Aktualizováno",
"components.StatusChecker.appUpdatedDescription": "Chcete-li aplikaci znovu načíst, klikněte na tlačítko níže.",
"components.StatusChecker.restartRequiredDescription": "Chcete-li použít aktualizovaná nastavení, restartujte server.",
"components.RequestCard.tmdbid": "TMDB ID",
"components.RequestList.RequestItem.tmdbid": "TMDB ID",
"components.TitleCard.tmdbid": "TMDB ID",
"components.TitleCard.tvdbid": "TheTVDB ID",
"components.RequestCard.tvdbid": "TheTVDB ID",
"components.RequestList.RequestItem.tvdbid": "TheTVDB ID",
"components.PermissionEdit.autorequestMovies": "Automatické vyžádání filmů",
"components.PermissionEdit.autorequestMoviesDescription": "Udělte oprávnění k automatickému odesílání žádostí o filmy v jiném rozlišení než 4K prostřednictvím Plex Watchlistu.",
"components.PermissionEdit.viewrecentDescription": "Udělte oprávnění k zobrazení seznamu nedávno přidaných médií.",
"components.Settings.restartrequiredTooltip": "Aby se změny tohoto nastavení projevily, musí být Overserr restartován",
"components.StatusChecker.reloadApp": "Znovu načíst {applicationTitle}",
"components.TitleCard.cleardata": "Vyčistit data",
"components.TitleCard.mediaerror": "{mediaType} Nenalezeno",
"components.PermissionEdit.autorequestDescription": "Udělte oprávnění k automatickému odesílání žádostí o média jiná než 4K prostřednictvím seznamu Plex Watchlist.",
"components.PermissionEdit.autorequest": "Automatická žádost",
"components.PermissionEdit.autorequestSeries": "Automaticky vyžádat seriál",
"components.PermissionEdit.viewwatchlists": "Zobrazit Plex Watchilisty",
"components.Settings.advancedTooltip": "Nesprávná konfigurace tohoto nastavení může vést k narušení funkčnosti",
"components.Settings.deleteServer": "Smazat server {serverType}",
"components.Settings.experimentalTooltip": "Povolení tohoto nastavení může vést k neočekávanému chování aplikace",
"components.Settings.SettingsLogs.viewdetails": "Zobrazit podrobnosti",
"components.PermissionEdit.autorequestSeriesDescription": "Udělte oprávnění k automatickému odesílání žádostí o seriály jiné než 4K prostřednictvím Plex Watchlist.",
"components.RequestBlock.approve": "Schválit žádost",
"components.RequestBlock.decline": "Odmítnout požadavek",
"components.RequestBlock.lastmodifiedby": "Naposledy změněno od",
"components.RequestBlock.requestdate": "Datum požadavku",
"components.RequestBlock.requestedby": "Vyžádáno od",
"components.RequestCard.approverequest": "Schválit žádost",
"components.RequestCard.cancelrequest": "Zrušit žádost",
"components.RequestCard.declinerequest": "Odmítnout požadavek",
"components.Settings.SettingsJobsCache.plex-watchlist-sync": "Plex Watchlist synchronizace",
"components.StatusBadge.managemedia": "Spravovat {mediaType}",
"components.StatusBadge.openinarr": "Otevřít v {arr}",
"components.StatusBadge.playonplex": "Přehrávání cez Plex",
"components.TvDetails.manageseries": "Spravovat sérii",
"components.RequestBlock.delete": "Smazat požadavek",
"components.RequestBlock.edit": "Upravit požadavek",
"components.RequestCard.editrequest": "Upravit požadavek",
"components.RequestModal.SearchByNameModal.nomatches": "Pro tuto sérii jsme nenašli shodu.",
"components.RequestModal.requestcollection4ktitle": "Vyžádejte si kolekci ve 4K",
"components.RequestModal.requestcollectiontitle": "Vyžádat kolekci",
"components.RequestModal.requestmovie4ktitle": "Vyžádejte si film ve 4K",
"components.RequestModal.requestmovietitle": "Vyžádat si film",
"components.RequestModal.requestseries4ktitle": "Žádost o sérii ve 4K",
"components.RequestModal.requestseriestitle": "Vyžádat sérii",
"components.TvDetails.episodeCount": "{episodeCount, plural, one {# Epizoda} other {# Epizody}}",
"components.NotificationTypeSelector.mediaautorequested": "Žádost byla odeslána automaticky",
"components.NotificationTypeSelector.mediaautorequestedDescription": "Získejte upozornění, když jsou automaticky odeslány nové požadavky na média pro položky na vašem Plex Watchlistu.",
"components.PermissionEdit.viewwatchlistsDescription": "Udělte oprávnění k zobrazení Plex Watchlistu ostatních uživatelů.",
"components.TvDetails.Season.somethingwentwrong": "Při načítání údajů o sezóně se něco pokazilo.",
"i18n.restartRequired": "Je vyžadován restart",
"components.Discover.plexwatchlist": "Váš Plex Watchlist",
"components.MovieDetails.theatricalrelease": "Dostupné v kinách",
"components.Discover.DiscoverWatchlist.watchlist": "Plex Watchlist",
"components.TvDetails.reportissue": "Nahlásit problém",
"components.MovieDetails.tmdbuserscore": "Uživatelské skóre TMDB",
"components.TvDetails.seasonstitle": "Sezóny",
"components.TvDetails.seasonnumber": "Sezóna {seasonNumber}",
"components.TvDetails.rtcriticsscore": "Rotten Tomatoes Tomatometer",
"components.TvDetails.rtaudiencescore": "Rotten Tomatoes Audience Skóre",
"components.TvDetails.tmdbuserscore": "Uživatelské skóre TMDB",
"components.TvDetails.status4k": "4K {status}",
"components.Discover.emptywatchlist": "Média přidaná do vašeho <PlexWatchlistSupportLink>Plex Watchlistu</PlexWatchlistSupportLink> se zobrazí zde.",
"components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncmoviestip": "Automaticky vyžádat filmy na vašem <PlexWatchlistSupportLink>Plex Watchlistu</PlexWatchlistSupportLink>",
"components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseriestip": "Automaticky vyžádejte sérii na vašem <PlexWatchlistSupportLink>Plex Watchlistu</PlexWatchlistSupportLink>",
"components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseries": "Automaticky vyžádat sérii",
"components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncmovies": "Automaticky vyžádat filmy",
"components.UserProfile.plexwatchlist": "Plex Watchlist",
"components.UserProfile.emptywatchlist": "Zde se zobrazí média přidaná do vašeho <PlexWatchlistSupportLink>Plex Watchlistu</PlexWatchlistSupportLink>."
}

View File

@@ -642,7 +642,8 @@
"components.Settings.SettingsJobsCache.download-sync": "Download Sync",
"components.Settings.SettingsJobsCache.download-sync-reset": "Download Sync Reset",
"components.Settings.SettingsJobsCache.editJobSchedule": "Modify Job",
"components.Settings.SettingsJobsCache.editJobSchedulePrompt": "Frequency",
"components.Settings.SettingsJobsCache.editJobScheduleCurrent": "Current Frequency",
"components.Settings.SettingsJobsCache.editJobSchedulePrompt": "New Frequency",
"components.Settings.SettingsJobsCache.editJobScheduleSelectorHours": "Every {jobScheduleHours, plural, one {hour} other {{jobScheduleHours} hours}}",
"components.Settings.SettingsJobsCache.editJobScheduleSelectorMinutes": "Every {jobScheduleMinutes, plural, one {minute} other {{jobScheduleMinutes} minutes}}",
"components.Settings.SettingsJobsCache.flushcache": "Flush Cache",

55
src/i18n/locale/hr.json Normal file
View File

@@ -0,0 +1,55 @@
{
"components.CollectionDetails.numberofmovies": "{count} Filmovi",
"components.CollectionDetails.overview": "Pregled",
"components.CollectionDetails.requestcollection4k": "Zahtjev za serijalom u 4K",
"components.CollectionDetails.requestcollection": "Zahtjev za serijalom",
"components.Discover.DiscoverMovieGenre.genreMovies": "{genre} Filmovi",
"components.Discover.DiscoverMovieLanguage.languageMovies": "{language} Filmovi",
"components.Discover.DiscoverNetwork.networkSeries": "{network} Serije",
"components.Discover.DiscoverStudio.studioMovies": "{studio} Filmovi",
"components.Discover.discover": "Otkrivanje",
"components.Discover.discovermovies": "Popularni Filmovi",
"components.Discover.discovertv": "Popularne Serije",
"components.Discover.DiscoverTvGenre.genreSeries": "{genre} Serije",
"components.Discover.DiscoverTvLanguage.languageSeries": "{language} Serije",
"components.Discover.DiscoverWatchlist.discoverwatchlist": "Vaš Plex popis za gledanje",
"components.Discover.MovieGenreList.moviegenres": "Filmski Žanrovi",
"components.Discover.StudioSlider.studios": "Studio",
"components.Discover.TvGenreList.seriesgenres": "Serijski Žanrovi",
"components.Discover.TvGenreSlider.tvgenres": "Serijski Žanrovi",
"components.Discover.plexwatchlist": "Vaš Plex popis za gledanje",
"components.Discover.popularmovies": "Popularni Filmovi",
"components.Discover.recentlyAdded": "Nedavno Dodano",
"components.Discover.recentrequests": "Nedavni Zahtjevi",
"components.Discover.trending": "Popularno",
"components.IssueDetails.IssueComment.edit": "Uredi Komentar",
"components.IssueDetails.IssueDescription.deleteissue": "Izbriši problem",
"components.IssueDetails.IssueDescription.description": "Opis",
"components.IssueDetails.IssueDescription.edit": "Uredi opis",
"components.IssueDetails.allepisodes": "Sve Epizode",
"components.IssueDetails.closeissue": "Zatvori Problem",
"components.IssueDetails.closeissueandcomment": "Zatvori s komentarom",
"components.IssueDetails.commentplaceholder": "Dodaj komentar…",
"components.IssueDetails.comments": "Komentari",
"components.IssueDetails.deleteissue": "Izbriši problem",
"components.AirDateBadge.airedrelative": "Emitirano {relativeTime}",
"components.AirDateBadge.airsrelative": "Emitiranje {relativeTime}",
"components.AppDataWarning.dockerVolumeMissingDescription": "Navedeni <code>{appDataPath}</code> mapirani volumen nije ispravno podešen. Svi podaci će biti izbrisani kada se spremnik (container) zaustavi ili ponovno pokrene.",
"components.Discover.DiscoverWatchlist.watchlist": "Plex popis za gledanje",
"components.Discover.emptywatchlist": "Filmovi dodani na Vaš <PlexWatchlistSupportLink> popis za gledanje </PlexWatchlistSupportLink> pojaviti će se ovdje.",
"components.Discover.MovieGenreSlider.moviegenres": "Filmski Žanrovi",
"components.Discover.NetworkSlider.networks": "Striming servisi",
"components.Discover.populartv": "Popularne Serije",
"components.Discover.upcomingtv": "Nadolazeće Serije",
"components.Discover.upcoming": "Nadolazeći Filmovi",
"components.Discover.upcomingmovies": "Nadolazeći Filmovi",
"components.DownloadBlock.estimatedtime": "Procijenjeno {time}",
"components.IssueDetails.IssueComment.areyousuredelete": "Jeste li sigurni da želite izbrisati ovaj komentar?",
"components.IssueDetails.IssueComment.delete": "Izbriši Komentar",
"components.IssueDetails.IssueComment.postedby": "Objavljeno u {relativeTime} od korisnika {username}",
"components.IssueDetails.IssueComment.validationComment": "Morate unijeti poruku",
"components.IssueDetails.IssueComment.postedbyedited": "Objavljeno u {relativeTime} od korisnika {username} (Uređeno)",
"components.IssueDetails.allseasons": "Sve Sezone",
"components.IssueDetails.episode": "Epizode {episodeNumber}",
"components.IssueDetails.deleteissueconfirm": "Jeste li sigurni da želite izbrisati ovaj problem?"
}

View File

@@ -337,7 +337,7 @@
"i18n.experimental": "Experimenteel",
"components.Settings.hideAvailable": "Beschikbare media verbergen",
"components.RequestModal.requesterror": "Er ging iets mis bij het aanvragen.",
"components.RequestModal.SearchByNameModal.notvdbiddescription": "We konden je verzoek niet automatisch matchen. Selecteer de juiste match uit de onderstaande lijst.",
"components.RequestModal.SearchByNameModal.notvdbiddescription": "We kunnen deze serie niet automatisch matchen. Selecteer hieronder de juiste match.",
"components.Login.signinwithplex": "Plex-account gebruiken",
"components.Login.signinheader": "Log in om verder te gaan",
"components.Login.signingin": "Bezig met inloggen…",
@@ -632,7 +632,7 @@
"components.Settings.SettingsJobsCache.jobsandcache": "Taken en cache",
"components.Settings.SettingsAbout.about": "Over",
"components.ResetPassword.passwordreset": "Wachtwoord opnieuw instellen",
"components.Settings.cacheImagesTip": "Alle afbeeldingen optimaliseren en lokaal opslaan (gebruikt een aanzienlijke hoeveelheid schijfruimte)",
"components.Settings.cacheImagesTip": "Cache en serveer geoptimaliseerde afbeeldingen (een aanzienlijke hoeveelheid schijfruimte is nodig)",
"components.Settings.cacheImages": "Afbeeldingscaching inschakelen",
"components.Settings.SettingsLogs.logDetails": "Loggegevens",
"components.Settings.SettingsLogs.extraData": "Aanvullende gegevens",
@@ -713,9 +713,9 @@
"components.RequestModal.AdvancedRequester.selecttags": "Labels selecteren",
"components.RequestModal.AdvancedRequester.notagoptions": "Geen labels.",
"components.Settings.RadarrModal.loadingTags": "Labels laden…",
"components.RequestList.RequestItem.mediaerror": "De gekoppelde titel voor dit verzoek is niet meer beschikbaar.",
"components.RequestList.RequestItem.mediaerror": "{mediaType} Niet Gevonden",
"components.RequestList.RequestItem.deleterequest": "Verzoek verwijderen",
"components.RequestCard.mediaerror": "De gekoppelde titel voor dit verzoek is niet meer beschikbaar.",
"components.RequestCard.mediaerror": "{mediaType} Niet Gevonden",
"components.RequestCard.deleterequest": "Verzoek verwijderen",
"components.UserProfile.UserSettings.UserNotificationSettings.validationPgpPublicKey": "Je moet een geldige openbare PGP-sleutel opgeven",
"components.UserProfile.UserSettings.UserNotificationSettings.telegramsettingssaved": "Instellingen Telegrammeldingen succesvol opgeslagen!",

View File

@@ -1034,5 +1034,44 @@
"i18n.next": "Tjetra",
"i18n.experimental": "Eksperimentale",
"i18n.noresults": "S'ka rezultate.",
"i18n.notrequested": "Nuk është Kerkuar"
"i18n.notrequested": "Nuk është Kerkuar",
"components.Settings.SettingsAbout.appDataPath": "Direktoria e të dhënave",
"components.MovieDetails.digitalrelease": "Publikimi Dixhital",
"components.MovieDetails.physicalrelease": "Lëshimi Fizik",
"components.MovieDetails.theatricalrelease": "Publikimi Teatror",
"components.PermissionEdit.viewrecent": "Shiko Shtuar së fundi",
"components.PermissionEdit.viewrecentDescription": "Jep leje për të parë listën e mediave të shtuara kohët e fundit.",
"components.Discover.DiscoverWatchlist.discoverwatchlist": "Lista juaj e shikimit në Plex",
"components.PermissionEdit.autorequestMoviesDescription": "Jepni lejen për të paraqitur automatikisht kërkesat për mediat jo-4K nëpërmjet Plex Watchlist.",
"components.PermissionEdit.autorequestSeries": "Kërkesa Automatike Serialesh",
"components.PermissionEdit.autorequestSeriesDescription": "Jep leje për të paraqitur automatikisht kërkesat për seri jo-4K nëpërmjet Plex Watchlist.",
"components.Discover.DiscoverWatchlist.watchlist": "Lista e Shikimit Plex",
"components.Discover.plexwatchlist": "Lista juaj e shikimit në Plex",
"components.MovieDetails.reportissue": "Raportoni një problem",
"components.NotificationTypeSelector.mediaautorequested": "Kërkesa u dorëzua automatikisht",
"components.PermissionEdit.autorequest": "Auto-Kërkesë",
"components.PermissionEdit.autorequestDescription": "Jepni lejen për të paraqitur automatikisht kërkesat për mediat jo-4K nëpërmjet Plex Watchlist.",
"components.PermissionEdit.autorequestMovies": "Kërkesë automatike për filma",
"components.PermissionEdit.viewwatchlists": "Shiko listat e shikimit të Plex",
"components.PermissionEdit.viewwatchlistsDescription": "Jep leje për të parë listat e Plex Watchlist të përdoruesve të tjerë.",
"components.MovieDetails.managemovie": "Menaxho filmin",
"components.AirDateBadge.airedrelative": "Transmetuar {relativeTime}",
"components.Layout.UserDropdown.MiniQuotaDisplay.movierequests": "Kërkesat e Filmave",
"components.Layout.UserDropdown.MiniQuotaDisplay.seriesrequests": "Kërkesat e Serialeve",
"components.Layout.UserDropdown.requests": "Kërkesat",
"components.MovieDetails.rtaudiencescore": "Rezultati i audiencës së Rotten Tomatoes",
"components.MovieDetails.rtcriticsscore": "Tomatometeri i Rotten Tomatoes",
"components.NotificationTypeSelector.mediaautorequestedDescription": "Njoftohuni kur kërkesat e reja të medias dorëzohen automatikisht për artikujt në Listën tuaj të Plex Watchlist.",
"components.RequestBlock.languageprofile": "Profili i gjuhës",
"components.AirDateBadge.airsrelative": "Duke u Transmetuar {relativeTime}",
"components.Discover.emptywatchlist": "Këtu do të shfaqet media e shtuar në listën tuaj <PlexWatchlistSupportLink>Plex</PlexWatchlistSupportLink>.",
"components.RequestBlock.decline": "Refuzo kërkesën",
"components.RequestBlock.delete": "Fshije Kërkesën",
"components.RequestBlock.edit": "Ndrysho kërkesën",
"components.MovieDetails.tmdbuserscore": "Nota e përdoruesve TMDB",
"components.RequestBlock.approve": "Mirato Kërkesën",
"components.RequestBlock.lastmodifiedby": "Ndryshuar së fundi nga",
"components.RequestBlock.requestdate": "Data e Kërkesës",
"components.RequestBlock.requestedby": "Kërkuar nga",
"components.RequestCard.approverequest": "Mirato Kërkesën"
}

View File

@@ -57,7 +57,7 @@
"components.UserList.creating": "創建中…",
"components.UserList.createlocaluser": "建立本地使用者",
"components.UserList.autogeneratepassword": "自動生成密碼",
"i18n.tvshows": "電視節目",
"i18n.tvshows": "影集",
"pages.oops": "哎呀",
"components.TvDetails.firstAirDate": "原始播出日期",
"i18n.delete": "刪除",
@@ -133,15 +133,15 @@
"components.Layout.Sidebar.users": "使用者",
"components.Layout.Sidebar.settings": "設定",
"components.Layout.Sidebar.requests": "請求",
"components.Layout.SearchInput.searchPlaceholder": "搜尋電影、電視節目、人物…",
"components.Layout.SearchInput.searchPlaceholder": "搜尋電影、影集、人物…",
"components.Discover.upcomingmovies": "即將上映的電影",
"components.Discover.upcoming": "即將上映的電影",
"components.Discover.trending": "趨勢",
"components.Discover.recentlyAdded": "最近新增",
"components.Discover.recentrequests": "最新請求",
"components.Discover.populartv": "熱門電視節目",
"components.Discover.populartv": "熱門影集",
"components.Discover.popularmovies": "熱門電影",
"components.Discover.discovertv": "熱門電視節目",
"components.Discover.discovertv": "熱門影集",
"components.Discover.discovermovies": "熱門電影",
"components.CollectionDetails.requestcollection": "提出電影系列請求",
"components.CollectionDetails.overview": "概要",
@@ -262,7 +262,7 @@
"components.TvDetails.overviewunavailable": "沒有概要。",
"components.MovieDetails.overviewunavailable": "沒有概要。",
"components.TvDetails.watchtrailer": "觀看預告片",
"components.TvDetails.showtype": "節目類型",
"components.TvDetails.showtype": "影集類型",
"components.TvDetails.similar": "類似",
"components.RequestModal.requestfrom": "{username} 的請求待處理。",
"components.Settings.toastApiKeySuccess": "生成新應用程式密鑰成功!",
@@ -306,7 +306,7 @@
"components.Settings.RadarrModal.add": "新增伺服器",
"components.RequestModal.requestcancelled": "<strong>{title}</strong> 的請求已被取消。",
"components.RequestModal.AdvancedRequester.qualityprofile": "品質設定",
"components.RequestModal.AdvancedRequester.animenote": "※這是個動漫節目。",
"components.RequestModal.AdvancedRequester.animenote": "※這是個動漫影集。",
"components.RequestModal.AdvancedRequester.advancedoptions": "進階選項",
"components.RequestModal.AdvancedRequester.default": "{name}(預設)",
"components.RequestModal.AdvancedRequester.destinationserver": "目標伺服器",
@@ -321,7 +321,7 @@
"components.Settings.SonarrModal.toastSonarrTestFailure": "Sonarr 伺服器連線失敗。",
"components.Settings.serverpreset": "伺服器",
"components.RequestModal.autoapproval": "自動批准",
"components.PermissionEdit.autoapproveSeries": "電視節目自動批准",
"components.PermissionEdit.autoapproveSeries": "影集自動批准",
"components.PermissionEdit.autoapproveMovies": "電影自動批准",
"components.PermissionEdit.autoapprove": "自動批准",
"components.PermissionEdit.admin": "管理員",
@@ -330,7 +330,7 @@
"components.Settings.serverpresetRefreshing": "載入中…",
"components.Settings.SonarrModal.syncEnabled": "啟用掃描",
"components.UserList.userssaved": "使用者權限儲存成功!",
"components.Settings.hideAvailable": "隱藏可觀看的電影和電視節目",
"components.Settings.hideAvailable": "隱藏可觀看的電影和影集",
"components.Settings.SonarrModal.externalUrl": "外部網址",
"components.Settings.RadarrModal.externalUrl": "外部網址",
"components.Settings.csrfProtection": "防止跨站請求偽造CSRF攻擊",
@@ -353,7 +353,7 @@
"components.PlexLoginButton.signinwithplex": "登入",
"components.PlexLoginButton.signingin": "登入中…",
"components.PermissionEdit.users": "管理使用者",
"components.PermissionEdit.request4kTv": "提出 4K 電視節目請求",
"components.PermissionEdit.request4kTv": "提出 4K 影集請求",
"components.PermissionEdit.request4kMovies": "提出 4K 電影請求",
"components.PermissionEdit.request4k": "提出 4K 請求",
"components.PermissionEdit.request": "提出請求",
@@ -432,7 +432,7 @@
"components.NotificationTypeSelector.mediadeclinedDescription": "當請求拒被絕時發送通知。",
"components.PermissionEdit.request4kDescription": "授予提出 4K 媒體請求的權限。",
"components.PermissionEdit.request4kMoviesDescription": "授予提出 4K 電影請求的權限。",
"components.PermissionEdit.request4kTvDescription": "授予提出 4K 電視節目請求的權限。",
"components.PermissionEdit.request4kTvDescription": "授予提出 4K 影集請求的權限。",
"components.PermissionEdit.requestDescription": "授予提出非 4K 媒體請求的權限。",
"components.PermissionEdit.viewrequestsDescription": "授予查看其他使用者提出的媒體請求的權限。",
"components.Settings.SonarrModal.validationLanguageProfileRequired": "請設定語言",
@@ -443,7 +443,7 @@
"components.Settings.SonarrModal.animelanguageprofile": "動漫語言設定",
"components.RequestModal.AdvancedRequester.languageprofile": "語言設定",
"components.PermissionEdit.usersDescription": "授予管理使用者的權限。有此權限的使用者不能編輯管理員或授予管理員權限。",
"components.PermissionEdit.autoapproveSeriesDescription": "自動批准非 4K 電視節目請求。",
"components.PermissionEdit.autoapproveSeriesDescription": "自動批准非 4K 影集請求。",
"components.PermissionEdit.autoapproveMoviesDescription": "自動批准非 4K 電影請求。",
"components.PermissionEdit.autoapproveDescription": "自動批准所有非 4K 媒體請求。",
"components.PermissionEdit.advancedrequestDescription": "授予使用進階媒體請求選項的權限。",
@@ -456,8 +456,8 @@
"components.UserList.sortCreated": "加入日期",
"components.UserList.sortDisplayName": "顯示名稱",
"components.UserList.sortRequests": "請求數",
"components.PermissionEdit.autoapprove4kSeriesDescription": "自動批准 4K 電視節目請求。",
"components.PermissionEdit.autoapprove4kSeries": "4K 電視節目自動批准",
"components.PermissionEdit.autoapprove4kSeriesDescription": "自動批准 4K 影集請求。",
"components.PermissionEdit.autoapprove4kSeries": "4K 影集自動批准",
"components.PermissionEdit.autoapprove4kMoviesDescription": "自動批准 4K 電影請求。",
"components.PermissionEdit.autoapprove4kMovies": "4K 電影自動批准",
"components.PermissionEdit.autoapprove4kDescription": "自動批准所有 4K 媒體請求。",
@@ -502,7 +502,7 @@
"components.UserProfile.UserSettings.UserNotificationSettings.validationDiscordId": "請輸入有效的使用者 ID",
"components.UserProfile.UserSettings.UserNotificationSettings.discordIdTip": "您的<FindDiscordIdLink>使用者 ID 號碼</FindDiscordIdLink>",
"components.UserProfile.UserSettings.UserPasswordChange.toastSettingsFailure": "重設密碼時出了點問題。",
"components.RequestModal.SearchByNameModal.notvdbiddescription": "無法自動配對此電視節目的數據。 請在以下選擇正確的媒體項。",
"components.RequestModal.SearchByNameModal.notvdbiddescription": "無法自動配對此影集的數據。 請在以下選擇正確的媒體項。",
"components.CollectionDetails.requestcollection4k": "提出 4K 電影系列請求",
"components.Settings.trustProxyTip": "使用代理伺服器時,允許 Jellyseerr 註冊客戶端的正確 IP 位址",
"components.Settings.csrfProtectionTip": "設定外部訪問權限為只讀(需要 HTTPS",
@@ -513,7 +513,7 @@
"components.Settings.region": "「探索」地區",
"components.UserProfile.UserSettings.UserGeneralSettings.originallanguage": "「探索」語言",
"components.Settings.originallanguage": "「探索」語言",
"components.Discover.upcomingtv": "即將上映的電視節目",
"components.Discover.upcomingtv": "即將上映的影集",
"components.Settings.webhook": "Webhook",
"components.Settings.email": "電子郵件",
"components.Settings.generalsettingsDescription": "Jellyseerr 的全域和預設設定。",
@@ -540,8 +540,8 @@
"components.Settings.SettingsJobsCache.download-sync": "下載狀態同步",
"components.Settings.SettingsJobsCache.unknownJob": "未知作業",
"components.TvDetails.seasons": "{seasonCount} 季",
"components.Discover.DiscoverTvGenre.genreSeries": "{genre}電視節目",
"components.Discover.DiscoverNetwork.networkSeries": "{network} 電視節目",
"components.Discover.DiscoverTvGenre.genreSeries": "{genre}影集",
"components.Discover.DiscoverNetwork.networkSeries": "{network} 影集",
"components.Discover.DiscoverStudio.studioMovies": "{studio} 電影",
"components.Discover.DiscoverMovieGenre.genreMovies": "{genre}電影",
"i18n.loading": "載入中…",
@@ -565,7 +565,7 @@
"components.Settings.SettingsJobsCache.radarr-scan": "Radarr 掃描",
"components.Settings.SettingsJobsCache.plex-recently-added-scan": "Plex 最近新增掃描",
"components.Settings.SettingsJobsCache.plex-full-scan": "Plex 媒體庫掃描",
"components.Discover.DiscoverTvLanguage.languageSeries": "{language}電視節目",
"components.Discover.DiscoverTvLanguage.languageSeries": "{language}影集",
"components.Discover.DiscoverMovieLanguage.languageMovies": "{language}電影",
"components.UserProfile.ProfileHeader.userid": "使用者 ID{userid}",
"components.UserProfile.ProfileHeader.joindate": "加入日期:{joindate}",
@@ -587,11 +587,11 @@
"components.TvDetails.episodeRuntime": "劇集片長",
"components.TvDetails.episodeRuntimeMinutes": "{runtime} 分鐘",
"components.RequestModal.AdvancedRequester.folder": "{path}{space}",
"components.Discover.TvGenreSlider.tvgenres": "電視節目類型",
"components.Discover.TvGenreSlider.tvgenres": "影集類型",
"components.Discover.MovieGenreSlider.moviegenres": "電影類型",
"components.Discover.MovieGenreList.moviegenres": "電影類型",
"components.Discover.TvGenreList.seriesgenres": "電視節目類型",
"components.Settings.partialRequestsEnabled": "允許不完整的電視節目請求",
"components.Discover.TvGenreList.seriesgenres": "影集類型",
"components.Settings.partialRequestsEnabled": "允許不完整的影集請求",
"components.RequestModal.alreadyrequested": "已經有請求",
"components.Settings.SettingsLogs.time": "時間戳",
"components.Settings.SettingsLogs.resumeLogs": "恢復",
@@ -636,16 +636,16 @@
"components.PersonDetails.lifespan": "{birthdate}{deathdate}",
"components.PersonDetails.alsoknownas": "別名:{names}",
"i18n.delimitedlist": "{a}、{b}",
"components.Settings.SettingsUsers.tvRequestLimitLabel": "電視節目請求全域限制",
"components.Settings.SettingsUsers.tvRequestLimitLabel": "影集請求全域限制",
"components.Settings.SettingsUsers.movieRequestLimitLabel": "電影請求全域限制",
"components.RequestModal.QuotaDisplay.seasonlimit": "季數",
"components.RequestModal.QuotaDisplay.season": "電視節目季數",
"components.RequestModal.QuotaDisplay.season": "影集季數",
"components.RequestModal.QuotaDisplay.requestsremaining": "{remaining, plural, =0 {電影請求剩餘數不足} other {剩餘 <strong>#</strong> 個{type}請求}}",
"components.RequestModal.QuotaDisplay.notenoughseasonrequests": "請求剩餘數不足",
"components.RequestModal.QuotaDisplay.movielimit": "電影",
"components.RequestModal.QuotaDisplay.allowedRequestsUser": "此使用者每 <strong>{days}</strong> 天能提出 <strong>{limit}</strong> 個{type}請求。",
"components.RequestModal.QuotaDisplay.allowedRequests": "您每 <strong>{days}</strong> 天能提出 <strong>{limit}</strong> 個{type}請求。",
"components.UserProfile.UserSettings.UserGeneralSettings.seriesrequestlimit": "電視節目請求限制",
"components.UserProfile.UserSettings.UserGeneralSettings.seriesrequestlimit": "影集請求限制",
"components.UserProfile.UserSettings.UserGeneralSettings.movierequestlimit": "電影請求限制",
"components.UserProfile.movierequests": "電影請求",
"components.UserProfile.limit": "{limit} 之 {remaining}",
@@ -656,9 +656,9 @@
"components.UserProfile.UserSettings.UserGeneralSettings.enableOverride": "覆寫全域限制",
"components.UserProfile.unlimited": "無限",
"components.UserProfile.totalrequests": "請求總數",
"components.UserProfile.seriesrequest": "電視節目請求",
"components.UserProfile.seriesrequest": "影集請求",
"i18n.view": "檢視",
"i18n.tvshow": "電視節目",
"i18n.tvshow": "影集",
"i18n.testing": "測試中…",
"i18n.test": "測試",
"i18n.status": "狀態",
@@ -677,8 +677,8 @@
"i18n.back": "返回",
"i18n.all": "所有",
"i18n.areyousure": "確定嗎?",
"components.RequestModal.QuotaDisplay.requiredquotaUser": "此使用者的電視節目請求數量必須至少剩餘 <strong>{seasons}</strong> 個季數才能提出此節目請求。",
"components.RequestModal.QuotaDisplay.requiredquota": "您的電視節目請求數量必須至少剩餘 <strong>{seasons}</strong> 個季數才能提出此節目請求。",
"components.RequestModal.QuotaDisplay.requiredquotaUser": "此使用者的影集請求數量必須至少剩餘 <strong>{seasons}</strong> 個季數才能提出此影集請求。",
"components.RequestModal.QuotaDisplay.requiredquota": "您的影集請求數量必須至少剩餘 <strong>{seasons}</strong> 個季數才能提出此影集請求。",
"components.TvDetails.originaltitle": "原始標題",
"components.MovieDetails.originaltitle": "原始標題",
"components.RequestModal.QuotaDisplay.quotaLinkUser": "訪問此使用者的<ProfileLink>個人資料頁面</ProfileLink>以查看使用者的請求限制 。",
@@ -734,7 +734,7 @@
"components.Settings.noDefaultNon4kServer": "如果您只有一個 {serverType} 伺服器,請勿把它設定為 4K 伺服器。",
"components.Settings.noDefaultServer": "您必須至少指定一個預設 {serverType} 伺服器,才能處理{mediaType}請求。",
"components.Settings.serviceSettingsDescription": "關於 {serverType} 伺服器的設定。{serverType} 伺服器數沒有最大值限制,但您只能指定兩個預設伺服器(一個非 4K、一個 4K。",
"components.Settings.mediaTypeSeries": "電視節目",
"components.Settings.mediaTypeSeries": "影集",
"components.Settings.mediaTypeMovie": "電影",
"components.UserProfile.UserSettings.UserPasswordChange.noPasswordSet": "此使用者的帳戶目前沒有設密碼。若在以下設定密碼,此使用者就能使用「本地登入」。",
"components.UserProfile.UserSettings.UserPasswordChange.noPasswordSetOwnAccount": "您的帳戶目前沒有設密碼。若在以下設定密碼,您就能使用「本地登入」。",
@@ -792,10 +792,10 @@
"components.Settings.Notifications.NotificationsWebhook.toastWebhookTestSuccess": "Webhook 測試通知已發送!",
"components.Settings.SettingsUsers.newPlexLoginTip": "讓還沒匯入的 Plex 使用者登入",
"components.Settings.SettingsUsers.newPlexLogin": "允許新的 Plex 登入",
"components.PermissionEdit.requestTv": "提出電視節目請求",
"components.PermissionEdit.requestTv": "提出影集請求",
"components.PermissionEdit.requestMovies": "提出電影請求",
"components.PermissionEdit.requestMoviesDescription": "授予提出非 4K 電影請求的權限。",
"components.PermissionEdit.requestTvDescription": "授予提出非 4K 電視節目請求的權限。",
"components.PermissionEdit.requestTvDescription": "授予提出非 4K 影集請求的權限。",
"components.UserProfile.UserSettings.UserGeneralSettings.languageDefault": "預設設定({language}",
"components.Settings.locale": "顯示語言",
"components.DownloadBlock.estimatedtime": "預計:{time}",
@@ -879,16 +879,16 @@
"components.ManageSlideOver.manageModalNoRequests": "沒有請求。",
"components.ManageSlideOver.openarr": "開啟 {arr} 伺服器",
"components.ManageSlideOver.openarr4k": "開啟 4K {arr} 伺服器",
"components.ManageSlideOver.movie": "電影",
"components.ManageSlideOver.movie": "電影",
"components.ManageSlideOver.markavailable": "標記為可觀看",
"components.IssueModal.issueAudio": "音訊",
"components.ManageSlideOver.downloadstatus": "下載狀態",
"components.IssueModal.CreateIssueModal.allepisodes": "所有集數",
"components.ManageSlideOver.manageModalClearMediaWarning": "※這將會刪除包括使用者請求在內所有有關{mediaType}的資料。如果這{mediaType}存在於您的 Plex 伺服器,資料將會在媒體庫掃描時重新建立。",
"components.ManageSlideOver.manageModalClearMediaWarning": "※這將會刪除包括使用者請求在內所有有關{mediaType}的資料。如果這{mediaType}存在於您的 Plex 伺服器,資料將會在媒體庫掃描時重新建立。",
"components.ManageSlideOver.mark4kavailable": "標記 4K 版為可觀看",
"components.IssueModal.issueSubtitles": "字幕",
"components.IssueModal.issueOther": "其他",
"components.ManageSlideOver.tvshow": "個電視節目",
"components.ManageSlideOver.tvshow": "影集",
"components.ManageSlideOver.manageModalTitle": "管理{mediaType}",
"components.IssueModal.issueVideo": "影片",
"components.IssueList.IssueItem.issuetype": "類型",
@@ -1053,19 +1053,19 @@
"components.RequestList.RequestItem.tvdbid": "TheTVDB ID",
"components.Discover.plexwatchlist": "您的 Plex Watchlist",
"components.PermissionEdit.autorequestMovies": "自動提出電影請求",
"components.PermissionEdit.autorequestSeries": "自動提出電視節目請求",
"components.PermissionEdit.autorequestSeries": "自動提出影集請求",
"components.Settings.SettingsJobsCache.plex-watchlist-sync": "Plex Watchlist 同步",
"components.PermissionEdit.autorequest": "自動提出請求",
"components.Discover.DiscoverWatchlist.discoverwatchlist": "您的 Plex Watchlist",
"components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncmovies": "自動提出電影請求",
"components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseries": "自動提出電視節目請求",
"components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseries": "自動提出影集請求",
"components.NotificationTypeSelector.mediaautorequested": "請求自動提出",
"components.PermissionEdit.autorequestMoviesDescription": "授予從 Plex Watchlist 中自動提出非 4K 電影請求的權限。",
"components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncmoviestip": "從您的 <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink> 中自動提出電影請求",
"components.NotificationTypeSelector.mediaautorequestedDescription": "當您的 Plex Watchlist 中的媒體自動提出請求時取得通知。",
"components.PermissionEdit.autorequestDescription": "授予從 Plex Watchlist 中自動提出非 4K 媒體請求的權限。",
"components.PermissionEdit.autorequestSeriesDescription": "授予從 Plex Watchlist 中自動提出非 4K 電視節目請求的權限。",
"components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseriestip": "從您的 <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink> 中自動提出電視節目請求",
"components.PermissionEdit.autorequestSeriesDescription": "授予從 Plex Watchlist 中自動提出非 4K 影集請求的權限。",
"components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseriestip": "從您的 <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink> 中自動提出影集請求",
"components.Settings.SettingsLogs.viewdetails": "查看詳細信息",
"components.TvDetails.reportissue": "報告問題",
"components.MovieDetails.managemovie": "管理電影",
@@ -1074,10 +1074,10 @@
"components.MovieDetails.reportissue": "報告問題",
"components.PermissionEdit.viewwatchlists": "查看 Plex Watchlists",
"components.PermissionEdit.viewwatchlistsDescription": "授予查看其他使用者的 Plex Watchlists 的權限。",
"components.TvDetails.manageseries": "管理電視節目",
"components.TvDetails.manageseries": "管理影集",
"components.Settings.restartrequiredTooltip": "Jellyseerr 必須重新啟動才能應用設定的變更",
"components.Layout.UserDropdown.MiniQuotaDisplay.movierequests": "電影請求",
"components.Layout.UserDropdown.MiniQuotaDisplay.seriesrequests": "電視節目請求",
"components.Layout.UserDropdown.MiniQuotaDisplay.seriesrequests": "影集請求",
"components.Layout.UserDropdown.requests": "請求",
"components.TvDetails.seasonstitle": "季數",
"components.RequestBlock.decline": "拒絕請求",
@@ -1109,10 +1109,10 @@
"components.RequestModal.requestmovietitle": "提出電影請求",
"components.RequestModal.requestmovie4ktitle": "提出 4K 電影請求",
"components.RequestModal.requestcollection4ktitle": "提出 4K 電影系列請求",
"components.RequestModal.requestseriestitle": "提出電視節目請求",
"components.RequestModal.requestseries4ktitle": "提出 4K 電視節目請求",
"components.RequestModal.requestseriestitle": "提出影集請求",
"components.RequestModal.requestseries4ktitle": "提出 4K 影集請求",
"components.RequestModal.requestcollectiontitle": "提出電影系列請求",
"components.RequestModal.SearchByNameModal.nomatches": "找不到此電視節目的數據。",
"components.RequestModal.SearchByNameModal.nomatches": "找不到此影集的數據。",
"components.UserProfile.emptywatchlist": "您的 <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink> 中的媒體會顯示在這裡。",
"components.Discover.emptywatchlist": "您的 <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink> 中的媒體會顯示在這裡。",
"components.Settings.advancedTooltip": "錯誤的設定可能會破壞應用程式功能",

View File

@@ -11,6 +11,7 @@
body {
@apply bg-gray-900;
overscroll-behavior-y: contain;
}
code {
@@ -453,3 +454,22 @@
}
}
}
.ptr--ptr {
box-shadow: initial !important;
position: absolute !important;
z-index: 30 !important;
}
.ptr--refresh {
overflow: visible !important;
z-index: 30 !important;
}
.ptr--pull {
z-index: 30 !important;
}
.ptr--ptr .ptr--box {
margin-bottom: -13px !important;
}