diff --git a/static/js/my-editor.js b/static/js/my-editor.js index a81eabb..c146ae7 100644 --- a/static/js/my-editor.js +++ b/static/js/my-editor.js @@ -666,6 +666,131 @@ console.log("[my-editor] Vvveb.NewSection.insert patched to prevent layout crashes."); } + // ── 動態中文化 VvvebJS 元件與區塊 ───────────────────────────────── + function patchI18n() { + if (typeof Vvveb === "undefined" || !Vvveb.ComponentsGroup || Object.keys(Vvveb.ComponentsGroup).length === 0) { + setTimeout(patchI18n, 500); + return; + } + + const translateMap = { + // 分類 (Groups) + "Grid": "網格系統", + "Components": "基礎元件", + "Basic": "基本", + "Typography": "排版", + "Media": "媒體", + "Forms": "表單", + "Widgets": "小工具", + "Advanced": "進階", + "Content": "內容區塊", + "Layout": "佈局", + "Blocks": "區塊", + "Features": "功能特色", + "Headers": "頁首", + "Footers": "頁尾", + "Pricing": "價格表", + "Testimonials": "客戶評價", + "Cards": "卡片", + "Services": "服務", + "Team": "團隊", + "About": "關於我們", + + // 元件 (Components) + "Grid Row": "網格列 (Row)", + "Grid Column": "網格欄 (Column)", + "Container": "容器 (Container)", + "Heading": "標題 (Heading)", + "Link": "超連結 (Link)", + "Image": "圖片 (Image)", + "Video": "影片 (Video)", + "Paragraph": "段落文字", + "List": "列表", + "List item": "列表項目", + "Button": "按鈕", + "Button Group": "按鈕群組", + "Button Toolbar": "按鈕工具列", + "Form": "表單", + "Text Input": "文字輸入框", + "Textarea": "多行文字框", + "Checkbox": "核取方塊", + "Radio": "單選按鈕", + "Select": "下拉選單", + "Label": "標籤文字", + "Alert": "警告提示", + "Badge": "徽章 (Badge)", + "Card": "卡片 (Card)", + "Table": "表格", + "Progress": "進度條", + "Navbar": "導覽列 (Navbar)", + "Breadcrumb": "麵包屑 (Breadcrumb)", + "Pagination": "分頁", + "Jumbotron": "大型看板", + "Panel": "面板", + "Icon": "圖示", + "Divider": "分隔線", + "Map": "地圖", + "Audio": "音訊", + "File Upload": "檔案上傳", + "Date Input": "日期輸入框", + "Password Input": "密碼輸入框", + "Email Input": "Email 輸入框" + }; + + // 1. 翻譯 Vvveb 物件內的資料 (供重新渲染時使用) + if (Vvveb.ComponentsGroup) { + const newGroups = {}; + for (let group in Vvveb.ComponentsGroup) { + let tGroup = translateMap[group] || group; + newGroups[tGroup] = Vvveb.ComponentsGroup[group]; + + newGroups[tGroup].forEach(compName => { + let comp = Vvveb.Components.get(compName); + if (comp && comp.name) { + comp.name = translateMap[comp.name] || comp.name; + } + }); + } + Vvveb.ComponentsGroup = newGroups; + } + + if (Vvveb.BlocksGroup) { + const newBlockGroups = {}; + for (let group in Vvveb.BlocksGroup) { + let tGroup = translateMap[group] || group; + newBlockGroups[tGroup] = Vvveb.BlocksGroup[group]; + } + Vvveb.BlocksGroup = newBlockGroups; + } + + // 2. 直接修改當前已渲染的 DOM 文字 + document.querySelectorAll(".components-list .header span, .blocks-list .header span, .sections-list .header span").forEach(el => { + const txt = el.textContent.trim(); + if (translateMap[txt]) { + el.textContent = translateMap[txt]; + } + }); + + document.querySelectorAll(".components-list li .name, .blocks-list li .name, .sections-list li .name").forEach(el => { + const txt = el.textContent.trim(); + if (translateMap[txt]) { + // 如果有子元素,只替換文本節點 + if (el.childNodes.length > 0) { + for (let i = 0; i < el.childNodes.length; i++) { + if (el.childNodes[i].nodeType === 3 && el.childNodes[i].textContent.trim() === txt) { + el.childNodes[i].textContent = translateMap[txt]; + break; + } + } + } else { + el.textContent = translateMap[txt]; + } + } + }); + + console.log("[my-editor] VvvebJS components and blocks localized."); + } + // ── 啟用 Save 按鈕(vvvebjs 預設 disabled)────────────────────── function enableSaveBtn() { const btn = document.querySelector(".save-btn"); @@ -698,12 +823,14 @@ patchSaveAjax(); patchFileManager(); patchNewSection(); + patchI18n(); enableSaveBtn(); }); } else { patchSaveAjax(); patchFileManager(); patchNewSection(); + patchI18n(); enableSaveBtn(); } })(); diff --git a/templates/editor.html b/templates/editor.html index eb3f4ea..880e2d1 100644 --- a/templates/editor.html +++ b/templates/editor.html @@ -21,23 +21,24 @@
-Page was successfully saved!.
+頁面已成功儲存!