From 84e2121f1aa2e8a9c85df1fd3fb95660913a427b Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sun, 7 Jun 2026 05:44:32 +0000 Subject: [PATCH 1/7] Import LocalizedComponent from @inventreedb/ui --- .../frontend/src/Panel.tsx | 2 +- .../frontend/src/locale.tsx | 89 ------------------- 2 files changed, 1 insertion(+), 90 deletions(-) delete mode 100644 plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/locale.tsx diff --git a/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/Panel.tsx b/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/Panel.tsx index 32815a6..b1b10ea 100644 --- a/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/Panel.tsx +++ b/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/Panel.tsx @@ -8,7 +8,7 @@ import { useQuery } from '@tanstack/react-query'; {% if cookiecutter.frontend.translation -%} import { t } from '@lingui/core/macro'; -import { LocalizedComponent } from './locale'; +import { LocalizedComponent } from '@inventreedb/ui'; {%- endif %} // Import for type checking diff --git a/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/locale.tsx b/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/locale.tsx deleted file mode 100644 index bd130d1..0000000 --- a/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/locale.tsx +++ /dev/null @@ -1,89 +0,0 @@ - -import { i18n } from '@lingui/core'; -import { Skeleton } from '@mantine/core'; -import { useEffect, useState } from 'react'; -import { I18nProvider } from '@lingui/react'; - - -/** - * Attempt to load the locale file for the given locale, returning null if it fails - */ -async function tryLoadLocale(locale: string): Promise { - try { - const messages = await import(`./locales/${locale}/messages.ts`); - return messages; - } catch (error) { - console.warn(`Failed to load locale ${locale}`); - return null; - } -} - - -/** - * Helper function to dynamically load frontend translations, - * based on the provided locale. - */ -async function loadPluginLocale(locale: string) { - - let messages = null; - - // Find the most specific locale file possible, with fallbacks to less specific locales if necessary - messages = await tryLoadLocale(locale); - - if (!messages && locale.includes('-')) { - const fallbackLocale = locale.split('-')[0]; - console.debug(`Locale ${locale} not found, trying fallback locale ${fallbackLocale}`); - messages = await tryLoadLocale(fallbackLocale); - } - - if (!messages && locale.includes('_')) { - const fallbackLocale = locale.split('_')[0]; - console.debug(`Locale ${locale} not found, trying fallback locale ${fallbackLocale}`); - messages = await tryLoadLocale(fallbackLocale); - } - - if (!messages && locale !== 'en') { - console.debug(`Locale ${locale} not found, trying fallback locale en`); - messages = await tryLoadLocale('en'); - } - - if (messages?.messages) { - i18n.load(locale, messages.messages); - i18n.activate(locale); - } else { - console.error(`Failed to load any locale for ${locale}`); - } -} - - -// Wrapper component for loading dynamic translations -export function LocalizedComponent({ - locale, - children -}: { - locale: string, - children: React.ReactNode -}) { - - const [loaded, setLoaded] = useState(false); - - // Reload componentwhen the locale changes - useEffect(() => { - setLoaded(false); - loadPluginLocale(locale).then(() => { - setLoaded(true); - }); - }, [locale]); - - if (!loaded) { - return ( - - ); - } - - return ( - - {children} - - ); -} From c9089b9ffdf5abf4b10a5bfa851053b0f90c5997 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sun, 7 Jun 2026 05:45:25 +0000 Subject: [PATCH 2/7] Offload HMR plugin --- .../frontend/vite.dev.config.ts | 38 +------------------ 1 file changed, 2 insertions(+), 36 deletions(-) diff --git a/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/vite.dev.config.ts b/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/vite.dev.config.ts index 67338aa..31311fc 100644 --- a/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/vite.dev.config.ts +++ b/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/vite.dev.config.ts @@ -2,47 +2,13 @@ import { defineConfig } from 'vite' import { viteExternalsPlugin } from 'vite-plugin-externals' import viteConfig, { externalLibs } from './vite.config' +import { InventreeHmrPlugin } from '@inventreedb/ui'; {% if cookiecutter.frontend.translation -%} import react from "@vitejs/plugin-react-swc" import { lingui } from "@lingui/vite-plugin" {%- endif %} -import type { Plugin } from 'vite' - -// Enable HMR support for this plugin by hooking into the InvenTree vite dev server -function inventreeHmrPlugin(): Plugin { - const fileRegex = /\.(js|jsx|ts|tsx)(\?|$)/; - - const hmrBlock = [ - '', - '// __inventree_hmr_injected__', - 'if (import.meta.hot) {', - ' import.meta.hot.accept((newModule) => {', - ' const key = new URL(import.meta.url).origin + new URL(import.meta.url).pathname;', - ' window.__plugin_hmr_callbacks?.[key]?.forEach(callback => {', - ' callback(newModule);', - ' });', - ' })', - '}', - ]; - - return { - name: 'inventree-hmr-plugin', - enforce: 'post', - - transform(code, id) { - if (!fileRegex.test(id)) return; - if (id.includes('node_modules')) return; - if (code.includes('__inventree_hmr_injected__')) return; - - return { - code: code + hmrBlock.join('\n'), - map: null, - } - } - } -} /** * Vite config to run the frontend plugin in development mode. @@ -81,7 +47,7 @@ export default defineConfig((cfg) => { }), {%- endif %} viteExternalsPlugin(externalLibs), - inventreeHmrPlugin(), + InventreeHmrPlugin(), ]; return config; From 7f65fd917f0c252564633b8b4ad97637e28ffae4 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sun, 7 Jun 2026 06:38:35 +0000 Subject: [PATCH 3/7] Fix for imports --- .../{{ cookiecutter.plugin_name }}/frontend/src/Panel.tsx | 2 +- .../{{ cookiecutter.plugin_name }}/frontend/vite.dev.config.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/Panel.tsx b/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/Panel.tsx index b1b10ea..cdf02cf 100644 --- a/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/Panel.tsx +++ b/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/Panel.tsx @@ -254,7 +254,7 @@ export function Render{{ cookiecutter.plugin_name }}Panel(context: InvenTreePlug {% if cookiecutter.frontend.translation -%} return ( - + <{{ cookiecutter.plugin_name }}Panel context={context} /> ); diff --git a/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/vite.dev.config.ts b/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/vite.dev.config.ts index 31311fc..eefaae6 100644 --- a/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/vite.dev.config.ts +++ b/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/vite.dev.config.ts @@ -2,7 +2,7 @@ import { defineConfig } from 'vite' import { viteExternalsPlugin } from 'vite-plugin-externals' import viteConfig, { externalLibs } from './vite.config' -import { InventreeHmrPlugin } from '@inventreedb/ui'; +import InventreeHmrPlugin from '@inventreedb/ui/vite'; {% if cookiecutter.frontend.translation -%} import react from "@vitejs/plugin-react-swc" From 0259afddf13182ae07337918e033d0c463860c03 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sun, 7 Jun 2026 06:41:12 +0000 Subject: [PATCH 4/7] Better layout --- .../{{ cookiecutter.plugin_name }}/frontend/src/Panel.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/Panel.tsx b/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/Panel.tsx index cdf02cf..80ba173 100644 --- a/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/Panel.tsx +++ b/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/Panel.tsx @@ -161,18 +161,22 @@ function {{ cookiecutter.plugin_name }}Panel({ {%- endif %} - + + {partId && } + + Counter: {counter} + {instance ? ( {instance} From 43f9f57cbb672ba929f6efd8c7d5f3385f1dbcf4 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sun, 7 Jun 2026 12:57:41 +0000 Subject: [PATCH 5/7] Generate callback for loading locales - Needs to be defined within the plugin code --- .../{{ cookiecutter.plugin_name }}/frontend/src/Panel.tsx | 3 ++- .../{{ cookiecutter.plugin_name }}/frontend/src/locales.tsx | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/locales.tsx diff --git a/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/Panel.tsx b/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/Panel.tsx index 80ba173..879700f 100644 --- a/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/Panel.tsx +++ b/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/Panel.tsx @@ -9,6 +9,7 @@ import { useQuery } from '@tanstack/react-query'; {% if cookiecutter.frontend.translation -%} import { t } from '@lingui/core/macro'; import { LocalizedComponent } from '@inventreedb/ui'; +import { loadLocale } from './locales'; {%- endif %} // Import for type checking @@ -258,7 +259,7 @@ export function Render{{ cookiecutter.plugin_name }}Panel(context: InvenTreePlug {% if cookiecutter.frontend.translation -%} return ( - + <{{ cookiecutter.plugin_name }}Panel context={context} /> ); diff --git a/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/locales.tsx b/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/locales.tsx new file mode 100644 index 0000000..381910b --- /dev/null +++ b/plugin_creator/template/{{ cookiecutter.plugin_name }}/frontend/src/locales.tsx @@ -0,0 +1,4 @@ +import { type LocaleLoader } from '@inventreedb/ui'; + +// Necessary callback function to dynamically load the locale messages for the plugin +export const loadLocale: LocaleLoader = async (locale: string) => import(`./locales/${locale}/messages.ts`).catch(() => null); From 413ab4eeea3139cdd98dd64a49c079d995a9ab8e Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sun, 7 Jun 2026 13:21:42 +0000 Subject: [PATCH 6/7] Fix cleanup --- plugin_creator/frontend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin_creator/frontend.py b/plugin_creator/frontend.py index b5ce5af..53ef99c 100644 --- a/plugin_creator/frontend.py +++ b/plugin_creator/frontend.py @@ -114,7 +114,7 @@ def update_frontend(plugin_dir: str, context: dict) -> None: if not translation: remove_dir(plugin_dir, "frontend", "src", "locales") remove_file(plugin_dir, "frontend", "src", "locales.tsx") - remove_file(plugin_dir, "frontend", ".linguirc") + remove_file(plugin_dir, "frontend", "lingui.config.ts") # Remove the translation check from the CI configuration remove_file(plugin_dir, ".github", "workflows", "translations.yaml") From 096c45252227cb20289420e149d8a38e38ccc958 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sun, 7 Jun 2026 13:22:40 +0000 Subject: [PATCH 7/7] Better comment --- plugin_creator/frontend.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugin_creator/frontend.py b/plugin_creator/frontend.py index 53ef99c..122a215 100644 --- a/plugin_creator/frontend.py +++ b/plugin_creator/frontend.py @@ -112,6 +112,7 @@ def update_frontend(plugin_dir: str, context: dict) -> None: remove_file(plugin_dir, "frontend", "src", f"{feature.capitalize()}.tsx") if not translation: + # Remove translation files and configuration from the frontend code remove_dir(plugin_dir, "frontend", "src", "locales") remove_file(plugin_dir, "frontend", "src", "locales.tsx") remove_file(plugin_dir, "frontend", "lingui.config.ts")