summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/locales/en-US.json2
-rw-r--r--backend/locales/it-IT.json2
-rw-r--r--frontend/src/components/modals/PluginInstallModal.tsx46
-rw-r--r--frontend/src/components/modals/TPluginInstallModal.tsx95
-rw-r--r--frontend/src/plugin-loader.tsx95
-rw-r--r--frontend/src/utils/TranslationHelper.tsx59
6 files changed, 159 insertions, 140 deletions
diff --git a/backend/locales/en-US.json b/backend/locales/en-US.json
index 9bcaed62..6301008d 100644
--- a/backend/locales/en-US.json
+++ b/backend/locales/en-US.json
@@ -56,7 +56,7 @@
"decky_title": "Decky",
"decky_update_available": "Update to {{tag_name}} available!",
"error": "Error",
- "plugin_error_uninstall": "Please go to <0></0> in the Decky menu if you need to uninstall this plugin.",
+ "plugin_error_uninstall": "Loading {{name}} has caused an exception as shown above. This usually means that the plugin requires an update for the new version of SteamUI. Check if an update is present or evaluate his removal in <0></0> Settings <1></1> <2></2> Plugins.",
"plugin_load_error": {
"message": "Error loading plugin {{name}}",
"toast": "Error loading {{name}}"
diff --git a/backend/locales/it-IT.json b/backend/locales/it-IT.json
index 3665bdfe..5092b051 100644
--- a/backend/locales/it-IT.json
+++ b/backend/locales/it-IT.json
@@ -56,7 +56,7 @@
"decky_title": "Decky",
"decky_update_available": "Disponibile aggiornamento a {{tag_name}}!",
"error": "Errore",
- "plugin_error_uninstall": "Per rimuovere questo plugin vai su <0></0> nel menu di Decky.",
+ "plugin_error_uninstall": "Il plugin {{name}} ha causato un'eccezione che è descritta sopra. Questo tipicamente significa che il plugin deve essere aggiornato per funzionare sulla nuova versione di SteamUI. Controlla se è disponibile un'aggiornamento o valutane la rimozione andando in <0></0> Impostazioni <1></1> <2></2> Plugins.",
"plugin_load_error": {
"message": "Errore caricando il plugin {{name}}",
"toast": "Errore caricando {{name}}"
diff --git a/frontend/src/components/modals/PluginInstallModal.tsx b/frontend/src/components/modals/PluginInstallModal.tsx
index 0e8e3d47..b37dbc65 100644
--- a/frontend/src/components/modals/PluginInstallModal.tsx
+++ b/frontend/src/components/modals/PluginInstallModal.tsx
@@ -2,7 +2,7 @@ import { ConfirmModal, Navigation, QuickAccessTab } from 'decky-frontend-lib';
import { FC, useState } from 'react';
import { useTranslation } from 'react-i18next';
-import TPluginInstallModal, { TranslatedPart } from './TPluginInstallModal';
+import TranslationHelper, { TranslationClass } from '../../utils/TranslationHelper';
interface PluginInstallModalProps {
artifact: string;
@@ -39,21 +39,47 @@ const PluginInstallModal: FC<PluginInstallModalProps> = ({
onCancel={async () => {
await onCancel();
}}
- strTitle={<TPluginInstallModal trans_part={TranslatedPart.TITLE} trans_type={installType} artifact={artifact} />}
+ strTitle={
+ <div>
+ <TranslationHelper
+ trans_class={TranslationClass.PLUGIN_INSTALL_MODAL}
+ trans_text="title"
+ i18n_args={{ artifact: artifact }}
+ install_type={installType}
+ />
+ </div>
+ }
strOKButtonText={
loading ? (
- <TPluginInstallModal trans_part={TranslatedPart.BUTTON_PROC} trans_type={installType} />
+ <div>
+ <TranslationHelper
+ trans_class={TranslationClass.PLUGIN_INSTALL_MODAL}
+ trans_text="button_processing"
+ install_type={installType}
+ />
+ </div>
) : (
- <TPluginInstallModal trans_part={TranslatedPart.BUTTON_IDLE} trans_type={installType} />
+ <div>
+ <TranslationHelper
+ trans_class={TranslationClass.PLUGIN_INSTALL_MODAL}
+ trans_text="button_idle"
+ install_type={installType}
+ />
+ </div>
)
}
>
- <TPluginInstallModal
- trans_part={TranslatedPart.DESC}
- trans_type={installType}
- artifact={artifact}
- version={version ? version : ''}
- />
+ <div>
+ <TranslationHelper
+ trans_class={TranslationClass.PLUGIN_INSTALL_MODAL}
+ trans_text="desc"
+ i18n_args={{
+ artifact: artifact,
+ version: version,
+ }}
+ install_type={installType}
+ />
+ </div>
{hash == 'False' && <span style={{ color: 'red' }}>{t('PluginInstallModal.no_hash')}</span>}
</ConfirmModal>
);
diff --git a/frontend/src/components/modals/TPluginInstallModal.tsx b/frontend/src/components/modals/TPluginInstallModal.tsx
deleted file mode 100644
index 3866560e..00000000
--- a/frontend/src/components/modals/TPluginInstallModal.tsx
+++ /dev/null
@@ -1,95 +0,0 @@
-import { FC } from 'react';
-import { Translation } from 'react-i18next';
-
-import { InstallType } from '../../plugin';
-
-export enum TranslatedPart {
- TITLE,
- DESC,
- BUTTON_IDLE,
- BUTTON_PROC,
-}
-interface TPluginInstallModalProps {
- trans_part: TranslatedPart;
- trans_type: number;
- artifact?: string;
- version?: string;
-}
-
-const TPluginInstallModal: FC<TPluginInstallModalProps> = ({ trans_part, trans_type, artifact, version }) => {
- return (
- <Translation>
- {(t, {}) => {
- switch (trans_part) {
- case TranslatedPart.TITLE:
- switch (trans_type) {
- case InstallType.INSTALL:
- return <div>{t('PluginInstallModal.install.title', { artifact: artifact })}</div>;
- case InstallType.REINSTALL:
- return <div>{t('PluginInstallModal.reinstall.title', { artifact: artifact })}</div>;
- case InstallType.UPDATE:
- return <div>{t('PluginInstallModal.update.title', { artifact: artifact })}</div>;
- default:
- return null;
- }
- case TranslatedPart.DESC:
- switch (trans_type) {
- case InstallType.INSTALL:
- return (
- <div>
- {t('PluginInstallModal.install.desc', {
- artifact: artifact,
- version: version,
- })}
- </div>
- );
- case InstallType.REINSTALL:
- return (
- <div>
- {t('PluginInstallModal.reinstall.desc', {
- artifact: artifact,
- version: version,
- })}
- </div>
- );
- case InstallType.UPDATE:
- return (
- <div>
- {t('PluginInstallModal.update.desc', {
- artifact: artifact,
- version: version,
- })}
- </div>
- );
- default:
- return null;
- }
- case TranslatedPart.BUTTON_IDLE:
- switch (trans_type) {
- case InstallType.INSTALL:
- return <div>{t('PluginInstallModal.install.button_idle')}</div>;
- case InstallType.REINSTALL:
- return <div>{t('PluginInstallModal.reinstall.button_idle')}</div>;
- case InstallType.UPDATE:
- return <div>{t('PluginInstallModal.update.button_idle')}</div>;
- default:
- return null;
- }
- case TranslatedPart.BUTTON_PROC:
- switch (trans_type) {
- case InstallType.INSTALL:
- return <div>{t('PluginInstallModal.install.button_processing')}</div>;
- case InstallType.REINSTALL:
- return <div>{t('PluginInstallModal.reinstall.button_processing')}</div>;
- case InstallType.UPDATE:
- return <div>{t('PluginInstallModal.update.button_processing')}</div>;
- default:
- return null;
- }
- }
- }}
- </Translation>
- );
-};
-
-export default TPluginInstallModal;
diff --git a/frontend/src/plugin-loader.tsx b/frontend/src/plugin-loader.tsx
index 71c8d0df..7a226920 100644
--- a/frontend/src/plugin-loader.tsx
+++ b/frontend/src/plugin-loader.tsx
@@ -1,8 +1,19 @@
-import { ConfirmModal, ModalRoot, Patch, QuickAccessTab, Router, showModal, sleep } from 'decky-frontend-lib';
-import { FC, lazy } from 'react';
-import { Trans, Translation } from 'react-i18next';
-import { IconContext } from 'react-icons';
-import { FaCog, FaExclamationCircle, FaPlug } from 'react-icons/fa';
+import {
+ ConfirmModal,
+ ModalRoot,
+ PanelSection,
+ PanelSectionRow,
+ Patch,
+ QuickAccessTab,
+ Router,
+ showModal,
+ sleep,
+ staticClasses,
+} from 'decky-frontend-lib';
+import { CSSProperties, FC, lazy } from 'react';
+import { Trans } from 'react-i18next';
+import { BsGearFill } from 'react-icons/bs';
+import { FaArrowRight, FaExclamationCircle, FaPlug } from 'react-icons/fa';
import { DeckyState, DeckyStateContextProvider, useDeckyState } from './components/DeckyState';
import LegacyPlugin from './components/LegacyPlugin';
@@ -21,6 +32,7 @@ import OldTabsHook from './tabs-hook.old';
import Toaster from './toaster';
import { VerInfo, callUpdaterMethod } from './updater';
import { getSetting } from './utils/settings';
+import TranslationHelper, { TranslationClass } from './utils/TranslationHelper';
const StorePage = lazy(() => import('./components/store/Store'));
const SettingsPage = lazy(() => import('./components/settings'));
@@ -100,10 +112,14 @@ class PluginLoader extends Logger {
const versionInfo = await this.updateVersion();
if (versionInfo?.remote && versionInfo?.remote?.tag_name != versionInfo?.current) {
this.toaster.toast({
- //title: t('PluginLoader.decky_title'),
- title: 'Decky',
- //body: t('PluginLoader.decky_update_available', { tag_name: versionInfo?.remote?.tag_name }),
- body: `Update to ${versionInfo?.remote?.tag_name} available!`,
+ title: <TranslationHelper trans_class={TranslationClass.PLUGIN_LOADER} trans_text="decky_title" />,
+ body: (
+ <TranslationHelper
+ trans_class={TranslationClass.PLUGIN_LOADER}
+ trans_text="decky_update_available"
+ i18n_args={{ tag_name: versionInfo?.remote?.tag_name }}
+ />
+ ),
onClick: () => Router.Navigate('/decky/settings'),
});
this.deckyState.setHasLoaderUpdate(true);
@@ -122,10 +138,14 @@ class PluginLoader extends Logger {
const updates = await this.checkPluginUpdates();
if (updates?.size > 0) {
this.toaster.toast({
- //title: t('PluginLoader.decky_title'),
- title: 'Decky',
- //body: t('PluginLoader.plugin_update', { count: updates.size }),
- body: `Updates available for ${updates.size} plugin${updates.size > 1 ? 's' : ''}!`,
+ title: <TranslationHelper trans_class={TranslationClass.PLUGIN_LOADER} trans_text="decky_title" />,
+ body: (
+ <TranslationHelper
+ trans_class={TranslationClass.PLUGIN_LOADER}
+ trans_text="plugin_update"
+ i18n_args={{ count: updates.size }}
+ />
+ ),
onClick: () => Router.Navigate('/decky/settings/plugins'),
});
}
@@ -256,25 +276,29 @@ class PluginLoader extends Logger {
});
} catch (e) {
this.error('Error loading plugin ' + name, e);
+ const style: CSSProperties = { verticalAlign: 'middle' };
const TheError: FC<{}> = () => (
- <Translation>
- {(t, {}) => {
- return (
- <>
- {t('PluginLoader.error')}:{' '}
- <pre>
- <code>{e instanceof Error ? e.stack : JSON.stringify(e)}</code>
- </pre>
- <div>
- <Trans
- i18nKey="PluginLoader.plugin_error_uninstall"
- components={[<FaCog style={{ verticalAlign: 'middle' }} />]}
- />
- </div>
- </>
- );
- }}
- </Translation>
+ <PanelSection>
+ <PanelSectionRow>
+ <div className={staticClasses.FriendsTitle} style={{ display: 'flex', justifyContent: 'center' }}>
+ {<TranslationHelper trans_class={TranslationClass.PLUGIN_LOADER} trans_text="error" />}
+ </div>
+ </PanelSectionRow>
+ <PanelSectionRow>
+ <pre style={{ overflowX: 'scroll' }}>
+ <code>{e instanceof Error ? e.stack : JSON.stringify(e)}</code>
+ </pre>
+ </PanelSectionRow>
+ <PanelSectionRow>
+ <div className={staticClasses.Text}>
+ <Trans
+ i18nKey="PluginLoader.plugin_error_uninstall"
+ values={{ name: name }}
+ components={[<BsGearFill style={style} />, <FaArrowRight style={style} />, <FaPlug style={style} />]}
+ />
+ </div>
+ </PanelSectionRow>
+ </PanelSection>
);
this.plugins.push({
name: name,
@@ -283,8 +307,13 @@ class PluginLoader extends Logger {
icon: <FaExclamationCircle />,
});
this.toaster.toast({
- //title: t('PluginLoader.plugin_load_error.toast', { name: name }),
- title: 'Error loading ' + name,
+ title: (
+ <TranslationHelper
+ trans_class={TranslationClass.PLUGIN_LOADER}
+ trans_text="plugin_load_error.toast"
+ i18n_args={{ name: name }}
+ />
+ ),
body: '' + e,
icon: <FaExclamationCircle />,
});
diff --git a/frontend/src/utils/TranslationHelper.tsx b/frontend/src/utils/TranslationHelper.tsx
new file mode 100644
index 00000000..457a3159
--- /dev/null
+++ b/frontend/src/utils/TranslationHelper.tsx
@@ -0,0 +1,59 @@
+import { FC } from 'react';
+import { Translation } from 'react-i18next';
+
+import Logger from '../logger';
+import { InstallType } from '../plugin';
+
+export enum TranslationClass {
+ PLUGIN_LOADER = 'PluginLoader',
+ PLUGIN_INSTALL_MODAL = 'PluginInstallModal',
+}
+
+interface TranslationHelperProps {
+ trans_class: TranslationClass;
+ trans_text: string;
+ i18n_args?: {};
+ install_type?: number;
+}
+
+const logger = new Logger('TranslationHelper');
+
+const TranslationHelper: FC<TranslationHelperProps> = ({
+ trans_class,
+ trans_text,
+ i18n_args = null,
+ install_type = 0,
+}) => {
+ return (
+ <Translation>
+ {(t, {}) => {
+ switch (trans_class) {
+ case TranslationClass.PLUGIN_LOADER:
+ return i18n_args
+ ? t(TranslationClass.PLUGIN_LOADER + '.' + trans_text, i18n_args)
+ : t(TranslationClass.PLUGIN_LOADER + '.' + trans_text);
+ case TranslationClass.PLUGIN_INSTALL_MODAL:
+ switch (install_type) {
+ case InstallType.INSTALL:
+ return i18n_args
+ ? t(TranslationClass.PLUGIN_INSTALL_MODAL + '.install.' + trans_text, i18n_args)
+ : t(TranslationClass.PLUGIN_INSTALL_MODAL + '.install.' + trans_text);
+ case InstallType.REINSTALL:
+ return i18n_args
+ ? t(TranslationClass.PLUGIN_INSTALL_MODAL + '.reinstall.' + trans_text, i18n_args)
+ : t(TranslationClass.PLUGIN_INSTALL_MODAL + '.reinstall.' + trans_text);
+ case InstallType.UPDATE:
+ return i18n_args
+ ? t(TranslationClass.PLUGIN_INSTALL_MODAL + '.update.' + trans_text, i18n_args)
+ : t(TranslationClass.PLUGIN_INSTALL_MODAL + '.update.' + trans_text);
+ }
+ default:
+ logger.error('We should never fall in the default case!');
+ return '';
+ }
+ }}
+ </Translation>
+ );
+};
+
+export default TranslationHelper;