Fixed: Ensure translations are fetched before loading app

(cherry picked from commit ad2721dc55f3233e4c299babe5744418bc530418)
This commit is contained in:
Mark McDowall
2023-07-14 16:55:25 -07:00
committed by Bogdan
parent b9a28f243e
commit 5e52627799
6 changed files with 41 additions and 19 deletions

View File

@@ -82,6 +82,10 @@ module.exports = (env) => {
hints: false hints: false
}, },
experiments: {
topLevelAwait: true
},
plugins: [ plugins: [
new webpack.DefinePlugin({ new webpack.DefinePlugin({
__DEV__: !isProduction, __DEV__: !isProduction,

View File

@@ -7,13 +7,13 @@ import PageConnector from 'Components/Page/PageConnector';
import ApplyTheme from './ApplyTheme'; import ApplyTheme from './ApplyTheme';
import AppRoutes from './AppRoutes'; import AppRoutes from './AppRoutes';
function App({ store, history }) { function App({ store, history, hasTranslationsError }) {
return ( return (
<DocumentTitle title={window.Prowlarr.instanceName}> <DocumentTitle title={window.Prowlarr.instanceName}>
<Provider store={store}> <Provider store={store}>
<ConnectedRouter history={history}> <ConnectedRouter history={history}>
<ApplyTheme> <ApplyTheme>
<PageConnector> <PageConnector hasTranslationsError={hasTranslationsError}>
<AppRoutes app={App} /> <AppRoutes app={App} />
</PageConnector> </PageConnector>
</ApplyTheme> </ApplyTheme>
@@ -25,7 +25,8 @@ function App({ store, history }) {
App.propTypes = { App.propTypes = {
store: PropTypes.object.isRequired, store: PropTypes.object.isRequired,
history: PropTypes.object.isRequired history: PropTypes.object.isRequired,
hasTranslationsError: PropTypes.bool.isRequired
}; };
export default App; export default App;

View File

@@ -7,6 +7,7 @@ function ErrorPage(props) {
const { const {
version, version,
isLocalStorageSupported, isLocalStorageSupported,
hasTranslationsError,
indexersError, indexersError,
indexerStatusError, indexerStatusError,
indexerCategoriesError, indexerCategoriesError,
@@ -21,6 +22,8 @@ function ErrorPage(props) {
if (!isLocalStorageSupported) { if (!isLocalStorageSupported) {
errorMessage = 'Local Storage is not supported or disabled. A plugin or private browsing may have disabled it.'; 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 (indexersError) { } else if (indexersError) {
errorMessage = getErrorMessage(indexersError, 'Failed to load indexers from API'); errorMessage = getErrorMessage(indexersError, 'Failed to load indexers from API');
} else if (indexerStatusError) { } else if (indexerStatusError) {
@@ -55,6 +58,7 @@ function ErrorPage(props) {
ErrorPage.propTypes = { ErrorPage.propTypes = {
version: PropTypes.string.isRequired, version: PropTypes.string.isRequired,
isLocalStorageSupported: PropTypes.bool.isRequired, isLocalStorageSupported: PropTypes.bool.isRequired,
hasTranslationsError: PropTypes.bool.isRequired,
indexersError: PropTypes.object, indexersError: PropTypes.object,
indexerStatusError: PropTypes.object, indexerStatusError: PropTypes.object,
indexerCategoriesError: PropTypes.object, indexerCategoriesError: PropTypes.object,

View File

@@ -232,6 +232,7 @@ class PageConnector extends Component {
render() { render() {
const { const {
hasTranslationsError,
isPopulated, isPopulated,
hasError, hasError,
dispatchFetchTags, dispatchFetchTags,
@@ -245,11 +246,12 @@ class PageConnector extends Component {
...otherProps ...otherProps
} = this.props; } = this.props;
if (hasError || !this.state.isLocalStorageSupported) { if (hasTranslationsError || hasError || !this.state.isLocalStorageSupported) {
return ( return (
<ErrorPage <ErrorPage
{...this.state} {...this.state}
{...otherProps} {...otherProps}
hasTranslationsError={hasTranslationsError}
/> />
); );
} }
@@ -270,6 +272,7 @@ class PageConnector extends Component {
} }
PageConnector.propTypes = { PageConnector.propTypes = {
hasTranslationsError: PropTypes.bool.isRequired,
isPopulated: PropTypes.bool.isRequired, isPopulated: PropTypes.bool.isRequired,
hasError: PropTypes.bool.isRequired, hasError: PropTypes.bool.isRequired,
isSidebarVisible: PropTypes.bool.isRequired, isSidebarVisible: PropTypes.bool.isRequired,

View File

@@ -1,22 +1,27 @@
import createAjaxRequest from 'Utilities/createAjaxRequest'; import createAjaxRequest from 'Utilities/createAjaxRequest';
function getTranslations() { function getTranslations() {
let localization = null; return createAjaxRequest({
const ajaxOptions = { global: false,
async: false,
dataType: 'json', dataType: 'json',
url: '/localization', url: '/localization'
success: function(data) { }).request;
localization = data.Strings;
}
};
createAjaxRequest(ajaxOptions);
return localization;
} }
const translations = getTranslations(); let translations = {};
export function fetchTranslations() {
return new Promise(async(resolve) => {
try {
const data = await getTranslations();
translations = data.Strings;
resolve(true);
} catch (error) {
resolve(false);
}
});
}
export default function translate(key, args = []) { export default function translate(key, args = []) {
const translation = translations[key] || key; const translation = translations[key] || key;

View File

@@ -1,8 +1,7 @@
import { createBrowserHistory } from 'history'; import { createBrowserHistory } from 'history';
import React from 'react'; import React from 'react';
import { render } from 'react-dom'; import { render } from 'react-dom';
import createAppStore from 'Store/createAppStore'; import { fetchTranslations } from 'Utilities/String/translate';
import App from './App/App';
import './preload'; import './preload';
import './polyfills'; import './polyfills';
@@ -10,12 +9,18 @@ import 'Styles/globals.css';
import './index.css'; import './index.css';
const history = createBrowserHistory(); const history = createBrowserHistory();
const hasTranslationsError = !await fetchTranslations();
const { default: createAppStore } = await import('Store/createAppStore');
const { default: App } = await import('./App/App');
const store = createAppStore(history); const store = createAppStore(history);
render( render(
<App <App
store={store} store={store}
history={history} history={history}
hasTranslationsError={hasTranslationsError}
/>, />,
document.getElementById('root') document.getElementById('root')
); );