mirror of
https://github.com/SteamDeckHomebrew/decky-loader.git
synced 2026-06-17 08:47:49 +00:00
Unified translation classes, fixed missing toaster translation and improved the error styling report.
This commit is contained in:
@@ -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}}"
|
||||
|
||||
@@ -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}}"
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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;
|
||||
@@ -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 />,
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user