2025-12-20 12:34:49 +08:00
"""
title : Smart Mind Map
2025-12-31 02:00:10 +08:00
author : Fu - Jie
2026-02-13 03:31:06 +00:00
author_url : https : / / github . com / Fu - Jie / openwebui - extensions
2026-01-15 00:24:52 +08:00
funding_url : https : / / github . com / open - webui
2026-02-21 17:50:44 +08:00
version : 1.0 .0
2026-01-08 00:16:56 +08:00
openwebui_id : 3094 c59a - b4dd - 4e0 c - 9449 - 15e2 dd547dc4
2025-12-30 02:28:46 +00:00
icon_url : data : image / svg + xml ; base64 , PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxyZWN0IHg9IjE2IiB5PSIxNiIgd2lkdGg9IjYiIGhlaWdodD0iNiIgcng9IjEiLz48cmVjdCB4PSIyIiB5PSIxNiIgd2lkdGg9IjYiIGhlaWdodD0iNiIgcng9IjEiLz48cmVjdCB4PSI5IiB5PSIyIiB3aWR0aD0iNiIgaGVpZ2h0PSI2IiByeD0iMSIvPjxwYXRoIGQ9Ik01IDE2di0zYTEgMSAwIDAgMSAxLTFoMTJhMSAxIDAgMCAxIDEgMXYzIi8 + PHBhdGggZD0iTTEyIDEyVjgiLz48L3N2Zz4 =
2025-12-31 02:00:10 +08:00
description : Intelligently analyzes text content and generates interactive mind maps to help users structure and visualize knowledge .
2025-12-20 12:34:49 +08:00
"""
2026-02-23 02:33:59 +08:00
import asyncio
2025-12-20 12:34:49 +08:00
import logging
2025-12-31 02:00:10 +08:00
import os
2025-12-20 12:34:49 +08:00
import re
2025-12-31 02:00:10 +08:00
import time
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
import json
2025-12-31 02:00:10 +08:00
from datetime import datetime , timezone
2026-01-06 19:26:43 +08:00
from typing import Any , Callable , Awaitable , Dict , Optional
2025-12-31 02:00:10 +08:00
from zoneinfo import ZoneInfo
2025-12-20 12:34:49 +08:00
from fastapi import Request
2025-12-31 02:00:10 +08:00
from pydantic import BaseModel , Field
2025-12-20 12:34:49 +08:00
from open_webui . utils . chat import generate_chat_completion
from open_webui . models . users import Users
2026-02-21 17:50:44 +08:00
try :
from open_webui . env import VERSION as open_webui_version
except ImportError :
open_webui_version = " 0.0.0 "
2025-12-20 12:34:49 +08:00
logging . basicConfig (
level = logging . INFO , format = " %(asctime)s - %(name)s - %(levelname)s - %(message)s "
)
logger = logging . getLogger ( __name__ )
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
TRANSLATIONS = {
" en-US " : {
" status_starting " : " Smart Mind Map is starting, generating mind map for you... " ,
" error_no_content " : " Unable to retrieve valid user message content. " ,
" error_text_too_short " : " Text content is too short ( {len} characters), unable to perform effective analysis. Please provide at least {min_len} characters of text. " ,
" status_analyzing " : " Smart Mind Map: Analyzing text structure in depth... " ,
" status_drawing " : " Smart Mind Map: Drawing completed! " ,
" notification_success " : " Mind map has been generated, {user_name} ! " ,
" error_processing " : " Smart Mind Map processing failed: {error} " ,
" error_user_facing " : " Sorry, Smart Mind Map encountered an error during processing: {error} . \n Please check the Open WebUI backend logs for more details. " ,
" status_failed " : " Smart Mind Map: Processing failed. " ,
" notification_failed " : " Smart Mind Map generation failed, {user_name} ! " ,
" status_rendering_image " : " Smart Mind Map: Rendering image... " ,
" status_image_generated " : " Smart Mind Map: Image generated! " ,
" notification_image_success " : " Mind map image has been generated, {user_name} ! " ,
" ui_title " : " 🧠 Smart Mind Map " ,
" ui_user " : " User: " ,
" ui_time " : " Time: " ,
" ui_download_png " : " PNG " ,
" ui_download_svg " : " SVG " ,
" ui_download_md " : " Markdown " ,
" ui_zoom_out " : " - " ,
" ui_zoom_reset " : " Reset " ,
" ui_zoom_in " : " + " ,
" ui_depth_select " : " Expand Level " ,
" ui_depth_all " : " Expand All " ,
" ui_depth_2 " : " Level 2 " ,
" ui_depth_3 " : " Level 3 " ,
" ui_fullscreen " : " Fullscreen " ,
" ui_theme " : " Theme " ,
2026-02-21 17:50:44 +08:00
" ui_footer " : " <b>Powered by</b> <a href= ' https://markmap.js.org/ ' target= ' _blank ' rel= ' noopener noreferrer ' >Markmap</a> " ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
" html_error_missing_content " : " ⚠️ Unable to load mind map: Missing valid content. " ,
" html_error_load_failed " : " ⚠️ Resource loading failed, please try again later. " ,
" js_done " : " Done " ,
" js_failed " : " Failed " ,
" js_generating " : " Generating... " ,
" js_filename " : " mindmap.png " ,
" js_upload_failed " : " Upload failed: " ,
2026-02-21 17:50:44 +08:00
" md_image_alt " : " 🧠 Mind Map " ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
} ,
" zh-CN " : {
" status_starting " : " 思维导图已启动,正在为您生成思维导图... " ,
" error_no_content " : " 无法获取有效的用户消息内容。 " ,
" error_text_too_short " : " 文本内容过短( {len} 字符),无法进行有效分析。请提供至少 {min_len} 字符的文本。 " ,
" status_analyzing " : " 思维导图:深入分析文本结构... " ,
" status_drawing " : " 思维导图:绘制完成! " ,
" notification_success " : " 思维导图已生成, {user_name} ! " ,
" error_processing " : " 思维导图处理失败: {error} " ,
" error_user_facing " : " 抱歉,思维导图在处理时遇到错误: {error} 。 \n 请检查Open WebUI后端日志获取更多详情。 " ,
" status_failed " : " 思维导图:处理失败。 " ,
" notification_failed " : " 思维导图生成失败, {user_name} ! " ,
" status_rendering_image " : " 思维导图:正在渲染图片... " ,
" status_image_generated " : " 思维导图:图片已生成! " ,
" notification_image_success " : " 思维导图图片已生成, {user_name} ! " ,
" ui_title " : " 🧠 智能思维导图 " ,
" ui_user " : " 用户: " ,
" ui_time " : " 时间: " ,
" ui_download_png " : " PNG " ,
" ui_download_svg " : " SVG " ,
" ui_download_md " : " Markdown " ,
" ui_zoom_out " : " 缩小 " ,
" ui_zoom_reset " : " 重置 " ,
" ui_zoom_in " : " 放大 " ,
" ui_depth_select " : " 展开层级 " ,
" ui_depth_all " : " 全部展开 " ,
" ui_depth_2 " : " 展开 2 级 " ,
" ui_depth_3 " : " 展开 3 级 " ,
" ui_fullscreen " : " 全屏 " ,
" ui_theme " : " 主题 " ,
2026-02-21 17:50:44 +08:00
" ui_footer " : " <b>Powered by</b> <a href= ' https://markmap.js.org/ ' target= ' _blank ' rel= ' noopener noreferrer ' >Markmap</a> " ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
" html_error_missing_content " : " ⚠️ 无法加载思维导图:缺少有效内容。 " ,
" html_error_load_failed " : " ⚠️ 资源加载失败,请稍后重试。 " ,
" js_done " : " 完成 " ,
" js_failed " : " 失败 " ,
" js_generating " : " 生成中... " ,
" js_filename " : " 思维导图.png " ,
" js_upload_failed " : " 上传失败: " ,
2026-02-21 17:50:44 +08:00
" md_image_alt " : " 🧠 思维导图 " ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
} ,
" zh-HK " : {
" status_starting " : " 思維導圖已啟動,正在為您生成思維導圖... " ,
" error_no_content " : " 無法獲取有效的用戶消息內容。 " ,
" error_text_too_short " : " 文本內容過短( {len} 字元),無法進行有效分析。請提供至少 {min_len} 字元的文本。 " ,
" status_analyzing " : " 思維導圖:深入分析文本結構... " ,
" status_drawing " : " 思維導圖:繪製完成! " ,
" notification_success " : " 思維導圖已生成, {user_name} ! " ,
" error_processing " : " 思維導圖處理失敗: {error} " ,
" error_user_facing " : " 抱歉,思維導圖在處理時遇到錯誤: {error} 。 \n 請檢查Open WebUI後端日誌獲取更多詳情。 " ,
" status_failed " : " 思維導圖:處理失敗。 " ,
" notification_failed " : " 思維導圖生成失敗, {user_name} ! " ,
" status_rendering_image " : " 思維導圖:正在渲染圖片... " ,
" status_image_generated " : " 思維導圖:圖片已生成! " ,
" notification_image_success " : " 思維導圖圖片已生成, {user_name} ! " ,
" ui_title " : " 🧠 智能思維導圖 " ,
" ui_user " : " 用戶: " ,
" ui_time " : " 時間: " ,
" ui_download_png " : " PNG " ,
" ui_download_svg " : " SVG " ,
" ui_download_md " : " Markdown " ,
" ui_zoom_out " : " 縮小 " ,
" ui_zoom_reset " : " 重置 " ,
" ui_zoom_in " : " 放大 " ,
" ui_depth_select " : " 展開層級 " ,
" ui_depth_all " : " 全部展開 " ,
" ui_depth_2 " : " 展開 2 級 " ,
" ui_depth_3 " : " 展開 3 級 " ,
" ui_fullscreen " : " 全屏 " ,
" ui_theme " : " 主題 " ,
2026-02-21 17:50:44 +08:00
" ui_footer " : " <b>Powered by</b> <a href= ' https://markmap.js.org/ ' target= ' _blank ' rel= ' noopener noreferrer ' >Markmap</a> " ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
" html_error_missing_content " : " ⚠️ 無法加載思維導圖:缺少有效內容。 " ,
" html_error_load_failed " : " ⚠️ 資源加載失敗,請稍後重試。 " ,
" js_done " : " 完成 " ,
" js_failed " : " 失敗 " ,
" js_generating " : " 生成中... " ,
" js_filename " : " 思維導圖.png " ,
" js_upload_failed " : " 上傳失敗: " ,
2026-02-21 17:50:44 +08:00
" md_image_alt " : " 🧠 思維導圖 " ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
} ,
2026-02-12 16:54:48 +00:00
" zh-TW " : {
" status_starting " : " 思維導圖已啟動,正在為您生成思維導圖... " ,
" error_no_content " : " 無法獲取有效的用戶消息內容。 " ,
" error_text_too_short " : " 文本內容過短( {len} 字元),無法進行有效分析。請提供至少 {min_len} 字元的文本。 " ,
" status_analyzing " : " 思維導圖:深入分析文本結構... " ,
" status_drawing " : " 思維導圖:繪製完成! " ,
" notification_success " : " 思維導圖已生成, {user_name} ! " ,
" error_processing " : " 思維導圖處理失敗: {error} " ,
" error_user_facing " : " 抱歉,思維導圖在處理時遇到錯誤: {error} 。 \n 請檢查Open WebUI後端日誌獲取更多詳情。 " ,
" status_failed " : " 思維導圖:處理失敗。 " ,
" notification_failed " : " 思維導圖生成失敗, {user_name} ! " ,
" status_rendering_image " : " 思維導圖:正在渲染圖片... " ,
" status_image_generated " : " 思維導圖:圖片已生成! " ,
" notification_image_success " : " 思維導圖圖片已生成, {user_name} ! " ,
" ui_title " : " 🧠 智能思維導圖 " ,
" ui_user " : " 用戶: " ,
" ui_time " : " 時間: " ,
" ui_download_png " : " PNG " ,
" ui_download_svg " : " SVG " ,
" ui_download_md " : " Markdown " ,
" ui_zoom_out " : " 縮小 " ,
" ui_zoom_reset " : " 重置 " ,
" ui_zoom_in " : " 放大 " ,
" ui_depth_select " : " 展開層級 " ,
" ui_depth_all " : " 全部展開 " ,
" ui_depth_2 " : " 展開 2 級 " ,
" ui_depth_3 " : " 展開 3 級 " ,
" ui_fullscreen " : " 全屏 " ,
" ui_theme " : " 主題 " ,
2026-02-21 17:50:44 +08:00
" ui_footer " : " <b>Powered by</b> <a href= ' https://markmap.js.org/ ' target= ' _blank ' rel= ' noopener noreferrer ' >Markmap</a> " ,
2026-02-12 16:54:48 +00:00
" html_error_missing_content " : " ⚠️ 無法加載思維導圖:缺少有效內容。 " ,
" html_error_load_failed " : " ⚠️ 資源加載失敗,請稍後重試。 " ,
" js_done " : " 完成 " ,
" js_failed " : " 失敗 " ,
" js_generating " : " 生成中... " ,
" js_filename " : " 思維導圖.png " ,
" js_upload_failed " : " 上傳失敗: " ,
2026-02-21 17:50:44 +08:00
" md_image_alt " : " 🧠 思維導圖 " ,
2026-02-12 16:54:48 +00:00
} ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
" ko-KR " : {
" status_starting " : " 스마트 마인드맵이 시작되었습니다, 마인드맵을 생성 중입니다... " ,
" error_no_content " : " 유효한 사용자 메시지 내용을 가져올 수 없습니다. " ,
" error_text_too_short " : " 텍스트 내용이 너무 짧아( {len} 자), 효과적인 분석을 수행할 수 없습니다. 최소 {min_len} 자 이상의 텍스트를 제공해 주세요. " ,
" status_analyzing " : " 스마트 마인드맵: 텍스트 구조 심층 분석 중... " ,
" status_drawing " : " 스마트 마인드맵: 그리기 완료! " ,
" notification_success " : " 마인드맵이 생성되었습니다, {user_name} 님! " ,
" error_processing " : " 스마트 마인드맵 처리 실패: {error} " ,
" error_user_facing " : " 죄송합니다, 스마트 마인드맵 처리 중 오류가 발생했습니다: {error} . \n 자세한 내용은 Open WebUI 백엔드 로그를 확인해 주세요. " ,
" status_failed " : " 스마트 마인드맵: 처리 실패. " ,
" notification_failed " : " 스마트 마인드맵 생성 실패, {user_name} 님! " ,
" status_rendering_image " : " 스마트 마인드맵: 이미지 렌더링 중... " ,
" status_image_generated " : " 스마트 마인드맵: 이미지 생성됨! " ,
" notification_image_success " : " 마인드맵 이미지가 생성되었습니다, {user_name} 님! " ,
" ui_title " : " 🧠 스마트 마인드맵 " ,
" ui_user " : " 사용자: " ,
" ui_time " : " 시간: " ,
" ui_download_png " : " PNG " ,
" ui_download_svg " : " SVG " ,
" ui_download_md " : " Markdown " ,
" ui_zoom_out " : " - " ,
" ui_zoom_reset " : " 초기화 " ,
" ui_zoom_in " : " + " ,
" ui_depth_select " : " 레벨 확장 " ,
" ui_depth_all " : " 모두 확장 " ,
" ui_depth_2 " : " 레벨 2 " ,
" ui_depth_3 " : " 레벨 3 " ,
" ui_fullscreen " : " 전체 화면 " ,
" ui_theme " : " 테마 " ,
2026-02-21 17:50:44 +08:00
" ui_footer " : " <b>Powered by</b> <a href= ' https://markmap.js.org/ ' target= ' _blank ' rel= ' noopener noreferrer ' >Markmap</a> " ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
" html_error_missing_content " : " ⚠️ 마인드맵을 로드할 수 없습니다: 유효한 내용이 없습니다. " ,
" html_error_load_failed " : " ⚠️ 리소스 로드 실패, 나중에 다시 시도해 주세요. " ,
" js_done " : " 완료 " ,
" js_failed " : " 실패 " ,
" js_generating " : " 생성 중... " ,
" js_filename " : " mindmap.png " ,
" js_upload_failed " : " 업로드 실패: " ,
2026-02-21 17:50:44 +08:00
" md_image_alt " : " 🧠 마인드맵 " ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
} ,
" ja-JP " : {
" status_starting " : " スマートマインドマップが起動しました。マインドマップを生成しています... " ,
" error_no_content " : " 有効なユーザーメッセージの内容を取得できませんでした。 " ,
" error_text_too_short " : " テキストの内容が短すぎるため( {len} 文字)、効果的な分析を実行できません。少なくとも {min_len} 文字のテキストを提供してください。 " ,
" status_analyzing " : " スマートマインドマップ:テキスト構造を詳細に分析中... " ,
" status_drawing " : " スマートマインドマップ:描画完了! " ,
" notification_success " : " マインドマップが生成されました、 {user_name} さん! " ,
" error_processing " : " スマートマインドマップ処理失敗: {error} " ,
" error_user_facing " : " 申し訳ありません、スマートマインドマップの処理中にエラーが発生しました: {error} 。 \n 詳細については、Open WebUIバックエンドログを確認してください。 " ,
" status_failed " : " スマートマインドマップ:処理失敗。 " ,
" notification_failed " : " スマートマインドマップ生成失敗、 {user_name} さん! " ,
" status_rendering_image " : " スマートマインドマップ:画像レンダリング中... " ,
" status_image_generated " : " スマートマインドマップ:画像生成完了! " ,
" notification_image_success " : " マインドマップ画像が生成されました、 {user_name} さん! " ,
" ui_title " : " 🧠 スマートマインドマップ " ,
" ui_user " : " ユーザー: " ,
" ui_time " : " 時間: " ,
" ui_download_png " : " PNG " ,
" ui_download_svg " : " SVG " ,
" ui_download_md " : " Markdown " ,
" ui_zoom_out " : " - " ,
" ui_zoom_reset " : " リセット " ,
" ui_zoom_in " : " + " ,
" ui_depth_select " : " レベル展開 " ,
" ui_depth_all " : " すべて展開 " ,
" ui_depth_2 " : " レベル2 " ,
" ui_depth_3 " : " レベル3 " ,
" ui_fullscreen " : " 全画面 " ,
" ui_theme " : " テーマ " ,
2026-02-21 17:50:44 +08:00
" ui_footer " : " <b>Powered by</b> <a href= ' https://markmap.js.org/ ' target= ' _blank ' rel= ' noopener noreferrer ' >Markmap</a> " ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
" html_error_missing_content " : " ⚠️ マインドマップを読み込めません:有効なコンテンツがありません。 " ,
" html_error_load_failed " : " ⚠️ リソースの読み込みに失敗しました。後でもう一度お試しください。 " ,
" js_done " : " 完了 " ,
" js_failed " : " 失敗 " ,
" js_generating " : " 生成中... " ,
" js_filename " : " mindmap.png " ,
" js_upload_failed " : " アップロード失敗: " ,
2026-02-21 17:50:44 +08:00
" md_image_alt " : " 🧠 マインドマップ " ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
} ,
" fr-FR " : {
" status_starting " : " Smart Mind Map démarre, génération de la carte heuristique en cours... " ,
" error_no_content " : " Impossible de récupérer le contenu valide du message utilisateur. " ,
" error_text_too_short " : " Le contenu du texte est trop court ( {len} caractères), impossible d ' effectuer une analyse efficace. Veuillez fournir au moins {min_len} caractères de texte. " ,
" status_analyzing " : " Smart Mind Map : Analyse approfondie de la structure du texte... " ,
" status_drawing " : " Smart Mind Map : Dessin terminé ! " ,
" notification_success " : " La carte heuristique a été générée, {user_name} ! " ,
" error_processing " : " Échec du traitement de Smart Mind Map : {error} " ,
" error_user_facing " : " Désolé, Smart Mind Map a rencontré une erreur lors du traitement : {error} . \n Veuillez vérifier les journaux backend d ' Open WebUI pour plus de détails. " ,
" status_failed " : " Smart Mind Map : Échec du traitement. " ,
" notification_failed " : " Échec de la génération de la carte heuristique, {user_name} ! " ,
" status_rendering_image " : " Smart Mind Map : Rendu de l ' image... " ,
" status_image_generated " : " Smart Mind Map : Image générée ! " ,
" notification_image_success " : " L ' image de la carte heuristique a été générée, {user_name} ! " ,
" ui_title " : " 🧠 Smart Mind Map " ,
" ui_user " : " Utilisateur : " ,
" ui_time " : " Heure : " ,
" ui_download_png " : " PNG " ,
" ui_download_svg " : " SVG " ,
" ui_download_md " : " Markdown " ,
" ui_zoom_out " : " - " ,
" ui_zoom_reset " : " Rénitialiser " ,
" ui_zoom_in " : " + " ,
" ui_depth_select " : " Niveau d ' expansion " ,
" ui_depth_all " : " Tout développer " ,
" ui_depth_2 " : " Niveau 2 " ,
" ui_depth_3 " : " Niveau 3 " ,
" ui_fullscreen " : " Plein écran " ,
" ui_theme " : " Thème " ,
2026-02-21 17:50:44 +08:00
" ui_footer " : " <b>Powered by</b> <a href= ' https://markmap.js.org/ ' target= ' _blank ' rel= ' noopener noreferrer ' >Markmap</a> " ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
" html_error_missing_content " : " ⚠️ Impossible de charger la carte heuristique : contenu valide manquant. " ,
" html_error_load_failed " : " ⚠️ Échec du chargement des ressources, veuillez réessayer plus tard. " ,
" js_done " : " Terminé " ,
" js_failed " : " Échec " ,
" js_generating " : " Génération... " ,
" js_filename " : " carte_heuristique.png " ,
" js_upload_failed " : " Échec du téléchargement : " ,
2026-02-21 17:50:44 +08:00
" md_image_alt " : " 🧠 Carte Heuristique " ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
} ,
" de-DE " : {
" status_starting " : " Smart Mind Map startet, Mindmap wird für Sie erstellt... " ,
" error_no_content " : " Gültiger Inhalt der Benutzernachricht konnte nicht abgerufen werden. " ,
" error_text_too_short " : " Der Textinhalt ist zu kurz ( {len} Zeichen), eine effektive Analyse ist nicht möglich. Bitte geben Sie mindestens {min_len} Zeichen Text an. " ,
" status_analyzing " : " Smart Mind Map: Detaillierte Analyse der Textstruktur... " ,
" status_drawing " : " Smart Mind Map: Zeichnen abgeschlossen! " ,
" notification_success " : " Mindmap wurde erstellt, {user_name} ! " ,
" error_processing " : " Smart Mind Map Verarbeitung fehlgeschlagen: {error} " ,
" error_user_facing " : " Entschuldigung, bei der Verarbeitung von Smart Mind Map ist ein Fehler aufgetreten: {error} . \n Bitte überprüfen Sie die Open WebUI Backend-Protokolle für weitere Details. " ,
" status_failed " : " Smart Mind Map: Verarbeitung fehlgeschlagen. " ,
" notification_failed " : " Erstellung der Mindmap fehlgeschlagen, {user_name} ! " ,
" status_rendering_image " : " Smart Mind Map: Bild wird gerendert... " ,
" status_image_generated " : " Smart Mind Map: Bild erstellt! " ,
" notification_image_success " : " Mindmap-Bild wurde erstellt, {user_name} ! " ,
" ui_title " : " 🧠 Smart Mind Map " ,
" ui_user " : " Benutzer: " ,
" ui_time " : " Zeit: " ,
" ui_download_png " : " PNG " ,
" ui_download_svg " : " SVG " ,
" ui_download_md " : " Markdown " ,
" ui_zoom_out " : " - " ,
" ui_zoom_reset " : " Zurücksetzen " ,
" ui_zoom_in " : " + " ,
" ui_depth_select " : " Ebene erweitern " ,
" ui_depth_all " : " Alles erweitern " ,
" ui_depth_2 " : " Ebene 2 " ,
" ui_depth_3 " : " Ebene 3 " ,
" ui_fullscreen " : " Vollbild " ,
" ui_theme " : " Thema " ,
2026-02-21 17:50:44 +08:00
" ui_footer " : " <b>Powered by</b> <a href= ' https://markmap.js.org/ ' target= ' _blank ' rel= ' noopener noreferrer ' >Markmap</a> " ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
" html_error_missing_content " : " ⚠️ Mindmap kann nicht geladen werden: Gültiger Inhalt fehlt. " ,
" html_error_load_failed " : " ⚠️ Ressourcenladen fehlgeschlagen, bitte versuchen Sie es später erneut. " ,
" js_done " : " Fertig " ,
" js_failed " : " Fehlgeschlagen " ,
" js_generating " : " Generiere... " ,
" js_filename " : " mindmap.png " ,
" js_upload_failed " : " Upload fehlgeschlagen: " ,
2026-02-21 17:50:44 +08:00
" md_image_alt " : " 🧠 Mindmap " ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
} ,
" es-ES " : {
" status_starting " : " Smart Mind Map se está iniciando, generando mapa mental para usted... " ,
" error_no_content " : " No se puede recuperar el contenido válido del mensaje del usuario. " ,
" error_text_too_short " : " El contenido del texto es demasiado corto ( {len} caracteres), no se puede realizar un análisis efectivo. Proporcione al menos {min_len} caracteres de texto. " ,
" status_analyzing " : " Smart Mind Map: Analizando la estructura del texto en profundidad... " ,
" status_drawing " : " Smart Mind Map: ¡Dibujo completado! " ,
" notification_success " : " ¡El mapa mental ha sido generado, {user_name} ! " ,
" error_processing " : " Falló el procesamiento de Smart Mind Map: {error} " ,
" error_user_facing " : " Lo sentimos, Smart Mind Map encontró un error durante el procesamiento: {error} . \n Consulte los registros del backend de Open WebUI para más detalles. " ,
" status_failed " : " Smart Mind Map: Procesamiento fallido. " ,
" notification_failed " : " ¡La generación del mapa mental falló, {user_name} ! " ,
" status_rendering_image " : " Smart Mind Map: Renderizando imagen... " ,
" status_image_generated " : " Smart Mind Map: ¡Imagen generada! " ,
" notification_image_success " : " ¡La imagen del mapa mental ha sido generada, {user_name} ! " ,
" ui_title " : " 🧠 Smart Mind Map " ,
" ui_user " : " Usuario: " ,
" ui_time " : " Hora: " ,
" ui_download_png " : " PNG " ,
" ui_download_svg " : " SVG " ,
" ui_download_md " : " Markdown " ,
" ui_zoom_out " : " - " ,
" ui_zoom_reset " : " Restablecer " ,
" ui_zoom_in " : " + " ,
" ui_depth_select " : " Expandir Nivel " ,
" ui_depth_all " : " Expandir Todo " ,
" ui_depth_2 " : " Nivel 2 " ,
" ui_depth_3 " : " Nivel 3 " ,
" ui_fullscreen " : " Pantalla completa " ,
" ui_theme " : " Tema " ,
2026-02-21 17:50:44 +08:00
" ui_footer " : " <b>Powered by</b> <a href= ' https://markmap.js.org/ ' target= ' _blank ' rel= ' noopener noreferrer ' >Markmap</a> " ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
" html_error_missing_content " : " ⚠️ No se puede cargar el mapa mental: Falta contenido válido. " ,
" html_error_load_failed " : " ⚠️ Falló la carga de recursos, inténtelo de nuevo más tarde. " ,
" js_done " : " Hecho " ,
" js_failed " : " Fallido " ,
" js_generating " : " Generando... " ,
" js_filename " : " mapa_mental.png " ,
" js_upload_failed " : " Carga fallida: " ,
2026-02-21 17:50:44 +08:00
" md_image_alt " : " 🧠 Mapa Mental " ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
} ,
" it-IT " : {
" status_starting " : " Smart Mind Map si sta avviando, generazione mappa mentale in corso... " ,
" error_no_content " : " Impossibile recuperare il contenuto valido del messaggio utente. " ,
" error_text_too_short " : " Il testo è troppo breve ( {len} caratteri), impossibile eseguire un ' analisi efficace. Fornire almeno {min_len} caratteri di testo. " ,
" status_analyzing " : " Smart Mind Map: Analisi approfondita della struttura del testo... " ,
" status_drawing " : " Smart Mind Map: Disegno completato! " ,
" notification_success " : " La mappa mentale è stata generata, {user_name} ! " ,
" error_processing " : " Elaborazione Smart Mind Map fallita: {error} " ,
" error_user_facing " : " Spiacenti, Smart Mind Map ha riscontrato un errore durante l ' elaborazione: {error} . \n Controllare i log del backend di Open WebUI per ulteriori dettagli. " ,
" status_failed " : " Smart Mind Map: Elaborazione fallita. " ,
" notification_failed " : " Generazione mappa mentale fallita, {user_name} ! " ,
" status_rendering_image " : " Smart Mind Map: Rendering immagine... " ,
" status_image_generated " : " Smart Mind Map: Immagine generata! " ,
" notification_image_success " : " L ' immagine della mappa mentale è stata generata, {user_name} ! " ,
" ui_title " : " 🧠 Smart Mind Map " ,
" ui_user " : " Utente: " ,
" ui_time " : " Ora: " ,
" ui_download_png " : " PNG " ,
" ui_download_svg " : " SVG " ,
" ui_download_md " : " Markdown " ,
" ui_zoom_out " : " - " ,
" ui_zoom_reset " : " Reimposta " ,
" ui_zoom_in " : " + " ,
" ui_depth_select " : " Espandi Livello " ,
" ui_depth_all " : " Espandi Tutto " ,
" ui_depth_2 " : " Livello 2 " ,
" ui_depth_3 " : " Livello 3 " ,
" ui_fullscreen " : " Schermo intero " ,
" ui_theme " : " Tema " ,
2026-02-21 17:50:44 +08:00
" ui_footer " : " <b>Powered by</b> <a href= ' https://markmap.js.org/ ' target= ' _blank ' rel= ' noopener noreferrer ' >Markmap</a> " ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
" html_error_missing_content " : " ⚠️ Impossibile caricare la mappa mentale: Contenuto valido mancante. " ,
" html_error_load_failed " : " ⚠️ Caricamento risorse fallito, riprovare più tardi. " ,
" js_done " : " Fatto " ,
" js_failed " : " Fallito " ,
" js_generating " : " Generazione... " ,
" js_filename " : " mappa_mentale.png " ,
" js_upload_failed " : " Caricamento fallito: " ,
2026-02-21 17:50:44 +08:00
" md_image_alt " : " 🧠 Mappa Mentale " ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
} ,
" vi-VN " : {
" status_starting " : " Smart Mind Map đang khởi động, đang tạo sơ đồ tư duy cho bạn... " ,
" error_no_content " : " Không thể lấy nội dung tin nhắn người dùng hợp lệ. " ,
" error_text_too_short " : " Nội dung văn bản quá ngắn ( {len} ký tự), không thể thực hiện phân tích hiệu quả. Vui lòng cung cấp ít nhất {min_len} ký tự văn bản. " ,
" status_analyzing " : " Smart Mind Map: Phân tích sâu cấu trúc văn bản... " ,
" status_drawing " : " Smart Mind Map: Vẽ hoàn tất! " ,
" notification_success " : " Sơ đồ tư duy đã được tạo, {user_name} ! " ,
" error_processing " : " Xử lý Smart Mind Map thất bại: {error} " ,
" error_user_facing " : " Xin lỗi, Smart Mind Map đã gặp lỗi trong quá trình xử lý: {error} . \n Vui lòng kiểm tra nhật ký backend Open WebUI để biết thêm chi tiết. " ,
" status_failed " : " Smart Mind Map: Xử lý thất bại. " ,
" notification_failed " : " Tạo sơ đồ tư duy thất bại, {user_name} ! " ,
" status_rendering_image " : " Smart Mind Map: Đang render hình ảnh... " ,
" status_image_generated " : " Smart Mind Map: Hình ảnh đã tạo! " ,
" notification_image_success " : " Hình ảnh sơ đồ tư duy đã được tạo, {user_name} ! " ,
" ui_title " : " 🧠 Smart Mind Map " ,
" ui_user " : " Người dùng: " ,
" ui_time " : " Thời gian: " ,
" ui_download_png " : " PNG " ,
" ui_download_svg " : " SVG " ,
" ui_download_md " : " Markdown " ,
" ui_zoom_out " : " - " ,
" ui_zoom_reset " : " Đặt lại " ,
" ui_zoom_in " : " + " ,
" ui_depth_select " : " Mở rộng Cấp độ " ,
" ui_depth_all " : " Mở rộng Tất cả " ,
" ui_depth_2 " : " Cấp độ 2 " ,
" ui_depth_3 " : " Cấp độ 3 " ,
" ui_fullscreen " : " Toàn màn hình " ,
" ui_theme " : " Chủ đề " ,
2026-02-21 17:50:44 +08:00
" ui_footer " : " <b>Powered by</b> <a href= ' https://markmap.js.org/ ' target= ' _blank ' rel= ' noopener noreferrer ' >Markmap</a> " ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
" html_error_missing_content " : " ⚠️ Không thể tải sơ đồ tư duy: Thiếu nội dung hợp lệ. " ,
" html_error_load_failed " : " ⚠️ Tải tài nguyên thất bại, vui lòng thử lại sau. " ,
" js_done " : " Xong " ,
" js_failed " : " Thất bại " ,
" js_generating " : " Đang tạo... " ,
" js_filename " : " sodo_tuduy.png " ,
" js_upload_failed " : " Tải lên thất bại: " ,
2026-02-21 17:50:44 +08:00
" md_image_alt " : " 🧠 Sơ đồ Tư duy " ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
} ,
" id-ID " : {
" status_starting " : " Smart Mind Map sedang dimulai, membuat peta pikiran untuk Anda... " ,
" error_no_content " : " Tidak dapat mengambil konten pesan pengguna yang valid. " ,
" error_text_too_short " : " Konten teks terlalu pendek ( {len} karakter), tidak dapat melakukan analisis efektif. Harap berikan setidaknya {min_len} karakter teks. " ,
" status_analyzing " : " Smart Mind Map: Menganalisis struktur teks secara mendalam... " ,
" status_drawing " : " Smart Mind Map: Menggambar selesai! " ,
" notification_success " : " Peta pikiran telah dibuat, {user_name} ! " ,
" error_processing " : " Pemrosesan Smart Mind Map gagal: {error} " ,
" error_user_facing " : " Maaf, Smart Mind Map mengalami kesalahan saat memproses: {error} . \n Silakan periksa log backend Open WebUI untuk detail lebih lanjut. " ,
" status_failed " : " Smart Mind Map: Pemrosesan gagal. " ,
" notification_failed " : " Pembuatan peta pikiran gagal, {user_name} ! " ,
" status_rendering_image " : " Smart Mind Map: Merender gambar... " ,
" status_image_generated " : " Smart Mind Map: Gambar dibuat! " ,
" notification_image_success " : " Gambar peta pikiran telah dibuat, {user_name} ! " ,
" ui_title " : " 🧠 Smart Mind Map " ,
" ui_user " : " Pengguna: " ,
" ui_time " : " Waktu: " ,
" ui_download_png " : " PNG " ,
" ui_download_svg " : " SVG " ,
" ui_download_md " : " Markdown " ,
" ui_zoom_out " : " - " ,
" ui_zoom_reset " : " Atur Ulang " ,
" ui_zoom_in " : " + " ,
" ui_depth_select " : " Perluas Level " ,
" ui_depth_all " : " Perluas Semua " ,
" ui_depth_2 " : " Level 2 " ,
" ui_depth_3 " : " Level 3 " ,
" ui_fullscreen " : " Layar Penuh " ,
" ui_theme " : " Tema " ,
2026-02-21 17:50:44 +08:00
" ui_footer " : " <b>Powered by</b> <a href= ' https://markmap.js.org/ ' target= ' _blank ' rel= ' noopener noreferrer ' >Markmap</a> " ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
" html_error_missing_content " : " ⚠️ Tidak dapat memuat peta pikiran: Konten valid hilang. " ,
" html_error_load_failed " : " ⚠️ Gagal memuat sumber daya, silakan coba lagi nanti. " ,
" js_done " : " Selesai " ,
" js_failed " : " Gagal " ,
" js_generating " : " Membuat... " ,
" js_filename " : " peta_pikiran.png " ,
" js_upload_failed " : " Unggah gagal: " ,
2026-02-21 17:50:44 +08:00
" md_image_alt " : " 🧠 Peta Pikiran " ,
} ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
}
2025-12-20 12:34:49 +08:00
SYSTEM_PROMPT_MINDMAP_ASSISTANT = """
You are a professional mind map generation assistant , capable of efficiently analyzing long - form text provided by users and structuring its core themes , key concepts , branches , and sub - branches into standard Markdown list syntax for rendering by Markmap . js .
Please strictly follow these guidelines :
2026-01-28 11:09:18 +08:00
- * * Language * * : All output must be in the exact same language as the input text ( the text you are analyzing ) .
- * * Format Consistency * * : Even if this system prompt is in English , if the user input is in Chinese , the mind map content must be in Chinese . If input is Japanese , output Japanese .
2025-12-20 12:34:49 +08:00
- * * Format * * : Your output must strictly be in Markdown list format , wrapped with ` ` ` markdown and ` ` ` .
- Use ` #` to define the central theme (root node).
- Use ` - ` with two - space indentation to represent branches and sub - branches .
2026-02-21 17:50:44 +08:00
- * * Root Node ( Central Theme ) — Strict Length Limits * * :
- The ` #` root node must be an ultra-compact title, like a newspaper headline. It should be a keyword or short phrase, NEVER a full sentence.
- * * CJK scripts ( Chinese , Japanese , Korean ) * * : Maximum * * 10 characters * * ( e . g . , ` # 老人缓解呼吸困难方法` ✓ / `# 老人在家时感到呼吸困难的缓解方法` ✗)
- * * Latin - script languages ( English , Spanish , French , Italian , Portuguese ) * * : Maximum * * 5 words or 35 characters * * ( e . g . , ` # Methods to Relieve Dyspnea` ✓ / `# How Elderly People Can Relieve Breathing Difficulty at Home` ✗)
- * * German , Dutch or languages with long compound words * * : Maximum * * 4 words or 30 characters * *
- * * Arabic , Hebrew and other RTL scripts * * : Maximum * * 5 words or 25 characters * *
- * * All other languages * * : Maximum * * 5 words or 30 characters * *
- If the identified theme would exceed the limit , distill it further into the single most essential keyword or 2 - 3 word phrase .
- * * Branch Node Content * * :
2025-12-20 12:34:49 +08:00
- Identify main concepts as first - level list items .
- Identify supporting details or sub - concepts as nested list items .
- Node content should be concise and clear , avoiding verbosity .
- * * Output Markdown syntax only * * : Do not include any additional greetings , explanations , or guiding text .
- * * If text is too short or cannot generate a valid mind map * * : Output a simple Markdown list indicating inability to generate , for example :
` ` ` markdown
# Unable to Generate Mind Map
- Reason : Insufficient or unclear text content
` ` `
2026-02-21 17:50:44 +08:00
- * * Awareness of Target Audience Layout * * : You will be provided ` Target Rendering Mode ` .
- If ` Target Rendering Mode ` is ` direct ` : The client has massive horizontal space but limited scrolling vertically . Extract more first - level concepts to make the mind map spread wide like a sprawling fan , rather than deep single columns .
- If ` Target Rendering Mode ` is ` legacy ` : The client uses a narrow , portrait sidebar . Extract fewer top - level nodes , and break points into deeper , tighter sub - branches so the map grows vertically downwards .
2025-12-20 12:34:49 +08:00
"""
USER_PROMPT_GENERATE_MINDMAP = """
Please analyze the following long - form text and structure its core themes , key concepts , branches , and sub - branches into standard Markdown list syntax for Markmap . js rendering .
- - -
* * User Context Information : * *
User Name : { user_name }
Current Date & Time : { current_date_time_str }
Current Weekday : { current_weekday }
Current Timezone : { current_timezone_str }
User Language : { user_language }
2026-02-21 17:50:44 +08:00
Target Rendering Mode : Auto - adapting ( Dynamic width based on viewport )
2025-12-20 12:34:49 +08:00
- - -
* * Long - form Text Content : * *
{ long_text_content }
"""
2025-12-20 15:43:58 +08:00
HTML_WRAPPER_TEMPLATE = """
2025-12-20 15:07:41 +08:00
< ! - - OPENWEBUI_PLUGIN_OUTPUT - - >
2025-12-20 12:34:49 +08:00
< ! DOCTYPE html >
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
< html lang = " {lang} " >
2025-12-20 12:34:49 +08:00
< head >
< meta charset = " UTF-8 " >
< meta name = " viewport " content = " width=device-width, initial-scale=1.0 " >
< style >
2025-12-20 15:43:58 +08:00
body {
font - family : - apple - system , BlinkMacSystemFont , " Segoe UI " , Roboto , Helvetica , Arial , sans - serif ;
margin : 0 ;
2026-02-21 17:50:44 +08:00
padding : 2 px ;
2025-12-20 15:43:58 +08:00
background - color : transparent ;
}
#main-container {
display : flex ;
2025-12-31 02:00:10 +08:00
flex - direction : column ;
2025-12-20 15:43:58 +08:00
gap : 20 px ;
2025-12-31 02:00:10 +08:00
align - items : stretch ;
2025-12-20 15:43:58 +08:00
width : 100 % ;
}
. plugin - item {
2025-12-31 02:00:10 +08:00
width : 100 % ;
2025-12-20 15:43:58 +08:00
border - radius : 12 px ;
2025-12-31 02:00:10 +08:00
overflow : visible ;
2025-12-20 15:43:58 +08:00
transition : all 0.3 s ease ;
}
. plugin - item : hover {
2025-12-28 20:08:50 +08:00
transform : translateY ( - 2 px ) ;
2025-12-20 15:43:58 +08:00
}
/ * STYLES_INSERTION_POINT * /
< / style >
< / head >
< body >
< div id = " main-container " >
< ! - - CONTENT_INSERTION_POINT - - >
< / div >
< ! - - SCRIPTS_INSERTION_POINT - - >
< / body >
< / html >
"""
CSS_TEMPLATE_MINDMAP = """
2025-12-20 12:34:49 +08:00
: root {
- - primary - color : #1e88e5;
- - secondary - color : #43a047;
- - background - color : #f4f6f8;
- - card - bg - color : #ffffff;
2025-12-31 02:00:10 +08:00
- - text - color : #000000;
- - link - color : #546e7a;
- - node - stroke - color : #90a4ae;
2025-12-20 12:34:49 +08:00
- - muted - text - color : #546e7a;
- - border - color : #e0e0e0;
- - header - gradient : linear - gradient ( 135 deg , var ( - - secondary - color ) , var ( - - primary - color ) ) ;
2025-12-31 02:00:10 +08:00
- - shadow : 0 10 px 20 px rgba ( 0 , 0 , 0 , 0.06 ) ;
2025-12-20 12:34:49 +08:00
- - border - radius : 12 px ;
- - font - family : - apple - system , BlinkMacSystemFont , " Segoe UI " , Roboto , " Helvetica Neue " , Arial , sans - serif ;
}
2025-12-31 02:00:10 +08:00
. theme - dark {
- - primary - color : #64b5f6;
- - secondary - color : #81c784;
- - background - color : #111827;
- - card - bg - color : #1f2937;
- - text - color : #ffffff;
- - link - color : #cbd5e1;
- - node - stroke - color : #94a3b8;
- - muted - text - color : #9ca3af;
- - border - color : #374151;
- - header - gradient : linear - gradient ( 135 deg , #0ea5e9, #22c55e);
- - shadow : 0 10 px 20 px rgba ( 0 , 0 , 0 , 0.3 ) ;
}
2026-02-21 17:50:44 +08:00
html , body {
margin : 0 ;
padding : 0 ;
width : 100 vw ;
height : 100 vh ;
background : var ( - - card - bg - color ) ;
overflow : hidden ;
}
2025-12-20 15:43:58 +08:00
. mindmap - container - wrapper {
2025-12-20 12:34:49 +08:00
font - family : var ( - - font - family ) ;
2025-12-31 02:00:10 +08:00
line - height : 1.6 ;
2025-12-20 12:34:49 +08:00
color : var ( - - text - color ) ;
margin : 0 ;
2025-12-20 15:43:58 +08:00
padding : 0 ;
2025-12-20 12:34:49 +08:00
- webkit - font - smoothing : antialiased ;
- moz - osx - font - smoothing : grayscale ;
2025-12-20 15:43:58 +08:00
display : flex ;
flex - direction : column ;
2026-02-21 17:50:44 +08:00
background : var ( - - card - bg - color ) ;
width : 100 vw ;
height : 100 vh ;
box - sizing : border - box ;
overflow : hidden ;
border : none ;
border - radius : 0 ;
box - shadow : none ;
2025-12-20 12:34:49 +08:00
}
. header {
2026-02-21 17:50:44 +08:00
background : var ( - - card - bg - color ) ;
color : var ( - - text - color ) ;
padding : 12 px 16 px ;
display : flex ;
flex - direction : column ;
gap : 12 px ;
flex - shrink : 0 ;
border - bottom : 1 px solid var ( - - border - color ) ;
z - index : 10 ;
}
. header - top {
display : flex ;
align - items : center ;
gap : 12 px ;
2025-12-20 12:34:49 +08:00
}
. header h1 {
margin : 0 ;
2026-02-21 17:50:44 +08:00
font - size : 1.2 em ;
2025-12-20 12:34:49 +08:00
font - weight : 600 ;
2026-02-21 17:50:44 +08:00
letter - spacing : 0.5 px ;
display : flex ;
align - items : center ;
gap : 8 px ;
2025-12-20 12:34:49 +08:00
}
2026-02-21 17:50:44 +08:00
. header - credits {
font - size : 0.8 em ;
2025-12-20 12:34:49 +08:00
color : var ( - - muted - text - color ) ;
2026-02-21 17:50:44 +08:00
opacity : 0.8 ;
white - space : nowrap ;
2025-12-31 02:00:10 +08:00
}
2026-02-21 17:50:44 +08:00
. header - credits a {
color : var ( - - primary - color ) ;
text - decoration : none ;
border - bottom : 1 px dotted var ( - - link - color ) ;
2025-12-20 12:34:49 +08:00
}
2026-03-16 00:02:53 +08:00
. star - btn {
background : transparent ! important ;
border : none ! important ;
color : #fbbf24 !important;
display : inline - flex ! important ;
align - items : center ;
justify - content : center ;
padding : 4 px 8 px ! important ;
cursor : pointer ;
transition : all 0.2 s ease ;
text - decoration : none ;
height : 28 px ;
}
. star - btn : hover {
color : #f59e0b !important;
transform : scale ( 1.15 ) ;
filter : drop - shadow ( 0 0 4 px rgba ( 251 , 191 , 36 , 0.5 ) ) ;
}
. star - btn svg {
width : 18 px ! important ;
height : 18 px ! important ;
fill : currentColor ! important ;
}
2026-02-21 17:50:44 +08:00
2025-12-31 02:00:10 +08:00
. content - area {
2026-02-21 17:50:44 +08:00
padding : 0 ;
flex : 1 1 0 ;
2026-02-22 00:24:37 +08:00
background : var ( - - card - bg - color ) ;
2026-02-21 17:50:44 +08:00
position : relative ;
overflow : hidden ;
width : 100 % ;
min - height : 0 ;
/ * Height will be computed dynamically by JS below * /
2025-12-20 12:34:49 +08:00
}
. markmap - container {
2026-02-21 17:50:44 +08:00
position : absolute ;
top : 0 ;
left : 0 ;
right : 0 ;
bottom : 0 ;
2025-12-31 02:00:10 +08:00
background - color : var ( - - card - bg - color ) ;
2025-12-20 12:34:49 +08:00
}
2025-12-31 02:00:10 +08:00
. markmap - container svg {
width : 100 % ;
height : 100 % ;
2026-02-21 17:50:44 +08:00
display : block ;
2025-12-31 02:00:10 +08:00
}
. markmap - container svg text {
fill : var ( - - text - color ) ! important ;
font - family : var ( - - font - family ) ;
}
. markmap - container svg foreignObject ,
. markmap - container svg . markmap - foreign ,
. markmap - container svg . markmap - foreign div {
color : var ( - - text - color ) ! important ;
font - family : var ( - - font - family ) ;
}
. markmap - container svg . markmap - link {
stroke : var ( - - link - color ) ! important ;
2026-02-21 17:50:44 +08:00
stroke - opacity : 0.6 ;
}
. theme - dark . markmap - node circle {
fill : var ( - - card - bg - color ) ! important ;
2025-12-20 12:34:49 +08:00
}
2025-12-31 02:00:10 +08:00
. markmap - container svg . markmap - node circle ,
. markmap - container svg . markmap - node rect {
stroke : var ( - - node - stroke - color ) ! important ;
}
. control - rows {
display : flex ;
2026-02-21 17:50:44 +08:00
align - items : center ;
2025-12-31 02:00:10 +08:00
flex - wrap : wrap ;
2026-02-21 17:50:44 +08:00
gap : 12 px ;
margin - left : auto ; / * Push controls to the right * /
2025-12-31 02:00:10 +08:00
}
. btn - group {
display : inline - flex ;
2026-02-21 17:50:44 +08:00
gap : 4 px ;
2025-12-31 02:00:10 +08:00
align - items : center ;
2026-02-21 17:50:44 +08:00
border : 1 px solid var ( - - border - color ) ;
border - radius : 6 px ;
padding : 2 px ;
background : var ( - - background - color ) ;
2025-12-31 02:00:10 +08:00
}
. control - btn {
2026-02-21 17:50:44 +08:00
background - color : transparent ;
color : var ( - - text - color ) ;
2025-12-20 12:34:49 +08:00
border : none ;
2026-02-21 17:50:44 +08:00
padding : 4 px 10 px ;
border - radius : 4 px ;
font - size : 0.85 em ;
2025-12-20 12:34:49 +08:00
font - weight : 500 ;
cursor : pointer ;
2026-02-21 17:50:44 +08:00
transition : all 0.2 s ease ;
2025-12-20 12:34:49 +08:00
display : inline - flex ;
align - items : center ;
2026-02-21 17:50:44 +08:00
justify - content : center ;
height : 28 px ;
2025-12-31 02:00:10 +08:00
box - sizing : border - box ;
2026-02-21 17:50:44 +08:00
opacity : 0.8 ;
}
. control - btn : hover {
background - color : var ( - - card - bg - color ) ;
opacity : 1 ;
box - shadow : 0 1 px 3 px rgba ( 0 , 0 , 0 , 0.1 ) ;
}
. control - btn : active {
transform : translateY ( 1 px ) ;
}
. control - btn . primary {
background - color : var ( - - primary - color ) ;
color : white ;
opacity : 1 ;
2025-12-20 12:34:49 +08:00
}
2026-02-21 17:50:44 +08:00
. control - btn . primary : hover {
box - shadow : 0 2 px 5 px rgba ( 30 , 136 , 229 , 0.3 ) ;
}
2025-12-31 02:00:10 +08:00
select . control - btn {
appearance : none ;
padding - right : 28 px ;
background - image : url ( " data:image/svg+xml;charset=US-ASCII, % 3Csvg %20x mlns % 3D % 22http % 3A %2F %2F www.w3.org %2F 2000 %2F svg %22% 20width % 3D %22292.4% 22 %20he ight % 3D %22292.4% 22 %3E % 3Cpath %20f ill % 3D %22% 23FFFFFF %22% 20d % 3D % 22M287 %2069.4a 17.6 %2017.6% 200 %200% 200-13-5.4H18.4c-5 % 200-9.3 % 201.8-12.9 % 205.4A17.6 %2017.6% 200 %200% 200 %200% 2082.2c0 %205% 201.8 %209.3% 205.4 % 2012.9l128 %20127.9c 3.6 %203.6% 207.8 %205.4% 2012.8 %205.4s 9.2-1.8 % 2012.8-5.4L287 %2095c 3.5-3.5 % 205.4-7.8 % 205.4-12.8 % 200-5-1.9-9.2-5.5-12.8z %22% 2F %3E % 3C %2F svg %3E " ) ;
background - repeat : no - repeat ;
background - position : right 8 px center ;
background - size : 10 px ;
2025-12-20 12:34:49 +08:00
}
2026-02-21 17:50:44 +08:00
. control - btn option {
2025-12-31 02:00:10 +08:00
background - color : var ( - - card - bg - color ) ;
2026-02-21 17:50:44 +08:00
color : var ( - - text - color ) ;
2025-12-20 12:34:49 +08:00
}
. error - message {
color : #c62828;
background - color : #ffcdd2;
border : 1 px solid #ef9a9a;
2025-12-31 02:00:10 +08:00
padding : 14 px ;
2025-12-20 15:43:58 +08:00
border - radius : 8 px ;
2025-12-20 12:34:49 +08:00
font - weight : 500 ;
2025-12-20 15:43:58 +08:00
font - size : 1 em ;
2026-02-21 17:50:44 +08:00
margin : 10 px ;
}
/ * Mobile Responsive Adjustments * /
@media screen and ( max - width : 768 px ) {
. mindmap - container - wrapper {
min - height : 400 px ;
height : 80 vh ;
}
. header {
flex - direction : column ;
gap : 10 px ;
}
. btn - group {
padding : 2 px ;
}
. control - btn {
padding : 4 px 6 px ;
font - size : 0.75 em ;
height : 28 px ;
}
select . control - btn {
padding - right : 20 px ;
background - position : right 4 px center ;
}
2025-12-20 12:34:49 +08:00
}
2025-12-20 15:43:58 +08:00
"""
CONTENT_TEMPLATE_MINDMAP = """
< div class = " mindmap-container-wrapper " >
< div class = " header " >
2026-02-21 17:50:44 +08:00
< div class = " header-top " >
< h1 > { t_ui_title } < / h1 >
< div class = " header-credits " >
< span > { t_ui_footer } < / span >
2025-12-31 02:00:10 +08:00
< / div >
2026-02-21 17:50:44 +08:00
< div class = " control-rows " >
< div class = " btn-group " >
< button id = " download-png-btn- {unique_id} " class = " control-btn primary " title = " {t_ui_download_png} " > PNG < / button >
< button id = " download-svg-btn- {unique_id} " class = " control-btn " title = " {t_ui_download_svg} " > SVG < / button >
< button id = " download-md-btn- {unique_id} " class = " control-btn " title = " {t_ui_download_md} " > MD < / button >
2026-03-16 00:02:53 +08:00
< a href = " https://github.com/Fu-Jie/openwebui-extensions " target = " _blank " rel = " noopener noreferrer " title = " Star on GitHub " class = " control-btn star-btn " >
< svg viewBox = " 0 0 24 24 " xmlns = " http://www.w3.org/2000/svg " style = " width: 18px; height: 18px; " >
< path d = " M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z " fill = " currentColor " / >
< / svg >
< / a >
2026-02-21 17:50:44 +08:00
< / div >
< div class = " btn-group " >
< button id = " zoom-out-btn- {unique_id} " class = " control-btn " title = " {t_ui_zoom_out} " > - < / button >
< button id = " zoom-reset-btn- {unique_id} " class = " control-btn " title = " {t_ui_zoom_reset} " > ↺ < / button >
< button id = " zoom-in-btn- {unique_id} " class = " control-btn " title = " {t_ui_zoom_in} " > + < / button >
< / div >
< div class = " btn-group " >
< select id = " depth-select- {unique_id} " class = " control-btn " title = " {t_ui_depth_select} " >
< option value = " 0 " selected > { t_ui_depth_all } < / option >
< option value = " 2 " > { t_ui_depth_2 } < / option >
< option value = " 3 " > { t_ui_depth_3 } < / option >
< / select >
< button id = " fullscreen-btn- {unique_id} " class = " control-btn " title = " {t_ui_fullscreen} " > ⛶ < / button >
< button id = " theme-toggle-btn- {unique_id} " class = " control-btn " title = " {t_ui_theme} " > ◑ < / button >
< / div >
2025-12-31 02:00:10 +08:00
< / div >
2025-12-20 15:43:58 +08:00
< / div >
< / div >
2026-02-21 17:50:44 +08:00
< div class = " content-area " >
< div class = " markmap-container " id = " markmap-container- {unique_id} " > < / div >
2025-12-20 12:34:49 +08:00
< / div >
< / div >
2025-12-20 15:43:58 +08:00
< script type = " text/template " id = " markdown-source- {unique_id} " > { markdown_syntax } < / script >
"""
2025-12-20 12:34:49 +08:00
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 18 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN, zh-TW).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Added explicit support for zh-TW (Traditional Chinese) with correct translations.
- Updated HTML/JS templates to use injected translations.
- Restored clickable "Markmap" link in the footer for all languages.
- Fixed SyntaxWarning in regex strings by properly escaping backslashes in standard strings.
- Implemented robust UI translation loading to prevent crashes on missing keys.
- Verified frontend rendering with Playwright and backend logic with unit tests.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 17:15:50 +00:00
SCRIPT_TEMPLATE_MINDMAP = """
2025-12-20 12:34:49 +08:00
< script >
( function ( ) {
2026-02-12 17:41:52 +00:00
const uniqueId = { unique_id_json } ;
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
const i18n = { i18n_json } ;
2025-12-31 02:00:10 +08:00
const loadScriptOnce = ( src , checkFn ) = > {
if ( checkFn ( ) ) return Promise . resolve ( ) ;
return new Promise ( ( resolve , reject ) = > {
const existing = document . querySelector ( ` script [ data - src = " $ {src} " ] ` ) ;
if ( existing ) {
existing . addEventListener ( ' load ' , ( ) = > resolve ( ) ) ;
existing . addEventListener ( ' error ' , ( ) = > reject ( new Error ( ' Loading failed: ' + src ) ) ) ;
return ;
}
const script = document . createElement ( ' script ' ) ;
script . src = src ;
script . async = true ;
script . dataset . src = src ;
script . onload = ( ) = > resolve ( ) ;
script . onerror = ( ) = > reject ( new Error ( ' Loading failed: ' + src ) ) ;
document . head . appendChild ( script ) ;
} ) ;
} ;
const ensureMarkmapReady = ( ) = >
loadScriptOnce ( ' https://cdn.jsdelivr.net/npm/d3@7 ' , ( ) = > window . d3 )
. then ( ( ) = > loadScriptOnce ( ' https://cdn.jsdelivr.net/npm/markmap-lib@0.17 ' , ( ) = > window . markmap & & window . markmap . Transformer ) )
. then ( ( ) = > loadScriptOnce ( ' https://cdn.jsdelivr.net/npm/markmap-view@0.17 ' , ( ) = > window . markmap & & window . markmap . Markmap ) ) ;
const parseColorLuma = ( colorStr ) = > {
if ( ! colorStr ) return null ;
/ / hex #rrggbb or rrggbb
let m = colorStr . match ( / ^ #?([0-9a-f]{6})$/i);
if ( m ) {
const hex = m [ 1 ] ;
const r = parseInt ( hex . slice ( 0 , 2 ) , 16 ) ;
const g = parseInt ( hex . slice ( 2 , 4 ) , 16 ) ;
const b = parseInt ( hex . slice ( 4 , 6 ) , 16 ) ;
return ( 0.2126 * r + 0.7152 * g + 0.0722 * b ) / 255 ;
}
/ / rgb ( r , g , b ) or rgba ( r , g , b , a )
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 18 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN, zh-TW).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Added explicit support for zh-TW (Traditional Chinese) with correct translations.
- Updated HTML/JS templates to use injected translations.
- Restored clickable "Markmap" link in the footer for all languages.
- Fixed SyntaxWarning in regex strings by properly escaping backslashes in standard strings.
- Implemented robust UI translation loading to prevent crashes on missing keys.
- Verified frontend rendering with Playwright and backend logic with unit tests.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 17:15:50 +00:00
m = colorStr . match ( / rgba ? \\s * \\( \\s * ( \\d + ) \\s * , \\s * ( \\d + ) \\s * , \\s * ( \\d + ) / i ) ;
2025-12-31 02:00:10 +08:00
if ( m ) {
const r = parseInt ( m [ 1 ] , 10 ) ;
const g = parseInt ( m [ 2 ] , 10 ) ;
const b = parseInt ( m [ 3 ] , 10 ) ;
return ( 0.2126 * r + 0.7152 * g + 0.0722 * b ) / 255 ;
}
return null ;
} ;
const getThemeFromMeta = ( doc , scope = ' self ' ) = > {
const metas = Array . from ( ( doc | | document ) . querySelectorAll ( ' meta[name= " theme-color " ] ' ) ) ;
if ( ! metas . length ) return null ;
const color = metas [ metas . length - 1 ] . content . trim ( ) ;
const luma = parseColorLuma ( color ) ;
if ( luma == = null ) return null ;
return luma < 0.5 ? ' dark ' : ' light ' ;
} ;
const getParentDocumentSafe = ( ) = > {
try {
if ( ! window . parent | | window . parent == = window ) return null ;
const pDoc = window . parent . document ;
void pDoc . title ;
return pDoc ;
} catch ( err ) {
return null ;
}
} ;
const getThemeFromParentClass = ( ) = > {
try {
if ( ! window . parent | | window . parent == = window ) return null ;
const pDoc = window . parent . document ;
const html = pDoc . documentElement ;
const body = pDoc . body ;
const htmlClass = html ? html . className : ' ' ;
const bodyClass = body ? body . className : ' ' ;
const htmlDataTheme = html ? html . getAttribute ( ' data-theme ' ) : ' ' ;
if ( htmlDataTheme == = ' dark ' | | bodyClass . includes ( ' dark ' ) | | htmlClass . includes ( ' dark ' ) ) return ' dark ' ;
if ( htmlDataTheme == = ' light ' | | bodyClass . includes ( ' light ' ) | | htmlClass . includes ( ' light ' ) ) return ' light ' ;
return null ;
} catch ( err ) {
return null ;
}
} ;
const setTheme = ( wrapperEl , explicitTheme ) = > {
const parentDoc = getParentDocumentSafe ( ) ;
const metaThemeParent = parentDoc ? getThemeFromMeta ( parentDoc , ' parent ' ) : null ;
const parentClassTheme = getThemeFromParentClass ( ) ;
const prefersDark = window . matchMedia & & window . matchMedia ( ' (prefers-color-scheme: dark) ' ) . matches ;
const chosen = explicitTheme | | metaThemeParent | | parentClassTheme | | ( prefersDark ? ' dark ' : ' light ' ) ;
wrapperEl . classList . toggle ( ' theme-dark ' , chosen == = ' dark ' ) ;
return chosen ;
} ;
2025-12-20 12:34:49 +08:00
const renderMindmap = ( ) = > {
const containerEl = document . getElementById ( ' markmap-container- ' + uniqueId ) ;
if ( ! containerEl | | containerEl . dataset . markmapRendered ) return ;
const sourceEl = document . getElementById ( ' markdown-source- ' + uniqueId ) ;
if ( ! sourceEl ) return ;
const markdownContent = sourceEl . textContent . trim ( ) ;
if ( ! markdownContent ) {
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
containerEl . innerHTML = ' <div class= " error-message " > ' + i18n . html_error_missing_content + ' </div> ' ;
2025-12-20 12:34:49 +08:00
return ;
}
2025-12-31 02:00:10 +08:00
ensureMarkmapReady ( ) . then ( ( ) = > {
const svgEl = document . createElementNS ( ' http://www.w3.org/2000/svg ' , ' svg ' ) ;
2025-12-20 12:34:49 +08:00
svgEl . style . width = ' 100 % ' ;
2025-12-31 02:00:10 +08:00
svgEl . style . height = ' 100 % ' ;
containerEl . innerHTML = ' ' ;
2025-12-20 12:34:49 +08:00
containerEl . appendChild ( svgEl ) ;
const { Transformer , Markmap } = window . markmap ;
const transformer = new Transformer ( ) ;
const { root } = transformer . transform ( markdownContent ) ;
2026-02-21 17:50:44 +08:00
const containerWidth = containerEl . clientWidth | | window . innerWidth ;
const containerHeight = containerEl . clientHeight | | window . innerHeight ;
const isPortrait = containerHeight > = containerWidth * 0.8 ;
2025-12-31 02:00:10 +08:00
const style = ( id ) = > `
2026-02-21 17:50:44 +08:00
$ { id } text , $ { id } foreignObject { font - size : 16 px ; }
$ { id } foreignObject { line - height : 1.6 ; }
$ { id } foreignObject div { padding : 2 px 0 ; }
$ { id } foreignObject h1 { font - size : 24 px ; font - weight : 700 ; margin : 0 0 6 px 0 ; border - bottom : 2 px solid currentColor ; padding - bottom : 4 px ; display : inline - block ; }
$ { id } foreignObject h2 { font - size : 18 px ; font - weight : 600 ; margin : 0 0 4 px 0 ; }
2025-12-31 02:00:10 +08:00
$ { id } foreignObject strong { font - weight : 700 ; }
2026-02-21 17:50:44 +08:00
$ { id } foreignObject p { margin : 2 px 0 ; }
2025-12-31 02:00:10 +08:00
` ;
2026-02-21 17:50:44 +08:00
let responsiveMaxWidth ;
let dynamicSpacingVertical = 5 ;
let dynamicSpacingHorizontal = 80 ;
if ( isPortrait ) {
/ / Old Version / Mobile : Force early text wrap to explode height and tighten width
responsiveMaxWidth = Math . max ( 140 , Math . floor ( containerWidth * 0.35 ) ) ;
dynamicSpacingVertical = 20 ; / / Explicitly spread out branches vertically
dynamicSpacingHorizontal = 60 ;
} else {
/ / New Version ( Direct Chat ) : Generous width to utilize massive horizontal space
responsiveMaxWidth = Math . max ( 220 , Math . floor ( containerWidth * 0.35 ) ) ;
dynamicSpacingVertical = 12 ;
dynamicSpacingHorizontal = 60 ; / / Tighter horizontal gaps so the chart doesn ' t get too wide to scale up
}
2025-12-31 02:00:10 +08:00
const options = {
2025-12-20 12:34:49 +08:00
autoFit : true ,
2025-12-31 02:00:10 +08:00
style : style ,
2026-02-21 17:50:44 +08:00
initialExpandLevel : 3 ,
2025-12-31 02:00:10 +08:00
zoom : true ,
2026-02-21 17:50:44 +08:00
pan : true ,
fitRatio : 0.95 , / / Maximize scale to make text bigger
maxWidth : responsiveMaxWidth ,
spacingVertical : dynamicSpacingVertical ,
spacingHorizontal : dynamicSpacingHorizontal ,
colorFreezeLevel : 2
2025-12-20 12:34:49 +08:00
} ;
2025-12-31 02:00:10 +08:00
const markmapInstance = Markmap . create ( svgEl , options , root ) ;
2026-02-21 17:50:44 +08:00
/ / Extra tick : force fit to make sure bounding box centers
setTimeout ( ( ) = > {
markmapInstance . fit ( ) ;
} , 100 ) ;
/ / Dynamically refit if the user drags to resize the sidebar / iframe
const resizeObserver = new ResizeObserver ( entries = > {
for ( let entry of entries ) {
if ( entry . contentRect . width > 0 & & entry . contentRect . height > 0 ) {
requestAnimationFrame ( ( ) = > markmapInstance . fit ( ) ) ;
}
}
} ) ;
resizeObserver . observe ( containerEl ) ;
window . markmapInstance = markmapInstance ; / / Expose for external triggers
2025-12-20 12:34:49 +08:00
containerEl . dataset . markmapRendered = ' true ' ;
2025-12-31 02:00:10 +08:00
setupControls ( {
containerEl ,
svgEl ,
markmapInstance ,
root ,
2026-02-21 17:50:44 +08:00
isPortrait
2025-12-31 02:00:10 +08:00
} ) ;
} ) . catch ( ( error ) = > {
console . error ( ' Markmap loading error: ' , error ) ;
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
containerEl . innerHTML = ' <div class= " error-message " > ' + i18n . html_error_load_failed + ' </div> ' ;
2025-12-31 02:00:10 +08:00
} ) ;
2025-12-20 12:34:49 +08:00
} ;
2026-02-21 17:50:44 +08:00
/ / Dynamically fix layout : measure header height and set content - area height precisely
const adjustLayout = ( ) = > {
const wrapper = document . querySelector ( ' .mindmap-container-wrapper ' ) ;
const header = document . querySelector ( ' .header ' ) ;
const contentArea = document . querySelector ( ' .content-area ' ) ;
if ( ! wrapper | | ! header | | ! contentArea ) return ;
const headerH = header . getBoundingClientRect ( ) . height ;
const totalH = wrapper . getBoundingClientRect ( ) . height ;
const contentH = Math . max ( totalH - headerH , 200 ) ;
contentArea . style . height = contentH + ' px ' ;
} ;
/ / Run once after DOM is ready , then on any resize
adjustLayout ( ) ;
window . addEventListener ( ' resize ' , ( ) = > {
adjustLayout ( ) ;
if ( window . markmapInstance ) {
requestAnimationFrame ( ( ) = > window . markmapInstance . fit ( ) ) ;
}
} ) ;
const setupControls = ( { containerEl , svgEl , markmapInstance , root , isPortrait } ) = > {
2025-12-20 12:34:49 +08:00
const downloadSvgBtn = document . getElementById ( ' download-svg-btn- ' + uniqueId ) ;
2025-12-31 02:00:10 +08:00
const downloadPngBtn = document . getElementById ( ' download-png-btn- ' + uniqueId ) ;
2025-12-20 12:34:49 +08:00
const downloadMdBtn = document . getElementById ( ' download-md-btn- ' + uniqueId ) ;
2025-12-31 02:00:10 +08:00
const zoomInBtn = document . getElementById ( ' zoom-in-btn- ' + uniqueId ) ;
const zoomOutBtn = document . getElementById ( ' zoom-out-btn- ' + uniqueId ) ;
const zoomResetBtn = document . getElementById ( ' zoom-reset-btn- ' + uniqueId ) ;
const depthSelect = document . getElementById ( ' depth-select- ' + uniqueId ) ;
const fullscreenBtn = document . getElementById ( ' fullscreen-btn- ' + uniqueId ) ;
const themeToggleBtn = document . getElementById ( ' theme-toggle-btn- ' + uniqueId ) ;
2026-02-21 17:50:44 +08:00
if ( depthSelect ) {
depthSelect . value = " 3 " ;
}
2025-12-31 02:00:10 +08:00
const wrapper = containerEl . closest ( ' .mindmap-container-wrapper ' ) ;
let currentTheme = setTheme ( wrapper ) ;
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
const showFeedback = ( button , textOk = i18n . js_done , textFail = i18n . js_failed ) = > {
2025-12-31 02:00:10 +08:00
if ( ! button ) return ;
const buttonText = button . querySelector ( ' .btn-text ' ) | | button ;
2025-12-20 12:34:49 +08:00
const originalText = buttonText . textContent ;
button . disabled = true ;
2025-12-31 02:00:10 +08:00
buttonText . textContent = textOk ;
button . classList . add ( ' copied ' ) ;
2025-12-20 12:34:49 +08:00
setTimeout ( ( ) = > {
buttonText . textContent = originalText ;
button . disabled = false ;
button . classList . remove ( ' copied ' ) ;
2025-12-31 02:00:10 +08:00
} , 1800 ) ;
2025-12-20 12:34:49 +08:00
} ;
const copyToClipboard = ( content , button ) = > {
if ( navigator . clipboard & & window . isSecureContext ) {
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
navigator . clipboard . writeText ( content ) . then ( ( ) = > showFeedback ( button ) , ( ) = > showFeedback ( button , i18n . js_failed , i18n . js_failed ) ) ;
2025-12-20 12:34:49 +08:00
} else {
const textArea = document . createElement ( ' textarea ' ) ;
textArea . value = content ;
textArea . style . position = ' fixed ' ;
textArea . style . opacity = ' 0 ' ;
document . body . appendChild ( textArea ) ;
textArea . focus ( ) ;
textArea . select ( ) ;
try {
document . execCommand ( ' copy ' ) ;
2025-12-31 02:00:10 +08:00
showFeedback ( button ) ;
2025-12-20 12:34:49 +08:00
} catch ( err ) {
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
showFeedback ( button , i18n . js_failed , i18n . js_failed ) ;
2025-12-20 12:34:49 +08:00
}
document . body . removeChild ( textArea ) ;
}
} ;
2025-12-31 02:00:10 +08:00
const handleDownloadSVG = ( ) = > {
const svg = containerEl . querySelector ( ' svg ' ) ;
if ( ! svg ) return ;
/ / Inline styles before export
const clonedSvg = svg . cloneNode ( true ) ;
const style = document . createElement ( ' style ' ) ;
style . textContent = `
text { font - family : sans - serif ; fill : $ { currentTheme == = ' dark ' ? ' #ffffff ' : ' #000000 ' } ; }
foreignObject , . markmap - foreign , . markmap - foreign div { color : $ { currentTheme == = ' dark ' ? ' #ffffff ' : ' #000000 ' } ; font - family : sans - serif ; font - size : 14 px ; }
h1 { font - size : 22 px ; font - weight : 700 ; margin : 0 ; }
h2 { font - size : 18 px ; font - weight : 600 ; margin : 0 ; }
strong { font - weight : 700 ; }
. markmap - link { stroke : $ { currentTheme == = ' dark ' ? ' #cbd5e1 ' : ' #546e7a ' } ; }
. markmap - node circle , . markmap - node rect { stroke : $ { currentTheme == = ' dark ' ? ' #94a3b8 ' : ' #94a3b8 ' } ; }
` ;
clonedSvg . prepend ( style ) ;
const svgData = new XMLSerializer ( ) . serializeToString ( clonedSvg ) ;
copyToClipboard ( svgData , downloadSvgBtn ) ;
} ;
2025-12-20 12:34:49 +08:00
2025-12-31 02:00:10 +08:00
const handleDownloadMD = ( ) = > {
const markdownContent = document . getElementById ( ' markdown-source- ' + uniqueId ) ? . textContent | | ' ' ;
if ( ! markdownContent ) return ;
copyToClipboard ( markdownContent , downloadMdBtn ) ;
} ;
const handleDownloadPNG = ( ) = > {
const btn = downloadPngBtn ;
2026-02-21 17:50:44 +08:00
const btnTextEl = btn . querySelector ( ' .btn-text ' ) | | btn ;
const originalText = btnTextEl . textContent ;
btnTextEl . textContent = i18n . js_generating ;
2025-12-31 02:00:10 +08:00
btn . disabled = true ;
const svg = containerEl . querySelector ( ' svg ' ) ;
if ( ! svg ) {
2026-02-21 17:50:44 +08:00
btnTextEl . textContent = originalText ;
2025-12-31 02:00:10 +08:00
btn . disabled = false ;
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
showFeedback ( btn , i18n . js_failed , i18n . js_failed ) ;
2025-12-31 02:00:10 +08:00
return ;
}
try {
/ / Clone SVG and inline styles
const clonedSvg = svg . cloneNode ( true ) ;
clonedSvg . setAttribute ( ' xmlns ' , ' http://www.w3.org/2000/svg ' ) ;
clonedSvg . setAttribute ( ' xmlns:xlink ' , ' http://www.w3.org/1999/xlink ' ) ;
const rect = svg . getBoundingClientRect ( ) ;
const width = rect . width | | 800 ;
const height = rect . height | | 600 ;
clonedSvg . setAttribute ( ' width ' , width ) ;
clonedSvg . setAttribute ( ' height ' , height ) ;
/ / Remove foreignObject ( HTML content ) and replace with text
const foreignObjects = clonedSvg . querySelectorAll ( ' foreignObject ' ) ;
foreignObjects . forEach ( fo = > {
const text = fo . textContent | | ' ' ;
const g = document . createElementNS ( ' http://www.w3.org/2000/svg ' , ' g ' ) ;
const textEl = document . createElementNS ( ' http://www.w3.org/2000/svg ' , ' text ' ) ;
textEl . setAttribute ( ' x ' , fo . getAttribute ( ' x ' ) | | ' 0 ' ) ;
textEl . setAttribute ( ' y ' , ( parseFloat ( fo . getAttribute ( ' y ' ) | | ' 0 ' ) + 14 ) . toString ( ) ) ;
textEl . setAttribute ( ' fill ' , currentTheme == = ' dark ' ? ' #ffffff ' : ' #000000 ' ) ;
textEl . setAttribute ( ' font-family ' , ' sans-serif ' ) ;
textEl . setAttribute ( ' font-size ' , ' 14 ' ) ;
textEl . textContent = text . trim ( ) ;
g . appendChild ( textEl ) ;
fo . parentNode . replaceChild ( g , fo ) ;
} ) ;
/ / Inline styles
const style = document . createElementNS ( ' http://www.w3.org/2000/svg ' , ' style ' ) ;
style . textContent = `
text { font - family : sans - serif ; font - size : 14 px ; fill : $ { currentTheme == = ' dark ' ? ' #ffffff ' : ' #000000 ' } ; }
. markmap - link { fill : none ; stroke : $ { currentTheme == = ' dark ' ? ' #cbd5e1 ' : ' #546e7a ' } ; stroke - width : 2 ; }
. markmap - node circle { stroke : $ { currentTheme == = ' dark ' ? ' #94a3b8 ' : ' #94a3b8 ' } ; stroke - width : 2 ; }
` ;
clonedSvg . insertBefore ( style , clonedSvg . firstChild ) ;
/ / Add background rect
const bgRect = document . createElementNS ( ' http://www.w3.org/2000/svg ' , ' rect ' ) ;
bgRect . setAttribute ( ' width ' , ' 100 % ' ) ;
bgRect . setAttribute ( ' height ' , ' 100 % ' ) ;
bgRect . setAttribute ( ' fill ' , currentTheme == = ' dark ' ? ' #1f2937 ' : ' #ffffff ' ) ;
clonedSvg . insertBefore ( bgRect , clonedSvg . firstChild ) ;
const svgData = new XMLSerializer ( ) . serializeToString ( clonedSvg ) ;
const svgBase64 = btoa ( unescape ( encodeURIComponent ( svgData ) ) ) ;
const dataUrl = ' data:image/svg+xml;base64, ' + svgBase64 ;
const img = new Image ( ) ;
img . onload = ( ) = > {
const canvas = document . createElement ( ' canvas ' ) ;
const scale = 9 ;
canvas . width = width * scale ;
canvas . height = height * scale ;
const ctx = canvas . getContext ( ' 2d ' ) ;
ctx . scale ( scale , scale ) ;
ctx . fillStyle = currentTheme == = ' dark ' ? ' #1f2937 ' : ' #ffffff ' ;
ctx . fillRect ( 0 , 0 , width , height ) ;
ctx . drawImage ( img , 0 , 0 , width , height ) ;
canvas . toBlob ( ( blob ) = > {
if ( ! blob ) {
2026-02-21 17:50:44 +08:00
btnTextEl . textContent = originalText ;
2025-12-31 02:00:10 +08:00
btn . disabled = false ;
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
showFeedback ( btn , i18n . js_failed , i18n . js_failed ) ;
2025-12-31 02:00:10 +08:00
return ;
}
/ / Use non - bubbling MouseEvent to avoid router interception
const a = document . createElement ( ' a ' ) ;
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
a . download = i18n . js_filename ;
2025-12-31 02:00:10 +08:00
a . href = URL . createObjectURL ( blob ) ;
a . style . display = ' none ' ;
document . body . appendChild ( a ) ;
const evt = new MouseEvent ( ' click ' , {
view : window ,
bubbles : false ,
cancelable : false
} ) ;
a . dispatchEvent ( evt ) ;
setTimeout ( ( ) = > {
document . body . removeChild ( a ) ;
URL . revokeObjectURL ( a . href ) ;
} , 100 ) ;
2026-02-21 17:50:44 +08:00
btnTextEl . textContent = originalText ;
2025-12-31 02:00:10 +08:00
btn . disabled = false ;
showFeedback ( btn ) ;
} , ' image/png ' ) ;
} ;
img . onerror = ( e ) = > {
console . error ( ' PNG image load error: ' , e ) ;
2026-02-21 17:50:44 +08:00
btnTextEl . textContent = originalText ;
2025-12-31 02:00:10 +08:00
btn . disabled = false ;
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
showFeedback ( btn , i18n . js_failed , i18n . js_failed ) ;
2025-12-31 02:00:10 +08:00
} ;
img . src = dataUrl ;
} catch ( err ) {
console . error ( ' PNG export error: ' , err ) ;
2026-02-21 17:50:44 +08:00
btnTextEl . textContent = originalText ;
2025-12-31 02:00:10 +08:00
btn . disabled = false ;
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
showFeedback ( btn , i18n . js_failed , i18n . js_failed ) ;
2025-12-31 02:00:10 +08:00
}
} ;
const handleZoom = ( direction ) = > {
if ( direction == = ' reset ' ) {
markmapInstance . fit ( ) ;
return ;
}
/ / Simple zoom simulation if d3 zoom instance is not accessible
/ / Markmap uses d3 - zoom , so we can try to select the svg and transition
const svg = d3 . select ( svgEl ) ;
/ / We can ' t easily access the internal zoom behavior object created by markmap
/ / So we rely on fit ( ) for reset , and maybe just let user scroll / pinch for zoom
/ / Or we can try to rescale if supported
if ( markmapInstance . rescale ) {
const scale = direction == = ' in ' ? 1.25 : 0.8 ;
markmapInstance . rescale ( scale ) ;
} else {
/ / Fallback : just fit , as manual transform manipulation conflicts with d3
/ / Or we could try to find the zoom behavior attached to the node
/ / const zoom = d3 . zoomTransform ( svgEl ) ;
/ / But we need the zoom behavior function to call scaleBy
}
} ;
2026-02-21 17:50:44 +08:00
const setExpandLevel = ( levelStr ) = > {
const level = parseInt ( levelStr , 10 ) ;
2025-12-31 02:00:10 +08:00
const expandLevel = level == = 0 ? Infinity : level ;
2026-02-21 17:50:44 +08:00
/ / Recursively set fold state on cloned tree nodes
const applyFold = ( node , currentDepth ) = > {
if ( ! node ) return ;
if ( ! node . payload ) node . payload = { } ;
if ( expandLevel == = Infinity ) {
/ / Expand ALL : clear all fold flags
node . payload . fold = 0 ;
} else {
/ / Fold any node deeper than the target level
node . payload . fold = currentDepth > = expandLevel ? 1 : 0 ;
}
if ( node . children ) {
node . children . forEach ( child = > applyFold ( child , currentDepth + 1 ) ) ;
}
} ;
2025-12-31 02:00:10 +08:00
const cleanRoot = JSON . parse ( JSON . stringify ( root ) ) ;
2026-02-21 17:50:44 +08:00
applyFold ( cleanRoot , 0 ) ;
2025-12-31 02:00:10 +08:00
markmapInstance . setOptions ( { initialExpandLevel : expandLevel } ) ;
markmapInstance . setData ( cleanRoot ) ;
2026-02-21 17:50:44 +08:00
setTimeout ( ( ) = > markmapInstance . fit ( ) , 50 ) ;
} ;
const handleDepthChange = ( e ) = > {
setExpandLevel ( e . target . value ) ;
2025-12-31 02:00:10 +08:00
} ;
const handleFullscreen = ( ) = > {
2026-02-21 17:50:44 +08:00
const el = wrapper | | containerEl ;
2025-12-31 02:00:10 +08:00
if ( ! document . fullscreenElement ) {
el . requestFullscreen ( ) . then ( ( ) = > {
2026-02-21 17:50:44 +08:00
if ( depthSelect ) depthSelect . value = " 0 " ;
setExpandLevel ( " 0 " ) ;
} ) . catch ( err = > {
console . error ( ' Fullscreen failed: ' , err ) ;
/ / Fallback to container if wrapper fails
containerEl . requestFullscreen ( ) . then ( ( ) = > {
if ( depthSelect ) depthSelect . value = " 0 " ;
setExpandLevel ( " 0 " ) ;
} ) ;
2025-12-31 02:00:10 +08:00
} ) ;
} else {
document . exitFullscreen ( ) ;
}
} ;
document . addEventListener ( ' fullscreenchange ' , ( ) = > {
2026-02-21 17:50:44 +08:00
const isFs = ! ! document . fullscreenElement ;
if ( isFs & & ( document . fullscreenElement == = containerEl | | document . fullscreenElement == = wrapper ) ) {
setTimeout ( ( ) = > markmapInstance . fit ( ) , 300 ) ;
} else if ( ! isFs ) {
/ / Revert to default depth when exiting fullscreen
const defaultLevel = " 3 " ;
if ( depthSelect ) depthSelect . value = defaultLevel ;
setExpandLevel ( defaultLevel ) ;
2025-12-31 02:00:10 +08:00
}
} ) ;
const handleThemeToggle = ( ) = > {
currentTheme = currentTheme == = ' dark ' ? ' light ' : ' dark ' ;
setTheme ( wrapper , currentTheme ) ;
} ;
downloadSvgBtn ? . addEventListener ( ' click ' , ( e ) = > { e . stopPropagation ( ) ; handleDownloadSVG ( ) ; } ) ;
downloadMdBtn ? . addEventListener ( ' click ' , ( e ) = > { e . stopPropagation ( ) ; handleDownloadMD ( ) ; } ) ;
downloadPngBtn ? . addEventListener ( ' click ' , ( e ) = > { e . stopPropagation ( ) ; handleDownloadPNG ( ) ; } ) ;
zoomInBtn ? . addEventListener ( ' click ' , ( e ) = > { e . stopPropagation ( ) ; handleZoom ( ' in ' ) ; } ) ;
zoomOutBtn ? . addEventListener ( ' click ' , ( e ) = > { e . stopPropagation ( ) ; handleZoom ( ' out ' ) ; } ) ;
zoomResetBtn ? . addEventListener ( ' click ' , ( e ) = > { e . stopPropagation ( ) ; handleZoom ( ' reset ' ) ; } ) ;
depthSelect ? . addEventListener ( ' change ' , ( e ) = > { e . stopPropagation ( ) ; handleDepthChange ( e ) ; } ) ;
fullscreenBtn ? . addEventListener ( ' click ' , ( e ) = > { e . stopPropagation ( ) ; handleFullscreen ( ) ; } ) ;
themeToggleBtn ? . addEventListener ( ' click ' , ( e ) = > { e . stopPropagation ( ) ; handleThemeToggle ( ) ; } ) ;
2025-12-20 12:34:49 +08:00
} ;
if ( document . readyState == = ' loading ' ) {
document . addEventListener ( ' DOMContentLoaded ' , renderMindmap ) ;
} else {
renderMindmap ( ) ;
}
} ) ( ) ;
< / script >
"""
class Action :
class Valves ( BaseModel ) :
2025-12-20 17:03:40 +08:00
SHOW_STATUS : bool = Field (
2025-12-20 12:34:49 +08:00
default = True ,
description = " Whether to show action status updates in the chat interface. " ,
)
2025-12-20 17:03:40 +08:00
MODEL_ID : str = Field (
2025-12-20 14:59:55 +08:00
default = " " ,
description = " Built-in LLM model ID for text analysis. If empty, uses the current conversation ' s model. " ,
2025-12-20 12:34:49 +08:00
)
MIN_TEXT_LENGTH : int = Field (
default = 100 ,
description = " Minimum text length (character count) required for mind map analysis. " ,
)
2025-12-20 15:07:41 +08:00
CLEAR_PREVIOUS_HTML : bool = Field (
default = False ,
2025-12-20 15:43:58 +08:00
description = " Whether to force clear previous plugin results (if True, overwrites instead of merging). " ,
2025-12-20 15:07:41 +08:00
)
2025-12-28 20:08:50 +08:00
MESSAGE_COUNT : int = Field (
default = 1 ,
description = " Number of recent messages to use for generation. Set to 1 for just the last message, or higher for more context. " ,
)
2026-01-06 19:26:43 +08:00
OUTPUT_MODE : str = Field (
default = " html " ,
description = " Output mode: ' html ' for interactive HTML (default), or ' image ' to embed as Markdown image. " ,
)
2026-01-15 00:24:52 +08:00
SHOW_DEBUG_LOG : bool = Field (
default = False ,
description = " Whether to print debug logs in the browser console. " ,
)
2026-02-21 17:50:44 +08:00
ENABLE_DIRECT_EMBED_MODE : bool = Field (
2026-03-16 00:02:53 +08:00
default = True ,
description = " Enable Direct Embed Mode (v0.8.0+ layout) instead of Legacy Mode. Defaults to True (Direct Embed Mode). " ,
2026-02-21 17:50:44 +08:00
)
2025-12-20 12:34:49 +08:00
def __init__ ( self ) :
self . valves = self . Valves ( )
self . weekday_map = {
" Monday " : " Monday " ,
" Tuesday " : " Tuesday " ,
" Wednesday " : " Wednesday " ,
" Thursday " : " Thursday " ,
" Friday " : " Friday " ,
" Saturday " : " Saturday " ,
" Sunday " : " Sunday " ,
}
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
# Fallback mapping for variants not in TRANSLATIONS keys
self . fallback_map = {
" es-AR " : " es-ES " ,
" es-MX " : " es-ES " ,
" fr-CA " : " fr-FR " ,
" en-CA " : " en-US " ,
" en-GB " : " en-US " ,
" en-AU " : " en-US " ,
" de-AT " : " de-DE " ,
}
2026-02-12 17:41:52 +00:00
def _resolve_language ( self , lang : str ) - > str :
""" Resolve the best matching language code from the TRANSLATIONS dict. """
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
target_lang = lang
# 1. Direct match
2026-02-12 17:41:52 +00:00
if target_lang in TRANSLATIONS :
return target_lang
# 2. Variant fallback (explicit mapping)
if target_lang in self . fallback_map :
target_lang = self . fallback_map [ target_lang ]
if target_lang in TRANSLATIONS :
return target_lang
# 3. Base language fallback (e.g. fr-BE -> fr-FR)
# Check if the base language (part before -) exists in translations
2026-02-21 17:50:44 +08:00
if " - " in lang :
base_lang = lang . split ( " - " ) [ 0 ]
2026-02-12 17:41:52 +00:00
# Try to find a supported language starting with base_lang
# Prioritize standard variants (e.g., fr -> fr-FR)
for supported_lang in TRANSLATIONS :
if supported_lang . startswith ( base_lang + " - " ) :
return supported_lang
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
# 4. Final Fallback to en-US
2026-02-12 17:41:52 +00:00
return " en-US "
def _get_translation ( self , lang : str , key : str , * * kwargs ) - > str :
""" Get translated string for the given language and key. """
target_lang = self . _resolve_language ( lang )
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
# Retrieve dictionary
lang_dict = TRANSLATIONS . get ( target_lang , TRANSLATIONS [ " en-US " ] )
# Get string
text = lang_dict . get ( key , TRANSLATIONS [ " en-US " ] . get ( key , key ) )
# Format if arguments provided
if kwargs :
try :
text = text . format ( * * kwargs )
except Exception as e :
logger . warning ( f " Translation formatting failed for { key } : { e } " )
return text
2026-01-28 11:09:18 +08:00
async def _get_user_context (
self ,
__user__ : Optional [ Dict [ str , Any ] ] ,
__event_call__ : Optional [ Callable [ [ Any ] , Awaitable [ None ] ] ] = None ,
2026-02-23 02:33:59 +08:00
__request__ : Optional [ Request ] = None ,
2026-01-28 11:09:18 +08:00
) - > Dict [ str , str ] :
2025-12-31 02:00:10 +08:00
""" Extract basic user context with safe fallbacks. """
if isinstance ( __user__ , ( list , tuple ) ) :
user_data = __user__ [ 0 ] if __user__ else { }
elif isinstance ( __user__ , dict ) :
user_data = __user__
else :
user_data = { }
2026-01-28 11:09:18 +08:00
user_id = user_data . get ( " id " , " unknown_user " )
user_name = user_data . get ( " name " , " User " )
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
# Default from profile
2026-01-28 11:09:18 +08:00
user_language = user_data . get ( " language " , " en-US " )
2026-02-23 02:33:59 +08:00
# Level 1 Fallback: Accept-Language from __request__ headers
if (
__request__
and hasattr ( __request__ , " headers " )
and " accept-language " in __request__ . headers
) :
raw_lang = __request__ . headers . get ( " accept-language " , " " )
if raw_lang :
user_language = raw_lang . split ( " , " ) [ 0 ] . split ( " ; " ) [ 0 ]
# Priority: Document Lang > LocalStorage (Frontend) > Browser > Request Header > Profile
2026-01-28 11:09:18 +08:00
if __event_call__ :
try :
js_code = """
2026-02-23 02:33:59 +08:00
try {
return (
document . documentElement . lang | |
localStorage . getItem ( ' locale ' ) | |
localStorage . getItem ( ' language ' ) | |
navigator . language | |
' en-US '
) ;
} catch ( e ) {
return ' en-US ' ;
}
2026-01-28 11:09:18 +08:00
"""
2026-02-23 02:33:59 +08:00
# Use asyncio.wait_for to prevent hanging if frontend fails to callback
frontend_lang = await asyncio . wait_for (
__event_call__ ( { " type " : " execute " , " data " : { " code " : js_code } } ) ,
timeout = 2.0 ,
2026-01-28 11:09:18 +08:00
)
if frontend_lang and isinstance ( frontend_lang , str ) :
user_language = frontend_lang
except Exception as e :
logger . warning ( f " Failed to retrieve frontend language: { e } " )
2025-12-31 02:00:10 +08:00
return {
2026-01-28 11:09:18 +08:00
" user_id " : user_id ,
" user_name " : user_name ,
" user_language " : user_language ,
2025-12-31 02:00:10 +08:00
}
2026-01-15 00:24:52 +08:00
def _get_chat_context (
self , body : dict , __metadata__ : Optional [ dict ] = None
) - > Dict [ str , str ] :
"""
Unified extraction of chat context information ( chat_id , message_id ) .
Prioritizes extraction from body , then metadata .
"""
chat_id = " "
message_id = " "
2026-01-06 19:26:43 +08:00
2026-01-15 00:24:52 +08:00
# 1. Try to get from body
2026-01-06 19:26:43 +08:00
if isinstance ( body , dict ) :
2026-01-15 00:24:52 +08:00
chat_id = body . get ( " chat_id " , " " )
message_id = body . get ( " id " , " " ) # message_id is usually 'id' in body
# Check body.metadata as fallback
if not chat_id or not message_id :
body_metadata = body . get ( " metadata " , { } )
if isinstance ( body_metadata , dict ) :
if not chat_id :
chat_id = body_metadata . get ( " chat_id " , " " )
if not message_id :
message_id = body_metadata . get ( " message_id " , " " )
# 2. Try to get from __metadata__ (as supplement)
if __metadata__ and isinstance ( __metadata__ , dict ) :
if not chat_id :
chat_id = __metadata__ . get ( " chat_id " , " " )
if not message_id :
message_id = __metadata__ . get ( " message_id " , " " )
2026-01-06 19:26:43 +08:00
2026-01-15 00:24:52 +08:00
return {
" chat_id " : str ( chat_id ) . strip ( ) ,
" message_id " : str ( message_id ) . strip ( ) ,
}
2026-01-06 19:26:43 +08:00
2025-12-20 12:34:49 +08:00
def _extract_markdown_syntax ( self , llm_output : str ) - > str :
match = re . search ( r " ```markdown \ s*(.*?) \ s*``` " , llm_output , re . DOTALL )
if match :
extracted_content = match . group ( 1 ) . strip ( )
else :
logger . warning (
" LLM output did not strictly follow the expected Markdown format, treating the entire output as summary. "
)
extracted_content = llm_output . strip ( )
return extracted_content . replace ( " </script> " , " < \\ /script> " )
2025-12-20 17:03:40 +08:00
async def _emit_status ( self , emitter , description : str , done : bool = False ) :
""" Emits a status update event. """
if self . valves . SHOW_STATUS and emitter :
await emitter (
{ " type " : " status " , " data " : { " description " : description , " done " : done } }
)
async def _emit_notification ( self , emitter , content : str , ntype : str = " info " ) :
""" Emits a notification event (info/success/warning/error). """
if emitter :
await emitter (
{ " type " : " notification " , " data " : { " type " : ntype , " content " : content } }
)
2026-01-15 00:24:52 +08:00
async def _emit_debug_log ( self , emitter , title : str , data : dict ) :
""" Print structured debug logs in the browser console """
if not self . valves . SHOW_DEBUG_LOG or not emitter :
return
try :
js_code = f """
( async function ( ) { {
console . group ( " 🛠️ {title} " ) ;
console . log ( { json . dumps ( data , ensure_ascii = False ) } ) ;
console . groupEnd ( ) ;
} } ) ( ) ;
"""
await emitter ( { " type " : " execute " , " data " : { " code " : js_code } } )
except Exception as e :
print ( f " Error emitting debug log: { e } " )
2025-12-20 15:07:41 +08:00
def _remove_existing_html ( self , content : str ) - > str :
""" Removes existing plugin-generated HTML code blocks from the content. """
pattern = r " ```html \ s*<!-- OPENWEBUI_PLUGIN_OUTPUT -->[ \ s \ S]*?``` "
return re . sub ( pattern , " " , content ) . strip ( )
2025-12-28 20:08:50 +08:00
def _extract_text_content ( self , content ) - > str :
""" Extract text from message content, supporting multimodal message formats """
if isinstance ( content , str ) :
return content
elif isinstance ( content , list ) :
# Multimodal message: [{"type": "text", "text": "..."}, {"type": "image_url", ...}]
text_parts = [ ]
for item in content :
if isinstance ( item , dict ) and item . get ( " type " ) == " text " :
text_parts . append ( item . get ( " text " , " " ) )
elif isinstance ( item , str ) :
text_parts . append ( item )
return " \n " . join ( text_parts )
return str ( content ) if content else " "
2025-12-20 15:43:58 +08:00
def _merge_html (
self ,
existing_html_code : str ,
new_content : str ,
new_styles : str = " " ,
new_scripts : str = " " ,
user_language : str = " en-US " ,
) - > str :
"""
Merges new content into an existing HTML container , or creates a new one .
"""
2026-02-12 17:41:52 +00:00
# Security: Escape user_language to prevent XSS
2026-02-21 17:50:44 +08:00
safe_language = user_language . replace ( ' " ' , " " " )
2026-02-12 17:41:52 +00:00
2025-12-20 15:43:58 +08:00
if (
" <!-- OPENWEBUI_PLUGIN_OUTPUT --> " in existing_html_code
and " <!-- CONTENT_INSERTION_POINT --> " in existing_html_code
) :
base_html = existing_html_code
base_html = re . sub ( r " ^```html \ s* " , " " , base_html )
base_html = re . sub ( r " \ s*```$ " , " " , base_html )
else :
2026-02-12 17:41:52 +00:00
base_html = HTML_WRAPPER_TEMPLATE . replace ( " {lang} " , safe_language )
2025-12-20 15:43:58 +08:00
wrapped_content = f ' <div class= " plugin-item " > \n { new_content } \n </div> '
if new_styles :
base_html = base_html . replace (
" /* STYLES_INSERTION_POINT */ " ,
f " { new_styles } \n /* STYLES_INSERTION_POINT */ " ,
)
base_html = base_html . replace (
" <!-- CONTENT_INSERTION_POINT --> " ,
f " { wrapped_content } \n <!-- CONTENT_INSERTION_POINT --> " ,
)
if new_scripts :
base_html = base_html . replace (
" <!-- SCRIPTS_INSERTION_POINT --> " ,
f " { new_scripts } \n <!-- SCRIPTS_INSERTION_POINT --> " ,
)
return base_html . strip ( )
2026-01-06 19:26:43 +08:00
def _generate_image_js_code (
self ,
unique_id : str ,
chat_id : str ,
message_id : str ,
markdown_syntax : str ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
lang : str ,
2026-01-06 19:26:43 +08:00
) - > str :
""" Generate JavaScript code for frontend SVG rendering and image embedding """
2026-01-06 21:35:27 +08:00
2026-01-06 19:26:43 +08:00
# Escape the syntax for JS embedding
syntax_escaped = (
2026-01-06 21:35:27 +08:00
markdown_syntax . replace ( " \\ " , " \\ \\ " )
2026-01-06 19:26:43 +08:00
. replace ( " ` " , " \\ ` " )
. replace ( " $ { " , " \\ $ { " )
. replace ( " </script> " , " < \\ /script> " )
)
2026-01-06 21:35:27 +08:00
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
# Prepare i18n for this specific context
2026-02-12 17:41:52 +00:00
i18n_data = { }
2026-02-21 17:50:44 +08:00
target_lang = lang
if target_lang not in TRANSLATIONS and target_lang in self . fallback_map :
target_lang = self . fallback_map [ target_lang ]
if target_lang not in TRANSLATIONS :
target_lang = " en-US "
full_trans = TRANSLATIONS . get ( target_lang , TRANSLATIONS [ " en-US " ] )
# We only need specific keys for the JS image generation part
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
keys = [ " js_upload_failed " , " md_image_alt " ]
for k in keys :
i18n_data [ k ] = full_trans . get ( k , TRANSLATIONS [ " en-US " ] . get ( k , k ) )
2026-02-21 17:50:44 +08:00
2026-02-12 17:41:52 +00:00
i18n_json = json . dumps ( i18n_data , ensure_ascii = False )
2026-02-21 17:50:44 +08:00
return f """
( async function ( ) { {
const uniqueId = " {unique_id} " ;
const chatId = " {chat_id} " ;
const messageId = " {message_id} " ;
const i18n = { i18n_json } ;
const defaultWidth = 1200 ;
/ / Theme detection - check parent document for OpenWebUI theme
const detectTheme = ( ) = > { {
try { {
/ / 1. Check parent document ' s html/body class or data-theme
const html = document . documentElement ;
const body = document . body ;
const htmlClass = html ? html . className : ' ' ;
const bodyClass = body ? body . className : ' ' ;
const htmlDataTheme = html ? html . getAttribute ( ' data-theme ' ) : ' ' ;
if ( htmlDataTheme == = ' dark ' | | bodyClass . includes ( ' dark ' ) | | htmlClass . includes ( ' dark ' ) ) { {
return ' dark ' ;
} }
if ( htmlDataTheme == = ' light ' | | bodyClass . includes ( ' light ' ) | | htmlClass . includes ( ' light ' ) ) { {
return ' light ' ;
} }
/ / 2. Check meta theme - color
const metas = document . querySelectorAll ( ' meta[name= " theme-color " ] ' ) ;
if ( metas . length > 0 ) { {
const color = metas [ metas . length - 1 ] . content . trim ( ) ;
const m = color . match ( / ^ #?([0-9a-f]{{6}})$/i);
if ( m ) { {
const hex = m [ 1 ] ;
const r = parseInt ( hex . slice ( 0 , 2 ) , 16 ) ;
const g = parseInt ( hex . slice ( 2 , 4 ) , 16 ) ;
const b = parseInt ( hex . slice ( 4 , 6 ) , 16 ) ;
const luma = ( 0.2126 * r + 0.7152 * g + 0.0722 * b ) / 255 ;
return luma < 0.5 ? ' dark ' : ' light ' ;
} }
} }
/ / 3. Check system preference
if ( window . matchMedia & & window . matchMedia ( ' (prefers-color-scheme: dark) ' ) . matches ) { {
return ' dark ' ;
} }
return ' light ' ;
} } catch ( e ) { {
return ' light ' ;
} }
} } ;
const currentTheme = detectTheme ( ) ;
console . log ( " [MindMap Image] Detected theme: " , currentTheme ) ;
/ / Theme - based colors
const colors = currentTheme == = ' dark ' ? { {
background : ' #1f2937 ' ,
text : ' #e5e7eb ' ,
link : ' #94a3b8 ' ,
nodeStroke : ' #94a3b8 '
} } : { {
background : ' #ffffff ' ,
text : ' #1f2937 ' ,
link : ' #546e7a ' ,
nodeStroke : ' #94a3b8 '
} } ;
/ / Auto - detect chat container width for responsive sizing
let svgWidth = defaultWidth ;
/ / Initial height placeholder , will be adjusted by fit ( )
let svgHeight = 600 ;
const chatContainer = document . getElementById ( ' chat-container ' ) ;
if ( chatContainer ) { {
const containerWidth = chatContainer . clientWidth ;
if ( containerWidth > 100 ) { {
/ / Use container width with some padding ( 90 % of container )
svgWidth = Math . floor ( containerWidth * 0.9 ) ;
} }
} }
try { {
/ / Load D3 if not loaded
if ( typeof d3 == = ' undefined ' ) { {
await new Promise ( ( resolve , reject ) = > { {
const script = document . createElement ( ' script ' ) ;
script . src = ' https://cdn.jsdelivr.net/npm/d3@7 ' ;
script . onload = resolve ;
script . onerror = reject ;
document . head . appendChild ( script ) ;
} } ) ;
} }
2026-01-06 19:26:43 +08:00
2026-02-21 17:50:44 +08:00
/ / Load markmap - lib if not loaded
if ( ! window . markmap | | ! window . markmap . Transformer ) { {
await new Promise ( ( resolve , reject ) = > { {
const script = document . createElement ( ' script ' ) ;
script . src = ' https://cdn.jsdelivr.net/npm/markmap-lib@0.17 ' ;
script . onload = resolve ;
script . onerror = reject ;
document . head . appendChild ( script ) ;
} } ) ;
} }
/ / Load markmap - view if not loaded
if ( ! window . markmap | | ! window . markmap . Markmap ) { {
await new Promise ( ( resolve , reject ) = > { {
const script = document . createElement ( ' script ' ) ;
script . src = ' https://cdn.jsdelivr.net/npm/markmap-view@0.17 ' ;
script . onload = resolve ;
script . onerror = reject ;
document . head . appendChild ( script ) ;
} } ) ;
} }
const { { Transformer , Markmap } } = window . markmap ;
/ / Get markdown syntax
let syntaxContent = ` { syntax_escaped } ` ;
/ / Create offscreen container
const container = document . createElement ( ' div ' ) ;
container . id = ' mindmap-offscreen- ' + uniqueId ;
/ / Start with a reasonably large height to allow layout , but we ' ll crop it later
container . style . cssText = ' position:absolute;left:-9999px;top:-9999px;width: ' + svgWidth + ' px;height:2000px;overflow:hidden; ' ;
document . body . appendChild ( container ) ;
/ / Create SVG element
const svgEl = document . createElementNS ( ' http://www.w3.org/2000/svg ' , ' svg ' ) ;
svgEl . setAttribute ( ' width ' , svgWidth ) ;
svgEl . setAttribute ( ' height ' , ' 2000 ' ) ; / / Initial large height
svgEl . style . width = svgWidth + ' px ' ;
svgEl . style . height = ' 2000px ' ;
svgEl . style . backgroundColor = colors . background ;
container . appendChild ( svgEl ) ;
/ / Transform markdown to tree
const transformer = new Transformer ( ) ;
const { { root } } = transformer . transform ( syntaxContent ) ;
/ / Create markmap instance
const options = { {
autoFit : false , / / We will manually fit and measure
initialExpandLevel : Infinity ,
zoom : false ,
pan : false ,
maxWidth : 280
} } ;
const markmapInstance = Markmap . create ( svgEl , options , root ) ;
/ / Wait for render to complete
await new Promise ( resolve = > setTimeout ( resolve , 1000 ) ) ;
/ / Fit to content to get bounds
markmapInstance . fit ( ) ;
/ / Calculate actual content height based on the graph state
/ / Markmap D3 logic : minY , maxY are stored in state or we can measure the group
let minY = Infinity ;
let maxY = - Infinity ;
/ / Inspect D3 nodes to find bounding box
const nodes = svgEl . querySelectorAll ( ' g.markmap-node ' ) ;
if ( nodes . length > 0 ) { {
/ / This is a rough estimation . Better to use D3 ' s getBBox if possible
/ / But we are in an isolated context .
/ / Let ' s try to get the main group transform which markmap sets for zoom/pan
const g = svgEl . querySelector ( ' g ' ) ;
if ( g ) { {
const bbox = g . getBBox ( ) ;
/ / Markmap applies a transform to ' g ' to center it .
/ / We want to adjust the SVG height to match this bbox height + padding
/ / And re - center .
/ / Add some padding
const padding = 20 ;
const contentHeight = bbox . height + ( padding * 2 ) ;
const contentWidth = bbox . width + ( padding * 2 ) ;
/ / Update SVG height to fit content exactly
svgHeight = Math . ceil ( contentHeight ) ;
/ / Ensure minimum height
if ( svgHeight < 300 ) svgHeight = 300 ;
svgEl . setAttribute ( ' height ' , svgHeight ) ;
svgEl . style . height = svgHeight + ' px ' ;
/ / Re - fit with new dimensions
markmapInstance . fit ( ) ;
await new Promise ( resolve = > setTimeout ( resolve , 500 ) ) ;
} }
} }
/ / Clone and prepare SVG for export
const clonedSvg = svgEl . cloneNode ( true ) ;
clonedSvg . setAttribute ( ' xmlns ' , ' http://www.w3.org/2000/svg ' ) ;
clonedSvg . setAttribute ( ' xmlns:xlink ' , ' http://www.w3.org/1999/xlink ' ) ;
/ / Explicitly set the final width / height on the cloned SVG
clonedSvg . setAttribute ( ' width ' , svgWidth ) ;
clonedSvg . setAttribute ( ' height ' , svgHeight ) ;
/ / Add background rect with theme color
const bgRect = document . createElementNS ( ' http://www.w3.org/2000/svg ' , ' rect ' ) ;
bgRect . setAttribute ( ' width ' , ' 100 % ' ) ;
bgRect . setAttribute ( ' height ' , ' 100 % ' ) ;
bgRect . setAttribute ( ' fill ' , colors . background ) ;
clonedSvg . insertBefore ( bgRect , clonedSvg . firstChild ) ;
/ / Add inline styles with theme colors
const style = document . createElementNS ( ' http://www.w3.org/2000/svg ' , ' style ' ) ;
style . textContent = `
text { { font - family : sans - serif ; font - size : 14 px ; fill : $ { { colors . text } } ; } }
foreignObject , . markmap - foreign , . markmap - foreign div { { color : $ { { colors . text } } ; font - family : sans - serif ; font - size : 14 px ; } }
h1 { { font - size : 22 px ; font - weight : 700 ; margin : 0 ; } }
h2 { { font - size : 18 px ; font - weight : 600 ; margin : 0 ; } }
strong { { font - weight : 700 ; } }
. markmap - link { { stroke : $ { { colors . link } } ; fill : none ; } }
. markmap - node circle , . markmap - node rect { { stroke : $ { { colors . nodeStroke } } ; } }
` ;
clonedSvg . insertBefore ( style , bgRect . nextSibling ) ;
/ / Convert foreignObject to text for better compatibility
const foreignObjects = clonedSvg . querySelectorAll ( ' foreignObject ' ) ;
foreignObjects . forEach ( fo = > { {
const text = fo . textContent | | ' ' ;
const g = document . createElementNS ( ' http://www.w3.org/2000/svg ' , ' g ' ) ;
const textEl = document . createElementNS ( ' http://www.w3.org/2000/svg ' , ' text ' ) ;
textEl . setAttribute ( ' x ' , fo . getAttribute ( ' x ' ) | | ' 0 ' ) ;
textEl . setAttribute ( ' y ' , ( parseFloat ( fo . getAttribute ( ' y ' ) | | ' 0 ' ) + 14 ) . toString ( ) ) ;
textEl . setAttribute ( ' fill ' , colors . text ) ;
textEl . setAttribute ( ' font-family ' , ' sans-serif ' ) ;
textEl . setAttribute ( ' font-size ' , ' 14 ' ) ;
textEl . textContent = text . trim ( ) ;
g . appendChild ( textEl ) ;
fo . parentNode . replaceChild ( g , fo ) ;
} } ) ;
/ / Serialize SVG to string
const svgData = new XMLSerializer ( ) . serializeToString ( clonedSvg ) ;
/ / Cleanup container
document . body . removeChild ( container ) ;
/ / Convert SVG string to Blob
const blob = new Blob ( [ svgData ] , { { type : ' image/svg+xml ' } } ) ;
const file = new File ( [ blob ] , ` mindmap - $ { { uniqueId } } . svg ` , { { type : ' image/svg+xml ' } } ) ;
/ / Upload file to OpenWebUI API
const token = localStorage . getItem ( " token " ) ;
const formData = new FormData ( ) ;
formData . append ( ' file ' , file ) ;
const uploadResponse = await fetch ( ' /api/v1/files/ ' , { {
method : ' POST ' ,
headers : { {
' Authorization ' : ` Bearer $ { { token } } `
} } ,
body : formData
} } ) ;
if ( ! uploadResponse . ok ) { {
throw new Error ( i18n . js_upload_failed + uploadResponse . statusText ) ;
} }
const fileData = await uploadResponse . json ( ) ;
const fileId = fileData . id ;
const imageUrl = ` / api / v1 / files / $ { { fileId } } / content ` ;
const markdownImage = ` ! [ $ { { i18n . md_image_alt } } ] ( $ { { imageUrl } } ) ` ;
/ / Update message via API
if ( chatId & & messageId ) { {
/ / Helper function with retry logic
const fetchWithRetry = async ( url , options , retries = 3 ) = > { {
for ( let i = 0 ; i < retries ; i + + ) { {
try { {
const response = await fetch ( url , options ) ;
if ( response . ok ) return response ;
if ( i < retries - 1 ) { {
await new Promise ( r = > setTimeout ( r , 1000 * ( i + 1 ) ) ) ;
} }
} } catch ( e ) { {
if ( i == = retries - 1 ) throw e ;
await new Promise ( r = > setTimeout ( r , 1000 * ( i + 1 ) ) ) ;
} }
} }
return null ;
} } ;
/ / Get current chat data
const getResponse = await fetch ( ` / api / v1 / chats / $ { { chatId } } ` , { {
method : " GET " ,
headers : { { " Authorization " : ` Bearer $ { { token } } ` } }
} } ) ;
if ( ! getResponse . ok ) { {
throw new Error ( " Failed to get chat data: " + getResponse . status ) ;
} }
const chatData = await getResponse . json ( ) ;
let updatedMessages = [ ] ;
let newContent = " " ;
if ( chatData . chat & & chatData . chat . messages ) { {
updatedMessages = chatData . chat . messages . map ( m = > { {
if ( m . id == = messageId ) { {
const originalContent = m . content | | " " ;
const mindmapPattern = / \\n * ! \\[ [ ^ [ \\] ] * \\] \\( ( ? : data : image \\/ [ ^ ) ] + | ( ? : \\/ api \\/ v1 \\/ files \\/ [ ^ ) ] + ) ) \\) / g ;
let cleanedContent = originalContent . replace ( mindmapPattern , " " ) ;
cleanedContent = cleanedContent . replace ( / \\n { { 3 , } } / g , " \\ n \\ n " ) . trim ( ) ;
newContent = cleanedContent + " \\ n \\ n " + markdownImage ;
/ / Critical : Update content in both messages array AND history object
/ / The history object is the source of truth for the database
if ( chatData . chat . history & & chatData . chat . history . messages ) { {
if ( chatData . chat . history . messages [ messageId ] ) { {
chatData . chat . history . messages [ messageId ] . content = newContent ;
} }
} }
return { { . . . m , content : newContent } } ;
} }
return m ;
} } ) ;
} }
if ( ! newContent ) { {
return ;
} }
/ / Try to update frontend display via event API ( optional )
try { {
await fetch ( ` / api / v1 / chats / $ { { chatId } } / messages / $ { { messageId } } / event ` , { {
method : " POST " ,
headers : { {
" Content-Type " : " application/json " ,
" Authorization " : ` Bearer $ { { token } } `
} } ,
body : JSON . stringify ( { {
type : " chat:message " ,
data : { { content : newContent } }
} } )
} } ) ;
} } catch ( eventErr ) { {
} }
/ / Persist to database
const updatePayload = { {
chat : { {
. . . chatData . chat ,
messages : updatedMessages
} }
} } ;
await fetchWithRetry ( ` / api / v1 / chats / $ { { chatId } } ` , { {
method : " POST " ,
headers : { {
" Content-Type " : " application/json " ,
" Authorization " : ` Bearer $ { { token } } `
} } ,
body : JSON . stringify ( updatePayload )
} } ) ;
} }
} } catch ( error ) { {
console . error ( " [MindMap Image] Error: " , error ) ;
} }
} } ) ( ) ;
"""
CSS_TEMPLATE_MINDMAP_DIRECT = """
: root {
- - primary - color : #1e88e5;
- - secondary - color : #43a047;
- - background - color : #f4f6f8;
- - card - bg - color : #ffffff;
- - text - color : #000000;
- - link - color : #546e7a;
- - node - stroke - color : #90a4ae;
- - muted - text - color : #546e7a;
- - border - color : #e0e0e0;
- - header - gradient : linear - gradient ( 135 deg , var ( - - secondary - color ) , var ( - - primary - color ) ) ;
- - shadow : 0 4 px 12 px rgba ( 0 , 0 , 0 , 0.05 ) ;
- - border - radius : 0 ;
- - font - family : - apple - system , BlinkMacSystemFont , " Segoe UI " , Roboto , " Helvetica Neue " , Arial , sans - serif ;
}
. theme - dark {
- - primary - color : #3b82f6; /* High contrast blue */
- - secondary - color : #22c55e; /* High contrast green */
- - background - color : #0d1117; /* Deep background */
- - card - bg - color : #161b22; /* Header background */
- - text - color : #ffffff; /* Pure white text for max contrast */
- - link - color : #58a6ff;
- - node - stroke - color : #8b949e; /* Brighter node lines */
- - muted - text - color : #7d8590;
- - border - color : #30363d;
- - header - gradient : linear - gradient ( 135 deg , #1e88e5, #43a047);
- - shadow : 0 4 px 12 px rgba ( 0 , 0 , 0 , 0.5 ) ;
/ * Legacy Control Styles * /
- - legacy - header - gradient : linear - gradient ( 135 deg , var ( - - secondary - color ) , var ( - - primary - color ) ) ;
}
html , body {
margin : 0 ;
padding : 0 ;
}
body {
font - family : var ( - - font - family ) ;
background - color : transparent ;
display : flex ;
flex - direction : column ;
}
. mindmap - container - wrapper {
font - family : var ( - - font - family ) ;
line - height : 1.5 ;
color : var ( - - text - color ) ;
margin : 0 ;
padding : 0 ;
width : 100 % ;
height : clamp ( 600 px , 85 vh , 1400 px ) ; / * Canvas area even larger * /
display : flex ;
flex - direction : column ;
background : var ( - - background - color ) ;
position : relative ;
overflow : hidden ;
box - sizing : border - box ;
border - radius : 8 px ;
border : 1 px solid var ( - - border - color ) ;
}
. header {
background : var ( - - card - bg - color ) ;
color : var ( - - text - color ) ;
padding : 12 px 16 px ;
display : flex ;
flex - direction : column ;
gap : 12 px ;
flex - shrink : 0 ;
border - bottom : 1 px solid var ( - - border - color ) ;
z - index : 10 ;
}
. header - top {
display : flex ;
align - items : center ;
gap : 12 px ;
}
. header h1 {
margin : 0 ;
font - size : 1.2 em ;
font - weight : 600 ;
letter - spacing : 0.5 px ;
display : flex ;
align - items : center ;
gap : 8 px ;
}
. header - credits {
font - size : 0.8 em ;
color : var ( - - muted - text - color ) ;
opacity : 0.8 ;
white - space : nowrap ;
}
. header - credits a {
color : var ( - - primary - color ) ;
text - decoration : none ;
border - bottom : 1 px dotted var ( - - link - color ) ;
}
. content - area {
flex - grow : 1 ;
position : relative ;
overflow : hidden ;
2026-02-22 00:24:37 +08:00
background : var ( - - card - bg - color ) ;
2026-02-21 17:50:44 +08:00
min - height : 0 ;
width : 100 % ;
height : 100 % ;
}
. markmap - container {
width : 100 % ;
height : 100 % ;
position : absolute ;
top : 0 ;
left : 0 ;
right : 0 ;
bottom : 0 ;
}
. markmap - container svg {
width : 100 % ;
height : 100 % ;
display : block ;
}
. markmap - container svg text {
fill : var ( - - text - color ) ! important ;
font - family : var ( - - font - family ) ;
}
/ * Force override all text containers within markmap * /
. markmap - container foreignObject ,
. markmap - container . markmap - foreign_object ,
. markmap - container . markmap - node - label ,
. markmap - container div {
color : var ( - - text - color ) ! important ;
fill : var ( - - text - color ) ! important ;
}
/ * Optimize branch line colors for dark mode * /
. theme - dark . markmap - link {
stroke - opacity : 0.6 ;
}
. theme - dark . markmap - node circle {
fill : var ( - - card - bg - color ) ! important ;
}
/ * Controls * /
. control - rows {
display : flex ;
align - items : center ;
flex - wrap : wrap ;
gap : 12 px ;
margin - left : auto ; / * Push controls to the right * /
}
. btn - group {
display : inline - flex ;
gap : 4 px ;
align - items : center ;
border : 1 px solid var ( - - border - color ) ;
border - radius : 6 px ;
padding : 2 px ;
background : var ( - - background - color ) ;
}
. control - btn {
background - color : transparent ;
color : var ( - - text - color ) ;
border : none ;
padding : 4 px 10 px ;
border - radius : 4 px ;
font - size : 0.85 em ;
font - weight : 500 ;
cursor : pointer ;
transition : all 0.2 s ease ;
display : inline - flex ;
align - items : center ;
justify - content : center ;
height : 28 px ;
box - sizing : border - box ;
opacity : 0.8 ;
}
. control - btn : hover {
background - color : var ( - - card - bg - color ) ;
opacity : 1 ;
box - shadow : 0 1 px 3 px rgba ( 0 , 0 , 0 , 0.1 ) ;
}
. control - btn : active {
transform : translateY ( 1 px ) ;
}
. control - btn . primary {
background - color : var ( - - primary - color ) ;
color : white ;
opacity : 1 ;
}
. control - btn . primary : hover {
box - shadow : 0 2 px 5 px rgba ( 30 , 136 , 229 , 0.3 ) ;
}
select . control - btn {
appearance : none ;
padding - right : 28 px ;
background - image : url ( " data:image/svg+xml;charset=US-ASCII, % 3Csvg %20x mlns % 3D % 22http % 3A %2F %2F www.w3.org %2F 2000 %2F svg %22% 20width % 3D %22292.4% 22 %20he ight % 3D %22292.4% 22 %3E % 3Cpath %20f ill % 3D %22% 23FFFFFF %22% 20d % 3D % 22M287 %2069.4a 17.6 %2017.6% 200 %200% 200-13-5.4H18.4c-5 % 200-9.3 % 201.8-12.9 % 205.4A17.6 %2017.6% 200 %200% 200 %200% 2082.2c0 %205% 201.8 %209.3% 205.4 % 2012.9l128 %20127.9c 3.6 %203.6% 207.8 %205.4% 2012.8 %205.4s 9.2-1.8 % 2012.8-5.4L287 %2095c 3.5-3.5 % 205.4-7.8 % 205.4-12.8 % 200-5-1.9-9.2-5.5-12.8z %22% 2F %3E % 3C %2F svg %3E " ) ;
background - repeat : no - repeat ;
background - position : right 8 px center ;
background - size : 10 px ;
}
. control - btn option {
background - color : var ( - - card - bg - color ) ;
color : var ( - - text - color ) ;
}
. error - message {
color : #d32f2f;
background - color : #ffebee;
padding : 20 px ;
text - align : center ;
border - bottom : 1 px solid #ffcdd2;
}
/ * Mobile Responsive Adjustments * /
@media screen and ( max - width : 768 px ) {
. mindmap - container - wrapper {
min - height : 480 px ;
height : 75 vh ;
}
. header {
flex - direction : column ;
gap : 10 px ;
}
. btn - group {
padding : 2 px ;
}
. control - btn {
padding : 4 px 6 px ;
font - size : 0.75 em ;
height : 28 px ;
}
select . control - btn {
padding - right : 20 px ;
background - position : right 4 px center ;
}
}
"""
CONTENT_TEMPLATE_MINDMAP_DIRECT = """
< div class = " mindmap-container-wrapper " >
< div class = " header " >
< div class = " header-top " >
< h1 > { t_ui_title } < / h1 >
< div class = " header-credits " >
< span > { t_ui_footer } < / span >
< / div >
< div class = " control-rows " >
< div class = " btn-group " >
< button id = " download-png-btn- {unique_id} " class = " control-btn primary " title = " {t_ui_download_png} " > PNG < / button >
< button id = " download-svg-btn- {unique_id} " class = " control-btn " title = " {t_ui_download_svg} " > SVG < / button >
< button id = " download-md-btn- {unique_id} " class = " control-btn " title = " {t_ui_download_md} " > MD < / button >
2026-03-16 00:02:53 +08:00
< a href = " https://github.com/Fu-Jie/openwebui-extensions " target = " _blank " rel = " noopener noreferrer " title = " Star on GitHub " class = " control-btn star-btn " >
< svg viewBox = " 0 0 24 24 " xmlns = " http://www.w3.org/2000/svg " style = " width: 18px; height: 18px; " >
< path d = " M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z " fill = " currentColor " / >
< / svg >
< / a >
2026-02-21 17:50:44 +08:00
< / div >
< div class = " btn-group " >
< button id = " zoom-out-btn- {unique_id} " class = " control-btn " title = " {t_ui_zoom_out} " > - < / button >
< button id = " zoom-reset-btn- {unique_id} " class = " control-btn " title = " {t_ui_zoom_reset} " > ↺ < / button >
< button id = " zoom-in-btn- {unique_id} " class = " control-btn " title = " {t_ui_zoom_in} " > + < / button >
< / div >
< div class = " btn-group " >
< select id = " depth-select- {unique_id} " class = " control-btn " title = " {t_ui_depth_select} " >
< option value = " 0 " selected > { t_ui_depth_all } < / option >
< option value = " 2 " > { t_ui_depth_2 } < / option >
< option value = " 3 " > { t_ui_depth_3 } < / option >
< / select >
< button id = " fullscreen-btn- {unique_id} " class = " control-btn " title = " {t_ui_fullscreen} " > ⛶ < / button >
< button id = " theme-toggle-btn- {unique_id} " class = " control-btn " title = " {t_ui_theme} " > ◑ < / button >
< / div >
< / div >
< / div >
< / div >
< div class = " content-area " >
< div class = " markmap-container " id = " markmap-container- {unique_id} " > < / div >
< / div >
< / div >
< script type = " text/template " id = " markdown-source- {unique_id} " > { markdown_syntax } < / script >
"""
2026-01-06 19:26:43 +08:00
2025-12-20 12:34:49 +08:00
async def action (
self ,
body : dict ,
__user__ : Optional [ Dict [ str , Any ] ] = None ,
__event_emitter__ : Optional [ Any ] = None ,
2026-01-06 19:26:43 +08:00
__event_call__ : Optional [ Callable [ [ Any ] , Awaitable [ None ] ] ] = None ,
__metadata__ : Optional [ dict ] = None ,
2025-12-20 12:34:49 +08:00
__request__ : Optional [ Request ] = None ,
) - > Optional [ dict ] :
2026-02-21 17:50:44 +08:00
logger . info ( " Action: Smart Mind Map (v1.0.0) started " )
2026-02-23 02:33:59 +08:00
user_ctx = await self . _get_user_context ( __user__ , __event_call__ , __request__ )
2025-12-31 02:00:10 +08:00
user_language = user_ctx [ " user_language " ]
user_name = user_ctx [ " user_name " ]
user_id = user_ctx [ " user_id " ]
2026-02-21 17:50:44 +08:00
long_text_content = " " # Initialize for exception handler safety
2025-12-20 12:34:49 +08:00
try :
2025-12-31 02:00:10 +08:00
tz_env = os . environ . get ( " TZ " )
tzinfo = ZoneInfo ( tz_env ) if tz_env else None
now_dt = datetime . now ( tzinfo or timezone . utc )
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
2026-02-21 17:50:44 +08:00
# Format current date time string for LLM parsing
current_date_time_str = now_dt . strftime ( " % Y- % m- %d % H: % M: % S " )
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
2025-12-31 02:00:10 +08:00
current_weekday_en = now_dt . strftime ( " % A " )
2025-12-20 12:34:49 +08:00
current_weekday_zh = self . weekday_map . get ( current_weekday_en , " Unknown " )
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
2025-12-31 02:00:10 +08:00
current_year = now_dt . strftime ( " % Y " )
current_timezone_str = tz_env or " UTC "
2025-12-20 12:34:49 +08:00
except Exception as e :
logger . warning ( f " Failed to get timezone info: { e } , using default values. " )
now = datetime . now ( )
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
current_date_time_str = now . strftime ( " % Y- % m- %d % H: % M: % S " )
2025-12-20 12:34:49 +08:00
current_weekday_zh = " Unknown "
current_year = now . strftime ( " % Y " )
current_timezone_str = " Unknown "
2025-12-20 17:03:40 +08:00
await self . _emit_notification (
__event_emitter__ ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
self . _get_translation ( user_language , " status_starting " ) ,
2025-12-20 17:03:40 +08:00
" info " ,
)
2025-12-20 12:34:49 +08:00
messages = body . get ( " messages " )
2025-12-28 20:08:50 +08:00
if not messages or not isinstance ( messages , list ) :
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
error_message = self . _get_translation ( user_language , " error_no_content " )
2025-12-20 17:03:40 +08:00
await self . _emit_notification ( __event_emitter__ , error_message , " error " )
2026-02-21 17:50:44 +08:00
body [ " messages " ] . append (
{ " role " : " assistant " , " content " : f " ❌ { error_message } " }
)
return body
2025-12-20 12:34:49 +08:00
2025-12-28 20:08:50 +08:00
# Get last N messages based on MESSAGE_COUNT
message_count = min ( self . valves . MESSAGE_COUNT , len ( messages ) )
recent_messages = messages [ - message_count : ]
# Aggregate content from selected messages with labels
aggregated_parts = [ ]
for i , msg in enumerate ( recent_messages , 1 ) :
text_content = self . _extract_text_content ( msg . get ( " content " ) )
if text_content :
2026-01-04 03:14:28 +08:00
aggregated_parts . append ( f " { text_content } " )
2025-12-28 20:08:50 +08:00
if not aggregated_parts :
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
error_message = self . _get_translation ( user_language , " error_no_content " )
2025-12-28 20:08:50 +08:00
await self . _emit_notification ( __event_emitter__ , error_message , " error " )
2026-02-21 17:50:44 +08:00
body [ " messages " ] . append (
{ " role " : " assistant " , " content " : f " ❌ { error_message } " }
)
return body
2025-12-28 20:08:50 +08:00
original_content = " \n \n --- \n \n " . join ( aggregated_parts )
parts = re . split ( r " ```html.*?``` " , original_content , flags = re . DOTALL )
2025-12-20 12:34:49 +08:00
long_text_content = " "
if parts :
for part in reversed ( parts ) :
if part . strip ( ) :
long_text_content = part . strip ( )
break
if not long_text_content :
2025-12-28 20:08:50 +08:00
long_text_content = original_content . strip ( )
2025-12-20 12:34:49 +08:00
if len ( long_text_content ) < self . valves . MIN_TEXT_LENGTH :
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
short_text_message = self . _get_translation (
user_language ,
" error_text_too_short " ,
len = len ( long_text_content ) ,
2026-02-21 17:50:44 +08:00
min_len = self . valves . MIN_TEXT_LENGTH ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
)
2025-12-20 17:03:40 +08:00
await self . _emit_notification (
__event_emitter__ , short_text_message , " warning "
)
2026-02-21 17:50:44 +08:00
body [ " messages " ] . append (
{ " role " : " assistant " , " content " : f " ⚠️ { short_text_message } " }
)
return body
await self . _emit_notification (
__event_emitter__ ,
self . _get_translation ( user_language , " status_analyzing " ) ,
" info " ,
)
2025-12-20 12:34:49 +08:00
2025-12-20 17:03:40 +08:00
await self . _emit_status (
__event_emitter__ ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
self . _get_translation ( user_language , " status_analyzing " ) ,
2025-12-20 17:03:40 +08:00
False ,
)
2025-12-20 12:34:49 +08:00
try :
unique_id = f " id_ { int ( time . time ( ) * 1000 ) } "
2026-02-21 17:50:44 +08:00
# Prepare LLM request
2025-12-20 12:34:49 +08:00
formatted_user_prompt = USER_PROMPT_GENERATE_MINDMAP . format (
user_name = user_name ,
current_date_time_str = current_date_time_str ,
current_weekday = current_weekday_zh ,
current_timezone_str = current_timezone_str ,
user_language = user_language ,
long_text_content = long_text_content ,
)
2025-12-20 14:59:55 +08:00
# Determine model to use
2025-12-20 17:03:40 +08:00
target_model = self . valves . MODEL_ID
2025-12-20 14:59:55 +08:00
if not target_model :
target_model = body . get ( " model " )
2025-12-20 12:34:49 +08:00
llm_payload = {
2025-12-20 14:59:55 +08:00
" model " : target_model ,
2025-12-20 12:34:49 +08:00
" messages " : [
{ " role " : " system " , " content " : SYSTEM_PROMPT_MINDMAP_ASSISTANT } ,
{ " role " : " user " , " content " : formatted_user_prompt } ,
] ,
" temperature " : 0.5 ,
" stream " : False ,
}
user_obj = Users . get_user_by_id ( user_id )
if not user_obj :
raise ValueError ( f " Unable to get user object, user ID: { user_id } " )
llm_response = await generate_chat_completion (
__request__ , llm_payload , user_obj
)
if (
not llm_response
or " choices " not in llm_response
or not llm_response [ " choices " ]
) :
raise ValueError ( " LLM response format is incorrect or empty. " )
assistant_response_content = llm_response [ " choices " ] [ 0 ] [ " message " ] [
" content "
]
2026-02-21 17:50:44 +08:00
logger . info ( f " LLM Response length: { len ( assistant_response_content ) } " )
if self . valves . SHOW_DEBUG_LOG :
logger . info (
f " LLM Response content: { assistant_response_content [ : 500 ] } ... "
)
2025-12-20 12:34:49 +08:00
markdown_syntax = self . _extract_markdown_syntax ( assistant_response_content )
2025-12-20 15:43:58 +08:00
# Prepare content components
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
# Resolve translations for UI
ui_trans = { }
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 18 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN, zh-TW).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Added explicit support for zh-TW (Traditional Chinese) with correct translations.
- Updated HTML/JS templates to use injected translations.
- Restored clickable "Markmap" link in the footer for all languages.
- Fixed SyntaxWarning in regex strings by properly escaping backslashes in standard strings.
- Implemented robust UI translation loading to prevent crashes on missing keys.
- Verified frontend rendering with Playwright and backend logic with unit tests.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 17:15:50 +00:00
# Iterate over base language keys to ensure no missing placeholders
for k in TRANSLATIONS [ " en-US " ] :
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
if k . startswith ( " ui_ " ) :
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 18 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN, zh-TW).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Added explicit support for zh-TW (Traditional Chinese) with correct translations.
- Updated HTML/JS templates to use injected translations.
- Restored clickable "Markmap" link in the footer for all languages.
- Fixed SyntaxWarning in regex strings by properly escaping backslashes in standard strings.
- Implemented robust UI translation loading to prevent crashes on missing keys.
- Verified frontend rendering with Playwright and backend logic with unit tests.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 17:15:50 +00:00
val = self . _get_translation ( user_language , k )
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
if k == " ui_footer " :
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 18 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN, zh-TW).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Added explicit support for zh-TW (Traditional Chinese) with correct translations.
- Updated HTML/JS templates to use injected translations.
- Restored clickable "Markmap" link in the footer for all languages.
- Fixed SyntaxWarning in regex strings by properly escaping backslashes in standard strings.
- Implemented robust UI translation loading to prevent crashes on missing keys.
- Verified frontend rendering with Playwright and backend logic with unit tests.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 17:15:50 +00:00
ui_trans [ f " t_ { k } " ] = val . format ( year = current_year )
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
else :
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 18 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN, zh-TW).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Added explicit support for zh-TW (Traditional Chinese) with correct translations.
- Updated HTML/JS templates to use injected translations.
- Restored clickable "Markmap" link in the footer for all languages.
- Fixed SyntaxWarning in regex strings by properly escaping backslashes in standard strings.
- Implemented robust UI translation loading to prevent crashes on missing keys.
- Verified frontend rendering with Playwright and backend logic with unit tests.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 17:15:50 +00:00
ui_trans [ f " t_ { k } " ] = val
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
2026-02-12 17:41:52 +00:00
# Security: Use simple string replacement instead of format() to prevent
# crashes if markdown_syntax contains braces { or }.
# Also escape user_name for basic HTML safety.
content_html = CONTENT_TEMPLATE_MINDMAP
for k , v in ui_trans . items ( ) :
content_html = content_html . replace ( f " {{ { k } }} " , v )
2026-02-21 17:50:44 +08:00
content_html = content_html . replace ( " {unique_id} " , unique_id ) . replace (
" {markdown_syntax} " , markdown_syntax
)
2025-12-20 12:34:49 +08:00
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
# Prepare JS i18n
2026-02-12 17:41:52 +00:00
target_lang = self . _resolve_language ( user_language )
full_trans = TRANSLATIONS . get ( target_lang , TRANSLATIONS [ " en-US " ] )
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
js_trans = { }
for k in full_trans :
if k . startswith ( " js_ " ) or k . startswith ( " html_ " ) :
js_trans [ k ] = full_trans [ k ]
2026-02-12 17:41:52 +00:00
i18n_json = json . dumps ( js_trans , ensure_ascii = False )
unique_id_json = json . dumps ( unique_id )
# Note: We don't need chat/message ID in HTML mode JS, but we do need uniqueId and i18n
# The SCRIPT_TEMPLATE_MINDMAP now uses {unique_id_json} for the ID
2026-02-21 17:50:44 +08:00
script_html = (
SCRIPT_TEMPLATE_MINDMAP . replace (
" {unique_id} " ,
unique_id , # Fallback for other non-JSON placeholders if any
)
. replace ( " {unique_id_json} " , unique_id_json )
. replace ( " {i18n_json} " , i18n_json )
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
)
2025-12-20 15:43:58 +08:00
# Extract existing HTML if any
existing_html_block = " "
match = re . search (
r " ```html \ s*(<!-- OPENWEBUI_PLUGIN_OUTPUT -->[ \ s \ S]*?)``` " ,
long_text_content ,
)
if match :
existing_html_block = match . group ( 1 )
2025-12-20 15:07:41 +08:00
if self . valves . CLEAR_PREVIOUS_HTML :
long_text_content = self . _remove_existing_html ( long_text_content )
2025-12-20 15:43:58 +08:00
final_html = self . _merge_html (
" " , content_html , CSS_TEMPLATE_MINDMAP , script_html , user_language
)
else :
# If we found existing HTML, we remove the old block from text and merge into it
if existing_html_block :
long_text_content = self . _remove_existing_html ( long_text_content )
final_html = self . _merge_html (
existing_html_block ,
content_html ,
CSS_TEMPLATE_MINDMAP ,
script_html ,
user_language ,
)
else :
final_html = self . _merge_html (
" " ,
content_html ,
CSS_TEMPLATE_MINDMAP ,
script_html ,
user_language ,
)
2026-01-06 19:26:43 +08:00
# Check output mode
if self . valves . OUTPUT_MODE == " image " :
# Image mode: use JavaScript to render and embed as Markdown image
2026-01-15 00:24:52 +08:00
chat_ctx = self . _get_chat_context ( body , __metadata__ )
chat_id = chat_ctx [ " chat_id " ]
message_id = chat_ctx [ " message_id " ]
2026-01-06 21:35:27 +08:00
2026-01-06 19:26:43 +08:00
await self . _emit_status (
__event_emitter__ ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
self . _get_translation ( user_language , " status_rendering_image " ) ,
2026-01-06 19:26:43 +08:00
False ,
)
2026-01-06 21:35:27 +08:00
2026-01-06 19:26:43 +08:00
if __event_call__ :
js_code = self . _generate_image_js_code (
unique_id = unique_id ,
chat_id = chat_id ,
message_id = message_id ,
markdown_syntax = markdown_syntax ,
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
lang = user_language ,
2026-01-06 19:26:43 +08:00
)
2026-01-06 21:35:27 +08:00
2026-01-06 19:26:43 +08:00
await __event_call__ (
{
" type " : " execute " ,
" data " : { " code " : js_code } ,
}
)
2026-01-06 21:35:27 +08:00
2026-01-06 19:26:43 +08:00
await self . _emit_status (
2026-02-21 17:50:44 +08:00
__event_emitter__ ,
self . _get_translation ( user_language , " status_image_generated " ) ,
True ,
2026-01-06 19:26:43 +08:00
)
await self . _emit_notification (
__event_emitter__ ,
2026-02-21 17:50:44 +08:00
self . _get_translation (
user_language , " notification_image_success " , user_name = user_name
) ,
2026-01-06 19:26:43 +08:00
" success " ,
)
2026-02-21 17:50:44 +08:00
logger . info ( " Action: Smart Mind Map (v1.0.0) completed in image mode " )
2026-01-06 19:26:43 +08:00
return body
2026-01-06 21:35:27 +08:00
2026-02-21 17:50:44 +08:00
# HTML mode
is_direct_mode = self . _is_direct_html_supported ( body )
if is_direct_mode :
# DIRECT EMBED MODE
# Use new templates
content_html_direct = self . CONTENT_TEMPLATE_MINDMAP_DIRECT
for k , v in ui_trans . items ( ) :
content_html_direct = content_html_direct . replace ( f " {{ { k } }} " , v )
content_html_direct = (
content_html_direct . replace ( " {unique_id} " , unique_id )
. replace (
" {user_name} " ,
user_name . replace ( " < " , " < " ) . replace ( " > " , " > " ) ,
)
. replace ( " {current_date_time_str} " , current_date_time_str )
. replace ( " {markdown_syntax} " , markdown_syntax )
)
2025-12-20 12:34:49 +08:00
2026-02-21 17:50:44 +08:00
# Script injection remains similar but tailored if needed
script_html_direct = (
SCRIPT_TEMPLATE_MINDMAP . replace ( " {unique_id} " , unique_id )
. replace ( " {unique_id_json} " , unique_id_json )
. replace ( " {i18n_json} " , i18n_json )
)
# We do NOT wrap in <html> body for Direct Mode if using standard return
# But we still need styles.
# We can prepend styles to the div or return a full html doc?
# The requirements say: `return (html_content, ...)`
# Usually standard Action returns full HTML or fragments.
# If "inline", fragments are better, but styles need to be scoped or global.
# Our CSS templates use specific classes, should be safe.
# But to ensure it renders correctly, we usually wrap in a div.
final_html_direct = f """
< ! DOCTYPE html >
< html >
< head >
< meta charset = " UTF-8 " >
< style >
{ self . CSS_TEMPLATE_MINDMAP_DIRECT }
< / style >
< / head >
< body >
{ content_html_direct }
{ script_html_direct }
< script >
/ / Extra fit insurance for Direct Mode
const triggerFit = ( ) = > { {
const svg = document . querySelector ( ' svg ' ) ;
if ( svg & & window . markmapInstance ) { {
window . markmapInstance . fit ( ) ;
} }
} } ;
window . addEventListener ( ' load ' , ( ) = > { {
triggerFit ( ) ;
setTimeout ( triggerFit , 300 ) ;
setTimeout ( triggerFit , 800 ) ;
} } ) ;
/ / Also trigger on resize
window . addEventListener ( ' resize ' , triggerFit ) ;
< / script >
< / body >
< / html >
"""
await self . _emit_status (
__event_emitter__ ,
self . _get_translation ( user_language , " status_drawing " ) ,
True ,
)
await self . _emit_notification (
__event_emitter__ ,
self . _get_translation (
user_language , " notification_success " , user_name = user_name
) ,
" success " ,
)
logger . info ( " Action: Smart Mind Map (v1.0.0) completed in Direct Mode " )
return (
final_html_direct ,
{ " Content-Disposition " : " inline " , " Content-Type " : " text/html " } ,
)
else :
# LEGACY MODE
# embed as HTML block into the message content
html_embed_tag = f " ```html \n { final_html } \n ``` "
body [ " messages " ] [ - 1 ] [
" content "
] = f " { long_text_content } \n \n { html_embed_tag } "
await self . _emit_status (
__event_emitter__ ,
self . _get_translation ( user_language , " status_drawing " ) ,
True ,
)
await self . _emit_notification (
__event_emitter__ ,
self . _get_translation (
user_language , " notification_success " , user_name = user_name
) ,
" success " ,
)
logger . info (
" Action: Smart Mind Map (v1.0.0) completed in Legacy HTML mode "
)
2025-12-20 12:34:49 +08:00
except Exception as e :
error_message = f " Smart Mind Map processing failed: { str ( e ) } "
logger . error ( f " Smart Mind Map error: { error_message } " , exc_info = True )
2026-02-21 17:50:44 +08:00
user_facing_error = self . _get_translation (
user_language , " error_user_facing " , error = str ( e )
)
feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
2025-12-20 12:34:49 +08:00
body [ " messages " ] [ - 1 ] [
" content "
] = f " { long_text_content } \n \n ❌ **Error:** { user_facing_error } "
2025-12-20 17:03:40 +08:00
await self . _emit_status (
2026-02-21 17:50:44 +08:00
__event_emitter__ ,
self . _get_translation ( user_language , " status_failed " ) ,
True ,
2025-12-20 17:03:40 +08:00
)
await self . _emit_notification (
__event_emitter__ ,
2026-02-21 17:50:44 +08:00
self . _get_translation (
user_language , " notification_failed " , user_name = user_name
) ,
2025-12-20 17:03:40 +08:00
" error " ,
)
2025-12-20 12:34:49 +08:00
return body
2026-02-21 17:50:44 +08:00
def _is_direct_html_supported ( self , body : dict ) - > bool :
"""
Check if the current Open WebUI version supports direct HTML return + inline display .
Target version > = 0.8 .0 .
"""
if not self . valves . ENABLE_DIRECT_EMBED_MODE :
return False
try :
# First check server-side version
version = open_webui_version
if not version or version == " 0.0.0 " :
# If server version unknown, fallback to body version
version = body . get ( " version " )
if not version :
# If still no version, default to True (assume modern)
return True
# If version is present, check 0.8.0+
# Simple lexicographical check usually works for semver if format is consistent x.y.z
# But "0.9.0" > "0.8.0" is true. "0.10.0" > "0.8.0" (lexicographically "0.1" < "0.8") fails.
# So we need safer parsing.
parts = version . split ( " . " )
if len ( parts ) > = 2 :
major = int ( parts [ 0 ] )
minor = int ( parts [ 1 ] )
if major > 0 or ( major == 0 and minor > = 8 ) :
return True
return False
except Exception :
# On error, default to True to assume modern features
return True
# ... (Rest of Action class methods) ...