mirror of
https://github.com/SteamDeckHomebrew/decky-loader.git
synced 2026-07-11 23:11:56 +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_title": "Decky",
|
||||||
"decky_update_available": "Update to {{tag_name}} available!",
|
"decky_update_available": "Update to {{tag_name}} available!",
|
||||||
"error": "Error",
|
"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": {
|
"plugin_load_error": {
|
||||||
"message": "Error loading plugin {{name}}",
|
"message": "Error loading plugin {{name}}",
|
||||||
"toast": "Error loading {{name}}"
|
"toast": "Error loading {{name}}"
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
"decky_title": "Decky",
|
"decky_title": "Decky",
|
||||||
"decky_update_available": "Disponibile aggiornamento a {{tag_name}}!",
|
"decky_update_available": "Disponibile aggiornamento a {{tag_name}}!",
|
||||||
"error": "Errore",
|
"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": {
|
"plugin_load_error": {
|
||||||
"message": "Errore caricando il plugin {{name}}",
|
"message": "Errore caricando il plugin {{name}}",
|
||||||
"toast": "Errore caricando {{name}}"
|
"toast": "Errore caricando {{name}}"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { ConfirmModal, Navigation, QuickAccessTab } from 'decky-frontend-lib';
|
|||||||
import { FC, useState } from 'react';
|
import { FC, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import TPluginInstallModal, { TranslatedPart } from './TPluginInstallModal';
|
import TranslationHelper, { TranslationClass } from '../../utils/TranslationHelper';
|
||||||
|
|
||||||
interface PluginInstallModalProps {
|
interface PluginInstallModalProps {
|
||||||
artifact: string;
|
artifact: string;
|
||||||
@@ -39,21 +39,47 @@ const PluginInstallModal: FC<PluginInstallModalProps> = ({
|
|||||||
onCancel={async () => {
|
onCancel={async () => {
|
||||||
await onCancel();
|
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={
|
strOKButtonText={
|
||||||
loading ? (
|
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
|
<div>
|
||||||
trans_part={TranslatedPart.DESC}
|
<TranslationHelper
|
||||||
trans_type={installType}
|
trans_class={TranslationClass.PLUGIN_INSTALL_MODAL}
|
||||||
artifact={artifact}
|
trans_text="desc"
|
||||||
version={version ? version : ''}
|
i18n_args={{
|
||||||
|
artifact: artifact,
|
||||||
|
version: version,
|
||||||
|
}}
|
||||||
|
install_type={installType}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
{hash == 'False' && <span style={{ color: 'red' }}>{t('PluginInstallModal.no_hash')}</span>}
|
{hash == 'False' && <span style={{ color: 'red' }}>{t('PluginInstallModal.no_hash')}</span>}
|
||||||
</ConfirmModal>
|
</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 {
|
||||||
import { FC, lazy } from 'react';
|
ConfirmModal,
|
||||||
import { Trans, Translation } from 'react-i18next';
|
ModalRoot,
|
||||||
import { IconContext } from 'react-icons';
|
PanelSection,
|
||||||
import { FaCog, FaExclamationCircle, FaPlug } from 'react-icons/fa';
|
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 { DeckyState, DeckyStateContextProvider, useDeckyState } from './components/DeckyState';
|
||||||
import LegacyPlugin from './components/LegacyPlugin';
|
import LegacyPlugin from './components/LegacyPlugin';
|
||||||
@@ -21,6 +32,7 @@ import OldTabsHook from './tabs-hook.old';
|
|||||||
import Toaster from './toaster';
|
import Toaster from './toaster';
|
||||||
import { VerInfo, callUpdaterMethod } from './updater';
|
import { VerInfo, callUpdaterMethod } from './updater';
|
||||||
import { getSetting } from './utils/settings';
|
import { getSetting } from './utils/settings';
|
||||||
|
import TranslationHelper, { TranslationClass } from './utils/TranslationHelper';
|
||||||
|
|
||||||
const StorePage = lazy(() => import('./components/store/Store'));
|
const StorePage = lazy(() => import('./components/store/Store'));
|
||||||
const SettingsPage = lazy(() => import('./components/settings'));
|
const SettingsPage = lazy(() => import('./components/settings'));
|
||||||
@@ -100,10 +112,14 @@ class PluginLoader extends Logger {
|
|||||||
const versionInfo = await this.updateVersion();
|
const versionInfo = await this.updateVersion();
|
||||||
if (versionInfo?.remote && versionInfo?.remote?.tag_name != versionInfo?.current) {
|
if (versionInfo?.remote && versionInfo?.remote?.tag_name != versionInfo?.current) {
|
||||||
this.toaster.toast({
|
this.toaster.toast({
|
||||||
//title: t('PluginLoader.decky_title'),
|
title: <TranslationHelper trans_class={TranslationClass.PLUGIN_LOADER} trans_text="decky_title" />,
|
||||||
title: 'Decky',
|
body: (
|
||||||
//body: t('PluginLoader.decky_update_available', { tag_name: versionInfo?.remote?.tag_name }),
|
<TranslationHelper
|
||||||
body: `Update to ${versionInfo?.remote?.tag_name} available!`,
|
trans_class={TranslationClass.PLUGIN_LOADER}
|
||||||
|
trans_text="decky_update_available"
|
||||||
|
i18n_args={{ tag_name: versionInfo?.remote?.tag_name }}
|
||||||
|
/>
|
||||||
|
),
|
||||||
onClick: () => Router.Navigate('/decky/settings'),
|
onClick: () => Router.Navigate('/decky/settings'),
|
||||||
});
|
});
|
||||||
this.deckyState.setHasLoaderUpdate(true);
|
this.deckyState.setHasLoaderUpdate(true);
|
||||||
@@ -122,10 +138,14 @@ class PluginLoader extends Logger {
|
|||||||
const updates = await this.checkPluginUpdates();
|
const updates = await this.checkPluginUpdates();
|
||||||
if (updates?.size > 0) {
|
if (updates?.size > 0) {
|
||||||
this.toaster.toast({
|
this.toaster.toast({
|
||||||
//title: t('PluginLoader.decky_title'),
|
title: <TranslationHelper trans_class={TranslationClass.PLUGIN_LOADER} trans_text="decky_title" />,
|
||||||
title: 'Decky',
|
body: (
|
||||||
//body: t('PluginLoader.plugin_update', { count: updates.size }),
|
<TranslationHelper
|
||||||
body: `Updates available for ${updates.size} plugin${updates.size > 1 ? 's' : ''}!`,
|
trans_class={TranslationClass.PLUGIN_LOADER}
|
||||||
|
trans_text="plugin_update"
|
||||||
|
i18n_args={{ count: updates.size }}
|
||||||
|
/>
|
||||||
|
),
|
||||||
onClick: () => Router.Navigate('/decky/settings/plugins'),
|
onClick: () => Router.Navigate('/decky/settings/plugins'),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -256,25 +276,29 @@ class PluginLoader extends Logger {
|
|||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.error('Error loading plugin ' + name, e);
|
this.error('Error loading plugin ' + name, e);
|
||||||
|
const style: CSSProperties = { verticalAlign: 'middle' };
|
||||||
const TheError: FC<{}> = () => (
|
const TheError: FC<{}> = () => (
|
||||||
<Translation>
|
<PanelSection>
|
||||||
{(t, {}) => {
|
<PanelSectionRow>
|
||||||
return (
|
<div className={staticClasses.FriendsTitle} style={{ display: 'flex', justifyContent: 'center' }}>
|
||||||
<>
|
{<TranslationHelper trans_class={TranslationClass.PLUGIN_LOADER} trans_text="error" />}
|
||||||
{t('PluginLoader.error')}:{' '}
|
</div>
|
||||||
<pre>
|
</PanelSectionRow>
|
||||||
|
<PanelSectionRow>
|
||||||
|
<pre style={{ overflowX: 'scroll' }}>
|
||||||
<code>{e instanceof Error ? e.stack : JSON.stringify(e)}</code>
|
<code>{e instanceof Error ? e.stack : JSON.stringify(e)}</code>
|
||||||
</pre>
|
</pre>
|
||||||
<div>
|
</PanelSectionRow>
|
||||||
|
<PanelSectionRow>
|
||||||
|
<div className={staticClasses.Text}>
|
||||||
<Trans
|
<Trans
|
||||||
i18nKey="PluginLoader.plugin_error_uninstall"
|
i18nKey="PluginLoader.plugin_error_uninstall"
|
||||||
components={[<FaCog style={{ verticalAlign: 'middle' }} />]}
|
values={{ name: name }}
|
||||||
|
components={[<BsGearFill style={style} />, <FaArrowRight style={style} />, <FaPlug style={style} />]}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</PanelSectionRow>
|
||||||
);
|
</PanelSection>
|
||||||
}}
|
|
||||||
</Translation>
|
|
||||||
);
|
);
|
||||||
this.plugins.push({
|
this.plugins.push({
|
||||||
name: name,
|
name: name,
|
||||||
@@ -283,8 +307,13 @@ class PluginLoader extends Logger {
|
|||||||
icon: <FaExclamationCircle />,
|
icon: <FaExclamationCircle />,
|
||||||
});
|
});
|
||||||
this.toaster.toast({
|
this.toaster.toast({
|
||||||
//title: t('PluginLoader.plugin_load_error.toast', { name: name }),
|
title: (
|
||||||
title: 'Error loading ' + name,
|
<TranslationHelper
|
||||||
|
trans_class={TranslationClass.PLUGIN_LOADER}
|
||||||
|
trans_text="plugin_load_error.toast"
|
||||||
|
i18n_args={{ name: name }}
|
||||||
|
/>
|
||||||
|
),
|
||||||
body: '' + e,
|
body: '' + e,
|
||||||
icon: <FaExclamationCircle />,
|
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