From 2a4e4effa5aae7d706a5082577e894270c075488 Mon Sep 17 00:00:00 2001 From: Roger Veciana Date: Sun, 21 Jan 2024 20:26:18 +0100 Subject: [PATCH] Update i18n and add svelte-i18next package --- .eslintrc | 4 +--- package-lock.json | 55 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + src/lang/i18n.ts | 24 ++++++++++++++++++++ src/starterIndex.ts | 46 +++++++++++++++++++------------------ src/ui/View.svelte | 17 +++++--------- src/ui/utils.ts | 2 +- 7 files changed, 112 insertions(+), 37 deletions(-) create mode 100644 src/lang/i18n.ts diff --git a/.eslintrc b/.eslintrc index 7d2dc27..48c3454 100644 --- a/.eslintrc +++ b/.eslintrc @@ -7,9 +7,7 @@ "eslint:recommended", "plugin:@typescript-eslint/eslint-recommended", "plugin:@typescript-eslint/recommended", - "plugin:svelte/recommended", - "prettier" - ], + "plugin:svelte/recommended" ], "parserOptions": { "sourceType": "module", "ecmaVersion": 2020, diff --git a/package-lock.json b/package-lock.json index 1ef208d..575712f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "obsidian": "0.15.9", "svelte": "^3.49.0", "svelte-check": "^2.8.0", + "svelte-i18next": "^2.2.2", "svelte-preprocess": "^5.1.3", "tslib": "2.4.0", "typescript": "5.3.3", @@ -36,6 +37,19 @@ "node": ">=0.10.0" } }, + "node_modules/@babel/runtime": { + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.8.tgz", + "integrity": "sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==", + "dev": true, + "peer": true, + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@codemirror/state": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.0.tgz", @@ -1677,6 +1691,30 @@ "node": ">=8" } }, + "node_modules/i18next": { + "version": "23.7.18", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.7.18.tgz", + "integrity": "sha512-b9N2KjRCYQNlUvE1Kc83g8knyUkL5NiZQOp9BsTR/v/LXk6Fzz+doOzTg2/826XK28mCgBkYLNAtixjE58qpCw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "peer": true, + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, "node_modules/ignore": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", @@ -2333,6 +2371,13 @@ "node": ">=8.10.0" } }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true, + "peer": true + }, "node_modules/resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -2791,6 +2836,16 @@ "svelte": ">=3.19.0" } }, + "node_modules/svelte-i18next": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/svelte-i18next/-/svelte-i18next-2.2.2.tgz", + "integrity": "sha512-IpJDZCH5cCgKfHQHgiLmGT4j9HCdg4fqsP3oP2deLu8PxmNj0Ui6khMiDoxAxedAiYEhr0xendv2xqh3Rq+uQQ==", + "dev": true, + "peerDependencies": { + "i18next": "*", + "svelte": "*" + } + }, "node_modules/svelte-preprocess": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-5.1.3.tgz", diff --git a/package.json b/package.json index ef054a8..29bd008 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "obsidian": "0.15.9", "svelte": "^3.49.0", "svelte-check": "^2.8.0", + "svelte-i18next": "^2.2.2", "svelte-preprocess": "^5.1.3", "tslib": "2.4.0", "typescript": "5.3.3", diff --git a/src/lang/i18n.ts b/src/lang/i18n.ts new file mode 100644 index 0000000..66c67a2 --- /dev/null +++ b/src/lang/i18n.ts @@ -0,0 +1,24 @@ +import i18next from "i18next"; +import { createI18nStore } from "svelte-i18next"; + +i18next.init({ + lng: 'en', + fallbackLng: 'en', + resources: { + en: { + translation: { + "empty": "Empty recipe. Edit it using the pencil icon.", + "method": "Method", + "ingredients": "Ingredients", + "cookware": "Cookware", + "step": "Step", + } + } + }, + interpolation: { + escapeValue: false, // not needed for svelte as it escapes by default + } +}); + +export const i18n = createI18nStore(i18next); +export default i18n; \ No newline at end of file diff --git a/src/starterIndex.ts b/src/starterIndex.ts index 3548eac..081351d 100644 --- a/src/starterIndex.ts +++ b/src/starterIndex.ts @@ -2,14 +2,17 @@ import { App, Plugin, PluginSettingTab, + TFile, TextFileView, WorkspaceLeaf, setIcon, } from "obsidian"; import { DEFAULT_SETTINGS, type CookLangSettings } from "./settings"; + import Edit from "./ui/Edit.svelte"; import View from "./ui/View.svelte"; +import { isTFile } from "./ui/utils"; const VIEW_TYPE = "svelte-view"; @@ -63,27 +66,26 @@ class CooklangSvelteView extends TextFileView { return this.data; } setViewData(data: string): void { - // const images = ( - // this.file.parent.children.filter( - // (f) => - // isTFile(f) && - // (f.basename === this.file.basename || - // f.basename.startsWith(this.file.basename + ".")) && - // f.name != this.file.name && - // ["png", "jpg", "jpeg", "gif"].includes(f.extension) - // ) as TFile[] - // ).reduce((acc, f) => { - // const split = f.basename.split("."); - // if (split.length > 1) { - // const name = split[1]; - // acc[name] = this.app.vault.getResourcePath(f); - // } else { - // acc["recipe"] = this.app.vault.getResourcePath(f); - // } - // return acc; - // }, {} as Record); - // this.images = images; - const images = {}; + + const images = ( + this.file.parent.children.filter( + (f) => isTFile(f) && + (f.basename === this.file.basename || + f.basename.startsWith(this.file.basename + ".")) && + f.name != this.file.name && + ["png", "jpg", "jpeg", "gif"].includes(f.extension) + ) as TFile[] + ).reduce((acc, f) => { + const split = f.basename.split("."); + if (split.length > 1) { + const name = split[1]; + acc[name] = this.app.vault.getResourcePath(f); + } else { + acc["recipe"] = this.app.vault.getResourcePath(f); + } + return acc; + }, {} as Record); + this.images = images; this.data = data; this.view.$set({ data, images }); @@ -110,7 +112,7 @@ class CooklangSvelteView extends TextFileView { target: this.contentEl, props: { data: this.data, - onChange: (newData) => (this.data = newData), + onChange: (newData:string) => (this.data = newData), }, }); } diff --git a/src/ui/View.svelte b/src/ui/View.svelte index e68817d..2dbdc57 100644 --- a/src/ui/View.svelte +++ b/src/ui/View.svelte @@ -1,23 +1,18 @@
{#if data.length === 0} -

Empty recipe. Edit it using the pencil icon.

+

{$i18n.t('empty')}

{:else} @@ -26,7 +21,7 @@ {/if} {#if recipe.ingredients.length > 0}
-

Ingredients:

+

{$i18n.t('ingredients')}

    {#each recipe.ingredients as ingredient}
  • {ingredient.quantity} {ingredient.units} {ingredient.name}
  • @@ -36,7 +31,7 @@ {/if} {#if recipe.cookwares.length > 0}
    -

    Cookware:

    +

    {$i18n.t('cookware')}

      {#each recipe.cookwares as cookware}
    • {cookware.name}
    • @@ -44,11 +39,11 @@
    {/if} -

    Method:

    +

    {$i18n.t('method')}:

    {#each recipe.steps as step, i} -

    Step {i+1}

    +

    {$i18n.t('step')} {i+1}

    {#if images[i]} Final result {/if} diff --git a/src/ui/utils.ts b/src/ui/utils.ts index 662c228..7db3c2e 100644 --- a/src/ui/utils.ts +++ b/src/ui/utils.ts @@ -23,5 +23,5 @@ export const isTimer = ( }; export const isTFile = (file: TAbstractFile): file is TFile => { - return (file as TFile).path !== undefined; + return (file as TFile).basename !== undefined; };