refactor(lang): use global strings where appropriate and remove unused strings (#1265)

pull/1271/head
TheCatLady 3 years ago committed by GitHub
parent 544c2d9442
commit e393b53b29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -27,14 +27,10 @@ import Transition from '../Transition';
const messages = defineMessages({
overviewunavailable: 'Overview unavailable.',
overview: 'Overview',
movies: 'Movies',
numberofmovies: '{count} Movies',
requesting: 'Requesting…',
request: 'Request',
requestcollection: 'Request Collection',
requestswillbecreated:
'The following titles will have requests created for them:',
request4k: 'Request 4K',
requestcollection4k: 'Request Collection in 4K',
requestswillbecreated4k:
'The following titles will have 4K requests created for them:',
@ -242,8 +238,10 @@ const CollectionDetails: React.FC<CollectionDetailsProps> = ({
onOk={() => requestBundle()}
okText={
isRequesting
? intl.formatMessage(messages.requesting)
: intl.formatMessage(is4k ? messages.request4k : messages.request)
? intl.formatMessage(globalMessages.requesting)
: intl.formatMessage(
is4k ? globalMessages.request4k : globalMessages.request
)
}
okDisabled={isRequesting}
okButtonType="primary"
@ -431,7 +429,7 @@ const CollectionDetails: React.FC<CollectionDetailsProps> = ({
</div>
<div className="slider-header">
<div className="slider-title">
<span>{intl.formatMessage(messages.movies)}</span>
<span>{intl.formatMessage(globalMessages.movies)}</span>
</div>
</div>
<Slider

@ -1,17 +1,14 @@
import React from 'react';
import { useIntl } from 'react-intl';
import {
TvResult,
MovieResult,
PersonResult,
TvResult,
} from '../../../../server/models/Search';
import TitleCard from '../../TitleCard';
import useVerticalScroll from '../../../hooks/useVerticalScroll';
import globalMessages from '../../../i18n/globalMessages';
import PersonCard from '../../PersonCard';
import { defineMessages, useIntl } from 'react-intl';
const messages = defineMessages({
noresults: 'No results.',
});
import TitleCard from '../../TitleCard';
interface ListViewProps {
items?: (TvResult | MovieResult | PersonResult)[];
@ -34,7 +31,7 @@ const ListView: React.FC<ListViewProps> = ({
<>
{isEmpty && (
<div className="w-full mt-64 text-2xl text-center text-gray-400">
{intl.formatMessage(messages.noresults)}
{intl.formatMessage(globalMessages.noresults)}
</div>
)}
<ul className="cards-vertical">

@ -36,7 +36,6 @@ import StatusBadge from '../StatusBadge';
const messages = defineMessages({
releasedate: 'Release Date',
status: 'Status',
revenue: 'Revenue',
budget: 'Budget',
watchtrailer: 'Watch Trailer',
@ -55,8 +54,6 @@ const messages = defineMessages({
'* This will irreversibly remove all data for this movie, including any requests. If this item exists in your Plex library, the media information will be recreated during the next scan.',
studio: '{studioCount, plural, one {Studio} other {Studios}}',
viewfullcrew: 'View Full Crew',
view: 'View',
areyousure: 'Are you sure?',
openradarr: 'Open Movie in Radarr',
openradarr4k: 'Open Movie in 4K Radarr',
downloadstatus: 'Download Status',
@ -382,7 +379,7 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
<div className="mt-8">
<ConfirmButton
onClick={() => deleteMedia()}
confirmText={intl.formatMessage(messages.areyousure)}
confirmText={intl.formatMessage(globalMessages.areyousure)}
className="w-full"
>
{intl.formatMessage(messages.manageModalClearMedia)}
@ -557,7 +554,7 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
<div className="relative z-10 flex items-center justify-between p-4 text-gray-200 transition duration-300 h-14 group-hover:text-white">
<div>{data.collection.name}</div>
<Button buttonSize="sm">
{intl.formatMessage(messages.view)}
{intl.formatMessage(globalMessages.view)}
</Button>
</div>
</div>
@ -605,7 +602,7 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
</div>
)}
<div className="media-fact">
<span>{intl.formatMessage(messages.status)}</span>
<span>{intl.formatMessage(globalMessages.status)}</span>
<span className="media-fact-value">{data.status}</span>
</div>
{data.releaseDate && (

@ -1,10 +1,10 @@
import React, { useState } from 'react';
import PlexOAuth from '../../utils/plex';
import { defineMessages, useIntl } from 'react-intl';
import globalMessages from '../../i18n/globalMessages';
import PlexOAuth from '../../utils/plex';
const messages = defineMessages({
signinwithplex: 'Sign In',
loading: 'Loading…',
signingin: 'Signing in…',
});
@ -49,7 +49,7 @@ const PlexLoginButton: React.FC<PlexLoginButtonProps> = ({
className="plex-button"
>
{loading
? intl.formatMessage(messages.loading)
? intl.formatMessage(globalMessages.loading)
: isProcessing
? intl.formatMessage(messages.signingin)
: intl.formatMessage(messages.signinwithplex)}

@ -2,8 +2,8 @@ import React, { useEffect, useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
const messages = defineMessages({
movieRequestLimit: '{quotaLimit} movies per {quotaDays} days',
tvRequestLimit: '{quotaLimit} seasons per {quotaDays} days',
movieRequestLimit: '{quotaLimit} movie(s) per {quotaDays} day(s)',
tvRequestLimit: '{quotaLimit} season(s) per {quotaDays} day(s)',
unlimited: 'Unlimited',
});

@ -9,14 +9,13 @@ import Media from '../../../server/entity/Media';
import { MediaRequest } from '../../../server/entity/MediaRequest';
import useSettings from '../../hooks/useSettings';
import { Permission, useUser } from '../../hooks/useUser';
import globalMessages from '../../i18n/globalMessages';
import ButtonWithDropdown from '../Common/ButtonWithDropdown';
import RequestModal from '../RequestModal';
const messages = defineMessages({
viewrequest: 'View Request',
viewrequest4k: 'View 4K Request',
request: 'Request',
request4k: 'Request 4K',
requestmore: 'Request More',
requestmore4k: 'Request More 4K',
approverequest: 'Approve Request',
@ -114,7 +113,7 @@ const RequestButton: React.FC<RequestButtonProps> = ({
) {
buttons.push({
id: 'request',
text: intl.formatMessage(messages.request),
text: intl.formatMessage(globalMessages.request),
action: () => {
setShowRequestModal(true);
},
@ -180,7 +179,7 @@ const RequestButton: React.FC<RequestButtonProps> = ({
) {
buttons.push({
id: 'request4k',
text: intl.formatMessage(messages.request4k),
text: intl.formatMessage(globalMessages.request4k),
action: () => {
setShowRequest4kModal(true);
},

@ -1,29 +1,27 @@
import axios from 'axios';
import Link from 'next/link';
import React, { useContext, useEffect } from 'react';
import { useInView } from 'react-intersection-observer';
import type { MediaRequest } from '../../../server/entity/MediaRequest';
import type { TvDetails } from '../../../server/models/Tv';
import type { MovieDetails } from '../../../server/models/Movie';
import { defineMessages, useIntl } from 'react-intl';
import useSWR from 'swr';
import { LanguageContext } from '../../context/LanguageContext';
import {
MediaRequestStatus,
MediaStatus,
} from '../../../server/constants/media';
import type { MediaRequest } from '../../../server/entity/MediaRequest';
import type { MovieDetails } from '../../../server/models/Movie';
import type { TvDetails } from '../../../server/models/Tv';
import { LanguageContext } from '../../context/LanguageContext';
import { Permission, useUser } from '../../hooks/useUser';
import globalMessages from '../../i18n/globalMessages';
import { withProperties } from '../../utils/typeHelpers';
import Badge from '../Common/Badge';
import { useUser, Permission } from '../../hooks/useUser';
import axios from 'axios';
import Button from '../Common/Button';
import { withProperties } from '../../utils/typeHelpers';
import Link from 'next/link';
import { defineMessages, useIntl } from 'react-intl';
import globalMessages from '../../i18n/globalMessages';
import StatusBadge from '../StatusBadge';
import CachedImage from '../Common/CachedImage';
import StatusBadge from '../StatusBadge';
const messages = defineMessages({
status: 'Status',
seasons: '{seasonCount, plural, one {Season} other {Seasons}}',
all: 'All',
});
const isMovie = (movie: MovieDetails | TvDetails): movie is MovieDetails => {
@ -156,7 +154,7 @@ const RequestCard: React.FC<RequestCardProps> = ({ request, onTitleData }) => {
{title.seasons.filter((season) => season.seasonNumber !== 0)
.length === request.seasons.length ? (
<span className="mr-2 uppercase">
<Badge>{intl.formatMessage(messages.all)}</Badge>
<Badge>{intl.formatMessage(globalMessages.all)}</Badge>
</span>
) : (
<div className="overflow-x-scroll hide-scrollbar">
@ -171,7 +169,7 @@ const RequestCard: React.FC<RequestCardProps> = ({ request, onTitleData }) => {
)}
<div className="flex items-center mt-2 text-sm sm:mt-1">
<span className="hidden mr-2 font-medium sm:block">
{intl.formatMessage(messages.status)}
{intl.formatMessage(globalMessages.status)}
</span>
{requestData.media[requestData.is4k ? 'status4k' : 'status'] ===
MediaStatus.UNKNOWN ||

@ -1,34 +1,30 @@
import axios from 'axios';
import Link from 'next/link';
import React, { useContext, useState } from 'react';
import { useInView } from 'react-intersection-observer';
import type { MediaRequest } from '../../../../server/entity/MediaRequest';
import { useIntl, FormattedRelativeTime, defineMessages } from 'react-intl';
import { useUser, Permission } from '../../../hooks/useUser';
import { LanguageContext } from '../../../context/LanguageContext';
import type { MovieDetails } from '../../../../server/models/Movie';
import type { TvDetails } from '../../../../server/models/Tv';
import { defineMessages, FormattedRelativeTime, useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import Badge from '../../Common/Badge';
import StatusBadge from '../../StatusBadge';
import {
MediaRequestStatus,
MediaStatus,
} from '../../../../server/constants/media';
import Button from '../../Common/Button';
import axios from 'axios';
import type { MediaRequest } from '../../../../server/entity/MediaRequest';
import type { MovieDetails } from '../../../../server/models/Movie';
import type { TvDetails } from '../../../../server/models/Tv';
import { LanguageContext } from '../../../context/LanguageContext';
import { Permission, useUser } from '../../../hooks/useUser';
import globalMessages from '../../../i18n/globalMessages';
import Link from 'next/link';
import { useToasts } from 'react-toast-notifications';
import RequestModal from '../../RequestModal';
import ConfirmButton from '../../Common/ConfirmButton';
import Badge from '../../Common/Badge';
import Button from '../../Common/Button';
import CachedImage from '../../Common/CachedImage';
import ConfirmButton from '../../Common/ConfirmButton';
import RequestModal from '../../RequestModal';
import StatusBadge from '../../StatusBadge';
const messages = defineMessages({
seasons: '{seasonCount, plural, one {Season} other {Seasons}}',
all: 'All',
notavailable: 'N/A',
failedretry: 'Something went wrong while retrying the request.',
areyousure: 'Are you sure?',
status: 'Status',
requested: 'Requested',
modified: 'Modified',
modifieduserdate: '{date} by {user}',
@ -218,7 +214,7 @@ const RequestItem: React.FC<RequestItemProps> = ({
{title.seasons.filter((season) => season.seasonNumber !== 0)
.length === request.seasons.length ? (
<span className="mr-2 uppercase">
<Badge>{intl.formatMessage(messages.all)}</Badge>
<Badge>{intl.formatMessage(globalMessages.all)}</Badge>
</span>
) : (
<div className="flex overflow-x-scroll hide-scrollbar flex-nowrap">
@ -236,7 +232,7 @@ const RequestItem: React.FC<RequestItemProps> = ({
<div className="z-10 flex flex-col justify-center w-full pr-4 mt-4 ml-4 text-sm sm:ml-2 sm:mt-0 xl:flex-1 xl:pr-0">
<div className="card-field">
<span className="card-field-name">
{intl.formatMessage(messages.status)}
{intl.formatMessage(globalMessages.status)}
</span>
{requestData.media[requestData.is4k ? 'status4k' : 'status'] ===
MediaStatus.UNKNOWN ||
@ -349,7 +345,7 @@ const RequestItem: React.FC<RequestItemProps> = ({
hasPermission(Permission.MANAGE_REQUESTS) && (
<ConfirmButton
onClick={() => deleteRequest()}
confirmText={intl.formatMessage(messages.areyousure)}
confirmText={intl.formatMessage(globalMessages.areyousure)}
className="w-full"
>
<svg

@ -1,27 +1,17 @@
import { useRouter } from 'next/router';
import React, { useEffect, useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import useSWR from 'swr';
import type { RequestResultsResponse } from '../../../server/interfaces/api/requestInterfaces';
import LoadingSpinner from '../Common/LoadingSpinner';
import RequestItem from './RequestItem';
import Header from '../Common/Header';
import globalMessages from '../../i18n/globalMessages';
import Button from '../Common/Button';
import { defineMessages, useIntl } from 'react-intl';
import Header from '../Common/Header';
import LoadingSpinner from '../Common/LoadingSpinner';
import PageTitle from '../Common/PageTitle';
import { useRouter } from 'next/router';
import RequestItem from './RequestItem';
const messages = defineMessages({
requests: 'Requests',
showingresults:
'Showing <strong>{from}</strong> to <strong>{to}</strong> of <strong>{total}</strong> results',
resultsperpage: 'Display {pageSize} results per page',
next: 'Next',
previous: 'Previous',
filterAll: 'All',
filterPending: 'Pending',
filterApproved: 'Approved',
filterAvailable: 'Available',
filterProcessing: 'Processing',
noresults: 'No results.',
showallrequests: 'Show All Requests',
sortAdded: 'Request Date',
sortModified: 'Last Modified',
@ -114,19 +104,19 @@ const RequestList: React.FC = () => {
className="rounded-r-only"
>
<option value="all">
{intl.formatMessage(messages.filterAll)}
{intl.formatMessage(globalMessages.all)}
</option>
<option value="pending">
{intl.formatMessage(messages.filterPending)}
{intl.formatMessage(globalMessages.pending)}
</option>
<option value="approved">
{intl.formatMessage(messages.filterApproved)}
{intl.formatMessage(globalMessages.approved)}
</option>
<option value="processing">
{intl.formatMessage(messages.filterProcessing)}
{intl.formatMessage(globalMessages.processing)}
</option>
<option value="available">
{intl.formatMessage(messages.filterAvailable)}
{intl.formatMessage(globalMessages.available)}
</option>
</select>
</div>
@ -175,7 +165,7 @@ const RequestList: React.FC = () => {
{data.results.length === 0 && (
<div className="flex flex-col items-center justify-center w-full py-24 text-white">
<span className="text-2xl text-gray-400">
{intl.formatMessage(messages.noresults)}
{intl.formatMessage(globalMessages.noresults)}
</span>
{currentFilter !== 'all' && (
<div className="mt-4">
@ -197,7 +187,7 @@ const RequestList: React.FC = () => {
<div className="hidden lg:flex lg:flex-1">
<p className="text-sm">
{data.results.length > 0 &&
intl.formatMessage(messages.showingresults, {
intl.formatMessage(globalMessages.showingresults, {
from: pageIndex * currentPageSize + 1,
to:
data.results.length < currentPageSize
@ -212,7 +202,7 @@ const RequestList: React.FC = () => {
</div>
<div className="flex justify-center sm:flex-1 sm:justify-start lg:justify-center">
<span className="items-center -mt-3 text-sm truncate sm:mt-0">
{intl.formatMessage(messages.resultsperpage, {
{intl.formatMessage(globalMessages.resultsperpage, {
pageSize: (
<select
id="pageSize"
@ -247,7 +237,7 @@ const RequestList: React.FC = () => {
.then(() => window.scrollTo(0, 0))
}
>
{intl.formatMessage(messages.previous)}
{intl.formatMessage(globalMessages.previous)}
</Button>
<Button
disabled={!hasNextPage}
@ -259,7 +249,7 @@ const RequestList: React.FC = () => {
.then(() => window.scrollTo(0, 0))
}
>
{intl.formatMessage(messages.next)}
{intl.formatMessage(globalMessages.next)}
</Button>
</div>
</nav>

@ -1,16 +1,17 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { Listbox, Transition } from '@headlessui/react';
import React, { useEffect, useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import useSWR from 'swr';
import { SmallLoadingSpinner } from '../../Common/LoadingSpinner';
import type {
ServiceCommonServer,
ServiceCommonServerWithDetails,
} from '../../../../server/interfaces/api/serviceInterfaces';
import { defineMessages, useIntl } from 'react-intl';
import { formatBytes } from '../../../utils/numberHelpers';
import { Listbox, Transition } from '@headlessui/react';
import { Permission, User, useUser } from '../../../hooks/useUser';
import type { UserResultsResponse } from '../../../../server/interfaces/api/userInterfaces';
import { Permission, User, useUser } from '../../../hooks/useUser';
import globalMessages from '../../../i18n/globalMessages';
import { formatBytes } from '../../../utils/numberHelpers';
import { SmallLoadingSpinner } from '../../Common/LoadingSpinner';
const messages = defineMessages({
advancedoptions: 'Advanced Options',
@ -22,7 +23,6 @@ const messages = defineMessages({
folder: '{path} ({space})',
requestas: 'Request As',
languageprofile: 'Language Profile',
loading: 'Loading…',
});
export type RequestOverrides = {
@ -307,7 +307,7 @@ const AdvancedRequester: React.FC<AdvancedRequesterProps> = ({
>
{(isValidating || !serverData) && (
<option value="">
{intl.formatMessage(messages.loading)}
{intl.formatMessage(globalMessages.loading)}
</option>
)}
{!isValidating &&
@ -351,7 +351,7 @@ const AdvancedRequester: React.FC<AdvancedRequesterProps> = ({
>
{(isValidating || !serverData) && (
<option value="">
{intl.formatMessage(messages.loading)}
{intl.formatMessage(globalMessages.loading)}
</option>
)}
{!isValidating &&
@ -405,7 +405,7 @@ const AdvancedRequester: React.FC<AdvancedRequesterProps> = ({
>
{(isValidating || !serverData) && (
<option value="">
{intl.formatMessage(messages.loading)}
{intl.formatMessage(globalMessages.loading)}
</option>
)}
{!isValidating &&

@ -20,25 +20,18 @@ import AdvancedRequester, { RequestOverrides } from './AdvancedRequester';
import QuotaDisplay from './QuotaDisplay';
const messages = defineMessages({
requestadmin: 'Your request will be approved automatically.',
cancelrequest:
'This will remove your request. Are you sure you want to continue?',
requestadmin: 'This request will be approved automatically.',
requestSuccess: '<strong>{title}</strong> requested successfully!',
requestCancel: 'Request for <strong>{title}</strong> canceled.',
requesttitle: 'Request {title}',
request4ktitle: 'Request {title} in 4K',
close: 'Close',
cancel: 'Cancel Request',
cancelling: 'Canceling…',
pendingrequest: 'Pending Request for {title}',
pending4krequest: 'Pending Request for {title} in 4K',
requesting: 'Requesting…',
request: 'Request',
request4k: 'Request 4K',
requestfrom: 'There is currently a pending request from {username}.',
request4kfrom: 'There is currently a pending 4K request from {username}.',
errorediting: 'Something went wrong while editing the request.',
requestedited: 'Request edited.',
requestedited: 'Request for <strong>{title}</strong> edited successfully!',
requesterror: 'Something went wrong while submitting the request.',
});
@ -182,10 +175,20 @@ const MovieRequestModal: React.FC<RequestModalProps> = ({
userId: requestOverrides?.user?.id,
});
addToast(<span>{intl.formatMessage(messages.requestedited)}</span>, {
appearance: 'success',
autoDismiss: true,
});
addToast(
<span>
{intl.formatMessage(messages.requestedited, {
title: data?.title,
strong: function strong(msg) {
return <strong>{msg}</strong>;
},
})}
</span>,
{
appearance: 'success',
autoDismiss: true,
}
);
if (onComplete) {
onComplete(MediaStatus.PENDING);
@ -225,11 +228,11 @@ const MovieRequestModal: React.FC<RequestModalProps> = ({
secondaryDisabled={isUpdating}
secondaryText={
isUpdating
? intl.formatMessage(messages.cancelling)
? intl.formatMessage(globalMessages.canceling)
: intl.formatMessage(messages.cancel)
}
secondaryButtonType="danger"
cancelText={intl.formatMessage(messages.close)}
cancelText={intl.formatMessage(globalMessages.close)}
iconSvg={<DownloadIcon className="w-6 h-6" />}
>
{intl.formatMessage(
@ -286,8 +289,10 @@ const MovieRequestModal: React.FC<RequestModalProps> = ({
)}
okText={
isUpdating
? intl.formatMessage(messages.requesting)
: intl.formatMessage(is4k ? messages.request4k : messages.request)
? intl.formatMessage(globalMessages.requesting)
: intl.formatMessage(
is4k ? globalMessages.request4k : globalMessages.request
)
}
okButtonType={'primary'}
iconSvg={<DownloadIcon className="w-6 h-6" />}

@ -6,7 +6,7 @@ import ProgressCircle from '../../Common/ProgressCircle';
const messages = defineMessages({
requestsremaining:
'{remaining, plural, =0 {No} other {<strong>#</strong>}} {type} {remaining, plural, one {requests} other {requests}} remaining',
'{remaining, plural, =0 {No} other {<strong>#</strong>}} {type} {remaining, plural, one {request} other {requests}} remaining',
movielimit: '{limit, plural, one {movie} other {movies}}',
seasonlimit: '{limit, plural, one {season} other {seasons}}',
allowedRequests:
@ -22,6 +22,8 @@ const messages = defineMessages({
notenoughseasonrequests: 'Not enough season requests remaining',
requiredquota:
'You need to have at least <strong>{seasons}</strong> {seasons, plural, one {season request} other {season requests}} remaining in order to submit a request for this series.',
requiredquotaUser:
'This user needs to have at least <strong>{seasons}</strong> {seasons, plural, one {season request} other {season requests}} remaining in order to submit a request for this series.',
});
interface QuotaDisplayProps {
@ -120,12 +122,17 @@ const QuotaDisplay: React.FC<QuotaDisplayProps> = ({
<div className="mt-4">
{overLimit !== undefined && (
<div className="mb-2">
{intl.formatMessage(messages.requiredquota, {
seasons: overLimit,
strong: function strong(msg) {
return <span className="font-bold">{msg}</span>;
},
})}
{intl.formatMessage(
userOverride
? messages.requiredquota
: messages.requiredquotaUser,
{
seasons: overLimit,
strong: function strong(msg) {
return <span className="font-bold">{msg}</span>;
},
}
)}
</div>
)}
<div>

@ -2,12 +2,12 @@ import React from 'react';
import { defineMessages, useIntl } from 'react-intl';
import useSWR from 'swr';
import { SonarrSeries } from '../../../../server/api/sonarr';
import globalMessages from '../../../i18n/globalMessages';
import Alert from '../../Common/Alert';
import { SmallLoadingSpinner } from '../../Common/LoadingSpinner';
import Modal from '../../Common/Modal';
const messages = defineMessages({
next: 'Next',
notvdbid: 'Manual Match Required',
notvdbiddescription:
"We couldn't automatically match your request. Please select the correct match from the list below.",
@ -49,7 +49,7 @@ const SearchByNameModal: React.FC<SearchByNameModalProps> = ({
onCancel={onCancel}
onOk={closeModal}
title={modalTitle}
okText={intl.formatMessage(messages.next)}
okText={intl.formatMessage(globalMessages.next)}
okDisabled={!tvdbId}
okButtonType="primary"
iconSvg={

@ -24,13 +24,10 @@ import QuotaDisplay from './QuotaDisplay';
import SearchByNameModal from './SearchByNameModal';
const messages = defineMessages({
requestadmin: 'Your request will be approved automatically.',
cancelrequest:
'This will remove your request. Are you sure you want to continue?',
requestadmin: 'This request will be approved automatically.',
requestSuccess: '<strong>{title}</strong> requested successfully!',
requesttitle: 'Request {title}',
request4ktitle: 'Request {title} in 4K',
requesting: 'Requesting…',
requestseasons:
'Request {seasonCount} {seasonCount, plural, one {Season} other {Seasons}}',
requestall: 'Request All Seasons',
@ -38,16 +35,13 @@ const messages = defineMessages({
selectseason: 'Select Season(s)',
season: 'Season',
numberofepisodes: '# of Episodes',
status: 'Status',
seasonnumber: 'Season {number}',
extras: 'Extras',
notrequested: 'Not Requested',
errorediting: 'Something went wrong while editing the request.',
requestedited: 'Request edited.',
requestcancelled: 'Request canceled.',
requestedited: 'Request for <strong>{title}</strong> edited successfully!',
requestcancelled: 'Request for <strong>{title}</strong> canceled.',
autoapproval: 'Automatic Approval',
requesterror: 'Something went wrong while submitting the request.',
backbutton: 'Back',
});
interface RequestModalProps extends React.HTMLAttributes<HTMLDivElement> {
@ -122,8 +116,18 @@ const TvRequestModal: React.FC<RequestModalProps> = ({
addToast(
<span>
{selectedSeasons.length > 0
? intl.formatMessage(messages.requestedited)
: intl.formatMessage(messages.requestcancelled)}
? intl.formatMessage(messages.requestedited, {
title: data?.name,
strong: function strong(msg) {
return <strong>{msg}</strong>;
},
})
: intl.formatMessage(messages.requestcancelled, {
title: data?.name,
strong: function strong(msg) {
return <strong>{msg}</strong>;
},
})}
</span>,
{
appearance: 'success',
@ -390,7 +394,7 @@ const TvRequestModal: React.FC<RequestModalProps> = ({
}
cancelText={
tvdbId
? intl.formatMessage(messages.backbutton)
? intl.formatMessage(globalMessages.back)
: intl.formatMessage(globalMessages.cancel)
}
iconSvg={
@ -507,7 +511,7 @@ const TvRequestModal: React.FC<RequestModalProps> = ({
{intl.formatMessage(messages.numberofepisodes)}
</th>
<th className="px-2 py-3 text-xs font-medium leading-4 tracking-wider text-left text-gray-200 uppercase bg-gray-500 md:px-6">
{intl.formatMessage(messages.status)}
{intl.formatMessage(globalMessages.status)}
</th>
</tr>
</thead>
@ -601,7 +605,9 @@ const TvRequestModal: React.FC<RequestModalProps> = ({
<td className="py-4 pr-2 text-sm leading-5 text-gray-200 md:px-6 whitespace-nowrap">
{!seasonRequest && !mediaSeason && (
<Badge>
{intl.formatMessage(messages.notrequested)}
{intl.formatMessage(
globalMessages.notrequested
)}
</Badge>
)}
{!mediaSeason &&

@ -1,17 +1,16 @@
import React from 'react';
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import useSWR from 'swr';
import LoadingSpinner from '../../Common/LoadingSpinner';
import Button from '../../Common/Button';
import React from 'react';
import { defineMessages, useIntl } from 'react-intl';
import axios from 'axios';
import * as Yup from 'yup';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import * as Yup from 'yup';
import globalMessages from '../../../i18n/globalMessages';
import Button from '../../Common/Button';
import LoadingSpinner from '../../Common/LoadingSpinner';
import NotificationTypeSelector from '../../NotificationTypeSelector';
const messages = defineMessages({
save: 'Save Changes',
saving: 'Saving…',
agentenabled: 'Enable Agent',
botUsername: 'Bot Username',
botAvatarUrl: 'Bot Avatar URL',
@ -20,7 +19,6 @@ const messages = defineMessages({
discordsettingssaved: 'Discord notification settings saved successfully!',
discordsettingsfailed: 'Discord notification settings failed to save.',
testsent: 'Test notification sent!',
test: 'Test',
notificationtypes: 'Notification Types',
validationUrl: 'You must provide a valid URL',
});
@ -197,7 +195,7 @@ const NotificationsDiscord: React.FC = () => {
testSettings();
}}
>
{intl.formatMessage(messages.test)}
{intl.formatMessage(globalMessages.test)}
</Button>
</span>
<span className="inline-flex ml-3 rounded-md shadow-sm">
@ -207,8 +205,8 @@ const NotificationsDiscord: React.FC = () => {
disabled={isSubmitting || !isValid}
>
{isSubmitting
? intl.formatMessage(messages.saving)
: intl.formatMessage(messages.save)}
? intl.formatMessage(globalMessages.saving)
: intl.formatMessage(globalMessages.save)}
</Button>
</span>
</div>

@ -13,8 +13,6 @@ import LoadingSpinner from '../../Common/LoadingSpinner';
import NotificationTypeSelector from '../../NotificationTypeSelector';
const messages = defineMessages({
save: 'Save Changes',
saving: 'Saving…',
validationSmtpHostRequired: 'You must provide a hostname or IP address',
validationSmtpPortRequired: 'You must provide a valid port number',
agentenabled: 'Enable Agent',
@ -26,7 +24,6 @@ const messages = defineMessages({
authPass: 'SMTP Password',
emailsettingssaved: 'Email notification settings saved successfully!',
emailsettingsfailed: 'Email notification settings failed to save.',
test: 'Test',
testsent: 'Test notification sent!',
allowselfsigned: 'Allow Self-Signed Certificates',
ssldisabletip:
@ -407,7 +404,7 @@ const NotificationsEmail: React.FC = () => {
testSettings();
}}
>
{intl.formatMessage(messages.test)}
{intl.formatMessage(globalMessages.test)}
</Button>
</span>
<span className="inline-flex ml-3 rounded-md shadow-sm">
@ -417,8 +414,8 @@ const NotificationsEmail: React.FC = () => {
disabled={isSubmitting || !isValid}
>
{isSubmitting
? intl.formatMessage(messages.saving)
: intl.formatMessage(messages.save)}
? intl.formatMessage(globalMessages.saving)
: intl.formatMessage(globalMessages.save)}
</Button>
</span>
</div>

@ -1,18 +1,17 @@
import React from 'react';
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import useSWR from 'swr';
import LoadingSpinner from '../../../Common/LoadingSpinner';
import Button from '../../../Common/Button';
import React from 'react';
import { defineMessages, useIntl } from 'react-intl';
import axios from 'axios';
import * as Yup from 'yup';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import * as Yup from 'yup';
import globalMessages from '../../../../i18n/globalMessages';
import Alert from '../../../Common/Alert';
import Button from '../../../Common/Button';
import LoadingSpinner from '../../../Common/LoadingSpinner';
import NotificationTypeSelector from '../../../NotificationTypeSelector';
const messages = defineMessages({
save: 'Save Changes',
saving: 'Saving…',
agentEnabled: 'Enable Agent',
accessToken: 'Access Token',
validationAccessTokenRequired: 'You must provide an access token',
@ -20,7 +19,6 @@ const messages = defineMessages({
'Pushbullet notification settings saved successfully!',
pushbulletSettingsFailed: 'Pushbullet notification settings failed to save.',
testSent: 'Test notification sent!',
test: 'Test',
settingUpPushbullet: 'Setting Up Pushbullet Notifications',
settingUpPushbulletDescription:
'To configure Pushbullet notifications, you will need to <CreateAccessTokenLink>create an access token</CreateAccessTokenLink> and enter it below.',
@ -174,7 +172,7 @@ const NotificationsPushbullet: React.FC = () => {
testSettings();
}}
>
{intl.formatMessage(messages.test)}
{intl.formatMessage(globalMessages.test)}
</Button>
</span>
<span className="inline-flex ml-3 rounded-md shadow-sm">
@ -184,8 +182,8 @@ const NotificationsPushbullet: React.FC = () => {
disabled={isSubmitting || !isValid}
>
{isSubmitting
? intl.formatMessage(messages.saving)
: intl.formatMessage(messages.save)}
? intl.formatMessage(globalMessages.saving)
: intl.formatMessage(globalMessages.save)}
</Button>
</span>
</div>

@ -5,14 +5,13 @@ import { defineMessages, useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import * as Yup from 'yup';
import globalMessages from '../../../../i18n/globalMessages';
import Alert from '../../../Common/Alert';
import Button from '../../../Common/Button';
import LoadingSpinner from '../../../Common/LoadingSpinner';
import NotificationTypeSelector from '../../../NotificationTypeSelector';
const messages = defineMessages({
save: 'Save Changes',
saving: 'Saving…',
agentenabled: 'Enable Agent',
accessToken: 'Application/API Token',
userToken: 'User Key',
@ -21,7 +20,6 @@ const messages = defineMessages({
pushoversettingssaved: 'Pushover notification settings saved successfully!',
pushoversettingsfailed: 'Pushover notification settings failed to save.',
testsent: 'Test notification sent!',
test: 'Test',
settinguppushover: 'Setting Up Pushover Notifications',
settinguppushoverDescription:
'To configure Pushover notifications, you will need to <RegisterApplicationLink>register an application</RegisterApplicationLink> and enter the API token below. (You can use one of our <IconLink>official icons on GitHub</IconLink>.) You will also need your user key.',
@ -218,7 +216,7 @@ const NotificationsPushover: React.FC = () => {
testSettings();
}}
>
{intl.formatMessage(messages.test)}
{intl.formatMessage(globalMessages.test)}
</Button>
</span>
<span className="inline-flex ml-3 rounded-md shadow-sm">
@ -228,8 +226,8 @@ const NotificationsPushover: React.FC = () => {
disabled={isSubmitting || !isValid}
>
{isSubmitting
? intl.formatMessage(messages.saving)
: intl.formatMessage(messages.save)}
? intl.formatMessage(globalMessages.saving)
: intl.formatMessage(globalMessages.save)}
</Button>
</span>
</div>

@ -1,24 +1,22 @@
import React from 'react';
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import useSWR from 'swr';
import LoadingSpinner from '../../../Common/LoadingSpinner';
import Button from '../../../Common/Button';
import React from 'react';
import { defineMessages, useIntl } from 'react-intl';
import axios from 'axios';
import * as Yup from 'yup';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import * as Yup from 'yup';
import globalMessages from '../../../../i18n/globalMessages';
import Alert from '../../../Common/Alert';
import Button from '../../../Common/Button';
import LoadingSpinner from '../../../Common/LoadingSpinner';
import NotificationTypeSelector from '../../../NotificationTypeSelector';
const messages = defineMessages({
save: 'Save Changes',
saving: 'Saving…',
agentenabled: 'Enable Agent',
webhookUrl: 'Webhook URL',
slacksettingssaved: 'Slack notification settings saved successfully!',
slacksettingsfailed: 'Slack notification settings failed to save.',
testsent: 'Test notification sent!',
test: 'Test',
settingupslack: 'Setting Up Slack Notifications',
settingupslackDescription:
'To configure Slack notifications, you will need to create an <WebhookLink>Incoming Webhook</WebhookLink> integration and enter the webhook URL below.',
@ -172,7 +170,7 @@ const NotificationsSlack: React.FC = () => {
testSettings();
}}
>
{intl.formatMessage(messages.test)}
{intl.formatMessage(globalMessages.test)}
</Button>
</span>
<span className="inline-flex ml-3 rounded-md shadow-sm">
@ -182,8 +180,8 @@ const NotificationsSlack: React.FC = () => {
disabled={isSubmitting || !isValid}
>
{isSubmitting
? intl.formatMessage(messages.saving)
: intl.formatMessage(messages.save)}
? intl.formatMessage(globalMessages.saving)
: intl.formatMessage(globalMessages.save)}
</Button>
</span>
</div>

@ -5,14 +5,13 @@ import { defineMessages, useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import * as Yup from 'yup';
import globalMessages from '../../../i18n/globalMessages';
import Alert from '../../Common/Alert';
import Button from '../../Common/Button';
import LoadingSpinner from '../../Common/LoadingSpinner';
import NotificationTypeSelector from '../../NotificationTypeSelector';
const messages = defineMessages({
save: 'Save Changes',
saving: 'Saving…',
agentenabled: 'Enable Agent',
botUsername: 'Bot Username',
botAPI: 'Bot Authentication Token',
@ -22,7 +21,6 @@ const messages = defineMessages({
telegramsettingssaved: 'Telegram notification settings saved successfully!',
telegramsettingsfailed: 'Telegram notification settings failed to save.',
testsent: 'Test notification sent!',
test: 'Test',
settinguptelegram: 'Setting Up Telegram Notifications',
settinguptelegramDescription:
'To configure Telegram notifications, you will need to <CreateBotLink>create a bot</CreateBotLink> and get the bot API key. Additionally, you will need the chat ID for the chat to which you would like to send notifications. You can find this by adding <GetIdBotLink>@get_id_bot</GetIdBotLink> to the chat and issuing the <code>/my_id</code> command.',
@ -260,7 +258,7 @@ const NotificationsTelegram: React.FC = () => {
testSettings();
}}
>
{intl.formatMessage(messages.test)}
{intl.formatMessage(globalMessages.test)}
</Button>
</span>
<span className="inline-flex ml-3 rounded-md shadow-sm">
@ -270,8 +268,8 @@ const NotificationsTelegram: React.FC = () => {
disabled={isSubmitting || !isValid}
>
{isSubmitting
? intl.formatMessage(messages.saving)
: intl.formatMessage(messages.save)}
? intl.formatMessage(globalMessages.saving)
: intl.formatMessage(globalMessages.save)}
</Button>
</span>
</div>

@ -1,13 +1,14 @@
import React from 'react';
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import dynamic from 'next/dynamic';
import useSWR from 'swr';
import LoadingSpinner from '../../../Common/LoadingSpinner';
import Button from '../../../Common/Button';
import React from 'react';
import { defineMessages, useIntl } from 'react-intl';
import axios from 'axios';
import * as Yup from 'yup';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import * as Yup from 'yup';
import globalMessages from '../../../../i18n/globalMessages';
import Button from '../../../Common/Button';
import LoadingSpinner from '../../../Common/LoadingSpinner';
import NotificationTypeSelector from '../../../NotificationTypeSelector';
const JSONEditor = dynamic(() => import('../../../JSONEditor'), { ssr: false });
@ -35,8 +36,6 @@ const defaultPayload = {
};
const messages = defineMessages({
save: 'Save Changes',
saving: 'Saving…',
agentenabled: 'Enable Agent',
webhookUrl: 'Webhook URL',
authheader: 'Authorization Header',
@ -44,7 +43,6 @@ const messages = defineMessages({
webhooksettingssaved: 'Webhook notification settings saved successfully!',
webhooksettingsfailed: 'Webhook notification settings failed to save.',
testsent: 'Test notification sent!',
test: 'Test',
notificationtypes: 'Notification Types',
resetPayload: 'Reset to Default',
resetPayloadSuccess: 'JSON payload reset successfully!',
@ -295,7 +293,7 @@ const NotificationsWebhook: React.FC = () => {
testSettings();
}}
>
{intl.formatMessage(messages.test)}
{intl.formatMessage(globalMessages.test)}
</Button>
</span>
<span className="inline-flex ml-3 rounded-md shadow-sm">
@ -305,8 +303,8 @@ const NotificationsWebhook: React.FC = () => {
disabled={isSubmitting || !isValid}
>
{isSubmitting
? intl.formatMessage(messages.saving)
: intl.formatMessage(messages.save)}
? intl.formatMessage(globalMessages.saving)
: intl.formatMessage(globalMessages.save)}
</Button>
</span>
</div>

@ -5,6 +5,7 @@ import { defineMessages, useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import * as Yup from 'yup';
import type { RadarrSettings } from '../../../../server/lib/settings';
import globalMessages from '../../../i18n/globalMessages';
import Modal from '../../Common/Modal';
import Transition from '../../Transition';
@ -21,11 +22,7 @@ const messages = defineMessages({
'You must select a minimum availability',
toastRadarrTestSuccess: 'Radarr connection established successfully!',
toastRadarrTestFailure: 'Failed to connect to Radarr.',
saving: 'Saving…',
save: 'Save Changes',
add: 'Add Server',
test: 'Test',
testing: 'Testing…',
defaultserver: 'Default Server',
servername: 'Server Name',
servernamePlaceholder: 'A Radarr Server',
@ -294,16 +291,16 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
okButtonType="primary"
okText={
isSubmitting
? intl.formatMessage(messages.saving)
? intl.formatMessage(globalMessages.saving)
: radarr
? intl.formatMessage(messages.save)
? intl.formatMessage(globalMessages.save)
: intl.formatMessage(messages.add)
}
secondaryButtonType="warning"
secondaryText={
isTesting
? intl.formatMessage(messages.testing)
: intl.formatMessage(messages.test)
? intl.formatMessage(globalMessages.testing)
: intl.formatMessage(globalMessages.test)
}
onSecondary={() => {
if (values.apiKey && values.hostname && values.port) {

@ -30,13 +30,7 @@ const messages = defineMessages({
filterInfo: 'Info',
filterWarn: 'Warning',
filterError: 'Error',
noresults: 'No results.',
showall: 'Show All Logs',
showingresults:
'Showing <strong>{from}</strong> to <strong>{to}</strong> of <strong>{total}</strong> results',
resultsperpage: 'Display {pageSize} results per page',
next: 'Next',
previous: 'Previous',
pauseLogs: 'Pause',
resumeLogs: 'Resume',
viewDetails: 'View Details',
@ -393,7 +387,7 @@ const SettingsLogs: React.FC = () => {
<Table.TD colSpan={4} noPadding>
<div className="flex flex-col items-center justify-center w-screen p-6 lg:w-full">
<span className="text-base">
{intl.formatMessage(messages.noresults)}
{intl.formatMessage(globalMessages.noresults)}
</span>
{currentFilter !== 'debug' && (
<div className="mt-4">
@ -419,7 +413,7 @@ const SettingsLogs: React.FC = () => {
<div className="hidden lg:flex lg:flex-1">
<p className="text-sm">
{data.results.length > 0 &&
intl.formatMessage(messages.showingresults, {
intl.formatMessage(globalMessages.showingresults, {
from: pageIndex * currentPageSize + 1,
to:
data.results.length < currentPageSize
@ -435,7 +429,7 @@ const SettingsLogs: React.FC = () => {
</div>
<div className="flex justify-center sm:flex-1 sm:justify-start lg:justify-center">
<span className="items-center -mt-3 text-sm sm:-ml-4 lg:ml-0 sm:mt-0">
{intl.formatMessage(messages.resultsperpage, {
{intl.formatMessage(globalMessages.resultsperpage, {
pageSize: (
<select
id="pageSize"
@ -473,7 +467,7 @@ const SettingsLogs: React.FC = () => {
.then(() => window.scrollTo(0, 0))
}
>
{intl.formatMessage(messages.previous)}
{intl.formatMessage(globalMessages.previous)}
</Button>
<Button
disabled={!hasNextPage}
@ -489,7 +483,7 @@ const SettingsLogs: React.FC = () => {
.then(() => window.scrollTo(0, 0))
}
>
{intl.formatMessage(messages.next)}
{intl.formatMessage(globalMessages.next)}
</Button>
</div>
</nav>

@ -20,8 +20,6 @@ const messages = defineMessages({
generalsettings: 'General Settings',
generalsettingsDescription:
'Configure global and default settings for Overseerr.',
save: 'Save Changes',
saving: 'Saving…',
apikey: 'API Key',
applicationTitle: 'Application Title',
applicationurl: 'Application URL',
@ -423,8 +421,8 @@ const SettingsMain: React.FC = () => {
disabled={isSubmitting}
>
{isSubmitting
? intl.formatMessage(messages.saving)
: intl.formatMessage(messages.save)}
? intl.formatMessage(globalMessages.saving)
: intl.formatMessage(globalMessages.save)}
</Button>
</span>
</div>

@ -1,27 +1,25 @@
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import Link from 'next/link';
import { useRouter } from 'next/router';
import React from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import Bolt from '../../assets/bolt.svg';
import DiscordLogo from '../../assets/extlogos/discord.svg';
import SlackLogo from '../../assets/extlogos/slack.svg';
import TelegramLogo from '../../assets/extlogos/telegram.svg';
import PushbulletLogo from '../../assets/extlogos/pushbullet.svg';
import PushoverLogo from '../../assets/extlogos/pushover.svg';
import Bolt from '../../assets/bolt.svg';
import { Field, Form, Formik } from 'formik';
import useSWR from 'swr';
import SlackLogo from '../../assets/extlogos/slack.svg';
import TelegramLogo from '../../assets/extlogos/telegram.svg';
import globalMessages from '../../i18n/globalMessages';
import Error from '../../pages/_error';
import LoadingSpinner from '../Common/LoadingSpinner';
import axios from 'axios';
import { useToasts } from 'react-toast-notifications';
import Button from '../Common/Button';
import LoadingSpinner from '../Common/LoadingSpinner';
import PageTitle from '../Common/PageTitle';
import globalMessages from '../../i18n/globalMessages';
const messages = defineMessages({
notifications: 'Notifications',
save: 'Save Changes',
saving: 'Saving…',
notificationsettings: 'Notification Settings',
notificationsettingsDescription:
'Configure global notification settings. The options below will apply to all notification agents.',
@ -248,8 +246,8 @@ const SettingsNotifications: React.FC = ({ children }) => {
disabled={isSubmitting}
>
{isSubmitting
? intl.formatMessage(messages.saving)
: intl.formatMessage(messages.save)}
? intl.formatMessage(globalMessages.saving)
: intl.formatMessage(globalMessages.save)}
</Button>
</span>
</div>

@ -45,8 +45,6 @@ const messages = defineMessages({
port: 'Port',
enablessl: 'Enable SSL',
timeout: 'Timeout',
save: 'Save Changes',
saving: 'Saving…',
plexlibraries: 'Plex Libraries',
plexlibrariesDescription:
'The libraries Overseerr scans for titles. Set up and save your Plex connection settings, then click the button below if no libraries are listed.',
@ -538,8 +536,8 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
disabled={isSubmitting}
>
{isSubmitting
? intl.formatMessage(messages.saving)
: intl.formatMessage(messages.save)}
? intl.formatMessage(globalMessages.saving)
: intl.formatMessage(globalMessages.save)}
</Button>
</span>
</div>

@ -1,21 +1,21 @@
import axios from 'axios';
import React, { useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import Badge from '../Common/Badge';
import Button from '../Common/Button';
import useSWR from 'swr';
import type {
RadarrSettings,
SonarrSettings,
} from '../../../server/lib/settings';
import globalMessages from '../../i18n/globalMessages';
import Alert from '../Common/Alert';
import Badge from '../Common/Badge';
import Button from '../Common/Button';
import LoadingSpinner from '../Common/LoadingSpinner';
import RadarrModal from './RadarrModal';
import Modal from '../Common/Modal';
import PageTitle from '../Common/PageTitle';
import Transition from '../Transition';
import axios from 'axios';
import RadarrModal from './RadarrModal';
import SonarrModal from './SonarrModal';
import Alert from '../Common/Alert';
import PageTitle from '../Common/PageTitle';
import globalMessages from '../../i18n/globalMessages';
const messages = defineMessages({
services: 'Services',
@ -26,8 +26,6 @@ const messages = defineMessages({
sonarrSettingsDescription:
'Configure your Sonarr connection below. You can have multiple Sonarr configurations, but only two can be active as defaults at any time (one for standard HD and one for 4K). Administrators can override the server which is used for new requests.',
deleteserverconfirm: 'Are you sure you want to delete this server?',
edit: 'Edit',
delete: 'Delete',
ssl: 'SSL',
default: 'Default',
default4k: 'Default 4K',
@ -139,7 +137,9 @@ const ServerInstance: React.FC<ServerInstanceProps> = ({
>
<path d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z" />
</svg>
<span className="ml-3">{intl.formatMessage(messages.edit)}</span>
<span className="ml-3">
{intl.formatMessage(globalMessages.edit)}
</span>
</button>
</div>
<div className="flex flex-1 w-0 -ml-px">
@ -160,7 +160,7 @@ const ServerInstance: React.FC<ServerInstanceProps> = ({
/>
</svg>
<span className="ml-3">
{intl.formatMessage(messages.delete)}
{intl.formatMessage(globalMessages.delete)}
</span>
</button>
</div>

@ -16,15 +16,11 @@ const messages = defineMessages({
users: 'Users',
userSettings: 'User Settings',
userSettingsDescription: 'Configure global and default user settings.',
save: 'Save Changes',
saving: 'Saving…',
toastSettingsSuccess: 'User settings saved successfully!',
toastSettingsFailure: 'Something went wrong while saving settings.',
localLogin: 'Enable Local Sign-In',
movieRequestLimitLabel: 'Global Movie Request Limit',
movieRequestLimit: '{quotaLimit} movies per {quotaDays} days',
tvRequestLimitLabel: 'Global Series Request Limit',
tvRequestLimit: '{quotaLimit} seasons per {quotaDays} days',
defaultPermissions: 'Default Permissions',
});
@ -173,8 +169,8 @@ const SettingsUsers: React.FC = () => {
disabled={isSubmitting}
>
{isSubmitting
? intl.formatMessage(messages.saving)
: intl.formatMessage(messages.save)}
? intl.formatMessage(globalMessages.saving)
: intl.formatMessage(globalMessages.save)}
</Button>
</span>
</div>

@ -1,12 +1,13 @@
import React, { useState, useEffect, useCallback, useRef } from 'react';
import Transition from '../../Transition';
import Modal from '../../Common/Modal';
import { Formik, Field } from 'formik';
import type { SonarrSettings } from '../../../../server/lib/settings';
import * as Yup from 'yup';
import axios from 'axios';
import { Field, Formik } from 'formik';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import { useIntl, defineMessages } from 'react-intl';
import * as Yup from 'yup';
import type { SonarrSettings } from '../../../../server/lib/settings';
import globalMessages from '../../../i18n/globalMessages';
import Modal from '../../Common/Modal';
import Transition from '../../Transition';
const messages = defineMessages({
createsonarr: 'Add New Sonarr Server',
@ -20,11 +21,7 @@ const messages = defineMessages({
validationLanguageProfileRequired: 'You must select a language profile',
toastSonarrTestSuccess: 'Sonarr connection established successfully!',
toastSonarrTestFailure: 'Failed to connect to Sonarr.',
saving: 'Saving…',
save: 'Save Changes',
add: 'Add Server',
test: 'Test',
testing: 'Testing…',
defaultserver: 'Default Server',
servername: 'Server Name',
servernamePlaceholder: 'A Sonarr Server',
@ -322,16 +319,16 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
okButtonType="primary"
okText={
isSubmitting
? intl.formatMessage(messages.saving)
? intl.formatMessage(globalMessages.saving)
: sonarr
? intl.formatMessage(messages.save)
? intl.formatMessage(globalMessages.save)
: intl.formatMessage(messages.add)
}
secondaryButtonType="warning"
secondaryText={
isTesting
? intl.formatMessage(messages.testing)
: intl.formatMessage(messages.test)
? intl.formatMessage(globalMessages.testing)
: intl.formatMessage(globalMessages.test)
}
onSecondary={() => {
if (values.apiKey && values.hostname && values.port) {

@ -1,18 +1,15 @@
import { debounce } from 'lodash';
import React, {
ReactNode,
useCallback,
useEffect,
useRef,
useState,
ReactNode,
} from 'react';
import { useIntl } from 'react-intl';
import { useSpring } from 'react-spring';
import globalMessages from '../../i18n/globalMessages';
import TitleCard from '../TitleCard';
import { defineMessages, useIntl } from 'react-intl';
const messages = defineMessages({
noresults: 'No results.',
});
interface SliderProps {
sliderKey: string;
@ -233,7 +230,7 @@ const Slider: React.FC<SliderProps> = ({
<div className="mt-16 mb-16 text-center text-white">
{emptyMessage
? emptyMessage
: intl.formatMessage(messages.noresults)}
: intl.formatMessage(globalMessages.noresults)}
</div>
)}
</div>

@ -1,22 +1,17 @@
import React, { useState, useCallback, useEffect } from 'react';
import type { MediaType } from '../../../server/models/Search';
import { withProperties } from '../../utils/typeHelpers';
import Transition from '../Transition';
import Placeholder from './Placeholder';
import Link from 'next/link';
import React, { useCallback, useEffect, useState } from 'react';
import { useIntl } from 'react-intl';
import { MediaStatus } from '../../../server/constants/media';
import RequestModal from '../RequestModal';
import { defineMessages, useIntl } from 'react-intl';
import type { MediaType } from '../../../server/models/Search';
import Spinner from '../../assets/spinner.svg';
import { useIsTouch } from '../../hooks/useIsTouch';
import { Permission, useUser } from '../../hooks/useUser';
import globalMessages from '../../i18n/globalMessages';
import Spinner from '../../assets/spinner.svg';
import { useUser, Permission } from '../../hooks/useUser';
import { withProperties } from '../../utils/typeHelpers';
import CachedImage from '../Common/CachedImage';
const messages = defineMessages({
movie: 'Movie',
tvshow: 'Series',
});
import RequestModal from '../RequestModal';
import Transition from '../Transition';
import Placeholder from './Placeholder';
interface TitleCardProps {
id: number;
@ -125,8 +120,8 @@ const TitleCard: React.FC<TitleCardProps> = ({
>
<div className="flex items-center h-4 px-2 py-2 text-xs font-normal tracking-wider text-center text-white uppercase sm:h-5">
{mediaType === 'movie'
? intl.formatMessage(messages.movie)
: intl.formatMessage(messages.tvshow)}
? intl.formatMessage(globalMessages.movie)
: intl.formatMessage(globalMessages.tvshow)}
</div>
</div>
<div className="z-40 pointer-events-none">

@ -40,7 +40,6 @@ import StatusBadge from '../StatusBadge';
const messages = defineMessages({
firstAirDate: 'First Air Date',
nextAirDate: 'Next Air Date',
status: 'Status',
originallanguage: 'Original Language',
overview: 'Overview',
cast: 'Cast',
@ -58,7 +57,6 @@ const messages = defineMessages({
anime: 'Anime',
network: '{networkCount, plural, one {Network} other {Networks}}',
viewfullcrew: 'View Full Crew',
areyousure: 'Are you sure?',
opensonarr: 'Open Series in Sonarr',
opensonarr4k: 'Open Series in 4K Sonarr',
downloadstatus: 'Download Status',
@ -420,7 +418,7 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
<div className="mt-8">
<ConfirmButton
onClick={() => deleteMedia()}
confirmText={intl.formatMessage(messages.areyousure)}
confirmText={intl.formatMessage(globalMessages.areyousure)}
className="w-full"
>
{intl.formatMessage(messages.manageModalClearMedia)}
@ -628,7 +626,7 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
</div>
)}
<div className="media-fact">
<span>{intl.formatMessage(messages.status)}</span>
<span>{intl.formatMessage(globalMessages.status)}</span>
<span className="media-fact-value">{data.status}</span>
</div>
{data.firstAirDate && (

@ -1,10 +1,11 @@
import axios from 'axios';
import React, { useEffect, useState } from 'react';
import PermissionEdit from '../PermissionEdit';
import Modal from '../Common/Modal';
import { User, useUser } from '../../hooks/useUser';
import { defineMessages, useIntl } from 'react-intl';
import axios from 'axios';
import { useToasts } from 'react-toast-notifications';
import { User, useUser } from '../../hooks/useUser';
import globalMessages from '../../i18n/globalMessages';
import Modal from '../Common/Modal';
import PermissionEdit from '../PermissionEdit';
interface BulkEditProps {
selectedUserIds: number[];
@ -16,8 +17,6 @@ interface BulkEditProps {
const messages = defineMessages({
userssaved: 'User permissions saved successfully!',
save: 'Save Changes',
saving: 'Saving…',
userfail: 'Something went wrong while saving user permissions.',
edituser: 'Edit User Permissions',
});
@ -89,7 +88,7 @@ const BulkEditModal: React.FC<BulkEditProps> = ({
updateUsers();
}}
okDisabled={isSaving}
okText={intl.formatMessage(messages.save)}
okText={intl.formatMessage(globalMessages.save)}
onCancel={onCancel}
>
<div className="mb-6">

@ -37,9 +37,7 @@ const messages = defineMessages({
role: 'Role',
created: 'Created',
lastupdated: 'Last Updated',
edit: 'Edit',
bulkedit: 'Bulk Edit',
delete: 'Delete',
owner: 'Owner',
admin: 'Admin',
plexuser: 'Plex User',
@ -68,11 +66,6 @@ const messages = defineMessages({
sortUpdated: 'Last Updated',
sortDisplayName: 'Display Name',
sortRequests: 'Request Count',
next: 'Next',
previous: 'Previous',
showingresults:
'Showing <strong>{from}</strong> to <strong>{to}</strong> of <strong>{total}</strong> results',
resultsperpage: 'Display {pageSize} results per page',
});
type Sort = 'created' | 'updated' | 'requests' | 'displayname';
@ -602,7 +595,7 @@ const UserList: React.FC = () => {
)
}
>
{intl.formatMessage(messages.edit)}
{intl.formatMessage(globalMessages.edit)}
</Button>
<Button
buttonType="danger"
@ -613,7 +606,7 @@ const UserList: React.FC = () => {
}
onClick={() => setDeleteModal({ isOpen: true, user })}
>
{intl.formatMessage(messages.delete)}
{intl.formatMessage(globalMessages.delete)}
</Button>
</Table.TD>
</tr>
@ -627,7 +620,7 @@ const UserList: React.FC = () => {
<div className="hidden lg:flex lg:flex-1">
<p className="text-sm">
{data.results.length > 0 &&
intl.formatMessage(messages.showingresults, {
intl.formatMessage(globalMessages.showingresults, {
from: pageIndex * currentPageSize + 1,
to:
data.results.length < currentPageSize
@ -642,7 +635,7 @@ const UserList: React.FC = () => {
</div>
<div className="flex justify-center sm:flex-1 sm:justify-start lg:justify-center">
<span className="items-center -mt-3 text-sm sm:-ml-4 lg:ml-0 sm:mt-0">
{intl.formatMessage(messages.resultsperpage, {
{intl.formatMessage(globalMessages.resultsperpage, {
pageSize: (
<select
id="pageSize"
@ -681,7 +674,7 @@ const UserList: React.FC = () => {
.then(() => window.scrollTo(0, 0))
}
>
{intl.formatMessage(messages.previous)}
{intl.formatMessage(globalMessages.previous)}
</Button>
<Button
disabled={!hasNextPage}
@ -697,7 +690,7 @@ const UserList: React.FC = () => {
.then(() => window.scrollTo(0, 0))
}
>
{intl.formatMessage(messages.next)}
{intl.formatMessage(globalMessages.next)}
</Button>
</div>
</nav>

@ -22,8 +22,6 @@ const messages = defineMessages({
general: 'General',
generalsettings: 'General Settings',
displayName: 'Display Name',
save: 'Save Changes',
saving: 'Saving…',
accounttype: 'Account Type',
plexuser: 'Plex User',
localuser: 'Local User',
@ -362,8 +360,8 @@ const UserGeneralSettings: React.FC = () => {
disabled={isSubmitting}
>
{isSubmitting
? intl.formatMessage(messages.saving)
: intl.formatMessage(messages.save)}
? intl.formatMessage(globalMessages.saving)
: intl.formatMessage(globalMessages.save)}
</Button>
</span>
</div>

@ -31,8 +31,6 @@ const messages = defineMessages({
sendSilently: 'Send Telegram Messages Silently',
sendSilentlyDescription: 'Send notifications with no sound',
validationTelegramChatId: 'You must provide a valid Telegram chat ID',
save: 'Save Changes',
saving: 'Saving…',
plexuser: 'Plex User',
localuser: 'Local User',
toastSettingsSuccess: 'Notification settings saved successfully!',
@ -283,8 +281,8 @@ const UserNotificationSettings: React.FC = () => {
disabled={isSubmitting}
>
{isSubmitting
? intl.formatMessage(messages.saving)
: intl.formatMessage(messages.save)}
? intl.formatMessage(globalMessages.saving)
: intl.formatMessage(globalMessages.save)}
</Button>
</span>
</div>

@ -20,8 +20,6 @@ const messages = defineMessages({
currentpassword: 'Current Password',
newpassword: 'New Password',
confirmpassword: 'Confirm Password',
save: 'Save Changes',
saving: 'Saving…',
toastSettingsSuccess: 'Password saved successfully!',
toastSettingsFailure: 'Something went wrong while saving the password.',
toastSettingsFailureVerifyCurrent:
@ -37,7 +35,6 @@ const messages = defineMessages({
'This user account currently does not have a password specifically for {applicationTitle}. Configure a password below to enable this account to sign in as a "local user."',
nopasswordsetDescriptionOwnAccount:
'Your account currently does not have a password specifically for {applicationTitle}. Configure a password below to enable sign in as a "local user" using your email address.',
nopermission: 'Unauthorized',
nopermissionDescription:
"You do not have permission to modify this user's password.",
});
@ -90,7 +87,10 @@ const UserPasswordChange: React.FC = () => {
<div className="mb-6">
<h3 className="heading">{intl.formatMessage(messages.password)}</h3>
</div>
<Alert title={intl.formatMessage(messages.nopermission)} type="error">
<Alert
title={intl.formatMessage(globalMessages.unauthorized)}
type="error"
>
{intl.formatMessage(messages.nopermissionDescription)}
</Alert>
</>
@ -224,8 +224,8 @@ const UserPasswordChange: React.FC = () => {
disabled={isSubmitting}
>
{isSubmitting
? intl.formatMessage(messages.saving)
: intl.formatMessage(messages.save)}
? intl.formatMessage(globalMessages.saving)
: intl.formatMessage(globalMessages.save)}
</Button>
</span>
</div>

@ -6,24 +6,21 @@ import { defineMessages, useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import { useUser } from '../../../../hooks/useUser';
import globalMessages from '../../../../i18n/globalMessages';
import Error from '../../../../pages/_error';
import Alert from '../../../Common/Alert';
import Button from '../../../Common/Button';
import LoadingSpinner from '../../../Common/LoadingSpinner';
import PermissionEdit from '../../../PermissionEdit';
import Alert from '../../../Common/Alert';
import PageTitle from '../../../Common/PageTitle';
import globalMessages from '../../../../i18n/globalMessages';
import PermissionEdit from '../../../PermissionEdit';
const messages = defineMessages({
displayName: 'Display Name',
save: 'Save Changes',
saving: 'Saving…',
plexuser: 'Plex User',
localuser: 'Local User',
toastSettingsSuccess: 'Permissions saved successfully!',
toastSettingsFailure: 'Something went wrong while saving settings.',
permissions: 'Permissions',
unauthorized: 'Unauthorized',
unauthorizedDescription: 'You cannot modify your own permissions.',
});
@ -53,7 +50,10 @@ const UserPermissions: React.FC = () => {
{intl.formatMessage(messages.permissions)}
</h3>
</div>
<Alert title={intl.formatMessage(messages.unauthorized)} type="error">
<Alert
title={intl.formatMessage(globalMessages.unauthorized)}
type="error"
>
{intl.formatMessage(messages.unauthorizedDescription)}
</Alert>
</>
@ -120,8 +120,8 @@ const UserPermissions: React.FC = () => {
disabled={isSubmitting}
>
{isSubmitting
? intl.formatMessage(messages.saving)
: intl.formatMessage(messages.save)}
? intl.formatMessage(globalMessages.saving)
: intl.formatMessage(globalMessages.save)}
</Button>
</span>
</div>

@ -17,7 +17,6 @@ const messages = defineMessages({
menuChangePass: 'Password',
menuNotifications: 'Notifications',
menuPermissions: 'Permissions',
unauthorized: 'Unauthorized',
unauthorizedDescription:
"You do not have permission to modify this user's settings.",
});
@ -123,7 +122,10 @@ const UserSettings: React.FC = ({ children }) => {
/>
<ProfileHeader user={user} isSettingsPage />
<div className="mt-6">
<Alert title={intl.formatMessage(messages.unauthorized)} type="error">
<Alert
title={intl.formatMessage(globalMessages.unauthorized)}
type="error"
>
{intl.formatMessage(messages.unauthorizedDescription)}
</Alert>
</div>

@ -5,28 +5,50 @@ const globalMessages = defineMessages({
partiallyavailable: 'Partially Available',
processing: 'Processing',
unavailable: 'Unavailable',
notrequested: 'Not Requested',
requested: 'Requested',
requesting: 'Requesting…',
request: 'Request',
request4k: 'Request 4K',
failed: 'Failed',
pending: 'Pending',
declined: 'Declined',
approved: 'Approved',
movie: 'Movie',
movies: 'Movies',
tvshow: 'Series',
tvshows: 'Series',
cancel: 'Cancel',
canceling: 'Canceling…',
approve: 'Approve',
decline: 'Decline',
delete: 'Delete',
retry: 'Retry',
view: 'View',
deleting: 'Deleting…',
test: 'Test',
testing: 'Testing…',
save: 'Save Changes',
saving: 'Saving…',
close: 'Close',
edit: 'Edit',
areyousure: 'Are you sure?',
back: 'Back',
next: 'Next',
previous: 'Previous',
status: 'Status',
all: 'All',
experimental: 'Experimental',
advanced: 'Advanced',
loading: 'Loading…',
settings: 'Settings',
usersettings: 'User Settings',
unauthorized: 'Unauthorized',
delimitedlist: '{a}, {b}',
showingresults:
'Showing <strong>{from}</strong> to <strong>{to}</strong> of <strong>{total}</strong> results',
resultsperpage: 'Display {pageSize} results per page',
noresults: 'No results.',
});
export default globalMessages;

@ -1,19 +1,14 @@
{
"components.AppDataWarning.dockerVolumeMissing": "Docker Volume Mount Missing",
"components.AppDataWarning.dockerVolumeMissingDescription": "The <code>{appDataPath}</code> volume mount was not configured properly. All data will be cleared when the container is stopped or restarted.",
"components.CollectionDetails.movies": "Movies",
"components.CollectionDetails.numberofmovies": "{count} Movies",
"components.CollectionDetails.overview": "Overview",
"components.CollectionDetails.overviewunavailable": "Overview unavailable.",
"components.CollectionDetails.request": "Request",
"components.CollectionDetails.request4k": "Request 4K",
"components.CollectionDetails.requestSuccess": "<strong>{title}</strong> requested successfully!",
"components.CollectionDetails.requestcollection": "Request Collection",
"components.CollectionDetails.requestcollection4k": "Request Collection in 4K",
"components.CollectionDetails.requesting": "Requesting…",
"components.CollectionDetails.requestswillbecreated": "The following titles will have requests created for them:",
"components.CollectionDetails.requestswillbecreated4k": "The following titles will have 4K requests created for them:",
"components.Common.ListView.noresults": "No results.",
"components.Discover.DiscoverMovieGenre.genreMovies": "{genre} Movies",
"components.Discover.DiscoverMovieLanguage.languageMovies": "{language} Movies",
"components.Discover.DiscoverNetwork.networkSeries": "{network} Series",
@ -62,7 +57,6 @@
"components.MediaSlider.ShowMoreCard.seemore": "See More",
"components.MovieDetails.MovieCast.fullcast": "Full Cast",
"components.MovieDetails.MovieCrew.fullcrew": "Full Crew",
"components.MovieDetails.areyousure": "Are you sure?",
"components.MovieDetails.budget": "Budget",
"components.MovieDetails.cast": "Cast",
"components.MovieDetails.downloadstatus": "Download Status",
@ -85,9 +79,7 @@
"components.MovieDetails.revenue": "Revenue",
"components.MovieDetails.runtime": "{minutes} minutes",
"components.MovieDetails.similar": "Similar Titles",
"components.MovieDetails.status": "Status",
"components.MovieDetails.studio": "{studioCount, plural, one {Studio} other {Studios}}",
"components.MovieDetails.view": "View",
"components.MovieDetails.viewfullcrew": "View Full Crew",
"components.MovieDetails.watchtrailer": "Watch Trailer",
"components.NotificationTypeSelector.mediaAutoApproved": "Media Automatically Approved",
@ -142,11 +134,10 @@
"components.PersonDetails.birthdate": "Born {birthdate}",
"components.PersonDetails.crewmember": "Crew",
"components.PersonDetails.lifespan": "{birthdate} {deathdate}",
"components.PlexLoginButton.loading": "Loading…",
"components.PlexLoginButton.signingin": "Signing in…",
"components.PlexLoginButton.signinwithplex": "Sign In",
"components.QuotaSelector.movieRequestLimit": "{quotaLimit} movies per {quotaDays} days",
"components.QuotaSelector.tvRequestLimit": "{quotaLimit} seasons per {quotaDays} days",
"components.QuotaSelector.movieRequestLimit": "{quotaLimit} movie(s) per {quotaDays} day(s)",
"components.QuotaSelector.tvRequestLimit": "{quotaLimit} season(s) per {quotaDays} day(s)",
"components.QuotaSelector.unlimited": "Unlimited",
"components.RegionSelector.regionDefault": "All Regions",
"components.RegionSelector.regionServerDefault": "Default ({region})",
@ -163,36 +154,18 @@
"components.RequestButton.declinerequest": "Decline Request",
"components.RequestButton.declinerequest4k": "Decline 4K Request",
"components.RequestButton.declinerequests": "Decline {requestCount} {requestCount, plural, one {Request} other {Requests}}",
"components.RequestButton.request": "Request",
"components.RequestButton.request4k": "Request 4K",
"components.RequestButton.requestmore": "Request More",
"components.RequestButton.requestmore4k": "Request More 4K",
"components.RequestButton.viewrequest": "View Request",
"components.RequestButton.viewrequest4k": "View 4K Request",
"components.RequestCard.all": "All",
"components.RequestCard.seasons": "{seasonCount, plural, one {Season} other {Seasons}}",
"components.RequestCard.status": "Status",
"components.RequestList.RequestItem.all": "All",
"components.RequestList.RequestItem.areyousure": "Are you sure?",
"components.RequestList.RequestItem.failedretry": "Something went wrong while retrying the request.",
"components.RequestList.RequestItem.modified": "Modified",
"components.RequestList.RequestItem.modifieduserdate": "{date} by {user}",
"components.RequestList.RequestItem.notavailable": "N/A",
"components.RequestList.RequestItem.requested": "Requested",
"components.RequestList.RequestItem.seasons": "{seasonCount, plural, one {Season} other {Seasons}}",
"components.RequestList.RequestItem.status": "Status",
"components.RequestList.filterAll": "All",
"components.RequestList.filterApproved": "Approved",
"components.RequestList.filterAvailable": "Available",
"components.RequestList.filterPending": "Pending",
"components.RequestList.filterProcessing": "Processing",
"components.RequestList.next": "Next",
"components.RequestList.noresults": "No results.",
"components.RequestList.previous": "Previous",
"components.RequestList.requests": "Requests",
"components.RequestList.resultsperpage": "Display {pageSize} results per page",
"components.RequestList.showallrequests": "Show All Requests",
"components.RequestList.showingresults": "Showing <strong>{from}</strong> to <strong>{to}</strong> of <strong>{total}</strong> results",
"components.RequestList.sortAdded": "Request Date",
"components.RequestList.sortModified": "Last Modified",
"components.RequestModal.AdvancedRequester.advancedoptions": "Advanced Options",
@ -201,7 +174,6 @@
"components.RequestModal.AdvancedRequester.destinationserver": "Destination Server",
"components.RequestModal.AdvancedRequester.folder": "{path} ({space})",
"components.RequestModal.AdvancedRequester.languageprofile": "Language Profile",
"components.RequestModal.AdvancedRequester.loading": "Loading…",
"components.RequestModal.AdvancedRequester.qualityprofile": "Quality Profile",
"components.RequestModal.AdvancedRequester.requestas": "Request As",
"components.RequestModal.AdvancedRequester.rootfolder": "Root Folder",
@ -212,46 +184,37 @@
"components.RequestModal.QuotaDisplay.notenoughseasonrequests": "Not enough season requests remaining",
"components.RequestModal.QuotaDisplay.quotaLink": "You can view a summary of your request limits on your <ProfileLink>profile page</ProfileLink>.",
"components.RequestModal.QuotaDisplay.quotaLinkUser": "You can view a summary of this user's request limits on their <ProfileLink>profile page</ProfileLink>.",
"components.RequestModal.QuotaDisplay.requestsremaining": "{remaining, plural, =0 {No} other {<strong>#</strong>}} {type} {remaining, plural, one {requests} other {requests}} remaining",
"components.RequestModal.QuotaDisplay.requestsremaining": "{remaining, plural, =0 {No} other {<strong>#</strong>}} {type} {remaining, plural, one {request} other {requests}} remaining",
"components.RequestModal.QuotaDisplay.requiredquota": "You need to have at least <strong>{seasons}</strong> {seasons, plural, one {season request} other {season requests}} remaining in order to submit a request for this series.",
"components.RequestModal.QuotaDisplay.requiredquotaUser": "This user needs to have at least <strong>{seasons}</strong> {seasons, plural, one {season request} other {season requests}} remaining in order to submit a request for this series.",
"components.RequestModal.QuotaDisplay.season": "season",
"components.RequestModal.QuotaDisplay.seasonlimit": "{limit, plural, one {season} other {seasons}}",
"components.RequestModal.SearchByNameModal.next": "Next",
"components.RequestModal.SearchByNameModal.nosummary": "No summary for this title was found.",
"components.RequestModal.SearchByNameModal.notvdbid": "Manual Match Required",
"components.RequestModal.SearchByNameModal.notvdbiddescription": "We couldn't automatically match your request. Please select the correct match from the list below.",
"components.RequestModal.alreadyrequested": "Already Requested",
"components.RequestModal.autoapproval": "Automatic Approval",
"components.RequestModal.backbutton": "Back",
"components.RequestModal.cancel": "Cancel Request",
"components.RequestModal.cancelling": "Canceling…",
"components.RequestModal.cancelrequest": "This will remove your request. Are you sure you want to continue?",
"components.RequestModal.close": "Close",
"components.RequestModal.errorediting": "Something went wrong while editing the request.",
"components.RequestModal.extras": "Extras",
"components.RequestModal.notrequested": "Not Requested",
"components.RequestModal.numberofepisodes": "# of Episodes",
"components.RequestModal.pending4krequest": "Pending Request for {title} in 4K",
"components.RequestModal.pendingrequest": "Pending Request for {title}",
"components.RequestModal.request": "Request",
"components.RequestModal.request4k": "Request 4K",
"components.RequestModal.request4kfrom": "There is currently a pending 4K request from {username}.",
"components.RequestModal.request4ktitle": "Request {title} in 4K",
"components.RequestModal.requestCancel": "Request for <strong>{title}</strong> canceled.",
"components.RequestModal.requestSuccess": "<strong>{title}</strong> requested successfully!",
"components.RequestModal.requestadmin": "Your request will be approved automatically.",
"components.RequestModal.requestadmin": "This request will be approved automatically.",
"components.RequestModal.requestall": "Request All Seasons",
"components.RequestModal.requestcancelled": "Request canceled.",
"components.RequestModal.requestedited": "Request edited.",
"components.RequestModal.requestcancelled": "Request for <strong>{title}</strong> canceled.",
"components.RequestModal.requestedited": "Request for <strong>{title}</strong> edited successfully!",
"components.RequestModal.requesterror": "Something went wrong while submitting the request.",
"components.RequestModal.requestfrom": "There is currently a pending request from {username}.",
"components.RequestModal.requesting": "Requesting…",
"components.RequestModal.requestseasons": "Request {seasonCount} {seasonCount, plural, one {Season} other {Seasons}}",
"components.RequestModal.requesttitle": "Request {title}",
"components.RequestModal.season": "Season",
"components.RequestModal.seasonnumber": "Season {number}",
"components.RequestModal.selectseason": "Select Season(s)",
"components.RequestModal.status": "Status",
"components.ResetPassword.confirmpassword": "Confirm Password",
"components.ResetPassword.email": "Email Address",
"components.ResetPassword.emailresetlink": "Email a Recovery Link",
@ -272,11 +235,8 @@
"components.Settings.Notifications.NotificationsPushbullet.notificationTypes": "Notification Types",
"components.Settings.Notifications.NotificationsPushbullet.pushbulletSettingsFailed": "Pushbullet notification settings failed to save.",
"components.Settings.Notifications.NotificationsPushbullet.pushbulletSettingsSaved": "Pushbullet notification settings saved successfully!",
"components.Settings.Notifications.NotificationsPushbullet.save": "Save Changes",
"components.Settings.Notifications.NotificationsPushbullet.saving": "Saving…",
"components.Settings.Notifications.NotificationsPushbullet.settingUpPushbullet": "Setting Up Pushbullet Notifications",
"components.Settings.Notifications.NotificationsPushbullet.settingUpPushbulletDescription": "To configure Pushbullet notifications, you will need to <CreateAccessTokenLink>create an access token</CreateAccessTokenLink> and enter it below.",
"components.Settings.Notifications.NotificationsPushbullet.test": "Test",
"components.Settings.Notifications.NotificationsPushbullet.testSent": "Test notification sent!",
"components.Settings.Notifications.NotificationsPushbullet.validationAccessTokenRequired": "You must provide an access token",
"components.Settings.Notifications.NotificationsPushover.accessToken": "Application/API Token",
@ -284,24 +244,18 @@
"components.Settings.Notifications.NotificationsPushover.notificationtypes": "Notification Types",
"components.Settings.Notifications.NotificationsPushover.pushoversettingsfailed": "Pushover notification settings failed to save.",
"components.Settings.Notifications.NotificationsPushover.pushoversettingssaved": "Pushover notification settings saved successfully!",
"components.Settings.Notifications.NotificationsPushover.save": "Save Changes",
"components.Settings.Notifications.NotificationsPushover.saving": "Saving…",
"components.Settings.Notifications.NotificationsPushover.settinguppushover": "Setting Up Pushover Notifications",
"components.Settings.Notifications.NotificationsPushover.settinguppushoverDescription": "To configure Pushover notifications, you will need to <RegisterApplicationLink>register an application</RegisterApplicationLink> and enter the API token below. (You can use one of our <IconLink>official icons on GitHub</IconLink>.) You will also need your user key.",
"components.Settings.Notifications.NotificationsPushover.test": "Test",
"components.Settings.Notifications.NotificationsPushover.testsent": "Test notification sent!",
"components.Settings.Notifications.NotificationsPushover.userToken": "User Key",
"components.Settings.Notifications.NotificationsPushover.validationAccessTokenRequired": "You must provide a valid application token",
"components.Settings.Notifications.NotificationsPushover.validationUserTokenRequired": "You must provide a valid user key",
"components.Settings.Notifications.NotificationsSlack.agentenabled": "Enable Agent",
"components.Settings.Notifications.NotificationsSlack.notificationtypes": "Notification Types",
"components.Settings.Notifications.NotificationsSlack.save": "Save Changes",
"components.Settings.Notifications.NotificationsSlack.saving": "Saving…",
"components.Settings.Notifications.NotificationsSlack.settingupslack": "Setting Up Slack Notifications",
"components.Settings.Notifications.NotificationsSlack.settingupslackDescription": "To configure Slack notifications, you will need to create an <WebhookLink>Incoming Webhook</WebhookLink> integration and enter the webhook URL below.",
"components.Settings.Notifications.NotificationsSlack.slacksettingsfailed": "Slack notification settings failed to save.",
"components.Settings.Notifications.NotificationsSlack.slacksettingssaved": "Slack notification settings saved successfully!",
"components.Settings.Notifications.NotificationsSlack.test": "Test",
"components.Settings.Notifications.NotificationsSlack.testsent": "Test notification sent!",
"components.Settings.Notifications.NotificationsSlack.validationWebhookUrl": "You must provide a valid URL",
"components.Settings.Notifications.NotificationsSlack.webhookUrl": "Webhook URL",
@ -311,10 +265,7 @@
"components.Settings.Notifications.NotificationsWebhook.notificationtypes": "Notification Types",
"components.Settings.Notifications.NotificationsWebhook.resetPayload": "Reset to Default",
"components.Settings.Notifications.NotificationsWebhook.resetPayloadSuccess": "JSON payload reset successfully!",
"components.Settings.Notifications.NotificationsWebhook.save": "Save Changes",
"components.Settings.Notifications.NotificationsWebhook.saving": "Saving…",
"components.Settings.Notifications.NotificationsWebhook.templatevariablehelp": "Template Variable Help",
"components.Settings.Notifications.NotificationsWebhook.test": "Test",
"components.Settings.Notifications.NotificationsWebhook.testsent": "Test notification sent!",
"components.Settings.Notifications.NotificationsWebhook.validationJsonPayloadRequired": "You must provide a valid JSON payload",
"components.Settings.Notifications.NotificationsWebhook.validationWebhookUrl": "You must provide a valid URL",
@ -343,8 +294,6 @@
"components.Settings.Notifications.pgpPasswordTip": "Sign encrypted email messages (PGP private key is also required)",
"components.Settings.Notifications.pgpPrivateKey": "<PgpLink>PGP</PgpLink> Private Key",
"components.Settings.Notifications.pgpPrivateKeyTip": "Sign encrypted email messages (PGP password is also required)",
"components.Settings.Notifications.save": "Save Changes",
"components.Settings.Notifications.saving": "Saving…",
"components.Settings.Notifications.sendSilently": "Send Silently",
"components.Settings.Notifications.sendSilentlyTip": "Send notifications with no sound",
"components.Settings.Notifications.senderName": "Sender Name",
@ -355,7 +304,6 @@
"components.Settings.Notifications.ssldisabletip": "SSL should be disabled on standard TLS connections (port 587)",
"components.Settings.Notifications.telegramsettingsfailed": "Telegram notification settings failed to save.",
"components.Settings.Notifications.telegramsettingssaved": "Telegram notification settings saved successfully!",
"components.Settings.Notifications.test": "Test",
"components.Settings.Notifications.testsent": "Test notification sent!",
"components.Settings.Notifications.validationBotAPIRequired": "You must provide a bot authentication token",
"components.Settings.Notifications.validationChatIdRequired": "You must provide a valid chat ID",
@ -383,8 +331,6 @@
"components.Settings.RadarrModal.preventSearch": "Disable Auto-Search",
"components.Settings.RadarrModal.qualityprofile": "Quality Profile",
"components.Settings.RadarrModal.rootfolder": "Root Folder",
"components.Settings.RadarrModal.save": "Save Changes",
"components.Settings.RadarrModal.saving": "Saving…",
"components.Settings.RadarrModal.selectMinimumAvailability": "Select minimum availability",
"components.Settings.RadarrModal.selectQualityProfile": "Select quality profile",
"components.Settings.RadarrModal.selectRootFolder": "Select root folder",
@ -393,10 +339,8 @@
"components.Settings.RadarrModal.servernamePlaceholder": "A Radarr Server",
"components.Settings.RadarrModal.ssl": "Enable SSL",
"components.Settings.RadarrModal.syncEnabled": "Enable Scan",
"components.Settings.RadarrModal.test": "Test",
"components.Settings.RadarrModal.testFirstQualityProfiles": "Test connection to load quality profiles",
"components.Settings.RadarrModal.testFirstRootFolders": "Test connection to load root folders",
"components.Settings.RadarrModal.testing": "Testing…",
"components.Settings.RadarrModal.toastRadarrTestFailure": "Failed to connect to Radarr.",
"components.Settings.RadarrModal.toastRadarrTestSuccess": "Radarr connection established successfully!",
"components.Settings.RadarrModal.validationApiKeyRequired": "You must provide an API key",
@ -473,25 +417,16 @@
"components.Settings.SettingsLogs.logs": "Logs",
"components.Settings.SettingsLogs.logsDescription": "You can also view these logs directly via <code>stdout</code>, or in <code>{configDir}/logs/overseerr.log</code>.",
"components.Settings.SettingsLogs.message": "Message",
"components.Settings.SettingsLogs.next": "Next",
"components.Settings.SettingsLogs.noresults": "No results.",
"components.Settings.SettingsLogs.pauseLogs": "Pause",
"components.Settings.SettingsLogs.previous": "Previous",
"components.Settings.SettingsLogs.resultsperpage": "Display {pageSize} results per page",
"components.Settings.SettingsLogs.resumeLogs": "Resume",
"components.Settings.SettingsLogs.showall": "Show All Logs",
"components.Settings.SettingsLogs.showingresults": "Showing <strong>{from}</strong> to <strong>{to}</strong> of <strong>{total}</strong> results",
"components.Settings.SettingsLogs.time": "Timestamp",
"components.Settings.SettingsLogs.viewDetails": "View Details",
"components.Settings.SettingsUsers.defaultPermissions": "Default Permissions",
"components.Settings.SettingsUsers.localLogin": "Enable Local Sign-In",
"components.Settings.SettingsUsers.movieRequestLimit": "{quotaLimit} movies per {quotaDays} days",
"components.Settings.SettingsUsers.movieRequestLimitLabel": "Global Movie Request Limit",
"components.Settings.SettingsUsers.save": "Save Changes",
"components.Settings.SettingsUsers.saving": "Saving…",
"components.Settings.SettingsUsers.toastSettingsFailure": "Something went wrong while saving settings.",
"components.Settings.SettingsUsers.toastSettingsSuccess": "User settings saved successfully!",
"components.Settings.SettingsUsers.tvRequestLimit": "{quotaLimit} seasons per {quotaDays} days",
"components.Settings.SettingsUsers.tvRequestLimitLabel": "Global Series Request Limit",
"components.Settings.SettingsUsers.userSettings": "User Settings",
"components.Settings.SettingsUsers.userSettingsDescription": "Configure global and default user settings.",
@ -518,8 +453,6 @@
"components.Settings.SonarrModal.preventSearch": "Disable Auto-Search",
"components.Settings.SonarrModal.qualityprofile": "Quality Profile",
"components.Settings.SonarrModal.rootfolder": "Root Folder",
"components.Settings.SonarrModal.save": "Save Changes",
"components.Settings.SonarrModal.saving": "Saving…",
"components.Settings.SonarrModal.seasonfolders": "Season Folders",
"components.Settings.SonarrModal.selectLanguageProfile": "Select language profile",
"components.Settings.SonarrModal.selectQualityProfile": "Select quality profile",
@ -529,11 +462,9 @@
"components.Settings.SonarrModal.servernamePlaceholder": "A Sonarr Server",
"components.Settings.SonarrModal.ssl": "Enable SSL",
"components.Settings.SonarrModal.syncEnabled": "Enable Scan",
"components.Settings.SonarrModal.test": "Test",
"components.Settings.SonarrModal.testFirstLanguageProfiles": "Test connection to load language profiles",
"components.Settings.SonarrModal.testFirstQualityProfiles": "Test connection to load quality profiles",
"components.Settings.SonarrModal.testFirstRootFolders": "Test connection to load root folders",
"components.Settings.SonarrModal.testing": "Testing…",
"components.Settings.SonarrModal.toastSonarrTestFailure": "Failed to connect to Sonarr.",
"components.Settings.SonarrModal.toastSonarrTestSuccess": "Sonarr connection established successfully!",
"components.Settings.SonarrModal.validationApiKeyRequired": "You must provide an API key",
@ -564,9 +495,7 @@
"components.Settings.currentlibrary": "Current Library: {name}",
"components.Settings.default": "Default",
"components.Settings.default4k": "Default 4K",
"components.Settings.delete": "Delete",
"components.Settings.deleteserverconfirm": "Are you sure you want to delete this server?",
"components.Settings.edit": "Edit",
"components.Settings.email": "Email",
"components.Settings.enablenotifications": "Enable Notifications",
"components.Settings.enablessl": "Enable SSL",
@ -610,8 +539,6 @@
"components.Settings.radarrsettings": "Radarr Settings",
"components.Settings.region": "Discover Region",
"components.Settings.regionTip": "Filter content by regional availability",
"components.Settings.save": "Save Changes",
"components.Settings.saving": "Saving…",
"components.Settings.scan": "Sync Libraries",
"components.Settings.scanning": "Syncing…",
"components.Settings.serverConnected": "connected",
@ -662,18 +589,14 @@
"components.Setup.signinMessage": "Get started by signing in with your Plex account",
"components.Setup.tip": "Tip",
"components.Setup.welcome": "Welcome to Overseerr",
"components.Slider.noresults": "No results.",
"components.StatusBadge.status4k": "4K {status}",
"components.StatusChacker.newversionDescription": "Overseerr has been updated! Please click the button below to reload the page.",
"components.StatusChacker.newversionavailable": "Application Update",
"components.StatusChacker.reloadOverseerr": "Reload",
"components.TitleCard.movie": "Movie",
"components.TitleCard.tvshow": "Series",
"components.TvDetails.TvCast.fullseriescast": "Full Series Cast",
"components.TvDetails.TvCrew.fullseriescrew": "Full Series Crew",
"components.TvDetails.allseasonsmarkedavailable": "* All seasons will be marked as available.",
"components.TvDetails.anime": "Anime",
"components.TvDetails.areyousure": "Are you sure?",
"components.TvDetails.cast": "Cast",
"components.TvDetails.downloadstatus": "Download Status",
"components.TvDetails.episodeRuntime": "Episode Runtime",
@ -699,7 +622,6 @@
"components.TvDetails.seasons": "{seasonCount, plural, one {# Season} other {# Seasons}}",
"components.TvDetails.showtype": "Series Type",
"components.TvDetails.similar": "Similar Series",
"components.TvDetails.status": "Status",
"components.TvDetails.viewfullcrew": "View Full Crew",
"components.TvDetails.watchtrailer": "Watch Trailer",
"components.UserList.accounttype": "Account Type",
@ -711,10 +633,8 @@
"components.UserList.createlocaluser": "Create Local User",
"components.UserList.createuser": "Create User",
"components.UserList.creating": "Creating…",
"components.UserList.delete": "Delete",
"components.UserList.deleteconfirm": "Are you sure you want to delete this user? All existing request data from this user will be removed.",
"components.UserList.deleteuser": "Delete User",
"components.UserList.edit": "Edit",
"components.UserList.edituser": "Edit User Permissions",
"components.UserList.email": "Email Address",
"components.UserList.importedfromplex": "{userCount, plural, one {# new user} other {# new users}} imported from Plex successfully!",
@ -722,19 +642,13 @@
"components.UserList.importfromplexerror": "Something went wrong while importing users from Plex.",
"components.UserList.lastupdated": "Last Updated",
"components.UserList.localuser": "Local User",
"components.UserList.next": "Next",
"components.UserList.nouserstoimport": "No new users to import from Plex.",
"components.UserList.owner": "Owner",
"components.UserList.password": "Password",
"components.UserList.passwordinfo": "Password Information",
"components.UserList.passwordinfodescription": "Email notifications need to be configured and enabled in order to automatically generate passwords.",
"components.UserList.plexuser": "Plex User",
"components.UserList.previous": "Previous",
"components.UserList.resultsperpage": "Display {pageSize} results per page",
"components.UserList.role": "Role",
"components.UserList.save": "Save Changes",
"components.UserList.saving": "Saving…",
"components.UserList.showingresults": "Showing <strong>{from}</strong> to <strong>{to}</strong> of <strong>{total}</strong> results",
"components.UserList.sortCreated": "Creation Date",
"components.UserList.sortDisplayName": "Display Name",
"components.UserList.sortRequests": "Request Count",
@ -772,8 +686,6 @@
"components.UserProfile.UserSettings.UserGeneralSettings.region": "Discover Region",
"components.UserProfile.UserSettings.UserGeneralSettings.regionTip": "Filter content by regional availability",
"components.UserProfile.UserSettings.UserGeneralSettings.role": "Role",
"components.UserProfile.UserSettings.UserGeneralSettings.save": "Save Changes",
"components.UserProfile.UserSettings.UserGeneralSettings.saving": "Saving…",
"components.UserProfile.UserSettings.UserGeneralSettings.seriesrequestlimit": "Series Request Limit",
"components.UserProfile.UserSettings.UserGeneralSettings.toastSettingsFailure": "Something went wrong while saving settings.",
"components.UserProfile.UserSettings.UserGeneralSettings.toastSettingsSuccess": "Settings saved successfully!",
@ -787,8 +699,6 @@
"components.UserProfile.UserSettings.UserNotificationSettings.pgpKey": "<PgpLink>PGP</PgpLink> Public Key",
"components.UserProfile.UserSettings.UserNotificationSettings.pgpKeyTip": "Encrypt email messages",
"components.UserProfile.UserSettings.UserNotificationSettings.plexuser": "Plex User",
"components.UserProfile.UserSettings.UserNotificationSettings.save": "Save Changes",
"components.UserProfile.UserSettings.UserNotificationSettings.saving": "Saving…",
"components.UserProfile.UserSettings.UserNotificationSettings.sendSilently": "Send Telegram Messages Silently",
"components.UserProfile.UserSettings.UserNotificationSettings.sendSilentlyDescription": "Send notifications with no sound",
"components.UserProfile.UserSettings.UserNotificationSettings.telegramChatId": "Telegram Chat ID",
@ -804,11 +714,8 @@
"components.UserProfile.UserSettings.UserPasswordChange.nopasswordset": "No Password Set",
"components.UserProfile.UserSettings.UserPasswordChange.nopasswordsetDescription": "This user account currently does not have a password specifically for {applicationTitle}. Configure a password below to enable this account to sign in as a \"local user.\"",
"components.UserProfile.UserSettings.UserPasswordChange.nopasswordsetDescriptionOwnAccount": "Your account currently does not have a password specifically for {applicationTitle}. Configure a password below to enable sign in as a \"local user\" using your email address.",
"components.UserProfile.UserSettings.UserPasswordChange.nopermission": "Unauthorized",
"components.UserProfile.UserSettings.UserPasswordChange.nopermissionDescription": "You do not have permission to modify this user's password.",
"components.UserProfile.UserSettings.UserPasswordChange.password": "Password",
"components.UserProfile.UserSettings.UserPasswordChange.save": "Save Changes",
"components.UserProfile.UserSettings.UserPasswordChange.saving": "Saving…",
"components.UserProfile.UserSettings.UserPasswordChange.toastSettingsFailure": "Something went wrong while saving the password.",
"components.UserProfile.UserSettings.UserPasswordChange.toastSettingsFailureVerifyCurrent": "Something went wrong while saving the password. Was your current password entered correctly?",
"components.UserProfile.UserSettings.UserPasswordChange.toastSettingsSuccess": "Password saved successfully!",
@ -821,17 +728,13 @@
"components.UserProfile.UserSettings.UserPermissions.localuser": "Local User",
"components.UserProfile.UserSettings.UserPermissions.permissions": "Permissions",
"components.UserProfile.UserSettings.UserPermissions.plexuser": "Plex User",
"components.UserProfile.UserSettings.UserPermissions.save": "Save Changes",
"components.UserProfile.UserSettings.UserPermissions.saving": "Saving…",
"components.UserProfile.UserSettings.UserPermissions.toastSettingsFailure": "Something went wrong while saving settings.",
"components.UserProfile.UserSettings.UserPermissions.toastSettingsSuccess": "Permissions saved successfully!",
"components.UserProfile.UserSettings.UserPermissions.unauthorized": "Unauthorized",
"components.UserProfile.UserSettings.UserPermissions.unauthorizedDescription": "You cannot modify your own permissions.",
"components.UserProfile.UserSettings.menuChangePass": "Password",
"components.UserProfile.UserSettings.menuGeneralSettings": "General",
"components.UserProfile.UserSettings.menuNotifications": "Notifications",
"components.UserProfile.UserSettings.menuPermissions": "Permissions",
"components.UserProfile.UserSettings.unauthorized": "Unauthorized",
"components.UserProfile.UserSettings.unauthorizedDescription": "You do not have permission to modify this user's settings.",
"components.UserProfile.limit": "{remaining} of {limit}",
"components.UserProfile.movierequests": "Movie Requests",
@ -843,10 +746,14 @@
"components.UserProfile.totalrequests": "Total Requests",
"components.UserProfile.unlimited": "Unlimited",
"i18n.advanced": "Advanced",
"i18n.all": "All",
"i18n.approve": "Approve",
"i18n.approved": "Approved",
"i18n.areyousure": "Are you sure?",
"i18n.available": "Available",
"i18n.back": "Back",
"i18n.cancel": "Cancel",
"i18n.canceling": "Canceling…",
"i18n.close": "Close",
"i18n.decline": "Decline",
"i18n.declined": "Declined",
@ -857,17 +764,34 @@
"i18n.experimental": "Experimental",
"i18n.failed": "Failed",
"i18n.loading": "Loading…",
"i18n.movie": "Movie",
"i18n.movies": "Movies",
"i18n.next": "Next",
"i18n.noresults": "No results.",
"i18n.notrequested": "Not Requested",
"i18n.partiallyavailable": "Partially Available",
"i18n.pending": "Pending",
"i18n.previous": "Previous",
"i18n.processing": "Processing",
"i18n.request": "Request",
"i18n.request4k": "Request 4K",
"i18n.requested": "Requested",
"i18n.requesting": "Requesting…",
"i18n.resultsperpage": "Display {pageSize} results per page",
"i18n.retry": "Retry",
"i18n.save": "Save Changes",
"i18n.saving": "Saving…",
"i18n.settings": "Settings",
"i18n.showingresults": "Showing <strong>{from}</strong> to <strong>{to}</strong> of <strong>{total}</strong> results",
"i18n.status": "Status",
"i18n.test": "Test",
"i18n.testing": "Testing…",
"i18n.tvshow": "Series",
"i18n.tvshows": "Series",
"i18n.unauthorized": "Unauthorized",
"i18n.unavailable": "Unavailable",
"i18n.usersettings": "User Settings",
"i18n.view": "View",
"pages.errormessagewithcode": "{statusCode} - {error}",
"pages.internalservererror": "Internal Server Error",
"pages.oops": "Oops",

Loading…
Cancel
Save