1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2024-10-29 23:12:39 +01:00

New: More translations for columns

This commit is contained in:
Bogdan 2023-07-29 04:39:06 +03:00 committed by GitHub
parent cda9cf726a
commit aee8579d18
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 269 additions and 196 deletions

View File

@ -206,9 +206,11 @@ class FilterBuilderRow extends Component {
const selectedFilterBuilderProp = this.selectedFilterBuilderProp;
const keyOptions = filterBuilderProps.map((availablePropFilter) => {
const { name, label } = availablePropFilter;
return {
key: availablePropFilter.name,
value: availablePropFilter.label
key: name,
value: typeof label === 'function' ? label() : label
};
}).sort((a, b) => a.value.localeCompare(b.value));

View File

@ -61,7 +61,7 @@ class SelectInput extends Component {
value={key}
{...otherOptionProps}
>
{optionValue}
{typeof optionValue === 'function' ? optionValue() : optionValue}
</option>
);
})
@ -75,7 +75,7 @@ SelectInput.propTypes = {
className: PropTypes.string,
disabledClassName: PropTypes.string,
name: PropTypes.string.isRequired,
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.func]).isRequired,
values: PropTypes.arrayOf(PropTypes.object).isRequired,
isDisabled: PropTypes.bool,
hasError: PropTypes.bool,

View File

@ -32,7 +32,7 @@ class FilterMenuContent extends Component {
selectedFilterKey={selectedFilterKey}
onPress={onFilterSelect}
>
{filter.label}
{typeof filter.label === 'function' ? filter.label() : filter.label}
</FilterMenuItem>
);
})

View File

@ -1,8 +1,10 @@
import React from 'react';
type PropertyFunction<T> = () => T;
interface Column {
name: string;
label: string | React.ReactNode;
label: string | PropertyFunction<string> | React.ReactNode;
columnLabel?: string;
isSortable?: boolean;
isVisible: boolean;

View File

@ -107,7 +107,7 @@ function Table(props) {
{...getTableHeaderCellProps(otherProps)}
{...column}
>
{column.label}
{typeof column.label === 'function' ? column.label() : column.label}
</TableHeaderCell>
);
})

View File

@ -30,6 +30,7 @@ class TableHeaderCell extends Component {
const {
className,
name,
label,
columnLabel,
isSortable,
isVisible,
@ -53,7 +54,8 @@ class TableHeaderCell extends Component {
{...otherProps}
component="th"
className={className}
title={columnLabel}
label={typeof label === 'function' ? label() : label}
title={typeof columnLabel === 'function' ? columnLabel() : columnLabel}
onPress={this.onPress}
>
{children}
@ -77,7 +79,8 @@ class TableHeaderCell extends Component {
TableHeaderCell.propTypes = {
className: PropTypes.string,
name: PropTypes.string.isRequired,
columnLabel: PropTypes.string,
label: PropTypes.oneOfType([PropTypes.string, PropTypes.func, PropTypes.node]),
columnLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
isSortable: PropTypes.bool,
isVisible: PropTypes.bool,
isModifiable: PropTypes.bool,

View File

@ -35,7 +35,7 @@ function TableOptionsColumn(props) {
isDisabled={isModifiable === false}
onChange={onVisibleChange}
/>
{label}
{typeof label === 'function' ? label() : label}
</label>
{
@ -56,7 +56,7 @@ function TableOptionsColumn(props) {
TableOptionsColumn.propTypes = {
name: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
label: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired,
isVisible: PropTypes.bool.isRequired,
isModifiable: PropTypes.bool.isRequired,
index: PropTypes.number.isRequired,

View File

@ -112,7 +112,7 @@ class TableOptionsColumnDragSource extends Component {
<TableOptionsColumn
name={name}
label={label}
label={typeof label === 'function' ? label() : label}
isVisible={isVisible}
isModifiable={isModifiable}
index={index}
@ -138,7 +138,7 @@ class TableOptionsColumnDragSource extends Component {
TableOptionsColumnDragSource.propTypes = {
name: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
label: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired,
isVisible: PropTypes.bool.isRequired,
isModifiable: PropTypes.bool.isRequired,
index: PropTypes.number.isRequired,

View File

@ -110,7 +110,7 @@ function SeriesIndexTableHeader(props: SeriesIndexTableHeaderProps) {
isSortable={isSortable}
onSortPress={onSortPress}
>
{label}
{typeof label === 'function' ? label() : label}
</VirtualTableHeaderCell>
);
})}

View File

@ -4,6 +4,7 @@ import { sortDirections } from 'Helpers/Props';
import { createThunk, handleThunks } from 'Store/thunks';
import createAjaxRequest from 'Utilities/createAjaxRequest';
import serverSideCollectionHandlers from 'Utilities/serverSideCollectionHandlers';
import translate from 'Utilities/String/translate';
import { set, updateItem } from './baseActions';
import createHandleActions from './Creators/createHandleActions';
import createRemoveItemHandler from './Creators/createRemoveItemHandler';
@ -32,47 +33,47 @@ export const defaultState = {
columns: [
{
name: 'series.sortTitle',
label: 'Series Title',
label: () => translate('SeriesTitle'),
isSortable: true,
isVisible: true
},
{
name: 'sourceTitle',
label: 'Source Title',
label: () => translate('SourceTitle'),
isSortable: true,
isVisible: true
},
{
name: 'languages',
label: 'Languages',
label: () => translate('Languages'),
isVisible: false
},
{
name: 'quality',
label: 'Quality',
label: () => translate('Quality'),
isVisible: true
},
{
name: 'customFormats',
label: 'Formats',
label: () => translate('Formats'),
isSortable: false,
isVisible: true
},
{
name: 'date',
label: 'Date',
label: () => translate('Date'),
isSortable: true,
isVisible: true
},
{
name: 'indexer',
label: 'Indexer',
label: () => translate('Indexer'),
isSortable: true,
isVisible: false
},
{
name: 'actions',
columnLabel: 'Actions',
columnLabel: () => translate('Actions'),
isVisible: true,
isModifiable: false
}

View File

@ -8,6 +8,7 @@ import { filterBuilderTypes, filterBuilderValueTypes, filterTypes } from 'Helper
import { createThunk, handleThunks } from 'Store/thunks';
import createAjaxRequest from 'Utilities/createAjaxRequest';
import findSelectedFilters from 'Utilities/Filter/findSelectedFilters';
import translate from 'Utilities/String/translate';
import { set, update } from './baseActions';
import { executeCommandHelper } from './commandActions';
import createHandleActions from './Creators/createHandleActions';
@ -56,7 +57,7 @@ export const defaultState = {
filters: [
{
key: 'all',
label: 'All',
label: () => translate('All'),
filters: [
{
key: 'unmonitored',
@ -67,7 +68,7 @@ export const defaultState = {
},
{
key: 'monitored',
label: 'Monitored Only',
label: () => translate('MonitoredOnly'),
filters: [
{
key: 'unmonitored',
@ -81,13 +82,13 @@ export const defaultState = {
filterBuilderProps: [
{
name: 'unmonitored',
label: 'Include Unmonitored',
label: () => translate('IncludeUnmonitored'),
type: filterBuilderTypes.EQUAL,
valueType: filterBuilderValueTypes.BOOL
},
{
name: 'tags',
label: 'Tags',
label: () => translate('Tags'),
type: filterBuilderTypes.CONTAINS,
valueType: filterBuilderValueTypes.TAG
}

View File

@ -33,7 +33,7 @@ export const defaultState = {
columns: [
{
name: 'monitored',
columnLabel: 'Monitored',
columnLabel: () => translate('Monitored'),
isVisible: true,
isModifiable: false
},
@ -44,94 +44,91 @@ export const defaultState = {
},
{
name: 'title',
label: 'Title',
label: () => translate('Title'),
isVisible: true
},
{
name: 'path',
label: 'Path',
label: () => translate('Path'),
isVisible: false
},
{
name: 'relativePath',
label: 'Relative Path',
label: () => translate('RelativePath'),
isVisible: false
},
{
name: 'airDateUtc',
label: 'Air Date',
label: () => translate('AirDate'),
isVisible: true
},
{
name: 'runtime',
label: 'Runtime',
label: () => translate('Runtime'),
isVisible: false
},
{
name: 'languages',
label: 'Languages',
label: () => translate('Languages'),
isVisible: false
},
{
name: 'audioInfo',
label: 'Audio Info',
label: () => translate('AudioInfo'),
isVisible: false
},
{
name: 'videoCodec',
label: 'Video Codec',
label: () => translate('VideoCodec'),
isVisible: false
},
{
name: 'videoDynamicRangeType',
label: 'Video Dynamic Range',
label: () => translate('VideoDynamicRange'),
isVisible: false
},
{
name: 'audioLanguages',
label: 'Audio Languages',
label: () => translate('AudioLanguages'),
isVisible: false
},
{
name: 'subtitleLanguages',
label: 'Subtitle Languages',
label: () => translate('SubtitleLanguages'),
isVisible: false
},
{
name: 'size',
label: 'Size',
label: () => translate('Size'),
isVisible: false
},
{
name: 'releaseGroup',
label: 'Release Group',
label: () => translate('ReleaseGroup'),
isVisible: false
},
{
name: 'customFormats',
label: 'Formats',
label: () => translate('Formats'),
isVisible: false
},
{
name: 'customFormatScore',
get columnLabel() {
return translate('CustomFormatScore');
},
columnLabel: () => translate('CustomFormatScore'),
label: React.createElement(Icon, {
name: icons.SCORE,
title: () => translate('CustomFormatScore')
}),
isVisible: false
},
{
name: 'status',
label: 'Status',
label: () => translate('Status'),
isVisible: true
},
{
name: 'actions',
columnLabel: 'Actions',
columnLabel: () => translate('Actions'),
isVisible: true,
isModifiable: false
}

View File

@ -5,6 +5,7 @@ import { filterTypes, icons, sortDirections } from 'Helpers/Props';
import { createThunk, handleThunks } from 'Store/thunks';
import createAjaxRequest from 'Utilities/createAjaxRequest';
import serverSideCollectionHandlers from 'Utilities/serverSideCollectionHandlers';
import translate from 'Utilities/String/translate';
import { updateItem } from './baseActions';
import createHandleActions from './Creators/createHandleActions';
import createServerSideCollectionHandlers from './Creators/createServerSideCollectionHandlers';
@ -31,80 +32,80 @@ export const defaultState = {
columns: [
{
name: 'eventType',
columnLabel: 'Event Type',
columnLabel: () => translate('EventType'),
isVisible: true,
isModifiable: false
},
{
name: 'series.sortTitle',
label: 'Series',
label: () => translate('Series'),
isSortable: true,
isVisible: true
},
{
name: 'episode',
label: 'Episode',
label: () => translate('Episode'),
isVisible: true
},
{
name: 'episodes.title',
label: 'Episode Title',
label: () => translate('EpisodeTitle'),
isVisible: true
},
{
name: 'languages',
label: 'Languages',
label: () => translate('Languages'),
isVisible: false
},
{
name: 'quality',
label: 'Quality',
label: () => translate('Quality'),
isVisible: true
},
{
name: 'customFormats',
label: 'Formats',
label: () => translate('Formats'),
isSortable: false,
isVisible: true
},
{
name: 'date',
label: 'Date',
label: () => translate('Date'),
isSortable: true,
isVisible: true
},
{
name: 'downloadClient',
label: 'Download Client',
label: () => translate('DownloadClient'),
isVisible: false
},
{
name: 'indexer',
label: 'Indexer',
label: () => translate('Indexer'),
isVisible: false
},
{
name: 'releaseGroup',
label: 'Release Group',
label: () => translate('ReleaseGroup'),
isVisible: false
},
{
name: 'sourceTitle',
label: 'Source Title',
label: () => translate('SourceTitle'),
isVisible: false
},
{
name: 'customFormatScore',
columnLabel: 'Custom Format Score',
columnLabel: () => translate('CustomFormatScore'),
label: React.createElement(Icon, {
name: icons.SCORE,
title: 'Custom format score'
title: () => translate('CustomFormatScore')
}),
isVisible: false
},
{
name: 'details',
columnLabel: 'Details',
columnLabel: () => translate('Details'),
isVisible: true,
isModifiable: false
}
@ -115,12 +116,12 @@ export const defaultState = {
filters: [
{
key: 'all',
label: 'All',
label: () => translate('All'),
filters: []
},
{
key: 'grabbed',
label: 'Grabbed',
label: () => translate('Grabbed'),
filters: [
{
key: 'eventType',
@ -131,7 +132,7 @@ export const defaultState = {
},
{
key: 'imported',
label: 'Imported',
label: () => translate('Imported'),
filters: [
{
key: 'eventType',
@ -142,7 +143,7 @@ export const defaultState = {
},
{
key: 'failed',
label: 'Failed',
label: () => translate('Failed'),
filters: [
{
key: 'eventType',
@ -153,7 +154,7 @@ export const defaultState = {
},
{
key: 'deleted',
label: 'Deleted',
label: () => translate('Deleted'),
filters: [
{
key: 'eventType',
@ -164,7 +165,7 @@ export const defaultState = {
},
{
key: 'renamed',
label: 'Renamed',
label: () => translate('Renamed'),
filters: [
{
key: 'eventType',
@ -175,7 +176,7 @@ export const defaultState = {
},
{
key: 'ignored',
label: 'Ignored',
label: () => translate('Ignored'),
filters: [
{
key: 'eventType',

View File

@ -7,6 +7,7 @@ import { icons, sortDirections } from 'Helpers/Props';
import { createThunk, handleThunks } from 'Store/thunks';
import createAjaxRequest from 'Utilities/createAjaxRequest';
import serverSideCollectionHandlers from 'Utilities/serverSideCollectionHandlers';
import translate from 'Utilities/String/translate';
import { set, updateItem } from './baseActions';
import createFetchHandler from './Creators/createFetchHandler';
import createHandleActions from './Creators/createHandleActions';
@ -59,113 +60,113 @@ export const defaultState = {
columns: [
{
name: 'status',
columnLabel: 'Status',
columnLabel: () => translate('Status'),
isSortable: true,
isVisible: true,
isModifiable: false
},
{
name: 'series.sortTitle',
label: 'Series',
label: () => translate('Series'),
isSortable: true,
isVisible: true
},
{
name: 'episode',
label: 'Episode',
label: () => translate('Episode'),
isSortable: true,
isVisible: true
},
{
name: 'episodes.title',
label: 'Episode Title',
label: () => translate('EpisodeTitle'),
isSortable: true,
isVisible: true
},
{
name: 'episodes.airDateUtc',
label: 'Episode Air Date',
label: () => translate('EpisodeAirDate'),
isSortable: true,
isVisible: false
},
{
name: 'languages',
label: 'Languages',
label: () => translate('Languages'),
isSortable: true,
isVisible: false
},
{
name: 'quality',
label: 'Quality',
label: () => translate('Quality'),
isSortable: true,
isVisible: true
},
{
name: 'customFormats',
label: 'Formats',
label: () => translate('Formats'),
isSortable: false,
isVisible: true
},
{
name: 'customFormatScore',
columnLabel: 'Custom Format Score',
columnLabel: () => translate('CustomFormatScore'),
label: React.createElement(Icon, {
name: icons.SCORE,
title: 'Custom format score'
title: () => translate('CustomFormatScore')
}),
isVisible: false
},
{
name: 'protocol',
label: 'Protocol',
label: () => translate('Protocol'),
isSortable: true,
isVisible: false
},
{
name: 'indexer',
label: 'Indexer',
label: () => translate('Indexer'),
isSortable: true,
isVisible: false
},
{
name: 'downloadClient',
label: 'Download Client',
label: () => translate('DownloadClient'),
isSortable: true,
isVisible: false
},
{
name: 'title',
label: 'Release Title',
label: () => translate('ReleaseTitle'),
isSortable: true,
isVisible: false
},
{
name: 'size',
label: 'Size',
label: () => translate('Size'),
isSortable: true,
isVisibile: false
},
{
name: 'outputPath',
label: 'Output Path',
label: () => translate('OutputPath'),
isSortable: false,
isVisible: false
},
{
name: 'estimatedCompletionTime',
label: 'Time Left',
label: () => translate('TimeLeft'),
isSortable: true,
isVisible: true
},
{
name: 'progress',
label: 'Progress',
label: () => translate('Progress'),
isSortable: true,
isVisible: true
},
{
name: 'actions',
columnLabel: 'Actions',
columnLabel: () => translate('Actions'),
isVisible: true,
isModifiable: false
}

View File

@ -3,6 +3,7 @@ import { filterBuilderTypes, filterBuilderValueTypes, filterTypePredicates, filt
import { createThunk, handleThunks } from 'Store/thunks';
import sortByName from 'Utilities/Array/sortByName';
import createAjaxRequest from 'Utilities/createAjaxRequest';
import translate from 'Utilities/String/translate';
import createFetchHandler from './Creators/createFetchHandler';
import createHandleActions from './Creators/createHandleActions';
import createSetClientSideCollectionFilterReducer from './Creators/Reducers/createSetClientSideCollectionFilterReducer';
@ -62,12 +63,12 @@ export const defaultState = {
filters: [
{
key: 'all',
label: 'All',
label: () => translate('All'),
filters: []
},
{
key: 'season-pack',
label: 'Season Pack',
label: () => translate('SeasonPack'),
filters: [
{
key: 'fullSeason',
@ -78,7 +79,7 @@ export const defaultState = {
},
{
key: 'not-season-pack',
label: 'Not Season Pack',
label: () => translate('NotSeasonPack'),
filters: [
{
key: 'fullSeason',
@ -173,51 +174,51 @@ export const defaultState = {
filterBuilderProps: [
{
name: 'title',
label: 'Title',
label: () => translate('Title'),
type: filterBuilderTypes.STRING
},
{
name: 'age',
label: 'Age',
label: () => translate('Age'),
type: filterBuilderTypes.NUMBER
},
{
name: 'protocol',
label: 'Protocol',
label: () => translate('Protocol'),
type: filterBuilderTypes.EXACT,
valueType: filterBuilderValueTypes.PROTOCOL
},
{
name: 'indexerId',
label: 'Indexer',
label: () => translate('Indexer'),
type: filterBuilderTypes.EXACT,
valueType: filterBuilderValueTypes.INDEXER
},
{
name: 'size',
label: 'Size',
label: () => translate('Size'),
type: filterBuilderTypes.NUMBER,
valueType: filterBuilderValueTypes.BYTES
},
{
name: 'seeders',
label: 'Seeders',
label: () => translate('Seeders'),
type: filterBuilderTypes.NUMBER
},
{
name: 'peers',
label: 'Peers',
label: () => translate('Peers'),
type: filterBuilderTypes.NUMBER
},
{
name: 'quality',
label: 'Quality',
label: () => translate('Quality'),
type: filterBuilderTypes.EXACT,
valueType: filterBuilderValueTypes.QUALITY
},
{
name: 'languages',
label: 'Languages',
label: () => translate('Languages'),
type: filterBuilderTypes.ARRAY,
optionsSelector: function(items) {
const genreList = items.reduce((acc, release) => {
@ -236,17 +237,17 @@ export const defaultState = {
},
{
name: 'customFormatScore',
label: 'Custom Format Score',
label: () => translate('CustomFormatScore'),
type: filterBuilderTypes.NUMBER
},
{
name: 'rejectionCount',
label: 'Rejection Count',
label: () => translate('RejectionCount'),
type: filterBuilderTypes.NUMBER
},
{
name: 'fullSeason',
label: 'Season Pack',
label: () => translate('SeasonPack'),
type: filterBuilderTypes.EXACT,
valueType: filterBuilderValueTypes.BOOL
}

View File

@ -6,6 +6,7 @@ import { createThunk, handleThunks } from 'Store/thunks';
import sortByName from 'Utilities/Array/sortByName';
import createAjaxRequest from 'Utilities/createAjaxRequest';
import dateFilterPredicate from 'Utilities/Date/dateFilterPredicate';
import translate from 'Utilities/String/translate';
import { set, updateItem } from './baseActions';
import createFetchHandler from './Creators/createFetchHandler';
import createHandleActions from './Creators/createHandleActions';
@ -29,12 +30,12 @@ export const section = 'series';
export const filters = [
{
key: 'all',
label: 'All',
label: () => translate('All'),
filters: []
},
{
key: 'monitored',
label: 'Monitored Only',
label: () => translate('MonitoredOnly'),
filters: [
{
key: 'monitored',
@ -45,7 +46,7 @@ export const filters = [
},
{
key: 'unmonitored',
label: 'Unmonitored Only',
label: () => translate('UnmonitoredOnly'),
filters: [
{
key: 'monitored',
@ -56,7 +57,7 @@ export const filters = [
},
{
key: 'continuing',
label: 'Continuing Only',
label: () => translate('ContinuingOnly'),
filters: [
{
key: 'status',
@ -67,7 +68,7 @@ export const filters = [
},
{
key: 'ended',
label: 'Ended Only',
label: () => translate('EndedOnly'),
filters: [
{
key: 'status',
@ -78,7 +79,7 @@ export const filters = [
},
{
key: 'missing',
label: 'Missing Episodes',
label: () => translate('MissingEpisodes'),
filters: [
{
key: 'missing',
@ -194,25 +195,25 @@ export const filterPredicates = {
export const filterBuilderProps = [
{
name: 'monitored',
label: 'Monitored',
label: () => translate('Monitored'),
type: filterBuilderTypes.EXACT,
valueType: filterBuilderValueTypes.BOOL
},
{
name: 'status',
label: 'Status',
label: () => translate('Status'),
type: filterBuilderTypes.EXACT,
valueType: filterBuilderValueTypes.SERIES_STATUS
},
{
name: 'seriesType',
label: 'Type',
label: () => translate('Type'),
type: filterBuilderTypes.EXACT,
valueType: filterBuilderValueTypes.SERIES_TYPES
},
{
name: 'network',
label: 'Network',
label: () => translate('Network'),
type: filterBuilderTypes.STRING,
optionsSelector: function(items) {
const tagList = items.reduce((acc, series) => {
@ -231,57 +232,57 @@ export const filterBuilderProps = [
},
{
name: 'qualityProfileId',
label: 'Quality Profile',
label: () => translate('QualityProfile'),
type: filterBuilderTypes.EXACT,
valueType: filterBuilderValueTypes.QUALITY_PROFILE
},
{
name: 'nextAiring',
label: 'Next Airing',
label: () => translate('NextAiring'),
type: filterBuilderTypes.DATE,
valueType: filterBuilderValueTypes.DATE
},
{
name: 'previousAiring',
label: 'Previous Airing',
label: () => translate('PreviousAiring'),
type: filterBuilderTypes.DATE,
valueType: filterBuilderValueTypes.DATE
},
{
name: 'added',
label: 'Added',
label: () => translate('Added'),
type: filterBuilderTypes.DATE,
valueType: filterBuilderValueTypes.DATE
},
{
name: 'seasonCount',
label: 'Season Count',
label: () => translate('SeasonCount'),
type: filterBuilderTypes.NUMBER
},
{
name: 'episodeProgress',
label: 'Episode Progress',
label: () => translate('EpisodeProgress'),
type: filterBuilderTypes.NUMBER
},
{
name: 'path',
label: 'Path',
label: () => translate('Path'),
type: filterBuilderTypes.STRING
},
{
name: 'rootFolderPath',
label: 'Root Folder Path',
label: () => translate('RootFolderPath'),
type: filterBuilderTypes.EXACT
},
{
name: 'sizeOnDisk',
label: 'Size on Disk',
label: () => translate('SizeOnDisk'),
type: filterBuilderTypes.NUMBER,
valueType: filterBuilderValueTypes.BYTES
},
{
name: 'genres',
label: 'Genres',
label: () => translate('Genres'),
type: filterBuilderTypes.ARRAY,
optionsSelector: function(items) {
const tagList = items.reduce((acc, series) => {
@ -300,7 +301,7 @@ export const filterBuilderProps = [
},
{
name: 'originalLanguage',
label: 'Original Language',
label: () => translate('OriginalLanguage'),
type: filterBuilderTypes.EXACT,
optionsSelector: function(items) {
const languageList = items.reduce((acc, series) => {
@ -319,33 +320,33 @@ export const filterBuilderProps = [
},
{
name: 'releaseGroups',
label: 'Release Groups',
label: () => translate('ReleaseGroups'),
type: filterBuilderTypes.ARRAY
},
{
name: 'ratings',
label: 'Rating',
label: () => translate('Rating'),
type: filterBuilderTypes.NUMBER
},
{
name: 'certification',
label: 'Certification',
label: () => translate('Certification'),
type: filterBuilderTypes.EXACT
},
{
name: 'tags',
label: 'Tags',
label: () => translate('Tags'),
type: filterBuilderTypes.ARRAY,
valueType: filterBuilderValueTypes.TAG
},
{
name: 'useSceneNumbering',
label: 'Scene Numbering',
label: () => translate('SceneNumbering'),
type: filterBuilderTypes.EXACT
},
{
name: 'hasMissingSeason',
label: 'Has Missing Season',
label: () => translate('HasMissingSeason'),
type: filterBuilderTypes.EXACT
}
];

View File

@ -1,6 +1,7 @@
import moment from 'moment';
import { createAction } from 'redux-actions';
import { sortDirections } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import createHandleActions from './Creators/createHandleActions';
import createSetClientSideCollectionFilterReducer from './Creators/Reducers/createSetClientSideCollectionFilterReducer';
import createSetClientSideCollectionSortReducer from './Creators/Reducers/createSetClientSideCollectionSortReducer';
@ -53,147 +54,147 @@ export const defaultState = {
columns: [
{
name: 'status',
columnLabel: 'Status',
columnLabel: () => translate('Status'),
isSortable: true,
isVisible: true,
isModifiable: false
},
{
name: 'sortTitle',
label: 'Series Title',
label: () => translate('SeriesTitle'),
isSortable: true,
isVisible: true,
isModifiable: false
},
{
name: 'seriesType',
label: 'Type',
label: () => translate('Type'),
isSortable: true,
isVisible: false
},
{
name: 'network',
label: 'Network',
label: () => translate('Network'),
isSortable: true,
isVisible: true
},
{
name: 'qualityProfileId',
label: 'Quality Profile',
label: () => translate('QualityProfile'),
isSortable: true,
isVisible: true
},
{
name: 'nextAiring',
label: 'Next Airing',
label: () => translate('NextAiring'),
isSortable: true,
isVisible: true
},
{
name: 'previousAiring',
label: 'Previous Airing',
label: () => translate('PreviousAiring'),
isSortable: true,
isVisible: false
},
{
name: 'originalLanguage',
label: 'Original Language',
label: () => translate('OriginalLanguage'),
isSortable: true,
isVisible: false
},
{
name: 'added',
label: 'Added',
label: () => translate('Added'),
isSortable: true,
isVisible: false
},
{
name: 'seasonCount',
label: 'Seasons',
label: () => translate('Seasons'),
isSortable: true,
isVisible: true
},
{
name: 'seasonFolder',
label: 'Season Folder',
label: () => translate('SeasonFolder'),
isSortable: true,
isVisible: false
},
{
name: 'episodeProgress',
label: 'Episodes',
label: () => translate('Episodes'),
isSortable: true,
isVisible: true
},
{
name: 'episodeCount',
label: 'Episode Count',
label: () => translate('EpisodeCount'),
isSortable: true,
isVisible: false
},
{
name: 'latestSeason',
label: 'Latest Season',
label: () => translate('LatestSeason'),
isSortable: true,
isVisible: false
},
{
name: 'year',
label: 'Year',
label: () => translate('Year'),
isSortable: true,
isVisible: false
},
{
name: 'path',
label: 'Path',
label: () => translate('Path'),
isSortable: true,
isVisible: false
},
{
name: 'sizeOnDisk',
label: 'Size on Disk',
label: () => translate('SizeOnDisk'),
isSortable: true,
isVisible: false
},
{
name: 'genres',
label: 'Genres',
label: () => translate('Genres'),
isSortable: false,
isVisible: false
},
{
name: 'ratings',
label: 'Rating',
label: () => translate('Rating'),
isSortable: true,
isVisible: false
},
{
name: 'certification',
label: 'Certification',
label: () => translate('Certification'),
isSortable: false,
isVisible: false
},
{
name: 'releaseGroups',
label: 'Release Groups',
label: () => translate('ReleaseGroups'),
isSortable: false,
isVisible: false
},
{
name: 'tags',
label: 'Tags',
label: () => translate('Tags'),
isSortable: true,
isVisible: false
},
{
name: 'useSceneNumbering',
label: 'Scene Numbering',
label: () => translate('SceneNumbering'),
isSortable: true,
isVisible: false
},
{
name: 'actions',
columnLabel: 'Actions',
columnLabel: () => translate('Actions'),
isVisible: true,
isModifiable: false
}

View File

@ -4,6 +4,7 @@ import { setAppValue } from 'Store/Actions/appActions';
import { createThunk, handleThunks } from 'Store/thunks';
import createAjaxRequest from 'Utilities/createAjaxRequest';
import serverSideCollectionHandlers from 'Utilities/serverSideCollectionHandlers';
import translate from 'Utilities/String/translate';
import { pingServer } from './appActions';
import { set } from './baseActions';
import createFetchHandler from './Creators/createFetchHandler';
@ -81,34 +82,34 @@ export const defaultState = {
columns: [
{
name: 'level',
columnLabel: 'Level',
columnLabel: () => translate('Level'),
isSortable: false,
isVisible: true,
isModifiable: false
},
{
name: 'time',
label: 'Time',
label: () => translate('Time'),
isSortable: true,
isVisible: true,
isModifiable: false
},
{
name: 'logger',
label: 'Component',
label: () => translate('Component'),
isSortable: false,
isVisible: true,
isModifiable: false
},
{
name: 'message',
label: 'Message',
label: () => translate('Message'),
isVisible: true,
isModifiable: false
},
{
name: 'actions',
columnLabel: 'Actions',
columnLabel: () => translate('Actions'),
isSortable: true,
isVisible: true,
isModifiable: false
@ -120,12 +121,12 @@ export const defaultState = {
filters: [
{
key: 'all',
label: 'All',
label: () => translate('All'),
filters: []
},
{
key: 'info',
label: 'Info',
label: () => translate('Info'),
filters: [
{
key: 'level',
@ -136,7 +137,7 @@ export const defaultState = {
},
{
key: 'warn',
label: 'Warn',
label: () => translate('Warn'),
filters: [
{
key: 'level',
@ -147,7 +148,7 @@ export const defaultState = {
},
{
key: 'error',
label: 'Error',
label: () => translate('Error'),
filters: [
{
key: 'level',

View File

@ -2,6 +2,7 @@ import { createAction } from 'redux-actions';
import { filterTypes, sortDirections } from 'Helpers/Props';
import { createThunk, handleThunks } from 'Store/thunks';
import serverSideCollectionHandlers from 'Utilities/serverSideCollectionHandlers';
import translate from 'Utilities/String/translate';
import createBatchToggleEpisodeMonitoredHandler from './Creators/createBatchToggleEpisodeMonitoredHandler';
import createHandleActions from './Creators/createHandleActions';
import createServerSideCollectionHandlers from './Creators/createServerSideCollectionHandlers';
@ -29,34 +30,34 @@ export const defaultState = {
columns: [
{
name: 'series.sortTitle',
label: 'Series Title',
label: () => translate('SeriesTitle'),
isSortable: true,
isVisible: true
},
{
name: 'episode',
label: 'Episode',
label: () => translate('Episode'),
isVisible: true
},
{
name: 'episodes.title',
label: 'Episode Title',
label: () => translate('EpisodeTitle'),
isVisible: true
},
{
name: 'episodes.airDateUtc',
label: 'Air Date',
label: () => translate('AirDate'),
isSortable: true,
isVisible: true
},
{
name: 'status',
label: 'Status',
label: () => translate('Status'),
isVisible: true
},
{
name: 'actions',
columnLabel: 'Actions',
columnLabel: () => translate('Actions'),
isVisible: true,
isModifiable: false
}
@ -67,7 +68,7 @@ export const defaultState = {
filters: [
{
key: 'monitored',
label: 'Monitored',
label: () => translate('Monitored'),
filters: [
{
key: 'monitored',
@ -78,7 +79,7 @@ export const defaultState = {
},
{
key: 'unmonitored',
label: 'Unmonitored',
label: () => translate('Unmonitored'),
filters: [
{
key: 'monitored',
@ -101,39 +102,39 @@ export const defaultState = {
columns: [
{
name: 'series.sortTitle',
label: 'Series Title',
label: () => translate('SeriesTitle'),
isSortable: true,
isVisible: true
},
{
name: 'episode',
label: 'Episode',
label: () => translate('Episode'),
isVisible: true
},
{
name: 'episodes.title',
label: 'Episode Title',
label: () => translate('EpisodeTitle'),
isVisible: true
},
{
name: 'episodes.airDateUtc',
label: 'Air Date',
label: () => translate('AirDate'),
isSortable: true,
isVisible: true
},
{
name: 'languages',
label: 'Languages',
label: () => translate('Languages'),
isVisible: false
},
{
name: 'status',
label: 'Status',
label: () => translate('Status'),
isVisible: true
},
{
name: 'actions',
columnLabel: 'Actions',
columnLabel: () => translate('Actions'),
isVisible: true,
isModifiable: false
}
@ -144,7 +145,7 @@ export const defaultState = {
filters: [
{
key: 'monitored',
label: 'Monitored',
label: () => translate('Monitored'),
filters: [
{
key: 'monitored',
@ -155,7 +156,7 @@ export const defaultState = {
},
{
key: 'unmonitored',
label: 'Unmonitored',
label: () => translate('Unmonitored'),
filters: [
{
key: 'monitored',

View File

@ -4,10 +4,12 @@
"Actions": "Actions",
"Activity": "Activity",
"Add": "Add",
"AddNew": "Add New",
"Added": "Added",
"AddingTag": "Adding tag",
"AddNew": "Add New",
"Age": "Age",
"AirDate": "Air Date",
"All": "All",
"AllTitles": "All Titles",
"ApiKeyValidationHealthCheckMessage": "Please update your API key to be at least {0} characters long. You can do this via settings or the config file",
"AppDataDirectory": "AppData directory",
@ -24,6 +26,8 @@
"ApplyTagsHelpTextRemove": "Remove: Remove the entered tags",
"ApplyTagsHelpTextReplace": "Replace: Replace the tags with the entered tags (enter no tags to clear all tags)",
"AptUpdater": "Use apt to install the update",
"AudioInfo": "Audio Info",
"AudioLanguages": "Audio Languages",
"AutoAdd": "Auto Add",
"AutomaticAdd": "Automatic Add",
"Backup": "Backup",
@ -38,20 +42,24 @@
"Calendar": "Calendar",
"Cancel": "Cancel",
"CancelPendingTask": "Are you sure you want to cancel this pending task?",
"Certification": "Certification",
"Clear": "Clear",
"CloneCondition": "Clone Condition",
"CloneCustomFormat": "Clone Custom Format",
"Close": "Close",
"Component": "Component",
"Connect": "Connect",
"ContinuingOnly": "Continuing Only",
"CountDownloadClientsSelected": "{count} download client(s) selected",
"CountImportListsSelected": "{count} import list(s) selected",
"CountIndexersSelected": "{count} indexer(s) selected",
"CountSeasons": "{count} seasons",
"CurrentlyInstalled": "Currently Installed",
"CustomFormats": "Custom Formats",
"CustomFormatScore": "Custom Format Score",
"CustomFormats": "Custom Formats",
"CutoffUnmet": "Cutoff Unmet",
"Daily": "Daily",
"Date": "Date",
"Delete": "Delete",
"DeleteBackup": "Delete Backup",
"DeleteBackupMessageText": "Are you sure you want to delete the backup '{name}'?",
@ -65,6 +73,7 @@
"DeleteSelectedImportListsMessageText": "Are you sure you want to delete {count} selected import list(s)?",
"DeleteSelectedIndexers": "Delete Indexer(s)",
"DeleteSelectedIndexersMessageText": "Are you sure you want to delete {count} selected indexer(s)?",
"Deleted": "Deleted",
"Details": "Details",
"Disabled": "Disabled",
"Discord": "Discord",
@ -74,13 +83,14 @@
"Donations": "Donations",
"DotNetVersion": ".NET",
"Download": "Download",
"DownloadClient": "Download Client",
"DownloadClientCheckNoneAvailableHealthCheckMessage": "No download client is available",
"DownloadClientCheckUnableToCommunicateWithHealthCheckMessage": "Unable to communicate with {0}.",
"DownloadClientRootFolderHealthCheckMessage": "Download client {0} places downloads in the root folder {1}. You should not download to a root folder.",
"DownloadClients": "Download Clients",
"DownloadClientSortingHealthCheckMessage": "Download client {0} has {1} sorting enabled for Sonarr's category. You should disable sorting in your download client to avoid import issues.",
"DownloadClientStatusAllClientHealthCheckMessage": "All download clients are unavailable due to failures",
"DownloadClientStatusSingleClientHealthCheckMessage": "Download clients unavailable due to failures: {0}",
"DownloadClients": "Download Clients",
"Duration": "Duration",
"Edit": "Edit",
"EditSelectedDownloadClients": "Edit Selected Download Clients",
@ -88,64 +98,84 @@
"EditSelectedIndexers": "Edit Selected Indexers",
"EditSeries": "Edit Series",
"EnableAutomaticSearch": "Enable Automatic Search",
"Enabled": "Enabled",
"EnableInteractiveSearch": "Enable Interactive Search",
"EnableRSS": "Enable RSS",
"Enabled": "Enabled",
"Ended": "Ended",
"EndedOnly": "Ended Only",
"Episode": "Episode",
"EpisodeAirDate": "Episode Air Date",
"EpisodeCount": "Episode Count",
"EpisodeInfo": "Episode Info",
"EpisodeNumbers": "Episode Number(s)",
"EpisodeProgress": "Episode Progress",
"EpisodeTitle": "Episode Title",
"Episodes": "Episodes",
"Error": "Error",
"ErrorRestoringBackup": "Error restoring backup",
"EventType": "Event Type",
"Events": "Events",
"Exception": "Exception",
"ExistingTag": "Existing tag",
"ExportCustomFormat": "Export Custom Format",
"ExternalUpdater": "Sonarr is configured to use an external update mechanism",
"Failed": "Failed",
"FailedToFetchUpdates": "Failed to fetch updates",
"FailedToUpdateSettings": "Failed to update settings",
"FeatureRequests": "Feature Requests",
"Filename": "Filename",
"Fixed": "Fixed",
"Formats": "Formats",
"Forums": "Forums",
"FreeSpace": "Free Space",
"From": "From",
"FullSeason": "Full Season",
"General": "General",
"GeneralSettings": "General Settings",
"Genres": "Genres",
"Grabbed": "Grabbed",
"HasMissingSeason": "Has Missing Season",
"Health": "Health",
"HiddenClickToShow": "Hidden, click to show",
"HideAdvanced": "Hide Advanced",
"History": "History",
"HomePage": "Home Page",
"IRC": "IRC",
"IRCLinkText": "#sonarr on Libera",
"Ignored": "Ignored",
"Implementation": "Implementation",
"ImportListRootFolderMissingRootHealthCheckMessage": "Missing root folder for import list(s): {0}",
"ImportListRootFolderMultipleMissingRootsHealthCheckMessage": "Multiple root folders are missing for import lists: {0}",
"ImportLists": "Import Lists",
"ImportListStatusAllUnavailableHealthCheckMessage": "All lists are unavailable due to failures",
"ImportListStatusUnavailableHealthCheckMessage": "Lists unavailable due to failures: {0}",
"ImportLists": "Import Lists",
"ImportMechanismEnableCompletedDownloadHandlingIfPossibleHealthCheckMessage": "Enable Completed Download Handling if possible",
"ImportMechanismEnableCompletedDownloadHandlingIfPossibleMultiComputerHealthCheckMessage": "Enable Completed Download Handling if possible (Multi-Computer unsupported)",
"ImportMechanismHandlingDisabledHealthCheckMessage": "Enable Completed Download Handling",
"Imported": "Imported",
"IncludeUnmonitored": "Include Unmonitored",
"Indexer": "Indexer",
"IndexerJackettAllHealthCheckMessage": "Indexers using the unsupported Jackett 'all' endpoint: {0}",
"IndexerLongTermStatusAllUnavailableHealthCheckMessage": "All indexers are unavailable due to failures for more than 6 hours",
"IndexerLongTermStatusUnavailableHealthCheckMessage": "Indexers unavailable due to failures for more than 6 hours: {0}",
"IndexerRssNoIndexersAvailableHealthCheckMessage": "All rss-capable indexers are temporarily unavailable due to recent indexer errors",
"IndexerRssNoIndexersEnabledHealthCheckMessage": "No indexers available with RSS sync enabled, Sonarr will not grab new releases automatically",
"Indexers": "Indexers",
"IndexerSearchNoAutomaticHealthCheckMessage": "No indexers available with Automatic Search enabled, Sonarr will not provide any automatic search results",
"IndexerSearchNoAvailableIndexersHealthCheckMessage": "All search-capable indexers are temporarily unavailable due to recent indexer errors",
"IndexerSearchNoInteractiveHealthCheckMessage": "No indexers available with Interactive Search enabled, Sonarr will not provide any interactive search results",
"IndexerStatusAllUnavailableHealthCheckMessage": "All indexers are unavailable due to failures",
"IndexerStatusUnavailableHealthCheckMessage": "Indexers unavailable due to failures: {0}",
"Indexers": "Indexers",
"Info": "Info",
"InstallLatest": "Install Latest",
"Interval": "Interval",
"IRC": "IRC",
"IRCLinkText": "#sonarr on Libera",
"Language": "Language",
"Language that Sonarr will use for UI": "Language that Sonarr will use for UI",
"Languages": "Languages",
"LastDuration": "Last Duration",
"LastExecution": "Last Execution",
"LastWriteTime": "Last Write Time",
"LatestSeason": "Latest Season",
"LiberaWebchat": "Libera Webchat",
"LibraryImport": "Library Import",
"Location": "Location",
@ -167,8 +197,10 @@
"Metadata": "Metadata",
"MetadataSource": "Metadata Source",
"Missing": "Missing",
"MissingEpisodes": "Missing Episodes",
"Mode": "Mode",
"Monitored": "Monitored",
"MonitoredOnly": "Monitored Only",
"MoreInfo": "More Info",
"MountHealthCheckMessage": "Mount containing a series path is mounted read-only: ",
"MultiSeason": "Multi-Season",
@ -190,19 +222,24 @@
"NoLogFiles": "No log files",
"NoSeasons": "No seasons",
"NoUpdatesAreAvailable": "No updates are available",
"OneSeason": "1 season",
"NotSeasonPack": "Not Season Pack",
"OnLatestVersion": "The latest version of Sonarr is already installed",
"OneSeason": "1 season",
"Options": "Options",
"OriginalLanguage": "Original Language",
"OutputPath": "Output Path",
"PackageVersion": "Package Version",
"PackageVersionInfo": "{packageVersion} by {packageAuthor}",
"PartialSeason": "Partial Season",
"Path": "Path",
"Peers": "Peers",
"PreviousAiring": "Previous Airing",
"PreviouslyInstalled": "Previously Installed",
"Priority": "Priority",
"Profiles": "Profiles",
"Progress": "Progress",
"Proper": "Proper",
"Protocol": "Protocol",
"ProxyBadRequestHealthCheckMessage": "Failed to test proxy. Status Code: {0}",
"ProxyFailedToTestHealthCheckMessage": "Failed to test proxy: {0}",
"ProxyResolveIpHealthCheckMessage": "Failed to resolve the IP Address for the Configured Proxy Host {0}",
@ -210,13 +247,17 @@
"QualityProfile": "Quality Profile",
"Queue": "Queue",
"Queued": "Queued",
"Rating": "Rating",
"ReadTheWikiForMoreInformation": "Read the Wiki for more information",
"Real": "Real",
"RecycleBinUnableToWriteHealthCheckMessage": "Unable to write to configured recycling bin folder: {0}. Ensure this path exists and is writable by the user running Sonarr",
"Refresh": "Refresh",
"RefreshSeries": "Refresh Series",
"RejectionCount": "Rejection Count",
"RelativePath": "Relative Path",
"Release": "Release",
"ReleaseGroup": "Release Group",
"ReleaseGroups": "Release Groups",
"ReleaseHash": "Release Hash",
"ReleaseTitle": "Release Title",
"Reload": "Reload",
@ -238,9 +279,6 @@
"Remove": "Remove",
"RemoveCompleted": "Remove Completed",
"RemoveCompletedDownloads": "Remove Completed Downloads",
"RemovedFromTaskQueue": "Removed from task queue",
"RemovedSeriesMultipleRemovedHealthCheckMessage": "Series {0} were removed from TheTVDB",
"RemovedSeriesSingleRemovedHealthCheckMessage": "Series {0} was removed from TheTVDB",
"RemoveFailed": "Remove Failed",
"RemoveFailedDownloads": "Remove Failed Downloads",
"RemoveFromDownloadClient": "Remove From Download Client",
@ -249,7 +287,11 @@
"RemoveSelectedItemQueueMessageText": "Are you sure you want to remove 1 item from the queue?",
"RemoveSelectedItems": "Remove Selected Items",
"RemoveSelectedItemsQueueMessageText": "Are you sure you want to remove {0} items from the queue?",
"RemovedFromTaskQueue": "Removed from task queue",
"RemovedSeriesMultipleRemovedHealthCheckMessage": "Series {0} were removed from TheTVDB",
"RemovedSeriesSingleRemovedHealthCheckMessage": "Series {0} was removed from TheTVDB",
"RemovingTag": "Removing tag",
"Renamed": "Renamed",
"Repack": "Repack",
"Replace": "Replace",
"Required": "Required",
@ -266,9 +308,17 @@
"RootFolder": "Root Folder",
"RootFolderMissingHealthCheckMessage": "Missing root folder: {0}",
"RootFolderMultipleMissingHealthCheckMessage": "Multiple root folders are missing: {0}",
"RootFolderPath": "Root Folder Path",
"Runtime": "Runtime",
"SceneNumbering": "Scene Numbering",
"Scheduled": "Scheduled",
"SearchForMonitoredEpisodes": "Search for monitored episodes",
"SeasonCount": "Season Count",
"SeasonFolder": "Season Folder",
"SeasonNumber": "Season Number",
"SeasonPack": "Season Pack",
"Seasons": "Seasons",
"Seeders": "Seeders",
"Series": "Series",
"SeriesEditor": "Series Editor",
"SeriesTitle": "Series Title",
@ -278,40 +328,50 @@
"ShownClickToHide": "Shown, click to hide",
"Size": "Size",
"SizeOnDisk": "Size on disk",
"SkipRedownloadHelpText": "Prevents Sonarr from trying to download an alternative release for this item",
"SkipRedownload": "Skip Redownload",
"SkipRedownloadHelpText": "Prevents Sonarr from trying to download an alternative release for this item",
"Source": "Source",
"SourceTitle": "Source Title",
"Special": "Special",
"Started": "Started",
"StartupDirectory": "Startup directory",
"Status": "Status",
"SubtitleLanguages": "Subtitle Languages",
"System": "System",
"SystemTimeHealthCheckMessage": "System time is off by more than 1 day. Scheduled tasks may not run correctly until the time is corrected",
"Tags": "Tags",
"Tasks": "Tasks",
"TaskUserAgentTooltip": "User-Agent provided by the app that called the API",
"Tasks": "Tasks",
"TestAll": "Test All",
"TestParsing": "Test Parsing",
"TheLogLevelDefault": "The log level defaults to 'Info' and can be changed in [General Settings](/settings/general)",
"Time": "Time",
"TimeLeft": "Time Left",
"Title": "Title",
"TotalSpace": "Total Space",
"Twitter": "Twitter",
"Type": "Type",
"UI": "UI",
"UI Language": "UI Language",
"UnableToLoadBackups": "Unable to load backups",
"UnableToUpdateSonarrDirectly": "Unable to update Sonarr directly,",
"Unmonitored": "Unmonitored",
"UnmonitoredOnly": "Unmonitored Only",
"UpdateAvailableHealthCheckMessage": "New update is available",
"UpdaterLogFiles": "Updater Log Files",
"Updates": "Updates",
"UpdateStartupNotWritableHealthCheckMessage": "Cannot install update because startup folder '{0}' is not writable by the user '{1}'.",
"UpdateStartupTranslocationHealthCheckMessage": "Cannot install update because startup folder '{0}' is in an App Translocation folder.",
"UpdateUINotWritableHealthCheckMessage": "Cannot install update because UI folder '{0}' is not writable by the user '{1}'.",
"UpdaterLogFiles": "Updater Log Files",
"Updates": "Updates",
"Uptime": "Uptime",
"Version": "Version",
"VideoCodec": "Video Codec",
"VideoDynamicRange": "Video Dynamic Range",
"Wanted": "Wanted",
"Warn": "Warn",
"Wiki": "Wiki",
"WouldYouLikeToRestoreBackup": "Would you like to restore the backup '{name}'?",
"Year": "Year",
"Yes": "Yes",
"YesCancel": "Yes, Cancel"
}