From b0ef7f86cb1a2a7e99e6e7b429c30081e9caec38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Ml=C3=A1dek?= Date: Tue, 25 Oct 2022 21:47:17 +0200 Subject: [PATCH] feat: add i18next, move attribute labels --- webui/package.json | 2 ++ webui/src/components/AttributeView.svelte | 3 +- webui/src/components/Inspect.svelte | 11 ++++--- .../display/blobs/AudioViewer.svelte | 9 ++++-- webui/src/components/widgets/EntryList.svelte | 9 +++--- webui/src/i18n/en.json | 14 ++++++++ webui/src/i18n/index.ts | 12 +++++++ webui/src/util/labels.ts | 32 +++++++++---------- webui/src/views/Home.svelte | 16 ++++++---- webui/yarn.lock | 30 +++++++++++++++++ 10 files changed, 103 insertions(+), 35 deletions(-) create mode 100644 webui/src/i18n/en.json create mode 100644 webui/src/i18n/index.ts diff --git a/webui/package.json b/webui/package.json index 64f17c0..18043b6 100644 --- a/webui/package.json +++ b/webui/package.json @@ -39,6 +39,7 @@ "dompurify": "^2.3.4", "filesize": "^8.0.6", "history": "^5.1.0", + "i18next": "^22.0.2", "lodash": "^4.17.21", "lru-cache": "^6.0.0", "marked": "^4.0.10", @@ -48,6 +49,7 @@ "sass": "^1.43.4", "sirv-cli": "^1.0.0", "sswr": "^1.3.1", + "svelte-i18next": "^1.2.2", "svelte-navigator": "^3.1.5", "three": "^0.136.0", "upend": "../tools/upend_js", diff --git a/webui/src/components/AttributeView.svelte b/webui/src/components/AttributeView.svelte index 4915d1f..99db197 100644 --- a/webui/src/components/AttributeView.svelte +++ b/webui/src/components/AttributeView.svelte @@ -7,6 +7,7 @@ import IconButton from "./utils/IconButton.svelte"; import { createEventDispatcher } from "svelte"; const dispatch = createEventDispatcher(); + import { i18n } from "../i18n"; export let entries: UpEntry[]; export let type: UpType | undefined = undefined; @@ -73,7 +74,7 @@ {#if type.name != "HIER"} {type.label || type.name || "???"} {:else} - Members + {$i18n.t("Members")} {/if} {:else} diff --git a/webui/src/components/Inspect.svelte b/webui/src/components/Inspect.svelte index 1343cc4..963fed0 100644 --- a/webui/src/components/Inspect.svelte +++ b/webui/src/components/Inspect.svelte @@ -18,6 +18,7 @@ import { deleteEntry, putEntityAttribute, putEntry } from "../lib/api"; import Icon from "./utils/Icon.svelte"; import BlobViewer from "./display/BlobViewer.svelte"; + import { i18n } from "../i18n"; const dispatch = createEventDispatcher(); const params = useParams(); @@ -188,7 +189,7 @@ } async function deleteObject() { - if (confirm(`Really delete "${identities.join(" | ")}"?`)) { + if (confirm(`${$i18n.t("Really delete")} "${identities.join(" | ")}"?`)) { await deleteEntry(address); dispatch("close"); } @@ -230,7 +231,7 @@
{#if groups?.length || editable}
-

Groups

+

{$i18n.t("Groups")}

{#each groups as [entryAddress, address]}
@@ -282,7 +283,7 @@ {#if currentUntypedAttributes.length > 0 || editable} 0} 20 MiB) and UpEnd failed to load waveform from server. Generating the waveform locally may slow down your browser. Do you wish to proceed anyway?" + $i18n.t( + "File is large (>20 MiB) and UpEnd failed to load waveform from server. Generating the waveform locally may slow down your browser. Do you wish to proceed anyway?" + ) ) ) { console.warn( diff --git a/webui/src/components/widgets/EntryList.svelte b/webui/src/components/widgets/EntryList.svelte index 125ebf5..0033aed 100644 --- a/webui/src/components/widgets/EntryList.svelte +++ b/webui/src/components/widgets/EntryList.svelte @@ -15,6 +15,7 @@ import { defaultEntitySort, entityValueSort } from "../../util/sort"; import { attributeLabels } from "../../util/labels"; import { formatDuration } from "../../util/fragments/time"; + import { i18n } from "../../i18n"; const dispatch = createEventDispatcher(); export let columns: string | undefined = undefined; @@ -49,7 +50,7 @@ newEntryValue = undefined; } async function removeEntry(address: string) { - if (confirm("Are you sure you want to remove the attribute?")) { + if (confirm($i18n.t("Are you sure you want to remove the attribute?"))) { dispatch("change", { type: "delete", address } as AttributeChange); } } @@ -144,9 +145,9 @@ // Formatting & Display const COLUMN_LABELS: { [key: string]: string } = { - entity: "Entity", - attribute: "Attribute", - value: "Value", + entity: $i18n.t("Entity"), + attribute: $i18n.t("Attribute"), + value: $i18n.t("Value"), }; function formatValue(value: string | number, attribute: string): string { diff --git a/webui/src/i18n/en.json b/webui/src/i18n/en.json new file mode 100644 index 0000000..26f9b80 --- /dev/null +++ b/webui/src/i18n/en.json @@ -0,0 +1,14 @@ +{ + "attributes": { + "FILE_MIME": "MIME type", + "FILE_MTIME": "Last modified", + "FILE_SIZE": "File size", + "ADDED": "Added at", + "LAST_VISITED": "Last visited at", + "NUM_VISITED": "Times visited", + "LBL": "Label", + "IS": "Type", + "TYPE": "Type ID", + "MEDIA_DURATION": "Duration" + } +} diff --git a/webui/src/i18n/index.ts b/webui/src/i18n/index.ts new file mode 100644 index 0000000..650b200 --- /dev/null +++ b/webui/src/i18n/index.ts @@ -0,0 +1,12 @@ +import i18next from "i18next"; +import { createI18nStore } from "svelte-i18next"; +import en from "./en.json"; + +i18next.init({ + lng: "en", + resources: { + en, + }, +}); + +export const i18n = createI18nStore(i18next); diff --git a/webui/src/util/labels.ts b/webui/src/util/labels.ts index b0861cb..1da62c2 100644 --- a/webui/src/util/labels.ts +++ b/webui/src/util/labels.ts @@ -1,23 +1,11 @@ -import { readable, type Readable } from "svelte/store"; +import { i18n } from "../i18n"; +import { derived, readable, type Readable } from "svelte/store"; import { fetchAllAttributes } from "../lib/api"; -const DEFAULT_ATTRIBUTE_LABELS = { - FILE_MIME: "MIME type", - FILE_MTIME: "Last modified", - FILE_SIZE: "File size", - ADDED: "Added at", - LAST_VISITED: "Last visited at", - NUM_VISITED: "Times visited", - LBL: "Label", - IS: "Type", - TYPE: "Type ID", - MEDIA_DURATION: "Duration", -}; - -export const attributeLabels: Readable<{ [key: string]: string }> = readable( - DEFAULT_ATTRIBUTE_LABELS, +const databaseAttributeLabels: Readable<{ [key: string]: string }> = readable( + {}, (set) => { - const result = Object.assign(DEFAULT_ATTRIBUTE_LABELS); + const result = {}; fetchAllAttributes().then((attributes) => { attributes.forEach((attribute) => { if (attribute.labels.length) { @@ -28,3 +16,13 @@ export const attributeLabels: Readable<{ [key: string]: string }> = readable( }); } ); + +export const attributeLabels: Readable<{ [key: string]: string }> = derived( + [i18n, databaseAttributeLabels], + ([i18n, attributeLabels]) => { + const result = {}; + Object.assign(result, i18n.getResourceBundle(i18n.language, "attributes")); + Object.assign(result, attributeLabels); + return result; + } +); diff --git a/webui/src/views/Home.svelte b/webui/src/views/Home.svelte index 9e27d78..aef2afb 100644 --- a/webui/src/views/Home.svelte +++ b/webui/src/views/Home.svelte @@ -11,6 +11,7 @@ import { query } from "../lib/entity"; import { vaultInfo } from "../util/info"; import { updateTitle } from "../util/title"; + import { i18n } from "../i18n"; const roots = (async () => { const data = await fetchRoots(); @@ -114,7 +115,7 @@
-

Roots

+

{$i18n.t("Roots")}

{#await roots} {:then data} @@ -133,7 +134,7 @@
{#if frequent.length || $frequentQuery === undefined}
-

Frequently visited

+

{$i18n.t("Frequently visited")}

{#if $frequentQuery == undefined} {:else} @@ -147,7 +148,7 @@ {/if} {#if recent.length || $recentQuery === undefined}
-

Recently visited

+

{$i18n.t("Recently visited")}

{#if $recentQuery == undefined} {:else} @@ -163,7 +164,7 @@ {#if latest.length || $latestQuery === undefined}
-

Most recently added

+

{$i18n.t("Most recently added")}

{#if $latestQuery == undefined} {:else} @@ -177,13 +178,14 @@ {/if}
- View store statistics + {$i18n.t("View store statistics")}