feat: add i18next, move attribute labels
parent
4b3e7fc7a1
commit
b0ef7f86cb
|
@ -39,6 +39,7 @@
|
||||||
"dompurify": "^2.3.4",
|
"dompurify": "^2.3.4",
|
||||||
"filesize": "^8.0.6",
|
"filesize": "^8.0.6",
|
||||||
"history": "^5.1.0",
|
"history": "^5.1.0",
|
||||||
|
"i18next": "^22.0.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"lru-cache": "^6.0.0",
|
"lru-cache": "^6.0.0",
|
||||||
"marked": "^4.0.10",
|
"marked": "^4.0.10",
|
||||||
|
@ -48,6 +49,7 @@
|
||||||
"sass": "^1.43.4",
|
"sass": "^1.43.4",
|
||||||
"sirv-cli": "^1.0.0",
|
"sirv-cli": "^1.0.0",
|
||||||
"sswr": "^1.3.1",
|
"sswr": "^1.3.1",
|
||||||
|
"svelte-i18next": "^1.2.2",
|
||||||
"svelte-navigator": "^3.1.5",
|
"svelte-navigator": "^3.1.5",
|
||||||
"three": "^0.136.0",
|
"three": "^0.136.0",
|
||||||
"upend": "../tools/upend_js",
|
"upend": "../tools/upend_js",
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
import IconButton from "./utils/IconButton.svelte";
|
import IconButton from "./utils/IconButton.svelte";
|
||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from "svelte";
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
import { i18n } from "../i18n";
|
||||||
|
|
||||||
export let entries: UpEntry[];
|
export let entries: UpEntry[];
|
||||||
export let type: UpType | undefined = undefined;
|
export let type: UpType | undefined = undefined;
|
||||||
|
@ -73,7 +74,7 @@
|
||||||
{#if type.name != "HIER"}
|
{#if type.name != "HIER"}
|
||||||
{type.label || type.name || "???"}
|
{type.label || type.name || "???"}
|
||||||
{:else}
|
{:else}
|
||||||
Members
|
{$i18n.t("Members")}
|
||||||
{/if}
|
{/if}
|
||||||
</UpLink>
|
</UpLink>
|
||||||
{:else}
|
{:else}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
import { deleteEntry, putEntityAttribute, putEntry } from "../lib/api";
|
import { deleteEntry, putEntityAttribute, putEntry } from "../lib/api";
|
||||||
import Icon from "./utils/Icon.svelte";
|
import Icon from "./utils/Icon.svelte";
|
||||||
import BlobViewer from "./display/BlobViewer.svelte";
|
import BlobViewer from "./display/BlobViewer.svelte";
|
||||||
|
import { i18n } from "../i18n";
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
|
|
||||||
|
@ -188,7 +189,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deleteObject() {
|
async function deleteObject() {
|
||||||
if (confirm(`Really delete "${identities.join(" | ")}"?`)) {
|
if (confirm(`${$i18n.t("Really delete")} "${identities.join(" | ")}"?`)) {
|
||||||
await deleteEntry(address);
|
await deleteEntry(address);
|
||||||
dispatch("close");
|
dispatch("close");
|
||||||
}
|
}
|
||||||
|
@ -230,7 +231,7 @@
|
||||||
<div class="detail-col">
|
<div class="detail-col">
|
||||||
{#if groups?.length || editable}
|
{#if groups?.length || editable}
|
||||||
<section class="groups labelborder">
|
<section class="groups labelborder">
|
||||||
<header><h3>Groups</h3></header>
|
<header><h3>{$i18n.t("Groups")}</h3></header>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
{#each groups as [entryAddress, address]}
|
{#each groups as [entryAddress, address]}
|
||||||
<div class="group">
|
<div class="group">
|
||||||
|
@ -282,7 +283,7 @@
|
||||||
|
|
||||||
{#if currentUntypedAttributes.length > 0 || editable}
|
{#if currentUntypedAttributes.length > 0 || editable}
|
||||||
<AttributeView
|
<AttributeView
|
||||||
title="Other attributes"
|
title={$i18n.t("Other attributes")}
|
||||||
{editable}
|
{editable}
|
||||||
entries={currentUntypedAttributes}
|
entries={currentUntypedAttributes}
|
||||||
on:change={onChange}
|
on:change={onChange}
|
||||||
|
@ -291,7 +292,9 @@
|
||||||
|
|
||||||
{#if currentBacklinks.length > 0}
|
{#if currentBacklinks.length > 0}
|
||||||
<AttributeView
|
<AttributeView
|
||||||
title={`Referred to (${$entity.backlinks.length})`}
|
title={`${$i18n.t("Referred to")} (${
|
||||||
|
$entity.backlinks.length
|
||||||
|
})`}
|
||||||
entries={currentBacklinks}
|
entries={currentBacklinks}
|
||||||
reverse
|
reverse
|
||||||
on:change={onChange}
|
on:change={onChange}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
import Icon from "../../utils/Icon.svelte";
|
import Icon from "../../utils/Icon.svelte";
|
||||||
import Selector from "../../utils/Selector.svelte";
|
import Selector from "../../utils/Selector.svelte";
|
||||||
import Spinner from "../../utils/Spinner.svelte";
|
import Spinner from "../../utils/Spinner.svelte";
|
||||||
|
import { i18n } from "../../../i18n";
|
||||||
|
|
||||||
export let address: string;
|
export let address: string;
|
||||||
export let detail: boolean;
|
export let detail: boolean;
|
||||||
|
@ -204,7 +205,9 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const peaksReq = await fetch(`${API_URL}/thumb/${address}?mime=audio&type=json`);
|
const peaksReq = await fetch(
|
||||||
|
`${API_URL}/thumb/${address}?mime=audio&type=json`
|
||||||
|
);
|
||||||
const peaks = await peaksReq.json();
|
const peaks = await peaksReq.json();
|
||||||
wavesurfer.load(`${API_URL}/raw/${address}`, peaks.data);
|
wavesurfer.load(`${API_URL}/raw/${address}`, peaks.data);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -213,7 +216,9 @@
|
||||||
if (
|
if (
|
||||||
(entity.get("FILE_SIZE") || 0) < 20_000_000 ||
|
(entity.get("FILE_SIZE") || 0) < 20_000_000 ||
|
||||||
confirm(
|
confirm(
|
||||||
"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?"
|
$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(
|
console.warn(
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
import { defaultEntitySort, entityValueSort } from "../../util/sort";
|
import { defaultEntitySort, entityValueSort } from "../../util/sort";
|
||||||
import { attributeLabels } from "../../util/labels";
|
import { attributeLabels } from "../../util/labels";
|
||||||
import { formatDuration } from "../../util/fragments/time";
|
import { formatDuration } from "../../util/fragments/time";
|
||||||
|
import { i18n } from "../../i18n";
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
export let columns: string | undefined = undefined;
|
export let columns: string | undefined = undefined;
|
||||||
|
@ -49,7 +50,7 @@
|
||||||
newEntryValue = undefined;
|
newEntryValue = undefined;
|
||||||
}
|
}
|
||||||
async function removeEntry(address: string) {
|
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);
|
dispatch("change", { type: "delete", address } as AttributeChange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,9 +145,9 @@
|
||||||
|
|
||||||
// Formatting & Display
|
// Formatting & Display
|
||||||
const COLUMN_LABELS: { [key: string]: string } = {
|
const COLUMN_LABELS: { [key: string]: string } = {
|
||||||
entity: "Entity",
|
entity: $i18n.t("Entity"),
|
||||||
attribute: "Attribute",
|
attribute: $i18n.t("Attribute"),
|
||||||
value: "Value",
|
value: $i18n.t("Value"),
|
||||||
};
|
};
|
||||||
|
|
||||||
function formatValue(value: string | number, attribute: string): string {
|
function formatValue(value: string | number, attribute: string): string {
|
||||||
|
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
|
@ -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";
|
import { fetchAllAttributes } from "../lib/api";
|
||||||
|
|
||||||
const DEFAULT_ATTRIBUTE_LABELS = {
|
const databaseAttributeLabels: Readable<{ [key: string]: string }> = readable(
|
||||||
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,
|
|
||||||
(set) => {
|
(set) => {
|
||||||
const result = Object.assign(DEFAULT_ATTRIBUTE_LABELS);
|
const result = {};
|
||||||
fetchAllAttributes().then((attributes) => {
|
fetchAllAttributes().then((attributes) => {
|
||||||
attributes.forEach((attribute) => {
|
attributes.forEach((attribute) => {
|
||||||
if (attribute.labels.length) {
|
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;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
import { query } from "../lib/entity";
|
import { query } from "../lib/entity";
|
||||||
import { vaultInfo } from "../util/info";
|
import { vaultInfo } from "../util/info";
|
||||||
import { updateTitle } from "../util/title";
|
import { updateTitle } from "../util/title";
|
||||||
|
import { i18n } from "../i18n";
|
||||||
|
|
||||||
const roots = (async () => {
|
const roots = (async () => {
|
||||||
const data = await fetchRoots();
|
const data = await fetchRoots();
|
||||||
|
@ -114,7 +115,7 @@
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<section class="roots">
|
<section class="roots">
|
||||||
<h2>Roots</h2>
|
<h2>{$i18n.t("Roots")}</h2>
|
||||||
{#await roots}
|
{#await roots}
|
||||||
<Spinner centered />
|
<Spinner centered />
|
||||||
{:then data}
|
{:then data}
|
||||||
|
@ -133,7 +134,7 @@
|
||||||
<div class="frecent">
|
<div class="frecent">
|
||||||
{#if frequent.length || $frequentQuery === undefined}
|
{#if frequent.length || $frequentQuery === undefined}
|
||||||
<section class="frequent">
|
<section class="frequent">
|
||||||
<h2>Frequently visited</h2>
|
<h2>{$i18n.t("Frequently visited")}</h2>
|
||||||
{#if $frequentQuery == undefined}
|
{#if $frequentQuery == undefined}
|
||||||
<Spinner centered />
|
<Spinner centered />
|
||||||
{:else}
|
{:else}
|
||||||
|
@ -147,7 +148,7 @@
|
||||||
{/if}
|
{/if}
|
||||||
{#if recent.length || $recentQuery === undefined}
|
{#if recent.length || $recentQuery === undefined}
|
||||||
<section class="recent">
|
<section class="recent">
|
||||||
<h2>Recently visited</h2>
|
<h2>{$i18n.t("Recently visited")}</h2>
|
||||||
{#if $recentQuery == undefined}
|
{#if $recentQuery == undefined}
|
||||||
<Spinner centered />
|
<Spinner centered />
|
||||||
{:else}
|
{:else}
|
||||||
|
@ -163,7 +164,7 @@
|
||||||
|
|
||||||
{#if latest.length || $latestQuery === undefined}
|
{#if latest.length || $latestQuery === undefined}
|
||||||
<section class="latest">
|
<section class="latest">
|
||||||
<h2>Most recently added</h2>
|
<h2>{$i18n.t("Most recently added")}</h2>
|
||||||
{#if $latestQuery == undefined}
|
{#if $latestQuery == undefined}
|
||||||
<Spinner centered />
|
<Spinner centered />
|
||||||
{:else}
|
{:else}
|
||||||
|
@ -177,13 +178,14 @@
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class="button store-button">
|
<div class="button store-button">
|
||||||
<Link to="/store">View store statistics</Link>
|
<Link to="/store">{$i18n.t("View store statistics")}</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
<div>
|
<div>
|
||||||
<strong>UpEnd</strong> - a database for the complex, the changing, and the
|
<strong>UpEnd</strong> - {$i18n.t(
|
||||||
indeterminate
|
"a database for the complex, the changing, and the indeterminate"
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<a target="_blank" href="https://upend.dev">
|
<a target="_blank" href="https://upend.dev">
|
||||||
|
|
|
@ -32,6 +32,15 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@babel/runtime@npm:^7.17.2":
|
||||||
|
version: 7.19.4
|
||||||
|
resolution: "@babel/runtime@npm:7.19.4"
|
||||||
|
dependencies:
|
||||||
|
regenerator-runtime: ^0.13.4
|
||||||
|
checksum: 66b7e3c13e9ee1d2c9397ea89144f29a875edee266a0eb2d9971be51b32fdbafc85808c7a45e011e6681899bb804b4e2ee2aed6dc07108dbbd6b11b6cc2afba6
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@emotion/cache@npm:^11.4.0, @emotion/cache@npm:^11.7.1":
|
"@emotion/cache@npm:^11.4.0, @emotion/cache@npm:^11.7.1":
|
||||||
version: 11.7.1
|
version: 11.7.1
|
||||||
resolution: "@emotion/cache@npm:11.7.1"
|
resolution: "@emotion/cache@npm:11.7.1"
|
||||||
|
@ -1943,6 +1952,15 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"i18next@npm:^22.0.2":
|
||||||
|
version: 22.0.2
|
||||||
|
resolution: "i18next@npm:22.0.2"
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime": ^7.17.2
|
||||||
|
checksum: d779ea7f8e35ad8fd9d38521b670dab9440c6f51eab4347800058ee311a5e55abacac7e55cb1ff9f6898b4222a5f2aac72175f0dc1faeffbf3b4b37800f8f924
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"iconv-lite@npm:^0.6.2":
|
"iconv-lite@npm:^0.6.2":
|
||||||
version: 0.6.3
|
version: 0.6.3
|
||||||
resolution: "iconv-lite@npm:0.6.3"
|
resolution: "iconv-lite@npm:0.6.3"
|
||||||
|
@ -3589,6 +3607,16 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"svelte-i18next@npm:^1.2.2":
|
||||||
|
version: 1.2.2
|
||||||
|
resolution: "svelte-i18next@npm:1.2.2"
|
||||||
|
peerDependencies:
|
||||||
|
i18next: "*"
|
||||||
|
svelte: "*"
|
||||||
|
checksum: 24f9ed0f5f796124e075b39dc65a34fbcf625bfc6a26fdab15095f4e2c7c289ba5bf3d0c48ea644544376f9d9ffc1e523626f3cac219cd804ccffdcb28dff937
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"svelte-navigator@npm:^3.1.5":
|
"svelte-navigator@npm:^3.1.5":
|
||||||
version: 3.1.5
|
version: 3.1.5
|
||||||
resolution: "svelte-navigator@npm:3.1.5"
|
resolution: "svelte-navigator@npm:3.1.5"
|
||||||
|
@ -3964,6 +3992,7 @@ __metadata:
|
||||||
eslint-plugin-svelte3: ^4.0.0
|
eslint-plugin-svelte3: ^4.0.0
|
||||||
filesize: ^8.0.6
|
filesize: ^8.0.6
|
||||||
history: ^5.1.0
|
history: ^5.1.0
|
||||||
|
i18next: ^22.0.2
|
||||||
lodash: ^4.17.21
|
lodash: ^4.17.21
|
||||||
lru-cache: ^6.0.0
|
lru-cache: ^6.0.0
|
||||||
marked: ^4.0.10
|
marked: ^4.0.10
|
||||||
|
@ -3975,6 +4004,7 @@ __metadata:
|
||||||
sswr: ^1.3.1
|
sswr: ^1.3.1
|
||||||
svelte: ^3.49.0
|
svelte: ^3.49.0
|
||||||
svelte-check: ^2.8.0
|
svelte-check: ^2.8.0
|
||||||
|
svelte-i18next: ^1.2.2
|
||||||
svelte-navigator: ^3.1.5
|
svelte-navigator: ^3.1.5
|
||||||
svelte-preprocess: ^4.10.7
|
svelte-preprocess: ^4.10.7
|
||||||
three: ^0.136.0
|
three: ^0.136.0
|
||||||
|
|
Loading…
Reference in New Issue