First iteration for internationalization of the loader

This commit is contained in:
Marco Rodolfi
2023-01-13 11:03:16 +01:00
parent 2ebcc67bb5
commit e4acd4aa1f
72 changed files with 73145 additions and 676 deletions
+932 -548
View File
File diff suppressed because it is too large Load Diff
+12 -15
View File
@@ -1,30 +1,27 @@
import commonjs from '@rollup/plugin-commonjs';
import json from '@rollup/plugin-json';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import externalGlobals from "rollup-plugin-external-globals";
import del from 'rollup-plugin-delete'
import replace from '@rollup/plugin-replace';
import typescript from '@rollup/plugin-typescript';
import { defineConfig } from 'rollup';
import del from 'rollup-plugin-delete';
import externalGlobals from 'rollup-plugin-external-globals';
const hiddenWarnings = [
"THIS_IS_UNDEFINED",
"EVAL"
];
const hiddenWarnings = ['THIS_IS_UNDEFINED', 'EVAL'];
export default defineConfig({
input: 'src/index.tsx',
plugins: [
del({ targets: "../backend/static/*", force: true }),
del({ targets: '../backend/static/*', force: true }),
commonjs(),
nodeResolve(),
externalGlobals({
react: 'SP_REACT',
'react-dom': 'SP_REACTDOM',
// hack to shut up react-markdown
'process': '{cwd: () => {}}',
'path': '{dirname: () => {}, join: () => {}, basename: () => {}, extname: () => {}}',
'url': '{fileURLToPath: (f) => f}'
process: '{cwd: () => {}}',
path: '{dirname: () => {}, join: () => {}, basename: () => {}, extname: () => {}}',
url: '{fileURLToPath: (f) => f}',
}),
typescript(),
json(),
@@ -38,11 +35,11 @@ export default defineConfig({
dir: '../backend/static',
format: 'esm',
chunkFileNames: (chunkInfo) => {
return 'chunk-[hash].js'
}
return 'chunk-[hash].js';
},
},
onwarn: function ( message, handleWarning ) {
if (hiddenWarnings.some(warning => message.code === warning)) return;
onwarn: function (message, handleWarning) {
if (hiddenWarnings.some((warning) => message.code === warning)) return;
handleWarning(message);
}
},
});
+1 -1
View File
@@ -38,5 +38,5 @@ export default function SettingsPage() {
route: '/decky/settings/developer',
});
return <SidebarNavigation title={t('settings_navbar') as string}showTitle pages={pages} />;
return <SidebarNavigation title={t('settings_navbar') as string} showTitle pages={pages} />;
}
@@ -19,8 +19,7 @@ export default function DeveloperSettings() {
label={t('label_valve_internal')}
description={
<span style={{ whiteSpace: 'pre-line' }}>
{t('valve_internal_desc1')}{' '}
<span style={{ color: 'red' }}>{t('valve_internal_desc2')}</span>
{t('valve_internal_desc1')} <span style={{ color: 'red' }}>{t('valve_internal_desc2')}</span>
</span>
}
icon={<FaSteamSymbol style={{ display: 'block' }} />}
@@ -60,9 +59,7 @@ export default function DeveloperSettings() {
label={t('react_devtools_label')}
description={
<>
<span style={{ whiteSpace: 'pre-line' }}>
{t('react_devtools_desc')}
</span>
<span style={{ whiteSpace: 'pre-line' }}>{t('react_devtools_desc')}</span>
<div ref={textRef}>
<TextField label={'IP'} value={reactDevtoolsIP} onChange={(e) => setReactDevtoolsIP(e?.target.value)} />
</div>
@@ -11,11 +11,7 @@ export default function RemoteDebuggingSettings() {
return (
<Field
label={t('remote_cef_label')}
description={
<span style={{ whiteSpace: 'pre-line' }}>
{t('remote_cef_desc')}
</span>
}
description={<span style={{ whiteSpace: 'pre-line' }}>{t('remote_cef_desc')}</span>}
icon={<FaBug style={{ display: 'block' }} />}
>
<Toggle
@@ -47,7 +47,7 @@ function PatchNotesModal({ versionInfo, closeModal }: { versionInfo: VerInfo | n
<MarkdownRenderer onDismiss={closeModal}>{versionInfo.all[id].body}</MarkdownRenderer>
</WithSuspense>
) : (
t("no_patch_notes_desc")
t('no_patch_notes_desc')
)}
</div>
</Focusable>
@@ -142,7 +142,7 @@ export default function UpdaterSettings() {
bottomSeparator="none"
nProgress={updateProgress}
indeterminate={reloading}
sOperationText={reloading ? t("updates_reloading") : t("updates_updating")}
sOperationText={reloading ? t('updates_reloading') : t('updates_updating')}
/>
)}
</Field>
@@ -26,8 +26,8 @@ export default function GeneralSettings({
<StoreSelect />
<RemoteDebuggingSettings />
<Field
label={t("developer_mode_label")}
description={<span style={{ whiteSpace: 'pre-line' }}>{t("developer_mode_desc")}</span>}
label={t('developer_mode_label')}
description={<span style={{ whiteSpace: 'pre-line' }}>{t('developer_mode_desc')}</span>}
icon={<FaTools style={{ display: 'block' }} />}
>
<Toggle
@@ -38,12 +38,12 @@ export default function GeneralSettings({
/>
</Field>
<Field
label={t("manual_plugin_label")}
label={t('manual_plugin_label')}
description={<TextField label={'URL'} value={pluginURL} onChange={(e) => setPluginURL(e?.target.value)} />}
icon={<FaShapes style={{ display: 'block' }} />}
>
<DialogButton disabled={pluginURL.length == 0} onClick={() => installFromURL(pluginURL)}>
{t("manual_plugin_install_button")}
{t('manual_plugin_install_button')}
</DialogButton>
</Field>
</div>
@@ -51,7 +51,9 @@ export default function PluginList() {
<MenuItem onSelected={() => window.DeckyPluginLoader.importPlugin(name, version)}>
{t('reload')}
</MenuItem>
<MenuItem onSelected={() => window.DeckyPluginLoader.uninstallPlugin(name)}>{t('uninstall')}</MenuItem>
<MenuItem onSelected={() => window.DeckyPluginLoader.uninstallPlugin(name)}>
{t('uninstall')}
</MenuItem>
</Menu>,
e.currentTarget ?? window,
)
+2 -2
View File
@@ -1,3 +1,5 @@
import 'i18n.ts';
import {
ReactRouter,
Router,
@@ -22,8 +24,6 @@ import { FaReact } from 'react-icons/fa';
import Logger from './logger';
import { getSetting } from './utils/settings';
import "i18n.ts";
const logger = new Logger('DeveloperMode');
let removeSettingsObserver: () => void = () => {};
+27 -28
View File
@@ -1,32 +1,31 @@
import i18next from "i18next";
import { initReactI18next } from "react-i18next";
import i18next from 'i18next';
import Backend from 'i18next-fs-backend';
import { initReactI18next } from 'react-i18next';
i18next
.use(initReactI18next)
.use(Backend)
.init({
backend:
{
// path where resources get loaded from, or a function
// returning a path:
// function(lngs, namespaces) { return customPath; }
// the returned path will interpolate lng, ns if provided like giving a static path
loadPath: '/locales/{{lng}}/{{ns}}.json',
// path to post missing resources
// addPath: '/locales/{{lng}}/{{ns}}.missing.json',
// if you use i18next-fs-backend as caching layer in combination with i18next-chained-backend, you can optionally set an expiration time
// an example on how to use it as cache layer can be found here: https://github.com/i18next/i18next-fs-backend/blob/master/example/caching/app.js
// expirationTime: 60 * 60 * 1000
},
fallbackLng:"en",
fallbackNS:"Common",
lng: "en",
interpolation: {
escapeValue: false,
},
});
.use(initReactI18next)
.use(Backend)
.init({
backend: {
// path where resources get loaded from, or a function
// returning a path:
// function(lngs, namespaces) { return customPath; }
// the returned path will interpolate lng, ns if provided like giving a static path
loadPath: '/locales/{{lng}}/{{ns}}.json',
export default i18next;
// path to post missing resources
// addPath: '/locales/{{lng}}/{{ns}}.missing.json',
// if you use i18next-fs-backend as caching layer in combination with i18next-chained-backend, you can optionally set an expiration time
// an example on how to use it as cache layer can be found here: https://github.com/i18next/i18next-fs-backend/blob/master/example/caching/app.js
// expirationTime: 60 * 60 * 1000
},
fallbackLng: 'en',
fallbackNS: 'Common',
lng: 'en',
interpolation: {
escapeValue: false,
},
});
export default i18next;
+2 -1
View File
@@ -1,6 +1,7 @@
import 'i18n.ts';
import PluginLoader from './plugin-loader';
import { DeckyUpdater } from './updater';
import "i18n.ts";
declare global {
interface Window {
+2 -2
View File
@@ -1,3 +1,3 @@
{
"update_channel_label": "Update Channel"
}
"update_channel_label": "Update Channel"
}
+3 -3
View File
@@ -1,4 +1,4 @@
{
"reload": "Reload",
"uninstall": "Uninstall"
}
"reload": "Reload",
"uninstall": "Uninstall"
}
+6 -6
View File
@@ -1,7 +1,7 @@
{
"valve_internal_label": "Enable Valve Internal",
"valve_internal_desc1": "Enables the Valve internal developer menu.",
"valve_internal_desc2": "Do not touch anything in this menu unless you know what it does.",
"react_devtools_label": "Enable React DevTools",
"react_devtools_desc": "Enables connection to a computer running React DevTools. Changing this setting will reload Steam. Set the IP address before enabling."
}
"valve_internal_label": "Enable Valve Internal",
"valve_internal_desc1": "Enables the Valve internal developer menu.",
"valve_internal_desc2": "Do not touch anything in this menu unless you know what it does.",
"react_devtools_label": "Enable React DevTools",
"react_devtools_desc": "Enables connection to a computer running React DevTools. Changing this setting will reload Steam. Set the IP address before enabling."
}
+2 -2
View File
@@ -1,3 +1,3 @@
{
"select_version": "Select a version"
}
"select_version": "Select a version"
}
+4 -4
View File
@@ -1,5 +1,5 @@
{
"list_no_plugin": "No plugins installed!",
"list_update_to": "Update to {{name}}",
"list_plug_actions_label": "Plugin Actions"
}
"list_no_plugin": "No plugins installed!",
"list_update_to": "Update to {{name}}",
"list_plug_actions_label": "Plugin Actions"
}
+3 -3
View File
@@ -1,4 +1,4 @@
{
"remote_cef_label": "Allow Remote CEF Debugging",
"remote_cef_desc": "Allow unauthenticated access to the CEF debugger to anyone in your network"
}
"remote_cef_label": "Allow Remote CEF Debugging",
"remote_cef_desc": "Allow unauthenticated access to the CEF debugger to anyone in your network"
}
@@ -1,6 +1,6 @@
{
"developer_mode_label": "Developer mode",
"developer_mode_desc": "Enables Decky's developer settings.",
"manual_plugin_label": "Manual plugin install",
"manual_plugin_install_button": "Install"
}
"developer_mode_label": "Developer mode",
"developer_mode_desc": "Enables Decky's developer settings.",
"manual_plugin_label": "Manual plugin install",
"manual_plugin_install_button": "Install"
}
+5 -5
View File
@@ -1,6 +1,6 @@
{
"general_title": "General",
"plugins_title": "Plugins",
"developer_title": "Developer",
"navbar_settings": "Decky Settings"
}
"general_title": "General",
"plugins_title": "Plugins",
"developer_title": "Developer",
"navbar_settings": "Decky Settings"
}
+3 -3
View File
@@ -1,4 +1,4 @@
{
"store_channel_label": "Store Channel",
"custom_store_label": "Custom Store"
}
"store_channel_label": "Store Channel",
"custom_store_label": "Custom Store"
}
+12 -12
View File
@@ -1,14 +1,14 @@
{
"no_patch_notes_desc": "no patch notes for this version",
"decky_updates": "Decky Updates",
"updates_label": "Updates",
"updates_cur_version": "Current version: {{ver}}",
"updates_lat_version": "Latest version: {{ver}}",
"no_patch_notes_desc": "no patch notes for this version",
"decky_updates": "Decky Updates",
"updates_checking": "'Checking",
"updates_check_button": "Check For Updates",
"updates_install_button": "Install Update",
"updates_reloading": "Reloading",
"updates_updating": "Updating"
}
"updates_label": "Updates",
"updates_cur_version": "Current version: {{ver}}",
"updates_lat_version": "Latest version: {{ver}}",
"updates_checking": "'Checking",
"updates_check_button": "Check For Updates",
"updates_install_button": "Install Update",
"updates_reloading": "Reloading",
"updates_updating": "Updating"
}
+12 -12
View File
@@ -1,13 +1,13 @@
{
"enabling":"Enabling",
"disabling":"Disabling",
"decky_update_available":"Update to {{tag_name}} available!",
"plugin_update_one":"Updates available for 1 plugin!",
"plugin_update_other":"Updates available for {{number}} plugins!",
"plugin_uninstall":"Uninstall {{name}}?",
"plugin_load_error":"Error loading plugin {{name}}",
"plugin_load_error_toast": "Error loading {{name}}",
"error":"Error",
"plugin_error_uninstall":"Please go to {{-icon}} in the Decky menu if you need to uninstall this plugin.",
"file_picker_cancel_text": "User canceled"
}
"enabling": "Enabling",
"disabling": "Disabling",
"decky_update_available": "Update to {{tag_name}} available!",
"plugin_update_one": "Updates available for 1 plugin!",
"plugin_update_other": "Updates available for {{number}} plugins!",
"plugin_uninstall": "Uninstall {{name}}?",
"plugin_load_error": "Error loading plugin {{name}}",
"plugin_load_error_toast": "Error loading {{name}}",
"error": "Error",
"plugin_error_uninstall": "Please go to {{-icon}} in the Decky menu if you need to uninstall this plugin.",
"file_picker_cancel_text": "User canceled"
}
@@ -0,0 +1,3 @@
{
"update_channel_label": "Canale di aggiornamento"
}
+4
View File
@@ -0,0 +1,4 @@
{
"reload": "Ricarica",
"uninstall": "Rimuovi"
}
@@ -0,0 +1,7 @@
{
"valve_internal_label": "Abilita Menu Sviluppatore",
"valve_internal_desc1": "Abilita il menu interno di sviluppo di Valve.",
"valve_internal_desc2": "Non toccare nulla in questo menu se non sai quello che fa.",
"react_devtools_label": "Abilita i DevTools di React",
"react_devtools_desc": "Abilita la connessione ad un computer che esegue i DevTools di React. Cambiando questa impostazione ricaricherà Steam. Imposta l'indirizzo IP prima di abilitarlo."
}
+3
View File
@@ -0,0 +1,3 @@
{
"select_version": "Seleziona una versione"
}
@@ -0,0 +1,5 @@
{
"list_no_plugin": "Nessun plugin installato!",
"list_update_to": "Aggiornamento a {{name}}",
"list_plug_actions_label": "Operazioni sui plugins"
}
@@ -0,0 +1,4 @@
{
"remote_cef_label": "Permetti il debug remoto di CEF",
"remote_cef_desc": "Permetti l'accesso non autenticato a chiunque sulla tua rete locale al debugger di CEF."
}
@@ -0,0 +1,6 @@
{
"developer_mode_label": "Modalità sviluppatore",
"developer_mode_desc": "Abilità le impostazioni di sviluppo di Decky.",
"manual_plugin_label": "Installazione manuale plugins",
"manual_plugin_install_button": "Installa"
}
@@ -0,0 +1,6 @@
{
"general_title": "Generali",
"plugins_title": "Plugins",
"developer_title": "Sviluppatore",
"navbar_settings": "Impostazioni Decky"
}
+4
View File
@@ -0,0 +1,4 @@
{
"store_channel_label": "Canale del negozio",
"custom_store_label": "Negozio custom"
}
+14
View File
@@ -0,0 +1,14 @@
{
"no_patch_notes_desc": "nessuna patch notes per questa versione",
"decky_updates": "Aggiornamenti di Decky",
"updates_label": "Aggiornamenti",
"updates_cur_version": "Versione attuale: {{ver}}",
"updates_lat_version": "Ultima versione: {{ver}}",
"updates_checking": "Controllando",
"updates_check_button": "Cerca aggiornamenti",
"updates_install_button": "Installa aggiornamento",
"updates_reloading": "Ricaricando",
"updates_updating": "Aggiornando"
}
@@ -0,0 +1,13 @@
{
"enabling": "Abilitando",
"disabling": "Disabilitando",
"decky_update_available": "Disponibile aggiornamento a {{tag_name}}!",
"plugin_update_one": "Aggiornamento disponibile per un plugin!",
"plugin_update_other": "Aggiornamento disponibile per {{number}} plugins!",
"plugin_uninstall": "Rimuovo {{name}}?",
"plugin_load_error": "Errore caricando il plugin {{name}}",
"plugin_load_error_toast": "Errore caricando {{name}}",
"error": "Errore",
"plugin_error_uninstall": "Per rimuovere questo plugin vai su {{-icon}} nel menu di Decky.",
"file_picker_cancel_text": "Annullato dall'utente"
}
+9 -7
View File
@@ -9,6 +9,7 @@ import {
staticClasses,
} from 'decky-frontend-lib';
import { FC, lazy } from 'react';
import { useTranslation } from 'react-i18next';
import { FaCog, FaExclamationCircle, FaPlug } from 'react-icons/fa';
import { DeckyState, DeckyStateContextProvider, useDeckyState } from './components/DeckyState';
@@ -27,7 +28,6 @@ import OldTabsHook from './tabs-hook.old';
import Toaster from './toaster';
import { VerInfo, callUpdaterMethod } from './updater';
import { getSetting } from './utils/settings';
import { useTranslation } from 'react-i18next';
const StorePage = lazy(() => import('./components/store/Store'));
const SettingsPage = lazy(() => import('./components/settings'));
@@ -133,7 +133,7 @@ class PluginLoader extends Logger {
this.toaster.toast({
title: 'Decky',
//body: `Updates available for ${updates.size} plugin${updates.size > 1 ? 's' : ''}!`,
body: t('plugin_update', updates.size.toString(10), {count: updates.size}),
body: t('plugin_update', updates.size.toString(10), { count: updates.size }),
onClick: () => Router.Navigate('/decky/settings/plugins'),
});
}
@@ -251,13 +251,11 @@ class PluginLoader extends Logger {
this.error(t('plugin_load_error', name), e);
const TheError: FC<{}> = () => (
<>
{t("error")}:{' '}
{t('error')}:{' '}
<pre>
<code>{e instanceof Error ? e.stack : JSON.stringify(e)}</code>
</pre>
<>
{t('plugin_error_uninstall', <FaCog style={{ display: 'inline' }} />)}
</>
<>{t('plugin_error_uninstall', <FaCog style={{ display: 'inline' }} />)}</>
</>
);
this.plugins.push({
@@ -266,7 +264,11 @@ class PluginLoader extends Logger {
content: <TheError />,
icon: <FaExclamationCircle />,
});
this.toaster.toast({ title: t('error_loading_plugin_toast', name), body: '' + e, icon: <FaExclamationCircle /> });
this.toaster.toast({
title: t('error_loading_plugin_toast', name),
body: '' + e,
icon: <FaExclamationCircle />,
});
}
} else throw new Error(`${name} frontend_bundle not OK`);
}