mirror of https://github.com/VERT-sh/VERT.git
initial localization support
This commit is contained in:
parent
c04507d1ee
commit
359c9a1e0d
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { language } from "$lib/store/language";
|
||||||
|
import { derived } from "svelte/store";
|
||||||
|
import translations from "./translations";
|
||||||
|
import type { Dictionary, Locales } from "$lib/types/locales";
|
||||||
|
|
||||||
|
export const locales = Object.keys(translations);
|
||||||
|
|
||||||
|
function translate(locale: Locales, key: Dictionary, vars: any) {
|
||||||
|
if (!key) throw new Error("no key provided to $t()");
|
||||||
|
if (!locale) throw new Error(`no translation for key "${key}"`);
|
||||||
|
|
||||||
|
let text = translations[locale][key];
|
||||||
|
|
||||||
|
if (!text) throw new Error(`no translation found for ${locale}.${key}`);
|
||||||
|
|
||||||
|
Object.keys(vars).map((k) => {
|
||||||
|
text = text.replaceAll(`{{${k}}}`, vars[k]);
|
||||||
|
});
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const t = derived(language, ($locale) => (key: Dictionary, vars = {}) =>
|
||||||
|
translate($locale, key, vars)
|
||||||
|
);
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export * from "./i18n";
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
import type { Dictionary, Locales } from "$lib/types/locales";
|
||||||
|
import en from "./translations/en";
|
||||||
|
import it from "./translations/it";
|
||||||
|
|
||||||
|
|
||||||
|
const translation: Record<Locales, Record<Dictionary, string>> = {
|
||||||
|
en: en,
|
||||||
|
it: it
|
||||||
|
}
|
||||||
|
|
||||||
|
export default translation;
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
import type { Dictionary } from "$lib/types/locales";
|
||||||
|
|
||||||
|
const en: Record<Dictionary, string> = {
|
||||||
|
'settings.languageTitle': 'Language',
|
||||||
|
'settings.chooseLanguage': 'Choose Language'
|
||||||
|
}
|
||||||
|
|
||||||
|
export default en;
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
import type { Dictionary } from "$lib/types/locales";
|
||||||
|
|
||||||
|
const it: Record<Dictionary, string> = {
|
||||||
|
'settings.languageTitle': 'Lingua',
|
||||||
|
'settings.chooseLanguage': 'Scegli Lingua'
|
||||||
|
}
|
||||||
|
export default it;
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import Dropdown from "$lib/components/functional/Dropdown.svelte";
|
||||||
|
import Panel from "$lib/components/visual/Panel.svelte";
|
||||||
|
import { language, setLanguage } from "$lib/store/language";
|
||||||
|
import { LanguagesIcon } from "lucide-svelte";
|
||||||
|
import { type Locales } from "$lib/types/locales";
|
||||||
|
import { t } from "$lib/locales";
|
||||||
|
|
||||||
|
export const supportedLanguages = {
|
||||||
|
en: "English",
|
||||||
|
it: "Italiano",
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSelect = (option: string) => {
|
||||||
|
console.log(option);
|
||||||
|
const lang = Object.keys(supportedLanguages)[
|
||||||
|
Object.values(supportedLanguages).findIndex(
|
||||||
|
(value) => value === option,
|
||||||
|
)
|
||||||
|
] as Locales;
|
||||||
|
if (lang) setLanguage(lang);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Panel class="flex flex-col gap-8 p-6">
|
||||||
|
<div class="flex flex-col gap-3">
|
||||||
|
<h2 class="text-2xl font-bold">
|
||||||
|
<LanguagesIcon
|
||||||
|
size="40"
|
||||||
|
class="inline-block -mt-1 mr-2 bg-accent-purple p-2 rounded-full"
|
||||||
|
color="black"
|
||||||
|
/>
|
||||||
|
{$t("settings.languageTitle")}
|
||||||
|
</h2>
|
||||||
|
<div class="flex flex-col gap-8">
|
||||||
|
<div class="flex flex-col gap-4">
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
<p class="text-base font-bold">
|
||||||
|
{$t("settings.chooseLanguage")}
|
||||||
|
</p>
|
||||||
|
<p class="text-sm text-muted font-normal italic"></p>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col gap-3 w-full">
|
||||||
|
<Dropdown
|
||||||
|
options={Object.values(supportedLanguages)}
|
||||||
|
onselect={(option) => handleSelect(option)}
|
||||||
|
selected={(()=>supportedLanguages[$language])()}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Panel>
|
||||||
|
|
@ -5,6 +5,7 @@ export { default as Appearance } from "./Appearance.svelte";
|
||||||
export { default as Conversion } from "./Conversion.svelte";
|
export { default as Conversion } from "./Conversion.svelte";
|
||||||
export { default as Vertd } from "./Vertd.svelte";
|
export { default as Vertd } from "./Vertd.svelte";
|
||||||
export { default as Privacy } from "./Privacy.svelte";
|
export { default as Privacy } from "./Privacy.svelte";
|
||||||
|
export { default as Language } from "./Language.svelte";
|
||||||
|
|
||||||
export interface ISettings {
|
export interface ISettings {
|
||||||
filenameFormat: string;
|
filenameFormat: string;
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@ import { converters } from "$lib/converters";
|
||||||
import { error, log } from "$lib/logger";
|
import { error, log } from "$lib/logger";
|
||||||
import { VertFile } from "$lib/types";
|
import { VertFile } from "$lib/types";
|
||||||
import { parseBlob, selectCover } from "music-metadata";
|
import { parseBlob, selectCover } from "music-metadata";
|
||||||
|
import PQueue from "p-queue";
|
||||||
import { writable } from "svelte/store";
|
import { writable } from "svelte/store";
|
||||||
import { addDialog } from "./DialogProvider";
|
import { addDialog } from "./DialogProvider";
|
||||||
import PQueue from "p-queue";
|
|
||||||
|
|
||||||
class Files {
|
class Files {
|
||||||
public files = $state<VertFile[]>([]);
|
public files = $state<VertFile[]>([]);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { log } from "$lib/logger";
|
||||||
|
import type { Locales } from "$lib/types/locales";
|
||||||
|
import { writable } from "svelte/store";
|
||||||
|
|
||||||
|
export const language = writable<Locales>("en");
|
||||||
|
export function setLanguage(locale: Locales) {
|
||||||
|
localStorage.setItem("language", locale);
|
||||||
|
log(["language"], `set to ${locale}`);
|
||||||
|
document.documentElement.lang = locale;
|
||||||
|
language.set(locale);
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
export * from "./file.svelte";
|
export * from "./file.svelte";
|
||||||
export * from "./util";
|
export * from "./util";
|
||||||
export * from "./conversion-worker";
|
export * from "./conversion-worker";
|
||||||
|
export * from "./locales";
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
export type Locales = 'en' | 'it';
|
||||||
|
export type Dictionary = 'settings.languageTitle' | 'settings.chooseLanguage';
|
||||||
|
|
@ -16,9 +16,11 @@
|
||||||
dropping,
|
dropping,
|
||||||
vertdLoaded,
|
vertdLoaded,
|
||||||
} from "$lib/store/index.svelte";
|
} from "$lib/store/index.svelte";
|
||||||
|
import { language } from "$lib/store/language";
|
||||||
import "$lib/css/app.scss";
|
import "$lib/css/app.scss";
|
||||||
import { browser } from "$app/environment";
|
import { browser } from "$app/environment";
|
||||||
import { page } from "$app/state";
|
import { page } from "$app/state";
|
||||||
|
import type { Locales } from "$lib/types/locales.js";
|
||||||
|
|
||||||
let { children, data } = $props();
|
let { children, data } = $props();
|
||||||
let enablePlausible = $state(false);
|
let enablePlausible = $state(false);
|
||||||
|
|
@ -66,6 +68,8 @@
|
||||||
(localStorage.getItem("theme") as "light" | "dark") || "light",
|
(localStorage.getItem("theme") as "light" | "dark") || "light",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
language.set((localStorage.getItem("language") as Locales) || "en");
|
||||||
|
|
||||||
Settings.instance.load();
|
Settings.instance.load();
|
||||||
|
|
||||||
fetch(`${Settings.instance.settings.vertdURL}/api/version`).then(
|
fetch(`${Settings.instance.settings.vertdURL}/api/version`).then(
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col gap-4 flex-1">
|
<div class="flex flex-col gap-4 flex-1">
|
||||||
|
<Settings.Language />
|
||||||
<Settings.Appearance />
|
<Settings.Appearance />
|
||||||
{#if PUB_PLAUSIBLE_URL}
|
{#if PUB_PLAUSIBLE_URL}
|
||||||
<Settings.Privacy {settings} />
|
<Settings.Privacy {settings} />
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue