From 9cf4a378f134e96e1dee6ef1e792deda13b0e785 Mon Sep 17 00:00:00 2001
From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com>
Date: Wed, 17 Sep 2025 18:07:10 +0900
Subject: [PATCH] =?UTF-8?q?[Update]=20UI:=20=E3=83=AD=E3=83=BC=E3=83=9E?=
=?UTF-8?q?=E5=AD=97/=E3=81=8B=E3=81=AA=20=E8=A1=A8=E7=A4=BA=E3=81=99?=
=?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
locales/en.yml | 7 ++
locales/ja.yml | 6 ++
.../setting_box/others/Others.jsx | 35 ++++++++
.../message_container/MessageContainer.jsx | 79 ++++++++++++++++---
src-ui/logics/common/useMessage.js | 28 ++++---
src-ui/logics/configs/others/useOthers.js | 60 ++++++++++++++
src-ui/logics/useReceiveRoutes.js | 10 ++-
src-ui/store.js | 2 +
8 files changed, 205 insertions(+), 22 deletions(-)
diff --git a/locales/en.yml b/locales/en.yml
index 1faf9639..5dabb4b2 100644
--- a/locales/en.yml
+++ b/locales/en.yml
@@ -250,6 +250,13 @@ config_page:
received_message_format:
label: "Message Format (Speaker2Chatbox)"
desc: "Currently, it is used in Speaker2Chatbox."
+ convert_message_to_romaji:
+ label: Show Romaji
+ desc: Supported only when Japanese is selected as the translation language. When enabled along with '{{convert_message_to_hiragana}}', romaji will be shown on mouse hover.
+ convert_message_to_hiragana:
+ label: Show Hiragana
+ desc: Supported only when Japanese is selected as the translation language.
+
hotkeys:
toggle_vrct_visibility:
diff --git a/locales/ja.yml b/locales/ja.yml
index d3da554e..b4097a9a 100644
--- a/locales/ja.yml
+++ b/locales/ja.yml
@@ -250,6 +250,12 @@ config_page:
received_message_format:
label: メッセージフォーマット(Speaker2Chatbox)
desc: 今のところ、Speaker2Chatboxで送信した時の表示に使われます。
+ convert_message_to_romaji:
+ label: ローマ字を表示
+ desc: 翻訳言語として日本語を選択した時のみサポート。「{{convert_message_to_hiragana}}」と同時に有効にした場合は、マウスホバーで表示されます。
+ convert_message_to_hiragana:
+ label: ひらがなを表示
+ desc: 翻訳言語として日本語を選択した時のみサポート。
hotkeys:
toggle_vrct_visibility:
diff --git a/src-ui/app/config_page/setting_section/setting_box/others/Others.jsx b/src-ui/app/config_page/setting_section/setting_box/others/Others.jsx
index 65027ef3..5ef39ce0 100644
--- a/src-ui/app/config_page/setting_section/setting_box/others/Others.jsx
+++ b/src-ui/app/config_page/setting_section/setting_box/others/Others.jsx
@@ -45,6 +45,10 @@ export const Others = () => {
+
+
+
+
);
};
@@ -201,4 +205,35 @@ const ReceivedMessageFormatPartsContainer = () => {
format_id="received"
/>
);
+};
+
+const ConvertMessageToRomajiContainer = () => {
+ const { t } = useI18n();
+ const { currentConvertMessageToRomaji, toggleConvertMessageToRomaji } = useOthers();
+
+ return (
+
+ );
+};
+
+const ConvertMessageToHiraganaContainer = () => {
+ const { t } = useI18n();
+ const { currentConvertMessageToHiragana, toggleConvertMessageToHiragana } = useOthers();
+
+ return (
+
+ );
};
\ No newline at end of file
diff --git a/src-ui/app/main_page/main_section/message_container/log_box/message_container/MessageContainer.jsx b/src-ui/app/main_page/main_section/message_container/log_box/message_container/MessageContainer.jsx
index d982f27c..cd36754d 100644
--- a/src-ui/app/main_page/main_section/message_container/log_box/message_container/MessageContainer.jsx
+++ b/src-ui/app/main_page/main_section/message_container/log_box/message_container/MessageContainer.jsx
@@ -39,7 +39,7 @@ export const MessageContainer = ({ messages, status, category, created_at }) =>
setIsLocked(true);
};
- const is_translated_exist = messages.translated?.length >= 1;
+ const is_translation_exist = messages.translations?.length > 0;
const is_pending = status === "pending";
const is_sent_message = category === "sent";
const is_system_message = category === "system";
@@ -69,11 +69,11 @@ export const MessageContainer = ({ messages, status, category, created_at }) =>
{is_system_message ? (
-
{messages.message}
- ) : is_translated_exist ? (
+
{messages.original.message}
+ ) : is_translation_exist ? (
) : (
-
{messages.original}
+
)}
@@ -88,13 +88,74 @@ export const MessageContainer = ({ messages, status, category, created_at }) =>
);
};
-const WithTranslatedMessages = ({ messages }) => {
- const translated_data = Array.isArray(messages.translated) ? messages.translated : [messages.translated];
+const MessageWithTransliteration = ({ item }) => {
+ const renderTokenNode = (token, key) => {
+ const orig = token.orig ?? "";
+ const hira = token.hira ?? "";
+ const hepburn = token.hepburn ?? "";
+
+ if ((hira && orig === hira) || (hepburn && orig === hepburn) || (!hira && !hepburn)) {
+ return (
+
+ {orig}
+
+ );
+ }
+
+ if (hira && hira !== orig) {
+ const needHepburn = hepburn && hepburn !== orig;
+ const titleAttr = needHepburn ? hepburn : undefined;
+ return (
+
+ {orig}
+
+
+ );
+ }
+
+ if (hepburn && hepburn !== orig) {
+ return (
+
+ {orig}
+
+
+ );
+ }
+
+ return (
+
+ {orig}
+
+ );
+ };
+
+ if (!item.transliteration.length) {
+ return {item.message}
;
+ }
+
+ return (
+
+ {item.transliteration.map((token, idx) => renderTokenNode(token, idx))}
+
+ );
+};
+
+const OriginalMessage = ({ messages }) => {
return (
<>
- {messages.original}
- {translated_data.map((message, index) => (
- {message}
+
+ >
+ );
+};
+
+const WithTranslatedMessages = ({ messages }) => {
+ return (
+ <>
+ {messages.original.message}
+ {messages.translations.map((item, idx) => (
+
+
+
))}
>
);
diff --git a/src-ui/logics/common/useMessage.js b/src-ui/logics/common/useMessage.js
index 78986b55..1b50bbbd 100644
--- a/src-ui/logics/common/useMessage.js
+++ b/src-ui/logics/common/useMessage.js
@@ -24,8 +24,8 @@ export const useMessage = () => {
status: "pending",
created_at: generateTimeData(),
messages: {
- original: message,
- translated: [],
+ original: { message: message, transliteration: [] },
+ translations: [],
},
});
};
@@ -39,20 +39,26 @@ export const useMessage = () => {
category: "system",
status: "system",
created_at: date,
- messages: {message: message},
+ messages: {
+ original: { message: message, transliteration: [] },
+ translations: [],
+ },
});
};
+
const addSystemMessageLog_FromBackend = (payload) => {
addSystemMessageLog(payload.message);
};
const updateSentMessageLogById = (payload) => {
- updateMessageLogs(updateItemById(payload.id, payload.translation));
+ updateMessageLogs(updateItemById(payload.id, payload));
};
+
const addSentMessageLog = (payload) => {
const message_object = generateMessageObject(payload, "sent");
addMessageLogs(message_object);
};
+
const addReceivedMessageLog = (payload) => {
const message_object = generateMessageObject(payload, "received");
addMessageLogs(message_object);
@@ -61,6 +67,7 @@ export const useMessage = () => {
const startTyping = () => {
asyncStdoutToPython("/run/typing_message_box");
};
+
const stopTyping = () => {
asyncStdoutToPython("/run/stop_typing_message_box");
};
@@ -83,11 +90,10 @@ export const useMessage = () => {
};
const generateTimeData = () => {
- const data = new Date().toLocaleTimeString(
+ return new Date().toLocaleTimeString(
"ja-JP",
- { hour12: false, hour: "2-digit", minute: "2-digit" },
+ { hour12: false, hour: "2-digit", minute: "2-digit" }
);
- return data;
};
const generateMessageObject = (data, category) => {
@@ -97,17 +103,17 @@ const generateMessageObject = (data, category) => {
category: category,
status: "ok",
messages: {
- original: data.message,
- translated: data.translation,
+ original: data.original,
+ translations: data.translations ?? [],
},
};
};
-const updateItemById = (id, translated_data) => (current_items) => {
+const updateItemById = (id, updated_data) => (current_items) => {
return current_items.data.map(item => {
if (item.id === id) {
item.status = "ok";
- item.messages.translated = translated_data;
+ if (updated_data.translations) item.messages.translations = updated_data.translations;
}
return item;
});
diff --git a/src-ui/logics/configs/others/useOthers.js b/src-ui/logics/configs/others/useOthers.js
index c2b0179f..855ab24e 100644
--- a/src-ui/logics/configs/others/useOthers.js
+++ b/src-ui/logics/configs/others/useOthers.js
@@ -9,6 +9,8 @@ import {
useStore_MessageFormat_ExampleViewFilter,
useStore_SendMessageFormatParts,
useStore_ReceivedMessageFormatParts,
+ useStore_ConvertMessageToRomaji,
+ useStore_ConvertMessageToHiragana,
} from "@store";
import { useStdoutToPython } from "@useStdoutToPython";
import { useNotificationStatus } from "@logics_common";
@@ -39,6 +41,11 @@ export const useOthers = () => {
// Received
const { currentReceivedMessageFormatParts, updateReceivedMessageFormatParts, pendingReceivedMessageFormatParts } = useStore_ReceivedMessageFormatParts();
+ // Convert Message To Romaji
+ const { currentConvertMessageToRomaji, updateConvertMessageToRomaji, pendingConvertMessageToRomaji } = useStore_ConvertMessageToRomaji();
+ // Convert Message To Hiragana
+ const { currentConvertMessageToHiragana, updateConvertMessageToHiragana, pendingConvertMessageToHiragana } = useStore_ConvertMessageToHiragana();
+
const { showNotification_SaveSuccess } = useNotificationStatus();
// Auto Clear Message Input Box
@@ -233,6 +240,45 @@ export const useOthers = () => {
});
};
+ // Convert Message To Romaji
+ const getConvertMessageToRomaji = () => {
+ pendingConvertMessageToRomaji();
+ asyncStdoutToPython("/get/data/convert_message_to_romaji");
+ };
+
+ const toggleConvertMessageToRomaji = () => {
+ pendingConvertMessageToRomaji();
+ if (currentConvertMessageToRomaji.data) {
+ asyncStdoutToPython("/set/disable/convert_message_to_romaji");
+ } else {
+ asyncStdoutToPython("/set/enable/convert_message_to_romaji");
+ }
+ };
+
+ const setSuccessConvertMessageToRomaji = (enabled) => {
+ updateConvertMessageToRomaji(enabled);
+ showNotification_SaveSuccess();
+ };
+
+ // Convert Message To Hiragana
+ const getConvertMessageToHiragana = () => {
+ pendingConvertMessageToHiragana();
+ asyncStdoutToPython("/get/data/convert_message_to_hiragana");
+ };
+
+ const toggleConvertMessageToHiragana = () => {
+ pendingConvertMessageToHiragana();
+ if (currentConvertMessageToHiragana.data) {
+ asyncStdoutToPython("/set/disable/convert_message_to_hiragana");
+ } else {
+ asyncStdoutToPython("/set/enable/convert_message_to_hiragana");
+ }
+ };
+
+ const setSuccessConvertMessageToHiragana = (enabled) => {
+ updateConvertMessageToHiragana(enabled);
+ showNotification_SaveSuccess();
+ };
return {
// Auto Clear Message Input Box
@@ -303,5 +349,19 @@ export const useOthers = () => {
getReceivedMessageFormatParts,
setReceivedMessageFormatParts,
setSuccessReceivedMessageFormatParts,
+
+ // Convert Message To Romaji
+ currentConvertMessageToRomaji,
+ getConvertMessageToRomaji,
+ toggleConvertMessageToRomaji,
+ updateConvertMessageToRomaji,
+ setSuccessConvertMessageToRomaji,
+
+ // Convert Message To Hiragana
+ currentConvertMessageToHiragana,
+ getConvertMessageToHiragana,
+ toggleConvertMessageToHiragana,
+ updateConvertMessageToHiragana,
+ setSuccessConvertMessageToHiragana,
};
};
\ No newline at end of file
diff --git a/src-ui/logics/useReceiveRoutes.js b/src-ui/logics/useReceiveRoutes.js
index c36b5fa7..a5e6d8ed 100644
--- a/src-ui/logics/useReceiveRoutes.js
+++ b/src-ui/logics/useReceiveRoutes.js
@@ -292,6 +292,14 @@ export const ROUTE_META_LIST = [
{ endpoint: "/get/data/received_message_format_parts", ns: configs, hook_name: "useOthers", method_name: "updateReceivedMessageFormatParts" },
{ endpoint: "/set/data/received_message_format_parts", ns: configs, hook_name: "useOthers", method_name: "setSuccessReceivedMessageFormatParts" },
+ { endpoint: "/get/data/convert_message_to_romaji", ns: configs, hook_name: "useOthers", method_name: "updateConvertMessageToRomaji" },
+ { endpoint: "/set/enable/convert_message_to_romaji", ns: configs, hook_name: "useOthers", method_name: "setSuccessConvertMessageToRomaji" },
+ { endpoint: "/set/disable/convert_message_to_romaji", ns: configs, hook_name: "useOthers", method_name: "setSuccessConvertMessageToRomaji" },
+
+ { endpoint: "/get/data/convert_message_to_hiragana", ns: configs, hook_name: "useOthers", method_name: "updateConvertMessageToHiragana" },
+ { endpoint: "/set/enable/convert_message_to_hiragana", ns: configs, hook_name: "useOthers", method_name: "setSuccessConvertMessageToHiragana" },
+ { endpoint: "/set/disable/convert_message_to_hiragana", ns: configs, hook_name: "useOthers", method_name: "setSuccessConvertMessageToHiragana" },
+
// Hotkeys
{ endpoint: "/get/data/hotkeys", ns: configs, hook_name: "useHotkeys", method_name: "updateHotkeys" },
{ endpoint: "/set/data/hotkeys", ns: configs, hook_name: "useHotkeys", method_name: "setSuccessHotkeys" },
@@ -323,8 +331,6 @@ export const ROUTE_META_LIST = [
{ endpoint: "/get/data/mic_no_speech_prob", ns: null, hook_name: null, method_name: null }, // Not implemented on UI yet
{ endpoint: "/get/data/speaker_avg_logprob", ns: null, hook_name: null, method_name: null }, // Not implemented on UI yet
{ endpoint: "/get/data/speaker_no_speech_prob", ns: null, hook_name: null, method_name: null }, // Not implemented on UI yet
- { endpoint: "/get/data/convert_message_to_romaji", ns: null, hook_name: null, method_name: null }, // Not implemented on UI yet
- { endpoint: "/get/data/convert_message_to_hiragana", ns: null, hook_name: null, method_name: null }, // Not implemented on UI yet
{ endpoint: "/get/data/transcription_engines", ns: null, hook_name: null, method_name: null }, // Not implemented on UI yet. (if ai_models has not been detected, this will be blank array[]. if the ai_models are ok but just network has not connected, it'l be only ["Whisper"])
];
diff --git a/src-ui/store.js b/src-ui/store.js
index e36aad46..6c31e87f 100644
--- a/src-ui/store.js
+++ b/src-ui/store.js
@@ -309,6 +309,8 @@ export const { atomInstance: Atom_ReceivedMessageFormatParts, useHook: useStore_
},
translation_first: false,
}, "ReceivedMessageFormatParts");
+export const { atomInstance: Atom_ConvertMessageToRomaji, useHook: useStore_ConvertMessageToRomaji } = createAtomWithHook(false, "ConvertMessageToRomaji");
+export const { atomInstance: Atom_ConvertMessageToHiragana, useHook: useStore_ConvertMessageToHiragana } = createAtomWithHook(false, "ConvertMessageToHiragana");
// Hotkeys