Draw the mockup with the screens' own words, compile every text while building, and send the language with the live updates
- The page takes the screens' words its mockup draws from their own texts: screen.ha (Home Assistant's words, filled from Home Assistant), screen.time, screen.date, screen.number and screen.tile.page, per language next to _meta and editor. The copies under editor.mockup go; the rest of `screen` and all of `addon` stay out of the build. - Numbers in the mockup follow the screens' language (screen.number, with its minimum grouping) or the chosen style, as the firmware writes them. - @intlify/unplugin-vue-i18n compiles every text at build time, so the page runs vue-i18n's runtime-only build without the message compiler; every language's _meta comes with the page. Empty texts stay out while building. - The live updates carry the editor's language (api/events?language=), as an EventSource sends no headers. - web/ needs Node 22.13 or newer: vue-i18n 11.4, Vite 7 and the unplugin ask for it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+27
-13
@@ -1,20 +1,39 @@
|
||||
import VueI18n from "@intlify/unplugin-vue-i18n/vite";
|
||||
import vue from "@vitejs/plugin-vue";
|
||||
import { readdirSync, readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { defineConfig, type Plugin } from "vite";
|
||||
import { pageTexts, TRANSLATIONS } from "./translations";
|
||||
|
||||
// Every language is one file in screen_manager/translations (app 0.2.90), shared with the firmware and the add-on. The
|
||||
// page needs only the language itself (_meta) and the editor's texts: the screens' and the add-on's texts stay out of
|
||||
// the build. Before Vite's own JSON step, so the modules it makes hold these two sections only.
|
||||
// Before vue-i18n's plugin compiles a file into the page's messages: only its page part goes in. Every language's
|
||||
// `_meta` (its name, plural rule, whether it is checked) comes with the page as virtual:esp-screens-languages, so the
|
||||
// editor knows the languages before it loads one.
|
||||
const LANGUAGES_ID = "virtual:esp-screens-languages";
|
||||
export function editorTexts(): Plugin {
|
||||
return {
|
||||
name: "esp-screens-editor-texts",
|
||||
enforce: "pre",
|
||||
resolveId: (id) => (id === LANGUAGES_ID ? `\0${LANGUAGES_ID}` : null),
|
||||
load(id) {
|
||||
if (id !== `\0${LANGUAGES_ID}`) return null;
|
||||
const languages: Record<string, unknown> = {};
|
||||
for (const name of readdirSync(TRANSLATIONS).filter((file) => file.endsWith(".json")).sort()) {
|
||||
this.addWatchFile(join(TRANSLATIONS, name));
|
||||
languages[name.slice(0, -".json".length)] = JSON.parse(readFileSync(join(TRANSLATIONS, name), "utf8"))._meta;
|
||||
}
|
||||
return `export default ${JSON.stringify(languages)};`;
|
||||
},
|
||||
transform(code, id) {
|
||||
if (!/[\\/]screen_manager[\\/]translations[\\/][^\\/?]+\.json$/.test(id)) return null;
|
||||
const { _meta, editor } = JSON.parse(code);
|
||||
return { code: JSON.stringify({ _meta, editor }), map: null };
|
||||
return { code: JSON.stringify(pageTexts(JSON.parse(code))), map: null };
|
||||
},
|
||||
};
|
||||
}
|
||||
// vue-i18n compiles every text while building (app 0.2.90), so the page runs its runtime-only build without the message
|
||||
// compiler, and no text is compiled in the browser. A text it can't read stops the build (tools/i18n.py check says so
|
||||
// first). `runtimeOnly: false` for the tests, which add texts of their own.
|
||||
export const translations = (runtimeOnly = true) =>
|
||||
VueI18n({ include: [join(TRANSLATIONS, "*.json")], runtimeOnly, compositionOnly: true, fullInstall: true, dropMessageCompiler: runtimeOnly });
|
||||
|
||||
// The add-on serves the built page from screen_manager/app/static behind Home Assistant ingress,
|
||||
// which lives on a sub path with a token. Everything is relative so the page works there and on
|
||||
@@ -22,14 +41,9 @@ export function editorTexts(): Plugin {
|
||||
// files change. `npm run dev` proxies /api to a running server (the demo home or SCREEN_DEV).
|
||||
export default defineConfig({
|
||||
base: "./",
|
||||
plugins: [editorTexts(), vue()],
|
||||
// vue-i18n's switches (app 0.2.90): the Composition API only, texts compiled in the page, no devtools in the build.
|
||||
define: {
|
||||
__VUE_I18N_FULL_INSTALL__: true,
|
||||
__VUE_I18N_LEGACY_API__: false,
|
||||
__INTLIFY_PROD_DEVTOOLS__: false,
|
||||
__INTLIFY_DROP_MESSAGE_COMPILER__: false,
|
||||
},
|
||||
plugins: [editorTexts(), translations(), vue()],
|
||||
// No vue-i18n devtools in the build; its other switches come from the plugin above.
|
||||
define: { __INTLIFY_PROD_DEVTOOLS__: false },
|
||||
build: {
|
||||
outDir: "../screen_manager/app/static",
|
||||
emptyOutDir: false,
|
||||
|
||||
Reference in New Issue
Block a user