diff --git a/src/components/ActionList.svelte b/src/components/ActionList.svelte index 0c1f3c8..c99dcba 100644 --- a/src/components/ActionList.svelte +++ b/src/components/ActionList.svelte @@ -3,6 +3,7 @@ import MagnifyingGlass from "phosphor-svelte/lib/MagnifyingGlass"; + import { t } from "$lib/i18n"; import { getWebserverUrl } from "$lib/ports"; import { copiedItem } from "$lib/propertyInspector"; import { localisations } from "$lib/settings"; @@ -81,13 +82,13 @@ - Use arrow keys to navigate between actions within a category. + {$t("action_list.hint")}
{#each filteredCategories as [name, { icon, actions }]}
diff --git a/src/components/DeviceSelector.svelte b/src/components/DeviceSelector.svelte index e04ca7b..f44f315 100644 --- a/src/components/DeviceSelector.svelte +++ b/src/components/DeviceSelector.svelte @@ -2,6 +2,7 @@ import type { DeviceInfo } from "$lib/DeviceInfo"; import type { Profile } from "$lib/Profile"; + import { t } from "$lib/i18n"; import { profileManager } from "$lib/singletons"; import { invoke } from "@tauri-apps/api/core"; @@ -73,8 +74,8 @@ {#if Object.keys(devices).length > 0}
- + {#each Object.entries(devices).sort() as [id, device]} diff --git a/src/components/DeviceView.svelte b/src/components/DeviceView.svelte index 53f5e85..56bf296 100644 --- a/src/components/DeviceView.svelte +++ b/src/components/DeviceView.svelte @@ -7,6 +7,7 @@ import Key from "./Key.svelte"; + import { t } from "$lib/i18n"; import { inspectedInstance, inspectedParentAction } from "$lib/propertyInspector"; import { invoke } from "@tauri-apps/api/core"; @@ -173,7 +174,7 @@ {#key device} - Use arrow keys to navigate between keys. Moving to a key will display its property inspector. + {$t("device_view.grid_description")}
handleDragStart(event, "Keypad", (r * device.columns) + c)} {handlePaste} size={device.id.startsWith("sd-") && device.rows == 4 && device.columns == 8 ? 192 : 144} - label="Key {String.fromCharCode(65 + r)}{c + 1}" + label="{$t('device_view.key')} {String.fromCharCode(65 + r)}{c + 1}" tabindex={focusedRow === r && focusedCol === c ? 0 : -1} /> {/each} @@ -220,7 +221,7 @@ on:dragstart={(event) => handleDragStart(event, "Encoder", i)} {handlePaste} size={device.id.startsWith("sd-") && device.rows == 4 && device.columns == 8 ? 192 : 144} - label="Encoder {i + 1}" + label="{$t('device_view.encoder')} {i + 1}" tabindex={focusedRow === encoderRowIndex && focusedCol === i ? 0 : -1} /> {/each} @@ -255,7 +256,7 @@ {handlePaste} size={device.id.startsWith("sd-") && device.rows == 4 && device.columns == 8 ? 192 : 144} isTouchPoint - label="Touch point {i + 1}" + label="{$t('device_view.touchpoint')} {i + 1}" tabindex={focusedRow === touchpointRowIndex && focusedCol === i ? 0 : -1} /> {/each} diff --git a/src/components/InstanceEditor.svelte b/src/components/InstanceEditor.svelte index 03fe2f7..aebfb5a 100644 --- a/src/components/InstanceEditor.svelte +++ b/src/components/InstanceEditor.svelte @@ -1,6 +1,7 @@ - - + +
{details.name}
- by + {$t("plugin_details.by")} Author avatar - Install + {$t("plugin_details.install")} diff --git a/src/components/PluginManager.svelte b/src/components/PluginManager.svelte index d9d1773..c3bd6c4 100644 --- a/src/components/PluginManager.svelte +++ b/src/components/PluginManager.svelte @@ -12,6 +12,7 @@ import Popup from "./Popup.svelte"; import Tooltip from "./Tooltip.svelte"; + import { t } from "$lib/i18n"; import { getWebserverUrl } from "$lib/ports"; import { localisations, settings } from "$lib/settings"; import { actionList, deviceSelector, PRODUCT_NAME } from "$lib/singletons"; @@ -29,14 +30,14 @@ }, 1e3); async function installPlugin(name: string, url: string | null, file: string | null, fallback_id: string | null) { - if (!file && !await ask(`It may take a while to install the plugin.`, { title: `Install "${name}"?` })) return; + if (!file && !await ask($t("plugin_manager.install.prompt"), { title: $t("plugin_manager.install.title", { name }), okLabel: $t("dialog.yes"), cancelLabel: $t("dialog.no") })) return; try { await invoke("install_plugin", { url, file, fallback_id }); - message(`Successfully installed "${name}".`, { title: `Installed "${name}"` }); + message($t("plugin_manager.install.success", { name }), { title: $t("plugin_manager.install.success.title", { name }), buttons: { ok: $t("dialog.ok") } }); $actionList?.reload(); installed = await invoke("list_plugins"); } catch (error: any) { - message(error, { title: `Failed to install "${name}"` }); + message(error, { title: $t("plugin_manager.install.error", { name }), buttons: { ok: $t("dialog.ok") } }); } } @@ -82,7 +83,7 @@ try { res = await (await fetch(endpoint)).json(); } catch (error: any) { - message(error, { title: `Failed to install "${plugin.name}"` }); + message(error, { title: $t("plugin_manager.install.error", { name: plugin.name }), buttons: { ok: $t("dialog.ok") } }); return; } @@ -116,15 +117,21 @@ } async function removePlugin(plugin: any) { - if (!await ask(`Are you sure you want to remove "${plugin.name}"?`, { title: `Remove "${plugin.name}"?` })) return; + if ( + !await ask($t("plugin_manager.remove.prompt", { name: plugin.name }), { + title: $t("plugin_manager.remove.title", { name: plugin.name }), + okLabel: $t("dialog.yes"), + cancelLabel: $t("dialog.no"), + }) + ) return; try { await invoke("remove_plugin", { id: plugin.id }); - message(`Successfully removed "${plugin.name}".`, { title: `Removed "${plugin.name}"` }); + message($t("plugin_manager.remove.success", { name: plugin.name }), { title: $t("plugin_manager.remove.success.title", { name: plugin.name }), buttons: { ok: $t("dialog.ok") } }); $actionList?.reload(); $deviceSelector?.reloadProfiles(); installed = await invoke("list_plugins"); } catch (error: any) { - message(error, { title: `Failed to remove "${plugin.name}"` }); + message(error, { title: $t("plugin_manager.remove.error", { name: plugin.name }), buttons: { ok: $t("dialog.ok") } }); } } @@ -199,7 +206,7 @@ class="px-3 py-1 text-sm text-neutral-300 bg-neutral-700 hover:bg-neutral-600 transition-colors border border-neutral-600 rounded-lg" on:click={() => showPopup = true} > - Plugins + {$t("plugin_manager.button")} - - -

Manage plugins

+ + +

{$t("plugin_manager.title")}

-

Installed plugins

+

{$t("plugin_manager.installed")}

{#each installed.sort((a, b) => @@ -235,15 +242,15 @@ if ($settings?.developer) invoke("reload_plugin", { id: plugin.id }); else removePlugin(plugin); }} - actionLabel={$settings?.developer ? "Reload" : "Remove"} + actionLabel={$settings?.developer ? $t("plugin_manager.reload") : $t("plugin_manager.remove")}} secondaryAction={!plugin.registered ? () => invoke("open_log_directory") : plugin.has_settings_interface ? () => invoke("show_settings_interface", { plugin: plugin.id }) : undefined} - secondaryActionLabel={!plugin.registered ? "View logs" : "Settings"} + secondaryActionLabel={!plugin.registered ? $t("plugin_manager.view_logs") : $t("plugin_manager.plugin_settings")}} > {plugin.version} {#if availableUpdates[plugin.id]} ( - available: + {$t("plugin_manager.available")}
-

Plugin store

+

{$t("plugin_manager.store")}

- If you are experiencing issues with a plugin, please reach out on one of the {PRODUCT_NAME} support channels before attempting to contact the plugin developer. + {$t("plugin_manager.warning", { PRODUCT_NAME })}
@@ -293,19 +300,19 @@
{#if !plugins} -

Loading open-source plugin list...

+

{$t("plugin_manager.loading.open_source")}

{:else}
-

Open-source plugins

- Open-source plugins downloaded from the author's releases +

{$t("plugin_manager.open_source")}

+ {$t("plugin_manager.open_source.tooltip")}
{#each Object.entries(plugins) as [id, plugin]} @@ -315,7 +322,7 @@ subtitle={plugin.author} hidden={!plugin.name.toLowerCase().includes(query.toLowerCase())} action={() => openDetailsView = id} - actionLabel="View details" + actionLabel={$t("plugin_manager.view_details")} > @@ -324,8 +331,8 @@ {/if}
-

Elgato App Store archive

- Plugins archived from the Elgato App Store (now replaced by the Elgato Marketplace) +

{$t("plugin_manager.elgato")}

+ {$t("plugin_manager.elgato.tooltip")}
{#if !showArchive} {:else if !archivePlugins} -

Loading Elgato App Store archive plugin list...

+

{$t("plugin_manager.loading.elgato")}

{:else}
{#each archivePlugins as plugin} @@ -348,7 +355,7 @@ subtitle={plugin.author} hidden={!plugin.name.toLowerCase().includes(query.toLowerCase())} action={() => installPluginElgato(plugin)} - actionLabel="Install" + actionLabel={$t("plugin_details.install")} > @@ -359,7 +366,7 @@ {#if "Tacto Connect".toLowerCase().includes(query.toLowerCase())}

Tacto

- Turn your phone or keyboard into a control centre for your computer + {$t("plugin_manager.tacto.tooltip")}
window.open("https://tacto.live")} - secondaryActionLabel="Visit website" + secondaryActionLabel={$t("plugin_manager.visit_website")} > @@ -402,9 +409,9 @@ {#if choices}
-

Choose a release asset

+

{$t("plugin_manager.choose_asset")}

- {#each choices as choice, i} {/each} @@ -414,7 +421,7 @@ class="mt-2 p-1 w-full text-sm text-neutral-300 bg-neutral-800 hover:bg-neutral-900 transition-colors border border-neutral-600 rounded-lg" on:click={finishChoice} > - Install + {$t("plugin_details.install")}
{/if} diff --git a/src/components/ProfileManager.svelte b/src/components/ProfileManager.svelte index 38762ad..870b55b 100644 --- a/src/components/ProfileManager.svelte +++ b/src/components/ProfileManager.svelte @@ -9,6 +9,7 @@ import Trash from "phosphor-svelte/lib/Trash"; import Popup from "./Popup.svelte"; + import { t } from "$lib/i18n"; import { inspectedInstance } from "$lib/propertyInspector"; import { invoke } from "@tauri-apps/api/core"; @@ -85,14 +86,14 @@ // Check if a profile with the new ID already exists const allProfiles = Object.values(folders).flat(); if (allProfiles.includes(newId)) { - message(`A profile with the ID "${newId}" already exists.`, { title: "Failed to rename profile" }); + message($t("profile_manager.rename.exists", { id: newId }), { title: $t("profile_manager.rename.failed"), buttons: { ok: $t("dialog.ok") } }); return; } try { await invoke("rename_profile", { device: device.id, oldId, newId, retain: false }); } catch (error: any) { - message(error, { title: "Failed to rename profile" }); + message(error, { title: $t("profile_manager.rename.failed"), buttons: { ok: $t("dialog.ok") } }); console.error(error); } @@ -125,14 +126,14 @@ $: if (renameInput) renameInput.focus(); async function duplicateProfile(id: string) { - let newId = id + " Copy"; + let newId = id + $t("profile_manager.duplicate.suffix"); // Check if a profile with the new ID already exists const allProfiles = Object.values(folders).flat(); let counter = 1; while (allProfiles.includes(newId)) { counter++; - newId = `${id} Copy ${counter}`; + newId = `${id}${$t("profile_manager.duplicate.suffix")} ${counter}`; } await invoke("rename_profile", { device: device.id, oldId: id, newId, retain: true }); @@ -188,7 +189,7 @@
- {#each Object.entries(folders).sort() as [id, profiles]} {#if id && profiles.length} @@ -202,7 +203,7 @@ {/each} {/if} {/each} - +
@@ -216,8 +217,8 @@ }} /> - - + +

{device.name}

@@ -225,8 +226,8 @@ bind:this={nameInput} pattern="[a-zA-Z0-9_ ]+(\/[a-zA-Z0-9_ ]+)?" class="grow p-2 text-neutral-300 invalid:text-red-400 bg-neutral-700 border-l border-y border-neutral-600 rounded-l-lg" - placeholder='Profile name or "folder/name"' - aria-label="Profile name" + placeholder={$t("profile_manager.create.placeholder")} + aria-label={$t("profile_manager.create.label")} /> @@ -277,23 +278,23 @@ if (e.key === "Enter") saveRenamedProfile(profile); }} /> - {:else} - {#if profile != value} - {/if} @@ -304,19 +305,23 @@
- - + +

{device.name}

- If your application isn't listed, try switching to it and back again. - The 'default profile' will activate when the focussed application has no profile associated with it. + {$t("profile_manager.application_profiles.hint.1")} + {$t("profile_manager.application_profiles.hint.2")} {#each Object.entries(applicationProfiles).sort((a, b) => a[0] == "opendeck_default" ? -1 : b[0] == "opendeck_default" ? 1 : a[0].localeCompare(b[0])) as [appName, devices]} {#if devices[device.id]} - + @@ -339,10 +344,10 @@ {/each}
{appName == "opendeck_default" ? "Default profile" : appName}:{appName == "opendeck_default" ? $t("profile_manager.default_profile") : appName}: - {#each Object.entries(folders) as [id, profiles]} {#if id && profiles.length} @@ -331,7 +336,7 @@ {/if} {/each} - +
- + {#if !applicationProfiles["opendeck_default"] || !applicationProfiles["opendeck_default"][device.id]} - + {#if applications.filter((appName) => !applicationProfiles[appName] || !applicationProfiles[appName][device.id]).length > 0} {/if} @@ -355,8 +360,8 @@ - + {#each Object.entries(folders) as [id, profiles]} {#if id && profiles.length} diff --git a/src/components/PropertyInspectorView.svelte b/src/components/PropertyInspectorView.svelte index fa10d09..bbd1a50 100644 --- a/src/components/PropertyInspectorView.svelte +++ b/src/components/PropertyInspectorView.svelte @@ -3,6 +3,7 @@ import type { DeviceInfo } from "$lib/DeviceInfo"; import type { Profile } from "$lib/Profile"; + import { t } from "$lib/i18n"; import { getWebserverUrl, getWebSocketPort } from "$lib/ports"; import { inspectedInstance } from "$lib/propertyInspector"; @@ -189,7 +190,7 @@ {#each instances as instance (instance.context)} {#if instance.action.property_inspector}