diff --git a/frontend/src/App/App.js b/frontend/src/App/App.js index ea29231c2..781b2ca10 100644 --- a/frontend/src/App/App.js +++ b/frontend/src/App/App.js @@ -7,13 +7,13 @@ import PageConnector from 'Components/Page/PageConnector'; import ApplyTheme from './ApplyTheme'; import AppRoutes from './AppRoutes'; -function App({ store, history, hasTranslationsError }) { +function App({ store, history }) { return ( - + @@ -25,8 +25,7 @@ function App({ store, history, hasTranslationsError }) { App.propTypes = { store: PropTypes.object.isRequired, - history: PropTypes.object.isRequired, - hasTranslationsError: PropTypes.bool.isRequired + history: PropTypes.object.isRequired }; export default App; diff --git a/frontend/src/Components/Page/ErrorPage.js b/frontend/src/Components/Page/ErrorPage.js index e7b436d61..214c9dcc9 100644 --- a/frontend/src/Components/Page/ErrorPage.js +++ b/frontend/src/Components/Page/ErrorPage.js @@ -7,7 +7,7 @@ function ErrorPage(props) { const { version, isLocalStorageSupported, - hasTranslationsError, + translationsError, seriesError, customFiltersError, tagsError, @@ -20,8 +20,8 @@ function ErrorPage(props) { if (!isLocalStorageSupported) { errorMessage = 'Local Storage is not supported or disabled. A plugin or private browsing may have disabled it.'; - } else if (hasTranslationsError) { - errorMessage = 'Failed to load translations from API'; + } else if (translationsError) { + errorMessage = getErrorMessage(translationsError, 'Failed to load translations from API'); } else if (seriesError) { errorMessage = getErrorMessage(seriesError, 'Failed to load series from API'); } else if (customFiltersError) { @@ -52,7 +52,7 @@ function ErrorPage(props) { ErrorPage.propTypes = { version: PropTypes.string.isRequired, isLocalStorageSupported: PropTypes.bool.isRequired, - hasTranslationsError: PropTypes.bool.isRequired, + translationsError: PropTypes.object, seriesError: PropTypes.object, customFiltersError: PropTypes.object, tagsError: PropTypes.object, diff --git a/frontend/src/Components/Page/PageConnector.js b/frontend/src/Components/Page/PageConnector.js index 37c7bf8d0..3aa82f31e 100644 --- a/frontend/src/Components/Page/PageConnector.js +++ b/frontend/src/Components/Page/PageConnector.js @@ -3,7 +3,7 @@ import React, { Component } from 'react'; import { connect } from 'react-redux'; import { withRouter } from 'react-router-dom'; import { createSelector } from 'reselect'; -import { saveDimensions, setIsSidebarVisible } from 'Store/Actions/appActions'; +import { fetchTranslations, saveDimensions, setIsSidebarVisible } from 'Store/Actions/appActions'; import { fetchCustomFilters } from 'Store/Actions/customFilterActions'; import { fetchSeries } from 'Store/Actions/seriesActions'; import { fetchImportLists, fetchLanguages, fetchQualityProfiles, fetchUISettings } from 'Store/Actions/settingsActions'; @@ -52,6 +52,7 @@ const selectIsPopulated = createSelector( (state) => state.settings.languages.isPopulated, (state) => state.settings.importLists.isPopulated, (state) => state.system.status.isPopulated, + (state) => state.app.translations.isPopulated, ( seriesIsPopulated, customFiltersIsPopulated, @@ -60,7 +61,8 @@ const selectIsPopulated = createSelector( qualityProfilesIsPopulated, languagesIsPopulated, importListsIsPopulated, - systemStatusIsPopulated + systemStatusIsPopulated, + translationsIsPopulated ) => { return ( seriesIsPopulated && @@ -70,7 +72,8 @@ const selectIsPopulated = createSelector( qualityProfilesIsPopulated && languagesIsPopulated && importListsIsPopulated && - systemStatusIsPopulated + systemStatusIsPopulated && + translationsIsPopulated ); } ); @@ -84,6 +87,7 @@ const selectErrors = createSelector( (state) => state.settings.languages.error, (state) => state.settings.importLists.error, (state) => state.system.status.error, + (state) => state.app.translations.error, ( seriesError, customFiltersError, @@ -92,7 +96,8 @@ const selectErrors = createSelector( qualityProfilesError, languagesError, importListsError, - systemStatusError + systemStatusError, + translationsError ) => { const hasError = !!( seriesError || @@ -102,7 +107,8 @@ const selectErrors = createSelector( qualityProfilesError || languagesError || importListsError || - systemStatusError + systemStatusError || + translationsError ); return { @@ -114,7 +120,8 @@ const selectErrors = createSelector( qualityProfilesError, languagesError, importListsError, - systemStatusError + systemStatusError, + translationsError }; } ); @@ -173,6 +180,9 @@ function createMapDispatchToProps(dispatch, props) { dispatchFetchStatus() { dispatch(fetchStatus()); }, + dispatchFetchTranslations() { + dispatch(fetchTranslations()); + }, onResize(dimensions) { dispatch(saveDimensions(dimensions)); }, @@ -205,6 +215,7 @@ class PageConnector extends Component { this.props.dispatchFetchImportLists(); this.props.dispatchFetchUISettings(); this.props.dispatchFetchStatus(); + this.props.dispatchFetchTranslations(); } } @@ -220,7 +231,6 @@ class PageConnector extends Component { render() { const { - hasTranslationsError, isPopulated, hasError, dispatchFetchSeries, @@ -230,15 +240,15 @@ class PageConnector extends Component { dispatchFetchImportLists, dispatchFetchUISettings, dispatchFetchStatus, + dispatchFetchTranslations, ...otherProps } = this.props; - if (hasTranslationsError || hasError || !this.state.isLocalStorageSupported) { + if (hasError || !this.state.isLocalStorageSupported) { return ( ); } @@ -259,7 +269,6 @@ class PageConnector extends Component { } PageConnector.propTypes = { - hasTranslationsError: PropTypes.bool.isRequired, isPopulated: PropTypes.bool.isRequired, hasError: PropTypes.bool.isRequired, isSidebarVisible: PropTypes.bool.isRequired, @@ -271,6 +280,7 @@ PageConnector.propTypes = { dispatchFetchImportLists: PropTypes.func.isRequired, dispatchFetchUISettings: PropTypes.func.isRequired, dispatchFetchStatus: PropTypes.func.isRequired, + dispatchFetchTranslations: PropTypes.func.isRequired, onSidebarVisibleChange: PropTypes.func.isRequired }; diff --git a/frontend/src/Components/Page/Sidebar/PageSidebar.js b/frontend/src/Components/Page/Sidebar/PageSidebar.js index fcf4bc02f..ba07578da 100644 --- a/frontend/src/Components/Page/Sidebar/PageSidebar.js +++ b/frontend/src/Components/Page/Sidebar/PageSidebar.js @@ -21,16 +21,22 @@ const SIDEBAR_WIDTH = parseInt(dimensions.sidebarWidth); const links = [ { iconName: icons.SERIES_CONTINUING, - title: translate('Series'), + get title() { + return translate('Series'); + }, to: '/', alias: '/series', children: [ { - title: translate('AddNew'), + get title() { + return translate('AddNew'); + }, to: '/add/new' }, { - title: translate('LibraryImport'), + get title() { + return translate('LibraryImport'); + }, to: '/add/import' } ] @@ -38,26 +44,36 @@ const links = [ { iconName: icons.CALENDAR, - title: translate('Calendar'), + get title() { + return translate('Calendar'); + }, to: '/calendar' }, { iconName: icons.ACTIVITY, - title: translate('Activity'), + get title() { + return translate('Activity'); + }, to: '/activity/queue', children: [ { - title: translate('Queue'), + get title() { + return translate('Queue'); + }, to: '/activity/queue', statusComponent: QueueStatusConnector }, { - title: translate('History'), + get title() { + return translate('History'); + }, to: '/activity/history' }, { - title: translate('Blocklist'), + get title() { + return translate('Blocklist'); + }, to: '/activity/blocklist' } ] @@ -65,15 +81,21 @@ const links = [ { iconName: icons.WARNING, - title: translate('Wanted'), + get title() { + return translate('Wanted'); + }, to: '/wanted/missing', children: [ { - title: translate('Missing'), + get title() { + return translate('Missing'); + }, to: '/wanted/missing' }, { - title: translate('CutoffUnmet'), + get title() { + return translate('CutoffUnmet'); + }, to: '/wanted/cutoffunmet' } ] @@ -81,59 +103,87 @@ const links = [ { iconName: icons.SETTINGS, - title: translate('Settings'), + get title() { + return translate('Settings'); + }, to: '/settings', children: [ { - title: translate('MediaManagement'), + get title() { + return translate('MediaManagement'); + }, to: '/settings/mediamanagement' }, { - title: translate('Profiles'), + get title() { + return translate('Profiles'); + }, to: '/settings/profiles' }, { - title: translate('Quality'), + get title() { + return translate('Quality'); + }, to: '/settings/quality' }, { - title: translate('CustomFormats'), + get title() { + return translate('CustomFormats'); + }, to: '/settings/customformats' }, { - title: translate('Indexers'), + get title() { + return translate('Indexers'); + }, to: '/settings/indexers' }, { - title: translate('DownloadClients'), + get title() { + return translate('DownloadClients'); + }, to: '/settings/downloadclients' }, { - title: translate('ImportLists'), + get title() { + return translate('ImportLists'); + }, to: '/settings/importlists' }, { - title: translate('Connect'), + get title() { + return translate('Connect'); + }, to: '/settings/connect' }, { - title: translate('Metadata'), + get title() { + return translate('Metadata'); + }, to: '/settings/metadata' }, { - title: translate('MetadataSource'), + get title() { + return translate('MetadataSource'); + }, to: '/settings/metadatasource' }, { - title: translate('Tags'), + get title() { + return translate('Tags'); + }, to: '/settings/tags' }, { - title: translate('General'), + get title() { + return translate('General'); + }, to: '/settings/general' }, { - title: translate('UI'), + get title() { + return translate('UI'); + }, to: '/settings/ui' } ] @@ -141,32 +191,46 @@ const links = [ { iconName: icons.SYSTEM, - title: translate('System'), + get title() { + return translate('System'); + }, to: '/system/status', children: [ { - title: translate('Status'), + get title() { + return translate('Status'); + }, to: '/system/status', statusComponent: HealthStatusConnector }, { - title: translate('Tasks'), + get title() { + return translate('Tasks'); + }, to: '/system/tasks' }, { - title: translate('Backup'), + get title() { + return translate('Backup'); + }, to: '/system/backup' }, { - title: translate('Updates'), + get title() { + return translate('Updates'); + }, to: '/system/updates' }, { - title: translate('Events'), + get title() { + return translate('Events'); + }, to: '/system/events' }, { - title: translate('LogFiles'), + get title() { + return translate('LogFiles'); + }, to: '/system/logs/files' } ] diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/Manage/Edit/ManageDownloadClientsEditModalContent.tsx b/frontend/src/Settings/DownloadClients/DownloadClients/Manage/Edit/ManageDownloadClientsEditModalContent.tsx index 458ee321e..3a024b559 100644 --- a/frontend/src/Settings/DownloadClients/DownloadClients/Manage/Edit/ManageDownloadClientsEditModalContent.tsx +++ b/frontend/src/Settings/DownloadClients/DownloadClients/Manage/Edit/ManageDownloadClientsEditModalContent.tsx @@ -27,9 +27,25 @@ interface ManageDownloadClientsEditModalContentProps { const NO_CHANGE = 'noChange'; const enableOptions = [ - { key: NO_CHANGE, value: translate('NoChange'), disabled: true }, - { key: 'enabled', value: translate('Enabled') }, - { key: 'disabled', value: translate('Disabled') }, + { + key: NO_CHANGE, + get value() { + return translate('NoChange'); + }, + disabled: true, + }, + { + key: 'enabled', + get value() { + return translate('Enabled'); + }, + }, + { + key: 'disabled', + get value() { + return translate('Disabled'); + }, + }, ]; function ManageDownloadClientsEditModalContent( diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/Manage/ManageDownloadClientsModalContent.tsx b/frontend/src/Settings/DownloadClients/DownloadClients/Manage/ManageDownloadClientsModalContent.tsx index 5d9f434c0..21f45cc97 100644 --- a/frontend/src/Settings/DownloadClients/DownloadClients/Manage/ManageDownloadClientsModalContent.tsx +++ b/frontend/src/Settings/DownloadClients/DownloadClients/Manage/ManageDownloadClientsModalContent.tsx @@ -36,37 +36,49 @@ type OnSelectedChangeCallback = React.ComponentProps< const COLUMNS = [ { name: 'name', - label: translate('Name'), + get label() { + return translate('Name'); + }, isSortable: true, isVisible: true, }, { name: 'implementation', - label: translate('Implementation'), + get label() { + return translate('Implementation'); + }, isSortable: true, isVisible: true, }, { name: 'enable', - label: translate('Enabled'), + get label() { + return translate('Enabled'); + }, isSortable: true, isVisible: true, }, { name: 'priority', - label: translate('Priority'), + get label() { + return translate('Priority'); + }, isSortable: true, isVisible: true, }, { name: 'removeCompletedDownloads', - label: translate('RemoveCompleted'), + get label() { + return translate('RemoveCompleted'); + }, isSortable: true, isVisible: true, }, { name: 'removeFailedDownloads', - label: translate('RemoveFailed'), + get label() { + return translate('RemoveFailed'); + }, isSortable: true, isVisible: true, }, diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/Manage/Tags/TagsModalContent.tsx b/frontend/src/Settings/DownloadClients/DownloadClients/Manage/Tags/TagsModalContent.tsx index 98f33c109..e0899ff39 100644 --- a/frontend/src/Settings/DownloadClients/DownloadClients/Manage/Tags/TagsModalContent.tsx +++ b/frontend/src/Settings/DownloadClients/DownloadClients/Manage/Tags/TagsModalContent.tsx @@ -72,9 +72,24 @@ function TagsModalContent(props: TagsModalContentProps) { }, [tags, applyTags, onApplyTagsPress]); const applyTagsOptions = [ - { key: 'add', value: translate('Add') }, - { key: 'remove', value: translate('Remove') }, - { key: 'replace', value: translate('Replace') }, + { + key: 'add', + get value() { + return translate('Add'); + }, + }, + { + key: 'remove', + get value() { + return translate('Remove'); + }, + }, + { + key: 'replace', + get value() { + return translate('Replace'); + }, + }, ]; return ( diff --git a/frontend/src/Settings/ImportLists/ImportLists/Manage/Edit/ManageImportListsEditModalContent.tsx b/frontend/src/Settings/ImportLists/ImportLists/Manage/Edit/ManageImportListsEditModalContent.tsx index e5b28adf3..8660f2fd3 100644 --- a/frontend/src/Settings/ImportLists/ImportLists/Manage/Edit/ManageImportListsEditModalContent.tsx +++ b/frontend/src/Settings/ImportLists/ImportLists/Manage/Edit/ManageImportListsEditModalContent.tsx @@ -26,9 +26,25 @@ interface ManageImportListsEditModalContentProps { const NO_CHANGE = 'noChange'; const autoAddOptions = [ - { key: NO_CHANGE, value: translate('NoChange'), disabled: true }, - { key: 'enabled', value: translate('Enabled') }, - { key: 'disabled', value: translate('Disabled') }, + { + key: NO_CHANGE, + get value() { + return translate('NoChange'); + }, + disabled: true, + }, + { + key: 'enabled', + get value() { + return translate('Enabled'); + }, + }, + { + key: 'disabled', + get value() { + return translate('Disabled'); + }, + }, ]; function ManageImportListsEditModalContent( diff --git a/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalContent.tsx b/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalContent.tsx index fdcc20f8b..5d78e38d2 100644 --- a/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalContent.tsx +++ b/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalContent.tsx @@ -36,37 +36,49 @@ type OnSelectedChangeCallback = React.ComponentProps< const COLUMNS = [ { name: 'name', - label: translate('Name'), + get label() { + return translate('Name'); + }, isSortable: true, isVisible: true, }, { name: 'implementation', - label: translate('Implementation'), + get label() { + return translate('Implementation'); + }, isSortable: true, isVisible: true, }, { name: 'qualityProfileId', - label: translate('QualityProfile'), + get label() { + return translate('QualityProfile'); + }, isSortable: true, isVisible: true, }, { name: 'rootFolderPath', - label: translate('RootFolder'), + get label() { + return translate('RootFolder'); + }, isSortable: true, isVisible: true, }, { name: 'enableAutomaticAdd', - label: translate('AutoAdd'), + get label() { + return translate('AutoAdd'); + }, isSortable: true, isVisible: true, }, { name: 'tags', - label: translate('Tags'), + get label() { + return translate('Tags'); + }, isSortable: true, isVisible: true, }, diff --git a/frontend/src/Settings/ImportLists/ImportLists/Manage/Tags/TagsModalContent.tsx b/frontend/src/Settings/ImportLists/ImportLists/Manage/Tags/TagsModalContent.tsx index 6072be5ff..9d4af820e 100644 --- a/frontend/src/Settings/ImportLists/ImportLists/Manage/Tags/TagsModalContent.tsx +++ b/frontend/src/Settings/ImportLists/ImportLists/Manage/Tags/TagsModalContent.tsx @@ -70,9 +70,24 @@ function TagsModalContent(props: TagsModalContentProps) { }, [tags, applyTags, onApplyTagsPress]); const applyTagsOptions = [ - { key: 'add', value: translate('Add') }, - { key: 'remove', value: translate('Remove') }, - { key: 'replace', value: translate('Replace') }, + { + key: 'add', + get value() { + return translate('Add'); + }, + }, + { + key: 'remove', + get value() { + return translate('Remove'); + }, + }, + { + key: 'replace', + get value() { + return translate('Replace'); + }, + }, ]; return ( diff --git a/frontend/src/Settings/Indexers/Indexers/Manage/Edit/ManageIndexersEditModalContent.tsx b/frontend/src/Settings/Indexers/Indexers/Manage/Edit/ManageIndexersEditModalContent.tsx index c06207fbb..8af789d93 100644 --- a/frontend/src/Settings/Indexers/Indexers/Manage/Edit/ManageIndexersEditModalContent.tsx +++ b/frontend/src/Settings/Indexers/Indexers/Manage/Edit/ManageIndexersEditModalContent.tsx @@ -27,9 +27,25 @@ interface ManageIndexersEditModalContentProps { const NO_CHANGE = 'noChange'; const enableOptions = [ - { key: NO_CHANGE, value: translate('NoChange'), disabled: true }, - { key: 'enabled', value: translate('Enabled') }, - { key: 'disabled', value: translate('Disabled') }, + { + key: NO_CHANGE, + get value() { + return translate('NoChange'); + }, + disabled: true, + }, + { + key: 'enabled', + get value() { + return translate('Enabled'); + }, + }, + { + key: 'disabled', + get value() { + return translate('Disabled'); + }, + }, ]; function ManageIndexersEditModalContent( diff --git a/frontend/src/Settings/Indexers/Indexers/Manage/ManageIndexersModalContent.tsx b/frontend/src/Settings/Indexers/Indexers/Manage/ManageIndexersModalContent.tsx index 20418c682..da24b4412 100644 --- a/frontend/src/Settings/Indexers/Indexers/Manage/ManageIndexersModalContent.tsx +++ b/frontend/src/Settings/Indexers/Indexers/Manage/ManageIndexersModalContent.tsx @@ -36,43 +36,57 @@ type OnSelectedChangeCallback = React.ComponentProps< const COLUMNS = [ { name: 'name', - label: translate('Name'), + get label() { + return translate('Name'); + }, isSortable: true, isVisible: true, }, { name: 'implementation', - label: translate('Implementation'), + get label() { + return translate('Implementation'); + }, isSortable: true, isVisible: true, }, { name: 'enableRss', - label: translate('EnableRSS'), + get label() { + return translate('EnableRSS'); + }, isSortable: true, isVisible: true, }, { name: 'enableAutomaticSearch', - label: translate('EnableAutomaticSearch'), + get label() { + return translate('EnableAutomaticSearch'); + }, isSortable: true, isVisible: true, }, { name: 'enableInteractiveSearch', - label: translate('EnableInteractiveSearch'), + get label() { + return translate('EnableInteractiveSearch'); + }, isSortable: true, isVisible: true, }, { name: 'priority', - label: translate('Priority'), + get label() { + return translate('Priority'); + }, isSortable: true, isVisible: true, }, { name: 'tags', - label: translate('Tags'), + get label() { + return translate('Tags'); + }, isSortable: true, isVisible: true, }, diff --git a/frontend/src/Settings/Indexers/Indexers/Manage/Tags/TagsModalContent.tsx b/frontend/src/Settings/Indexers/Indexers/Manage/Tags/TagsModalContent.tsx index 32138fb5f..fb1e6b847 100644 --- a/frontend/src/Settings/Indexers/Indexers/Manage/Tags/TagsModalContent.tsx +++ b/frontend/src/Settings/Indexers/Indexers/Manage/Tags/TagsModalContent.tsx @@ -70,9 +70,24 @@ function TagsModalContent(props: TagsModalContentProps) { }, [tags, applyTags, onApplyTagsPress]); const applyTagsOptions = [ - { key: 'add', value: translate('Add') }, - { key: 'remove', value: translate('Remove') }, - { key: 'replace', value: translate('Replace') }, + { + key: 'add', + get value() { + return translate('Add'); + }, + }, + { + key: 'remove', + get value() { + return translate('Remove'); + }, + }, + { + key: 'replace', + get value() { + return translate('Replace'); + }, + }, ]; return ( diff --git a/frontend/src/Store/Actions/appActions.js b/frontend/src/Store/Actions/appActions.js index 464b7b1a0..3564c7fa0 100644 --- a/frontend/src/Store/Actions/appActions.js +++ b/frontend/src/Store/Actions/appActions.js @@ -4,6 +4,7 @@ import { createThunk, handleThunks } from 'Store/thunks'; import createAjaxRequest from 'Utilities/createAjaxRequest'; import getSectionState from 'Utilities/State/getSectionState'; import updateSectionState from 'Utilities/State/updateSectionState'; +import { fetchTranslations as fetchAppTranslations } from 'Utilities/String/translate'; import createHandleActions from './Creators/createHandleActions'; function getDimensions(width, height) { @@ -41,7 +42,12 @@ export const defaultState = { isReconnecting: false, isDisconnected: false, isRestarting: false, - isSidebarVisible: !getDimensions(window.innerWidth, window.innerHeight).isSmallScreen + isSidebarVisible: !getDimensions(window.innerWidth, window.innerHeight).isSmallScreen, + translations: { + isFetching: true, + isPopulated: false, + error: null + } }; // @@ -53,6 +59,7 @@ export const SAVE_DIMENSIONS = 'app/saveDimensions'; export const SET_VERSION = 'app/setVersion'; export const SET_APP_VALUE = 'app/setAppValue'; export const SET_IS_SIDEBAR_VISIBLE = 'app/setIsSidebarVisible'; +export const FETCH_TRANSLATIONS = 'app/fetchTranslations'; export const PING_SERVER = 'app/pingServer'; @@ -66,6 +73,7 @@ export const setAppValue = createAction(SET_APP_VALUE); export const showMessage = createAction(SHOW_MESSAGE); export const hideMessage = createAction(HIDE_MESSAGE); export const pingServer = createThunk(PING_SERVER); +export const fetchTranslations = createThunk(FETCH_TRANSLATIONS); // // Helpers @@ -127,6 +135,17 @@ function pingServerAfterTimeout(getState, dispatch) { export const actionHandlers = handleThunks({ [PING_SERVER]: function(getState, payload, dispatch) { pingServerAfterTimeout(getState, dispatch); + }, + [FETCH_TRANSLATIONS]: async function(getState, payload, dispatch) { + const isFetchingComplete = await fetchAppTranslations(); + + dispatch(setAppValue({ + translations: { + isFetching: false, + isPopulated: isFetchingComplete, + error: isFetchingComplete ? null : 'Failed to load translations from API' + } + })); } }); diff --git a/frontend/src/Store/Actions/episodeActions.js b/frontend/src/Store/Actions/episodeActions.js index b1860c089..c7f05aa8b 100644 --- a/frontend/src/Store/Actions/episodeActions.js +++ b/frontend/src/Store/Actions/episodeActions.js @@ -114,10 +114,14 @@ export const defaultState = { }, { name: 'customFormatScore', - columnLabel: translate('CustomFormatScore'), + get columnLabel() { + return translate('CustomFormatScore'); + }, label: React.createElement(Icon, { name: icons.SCORE, - title: translate('CustomFormatScore') + get title() { + return translate('CustomFormatScore'); + } }), isVisible: false }, diff --git a/frontend/src/Utilities/String/translate.js b/frontend/src/Utilities/String/translate.ts similarity index 66% rename from frontend/src/Utilities/String/translate.js rename to frontend/src/Utilities/String/translate.ts index c2dd96291..9197e5137 100644 --- a/frontend/src/Utilities/String/translate.js +++ b/frontend/src/Utilities/String/translate.ts @@ -4,14 +4,14 @@ function getTranslations() { return createAjaxRequest({ global: false, dataType: 'json', - url: '/localization' + url: '/localization', }).request; } -let translations = {}; +let translations: Record = {}; -export function fetchTranslations() { - return new Promise(async(resolve) => { +export async function fetchTranslations(): Promise { + return new Promise(async (resolve) => { try { const data = await getTranslations(); translations = data.strings; @@ -23,7 +23,10 @@ export function fetchTranslations() { }); } -export default function translate(key, tokens) { +export default function translate( + key: string, + tokens?: Record +) { const translation = translations[key] || key; if (tokens) { diff --git a/frontend/src/bootstrap.tsx b/frontend/src/bootstrap.tsx index a729cb3c5..6a6d7fc67 100644 --- a/frontend/src/bootstrap.tsx +++ b/frontend/src/bootstrap.tsx @@ -2,7 +2,6 @@ import { createBrowserHistory } from 'history'; import React from 'react'; import { render } from 'react-dom'; import createAppStore from 'Store/createAppStore'; -import { fetchTranslations } from 'Utilities/String/translate'; import App from './App/App'; import 'Diag/ConsoleApi'; @@ -10,14 +9,9 @@ import 'Diag/ConsoleApi'; export async function bootstrap() { const history = createBrowserHistory(); const store = createAppStore(history); - const hasTranslationsError = !(await fetchTranslations()); render( - , + , document.getElementById('root') ); }