mirror of
https://github.com/SteamDeckHomebrew/decky-loader.git
synced 2026-07-11 12:42:01 +00:00
Unified translation classes, fixed missing toaster translation and improved the error styling report.
This commit is contained in:
@@ -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