diff --git a/frontend/src/Components/Page/Sidebar/PageSidebar.js b/frontend/src/Components/Page/Sidebar/PageSidebar.js
index ef4bad06a..30d7c887a 100644
--- a/frontend/src/Components/Page/Sidebar/PageSidebar.js
+++ b/frontend/src/Components/Page/Sidebar/PageSidebar.js
@@ -109,11 +109,11 @@ const links = [
to: '/settings/quality'
},
{
- title: translate('CustomFormats'),
+ title: () => translate('CustomFormats'),
to: '/settings/customformats'
},
{
- title: translate('Indexers'),
+ title: () => translate('Indexers'),
to: '/settings/indexers'
},
{
diff --git a/frontend/src/Components/Page/Sidebar/PageSidebarItem.js b/frontend/src/Components/Page/Sidebar/PageSidebarItem.js
index 9ad78db6b..754071c79 100644
--- a/frontend/src/Components/Page/Sidebar/PageSidebarItem.js
+++ b/frontend/src/Components/Page/Sidebar/PageSidebarItem.js
@@ -64,7 +64,7 @@ class PageSidebarItem extends Component {
}
- {title}
+ {typeof title === 'function' ? title() : title}
{
@@ -88,7 +88,7 @@ class PageSidebarItem extends Component {
PageSidebarItem.propTypes = {
iconName: PropTypes.object,
- title: PropTypes.string.isRequired,
+ title: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired,
to: PropTypes.string.isRequired,
isActive: PropTypes.bool,
isActiveParent: PropTypes.bool,
diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/Manage/ManageDownloadClientsModalContent.tsx b/frontend/src/Settings/DownloadClients/DownloadClients/Manage/ManageDownloadClientsModalContent.tsx
index a783ef822..078fed25d 100644
--- a/frontend/src/Settings/DownloadClients/DownloadClients/Manage/ManageDownloadClientsModalContent.tsx
+++ b/frontend/src/Settings/DownloadClients/DownloadClients/Manage/ManageDownloadClientsModalContent.tsx
@@ -36,49 +36,37 @@ type OnSelectedChangeCallback = React.ComponentProps<
const COLUMNS = [
{
name: 'name',
- get label() {
- return translate('Name');
- },
+ label: () => translate('Name'),
isSortable: true,
isVisible: true,
},
{
name: 'implementation',
- get label() {
- return translate('Implementation');
- },
+ label: () => translate('Implementation'),
isSortable: true,
isVisible: true,
},
{
name: 'enable',
- get label() {
- return translate('Enabled');
- },
+ label: () => translate('Enabled'),
isSortable: true,
isVisible: true,
},
{
name: 'priority',
- get label() {
- return translate('Priority');
- },
+ label: () => translate('Priority'),
isSortable: true,
isVisible: true,
},
{
name: 'removeCompletedDownloads',
- get label() {
- return translate('RemoveCompleted');
- },
+ label: () => translate('RemoveCompleted'),
isSortable: true,
isVisible: true,
},
{
name: 'removeFailedDownloads',
- get label() {
- return translate('RemoveFailed');
- },
+ label: () => translate('RemoveFailed'),
isSortable: true,
isVisible: true,
},
diff --git a/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalContent.tsx b/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalContent.tsx
index 8bec6ee76..1c004bb34 100644
--- a/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalContent.tsx
+++ b/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalContent.tsx
@@ -36,25 +36,19 @@ type OnSelectedChangeCallback = React.ComponentProps<
const COLUMNS = [
{
name: 'name',
- get label() {
- return translate('Name');
- },
+ label: () => translate('Name'),
isSortable: true,
isVisible: true,
},
{
name: 'implementation',
- get label() {
- return translate('Implementation');
- },
+ label: () => translate('Implementation'),
isSortable: true,
isVisible: true,
},
{
name: 'qualityProfileId',
- get label() {
- return translate('QualityProfile');
- },
+ label: () => translate('QualityProfile'),
isSortable: true,
isVisible: true,
},
@@ -66,25 +60,19 @@ const COLUMNS = [
},
{
name: 'rootFolderPath',
- get label() {
- return translate('RootFolder');
- },
+ label: () => translate('RootFolder'),
isSortable: true,
isVisible: true,
},
{
name: 'enableAutomaticAdd',
- get label() {
- return translate('AutoAdd');
- },
+ label: () => translate('AutoAdd'),
isSortable: true,
isVisible: true,
},
{
name: 'tags',
- get label() {
- return translate('Tags');
- },
+ label: () => translate('Tags'),
isSortable: true,
isVisible: true,
},
diff --git a/frontend/src/Settings/Indexers/Indexers/Manage/ManageIndexersModalContent.tsx b/frontend/src/Settings/Indexers/Indexers/Manage/ManageIndexersModalContent.tsx
index 7b577d345..7c1a7db63 100644
--- a/frontend/src/Settings/Indexers/Indexers/Manage/ManageIndexersModalContent.tsx
+++ b/frontend/src/Settings/Indexers/Indexers/Manage/ManageIndexersModalContent.tsx
@@ -36,57 +36,43 @@ type OnSelectedChangeCallback = React.ComponentProps<
const COLUMNS = [
{
name: 'name',
- get label() {
- return translate('Name');
- },
+ label: () => translate('Name'),
isSortable: true,
isVisible: true,
},
{
name: 'implementation',
- get label() {
- return translate('Implementation');
- },
+ label: () => translate('Implementation'),
isSortable: true,
isVisible: true,
},
{
name: 'enableRss',
- get label() {
- return translate('EnableRSS');
- },
+ label: () => translate('EnableRSS'),
isSortable: true,
isVisible: true,
},
{
name: 'enableAutomaticSearch',
- get label() {
- return translate('EnableAutomaticSearch');
- },
+ label: () => translate('EnableAutomaticSearch'),
isSortable: true,
isVisible: true,
},
{
name: 'enableInteractiveSearch',
- get label() {
- return translate('EnableInteractiveSearch');
- },
+ label: () => translate('EnableInteractiveSearch'),
isSortable: true,
isVisible: true,
},
{
name: 'priority',
- get label() {
- return translate('Priority');
- },
+ label: () => translate('Priority'),
isSortable: true,
isVisible: true,
},
{
name: 'tags',
- get label() {
- return translate('Tags');
- },
+ label: () => translate('Tags'),
isSortable: true,
isVisible: true,
},
diff --git a/frontend/src/Settings/Settings.js b/frontend/src/Settings/Settings.js
index 6367e7d96..5bc55d0c2 100644
--- a/frontend/src/Settings/Settings.js
+++ b/frontend/src/Settings/Settings.js
@@ -139,7 +139,7 @@ function Settings() {
className={styles.link}
to="/settings/ui"
>
- {translate('UI')}
+ {translate('Ui')}
diff --git a/frontend/src/System/Backup/Backups.js b/frontend/src/System/Backup/Backups.js
index 7abcf4237..8f7a5b0a5 100644
--- a/frontend/src/System/Backup/Backups.js
+++ b/frontend/src/System/Backup/Backups.js
@@ -21,17 +21,17 @@ const columns = [
},
{
name: 'name',
- label: 'Name',
+ label: () => translate('Name'),
isVisible: true
},
{
name: 'size',
- label: 'Size',
+ label: () => translate('Size'),
isVisible: true
},
{
name: 'time',
- label: 'Time',
+ label: () => translate('Time'),
isVisible: true
},
{
diff --git a/frontend/src/System/Logs/Files/LogFiles.js b/frontend/src/System/Logs/Files/LogFiles.js
index a3aac7f4c..83736c617 100644
--- a/frontend/src/System/Logs/Files/LogFiles.js
+++ b/frontend/src/System/Logs/Files/LogFiles.js
@@ -19,12 +19,12 @@ import LogFilesTableRow from './LogFilesTableRow';
const columns = [
{
name: 'filename',
- label: 'Filename',
+ label: () => translate('Filename'),
isVisible: true
},
{
name: 'lastWriteTime',
- label: 'Last Write Time',
+ label: () => translate('LastWriteTime'),
isVisible: true
},
{
diff --git a/frontend/src/System/Status/DiskSpace/DiskSpace.js b/frontend/src/System/Status/DiskSpace/DiskSpace.js
index 87674c7a9..38cf9254a 100644
--- a/frontend/src/System/Status/DiskSpace/DiskSpace.js
+++ b/frontend/src/System/Status/DiskSpace/DiskSpace.js
@@ -15,17 +15,17 @@ import styles from './DiskSpace.css';
const columns = [
{
name: 'path',
- label: 'Location',
+ label: () => translate('Location'),
isVisible: true
},
{
name: 'freeSpace',
- label: 'Free Space',
+ label: () => translate('FreeSpace'),
isVisible: true
},
{
name: 'totalSpace',
- label: 'Total Space',
+ label: () => translate('TotalSpace'),
isVisible: true
},
{
diff --git a/frontend/src/System/Status/Health/Health.js b/frontend/src/System/Status/Health/Health.js
index 9671f388e..4d416762b 100644
--- a/frontend/src/System/Status/Health/Health.js
+++ b/frontend/src/System/Status/Health/Health.js
@@ -95,12 +95,12 @@ const columns = [
},
{
name: 'message',
- label: 'Message',
+ label: () => translate('Message'),
isVisible: true
},
{
name: 'actions',
- label: 'Actions',
+ label: () => translate('Actions'),
isVisible: true
}
];
diff --git a/frontend/src/System/Tasks/Queued/QueuedTasks.js b/frontend/src/System/Tasks/Queued/QueuedTasks.js
index 5dc901ae4..dac38f1d4 100644
--- a/frontend/src/System/Tasks/Queued/QueuedTasks.js
+++ b/frontend/src/System/Tasks/Queued/QueuedTasks.js
@@ -15,27 +15,27 @@ const columns = [
},
{
name: 'commandName',
- label: translate('Name'),
+ label: () => translate('Name'),
isVisible: true
},
{
name: 'queued',
- label: translate('Queued'),
+ label: () => translate('Queued'),
isVisible: true
},
{
name: 'started',
- label: translate('Started'),
+ label: () => translate('Started'),
isVisible: true
},
{
name: 'ended',
- label: translate('Ended'),
+ label: () => translate('Ended'),
isVisible: true
},
{
name: 'duration',
- label: translate('Duration'),
+ label: () => translate('Duration'),
isVisible: true
},
{
diff --git a/frontend/src/System/Tasks/Scheduled/ScheduledTasks.js b/frontend/src/System/Tasks/Scheduled/ScheduledTasks.js
index 8bde6f5f5..bec151613 100644
--- a/frontend/src/System/Tasks/Scheduled/ScheduledTasks.js
+++ b/frontend/src/System/Tasks/Scheduled/ScheduledTasks.js
@@ -10,27 +10,27 @@ import ScheduledTaskRowConnector from './ScheduledTaskRowConnector';
const columns = [
{
name: 'name',
- label: 'Name',
+ label: () => translate('Name'),
isVisible: true
},
{
name: 'interval',
- label: 'Interval',
+ label: () => translate('Interval'),
isVisible: true
},
{
name: 'lastExecution',
- label: 'Last Execution',
+ label: () => translate('LastExecution'),
isVisible: true
},
{
name: 'lastDuration',
- label: 'Last Duration',
+ label: () => translate('LastDuration'),
isVisible: true
},
{
name: 'nextExecution',
- label: 'Next Execution',
+ label: () => translate('NextExecution'),
isVisible: true
},
{
diff --git a/frontend/src/Utilities/String/translate.ts b/frontend/src/Utilities/String/translate.ts
index 9c6fa778b..459369a7d 100644
--- a/frontend/src/Utilities/String/translate.ts
+++ b/frontend/src/Utilities/String/translate.ts
@@ -27,6 +27,10 @@ export default function translate(
key: string,
args?: (string | number | boolean)[]
) {
+ if (!(key in translations)) {
+ console.debug(key);
+ }
+
const translation = translations[key] || key;
if (args) {
diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json
index 0bfa95f43..90ca63d8f 100644
--- a/src/NzbDrone.Core/Localization/Core/en.json
+++ b/src/NzbDrone.Core/Localization/Core/en.json
@@ -6,10 +6,12 @@
"ASIN": "ASIN",
"About": "About",
"Actions": "Actions",
+ "Activity": "Activity",
"AddImportListExclusionHelpText": "Prevent book from being added to Readarr by Import Lists or Author Refresh",
"AddList": "Add List",
"AddListExclusion": "Add List Exclusion",
"AddMissing": "Add missing",
+ "AddNew": "Add New",
"AddNewItem": "Add New Item",
"AddedAuthorSettings": "Added Author Settings",
"AddingTag": "Adding tag",
@@ -331,6 +333,7 @@
"ForeignId": "Foreign ID",
"ForeignIdHelpText": "The Musicbrainz Id of the author/book to exclude",
"Formats": "Formats",
+ "FreeSpace": "Free Space",
"FutureBooks": "Future Books",
"FutureDays": "Future Days",
"FutureDaysHelpText": "Days for iCal feed to look into the future",
@@ -431,9 +434,11 @@
"ItsEasyToAddANewAuthorOrBookJustStartTypingTheNameOfTheItemYouWantToAdd": "It's easy to add a New Author or Book just start typing the name of the item you want to add",
"Label": "Label",
"Language": "Language",
+ "LastWriteTime": "Last Write Time",
"LatestBook": "Latest Book",
"LaunchBrowserHelpText": " Open a web browser and navigate to Readarr homepage on app start.",
"Level": "Level",
+ "Library": "Library",
"LibraryHelpText": "Calibre content server library name. Leave blank for default.",
"ListRefreshInterval": "List Refresh Interval",
"ListWillRefreshEveryInterp": "List will refresh every {0}",
@@ -444,6 +449,7 @@
"LoadingBooksFailed": "Loading books failed",
"LoadingEditionsFailed": "Loading editions failed",
"Local": "Local",
+ "Location": "Location",
"LogFiles": "Log Files",
"LogLevel": "Log Level",
"LogLevelvalueTraceTraceLoggingShouldOnlyBeEnabledTemporarily": "Trace logging should only be enabled temporarily",
@@ -854,6 +860,7 @@
"SupportsSearchvalueSearchIsNotSupportedWithThisIndexer": "Search is not supported with this indexer",
"SupportsSearchvalueWillBeUsedWhenAutomaticSearchesArePerformedViaTheUIOrByReadarr": "Will be used when automatic searches are performed via the UI or by Readarr",
"SupportsSearchvalueWillBeUsedWhenInteractiveSearchIsUsed": "Will be used when interactive search is used",
+ "System": "System",
"SystemTimeCheckMessage": "System time is off by more than 1 day. Scheduled tasks may not run correctly until the time is corrected",
"TagIsNotUsedAndCanBeDeleted": "Tag is not used and can be deleted",
"Tags": "Tags",
@@ -886,15 +893,16 @@
"Torrents": "Torrents",
"TotalBookCountBooksTotalBookFileCountBooksWithFilesInterp": "{0} books total. {1} books with files.",
"TotalFileSize": "Total File Size",
+ "TotalSpace": "Total Space",
"TrackNumber": "Track Number",
"TrackTitle": "Track Title",
- "UI": "UI",
"UILanguage": "UI Language",
"UILanguageHelpText": "Language that Readarr will use for UI",
"UILanguageHelpTextWarning": "Browser Reload Required",
"UISettings": "UI Settings",
"UISettingsSummary": "Calendar, date and color impaired options",
"URLBase": "URL Base",
+ "Ui": "UI",
"UnableToAddANewDownloadClientPleaseTryAgain": "Unable to add a new download client, please try again.",
"UnableToAddANewImportListExclusionPleaseTryAgain": "Unable to add a new import list exclusion, please try again.",
"UnableToAddANewIndexerPleaseTryAgain": "Unable to add a new indexer, please try again.",
@@ -932,7 +940,7 @@
"UnableToLoadTheCalendar": "Unable to load the calendar",
"UnableToLoadUISettings": "Unable to load UI settings",
"Ungroup": "Ungroup",
- "UnmappedFiles": "UnmappedFiles",
+ "UnmappedFiles": "Unmapped Files",
"Unmonitored": "Unmonitored",
"UnmonitoredHelpText": "Include unmonitored books in the iCal feed",
"UnselectAll": "Unselect All",