From 5ca7d73be4df3ccd441cac3efb54d444e3504a11 Mon Sep 17 00:00:00 2001
From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com>
Date: Mon, 14 Jul 2025 11:06:13 +0900
Subject: [PATCH 01/16] [bugfix] Fix settings data has not sync when init
startup the software.(Mic Word Filter, VRC Mic Mute Sync)
---
src-ui/logics/configs/others/useOthers.js | 5 +++++
.../configs/transcription/useTranscription.js | 16 ++++++++++++++++
src-ui/logics/useReceiveRoutes.js | 7 +++++--
3 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/src-ui/logics/configs/others/useOthers.js b/src-ui/logics/configs/others/useOthers.js
index 62a14364..c8a417d6 100644
--- a/src-ui/logics/configs/others/useOthers.js
+++ b/src-ui/logics/configs/others/useOthers.js
@@ -107,6 +107,10 @@ export const useOthers = () => {
}
};
+ const getSuccessEnableVrcMicMuteSync = (is_enabled) => {
+ updateEnableVrcMicMuteSync(old => ({ ...old.data, is_enabled: is_enabled }));
+ };
+
const setSuccessEnableVrcMicMuteSync = (is_enabled) => {
updateEnableVrcMicMuteSync(old => ({ ...old.data, is_enabled: is_enabled }));
showNotification_SaveSuccess();
@@ -199,6 +203,7 @@ export const useOthers = () => {
// VRC Mic Mute Sync
currentEnableVrcMicMuteSync,
getEnableVrcMicMuteSync,
+ getSuccessEnableVrcMicMuteSync,
toggleEnableVrcMicMuteSync,
updateEnableVrcMicMuteSync,
setSuccessEnableVrcMicMuteSync,
diff --git a/src-ui/logics/configs/transcription/useTranscription.js b/src-ui/logics/configs/transcription/useTranscription.js
index 0c4b8b2b..147aa9e6 100644
--- a/src-ui/logics/configs/transcription/useTranscription.js
+++ b/src-ui/logics/configs/transcription/useTranscription.js
@@ -97,6 +97,21 @@ export const useTranscription = () => {
asyncStdoutToPython("/set/data/mic_word_filter", selected_mic_word_filter);
};
+ const getSuccessMicWordFilterList = (payload) => {
+ updateMicWordFilterList((prev_list) => {
+ const updated_list = [...prev_list.data];
+ for (const value of payload) {
+ const existing_item = updated_list.find(item => item.value === value);
+ if (existing_item) {
+ existing_item.is_redoable = false;
+ } else {
+ updated_list.push({ value, is_redoable: false });
+ }
+ }
+ return updated_list;
+ });
+ };
+
const setSuccessMicWordFilterList = (payload) => {
updateMicWordFilterList((prev_list) => {
const updated_list = [...prev_list.data];
@@ -283,6 +298,7 @@ export const useTranscription = () => {
currentMicWordFilterList,
getMicWordFilterList,
+ getSuccessMicWordFilterList,
updateMicWordFilterList,
setMicWordFilterList,
setSuccessMicWordFilterList,
diff --git a/src-ui/logics/useReceiveRoutes.js b/src-ui/logics/useReceiveRoutes.js
index d83054d3..00c48a0b 100644
--- a/src-ui/logics/useReceiveRoutes.js
+++ b/src-ui/logics/useReceiveRoutes.js
@@ -194,7 +194,7 @@ export const ROUTE_META_LIST = [
{ endpoint: "/get/data/mic_max_phrases", ns: configs, hook_name: "useTranscription", method_name: "updateMicMaxWords" },
{ endpoint: "/set/data/mic_max_phrases", ns: configs, hook_name: "useTranscription", method_name: "setSuccessMicMaxWords" },
- { endpoint: "/get/data/mic_word_filter", ns: configs, hook_name: "useTranscription", method_name: "updateMicWordFilterList" },
+ { endpoint: "/get/data/mic_word_filter", ns: configs, hook_name: "useTranscription", method_name: "getSuccessMicWordFilterList" },
{ endpoint: "/set/data/mic_word_filter", ns: configs, hook_name: "useTranscription", method_name: "setSuccessMicWordFilterList" },
// Transcription (Speaker)
@@ -259,7 +259,7 @@ export const ROUTE_META_LIST = [
{ endpoint: "/set/enable/logger_feature", ns: configs, hook_name: "useOthers", method_name: "setSuccessEnableAutoExportMessageLogs" },
{ endpoint: "/set/disable/logger_feature", ns: configs, hook_name: "useOthers", method_name: "setSuccessEnableAutoExportMessageLogs" },
- { endpoint: "/get/data/vrc_mic_mute_sync", ns: configs, hook_name: "useOthers", method_name: "updateEnableVrcMicMuteSync_FromBackend" },
+ { endpoint: "/get/data/vrc_mic_mute_sync", ns: configs, hook_name: "useOthers", method_name: "getSuccessEnableVrcMicMuteSync" },
{ endpoint: "/set/enable/vrc_mic_mute_sync", ns: configs, hook_name: "useOthers", method_name: "setSuccessEnableVrcMicMuteSync" },
{ endpoint: "/set/disable/vrc_mic_mute_sync", ns: configs, hook_name: "useOthers", method_name: "setSuccessEnableVrcMicMuteSync" },
@@ -334,6 +334,9 @@ export const useReceiveRoutes = () => {
ROUTE_META_LIST.map(({ endpoint, hook_name, method_name }) => {
const result_obj = hook_results[hook_name] || {};
const fn = result_obj[method_name];
+ if (fn === undefined && method_name !== null) {
+ console.error("Method not found.", {endpoint, hook_name, method_name, result_obj, fn});
+ }
return [endpoint, typeof fn === "function" ? fn : noop];
})
);
From 3403b52fb930eaa0f7d89b7296f539d4d4e0aab0 Mon Sep 17 00:00:00 2001
From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com>
Date: Sat, 2 Aug 2025 17:03:04 +0900
Subject: [PATCH 02/16] [Update/Refactor] Add link to notification component to
guide users to get more information. (handleAiModelsAvailability)
---
.../PosterShowcaseWorldsContents.jsx | 2 +-
.../setting_box/plugins/Plugins.jsx | 55 +------------------
.../setting_box/plugins/Plugins.module.scss | 43 +--------------
.../SnackbarController.jsx | 2 +-
.../HomepageLinkButton.jsx | 54 ++++++++++++++++++
.../HomepageLinkButton.module.scss | 39 +++++++++++++
src-ui/common_components/index.js | 3 +-
src-ui/logics/common/useIsVrctAvailable.js | 21 -------
src-ui/logics/common/useIsVrctAvailable.jsx | 33 +++++++++++
9 files changed, 133 insertions(+), 119 deletions(-)
create mode 100644 src-ui/common_components/homepage_link_button/HomepageLinkButton.jsx
create mode 100644 src-ui/common_components/homepage_link_button/HomepageLinkButton.module.scss
delete mode 100644 src-ui/logics/common/useIsVrctAvailable.js
create mode 100644 src-ui/logics/common/useIsVrctAvailable.jsx
diff --git a/src-ui/app/config_page/setting_section/setting_box/about_vrct/poster_showcase_contents/poster_showcase_worlds_contents/PosterShowcaseWorldsContents.jsx b/src-ui/app/config_page/setting_section/setting_box/about_vrct/poster_showcase_contents/poster_showcase_worlds_contents/PosterShowcaseWorldsContents.jsx
index e51c8ea5..4d2044e1 100644
--- a/src-ui/app/config_page/setting_section/setting_box/about_vrct/poster_showcase_contents/poster_showcase_worlds_contents/PosterShowcaseWorldsContents.jsx
+++ b/src-ui/app/config_page/setting_section/setting_box/about_vrct/poster_showcase_contents/poster_showcase_worlds_contents/PosterShowcaseWorldsContents.jsx
@@ -37,7 +37,7 @@ export const PosterShowcaseWorldsContents = () => {
);
if (poster.x_post_num !== null) {
return (
-
+
{content}
);
diff --git a/src-ui/app/config_page/setting_section/setting_box/plugins/Plugins.jsx b/src-ui/app/config_page/setting_section/setting_box/plugins/Plugins.jsx
index 6c80beb2..4115b667 100644
--- a/src-ui/app/config_page/setting_section/setting_box/plugins/Plugins.jsx
+++ b/src-ui/app/config_page/setting_section/setting_box/plugins/Plugins.jsx
@@ -1,10 +1,10 @@
-import { useEffect, useRef, useState, useCallback } from "react";
+import { useEffect, useRef } from "react";
import { useI18n } from "@useI18n";
import { usePlugins } from "@logics_configs";
import styles from "./Plugins.module.scss";
import { PluginsControlComponent } from "./plugins_control_component/PluginsControlComponent";
import { useNotificationStatus } from "@logics_common";
-import ExternalLink from "@images/external_link.svg?react";
+import { HomepageLinkButton } from "@common_components";
export const Plugins = () => {
const {
@@ -125,55 +125,4 @@ const PluginDownloadContainer = () => {
})}
);
-};
-
-const HomepageLinkButton = ({ homepage_link, speed = 40 /* px/s */ }) => {
- const containerRef = useRef(null);
- const textRef = useRef(null);
- const [inlineStyle, setInlineStyle] = useState({});
-
- const handleMouseEnter = useCallback(() => {
- const container = containerRef.current;
- const text = textRef.current;
- if (!container || !text) return;
- const overflow = text.scrollWidth - container.clientWidth;
- if (overflow > 0) {
- const duration = overflow / speed;
- setInlineStyle({
- transform: `translateX(-${overflow}px)`,
- transition: `transform ${duration}s linear`,
- });
- }
- }, [speed]);
-
- const handleMouseLeave = useCallback(() => {
- setInlineStyle({
- transform: 'translateX(0)',
- transition: 'transform 0.3s ease-out',
- });
- }, []);
-
- return (
-
-
+
+
{
+ const { currentIsBreakPoint } = useStore_IsBreakPoint();
+ const message_format_container_class = clsx(styles.container, {
+ [styles.is_break_point]: currentIsBreakPoint.data,
+ });
+
+ return (
+
+ );
+};
+
+const ExampleComponent = ({ format, example_view_filter_variable, exampleViewFilterToggleFunction, format_id }) => {
+ const { currentUiLanguage } = useAppearance();
+ const { t } = useTranslation();
+
+
+ const locale_base_path = "config_page.others.message_format_common.example_view.";
+
+ const label_title = t(locale_base_path + "title");
+
+ const label_original_translated = t(locale_base_path + "original_translated");
+ const label_original_translated_multi = t(locale_base_path + "original_translated_multi");
+ const label_translated_only_multi = t(locale_base_path + "translated_only_multi");
+ const label_translated_only = t(locale_base_path + "translated_only");
+ const label_original_only = t(locale_base_path + "original_only");
+
+ const createExampleMessage = (id) => {
+ // 言語順序を決定
+ let example_text_order = [];
+ switch (currentUiLanguage.data) {
+ case "ja":
+ example_text_order = ["ja", "en", "ko", "fr"];
+ break;
+ case "ko":
+ example_text_order = ["ko", "ja", "en", "fr"];
+ break;
+ default: // en
+ example_text_order = ["en", "ja", "ko", "fr"];
+ break;
+ }
+
+ const original = EXAMPLE_TEXTS[example_text_order[0]];
+ const translations = example_text_order.slice(1).map(lang => EXAMPLE_TEXTS[lang]);
+
+ const originalPart = `${format.message.prefix}${original}${format.message.suffix}`;
+ const translationSingle = `${format.translation.prefix}${translations[0]}${format.translation.suffix}`;
+ const translationMulti = `${format.translation.prefix}${translations.join(format.translation.separator)}${format.translation.suffix}`;
+
+ switch (id) {
+ case "original_translated":
+ return format.translation_first
+ ? `${translationSingle}${format.separator}${originalPart}`
+ : `${originalPart}${format.separator}${translationSingle}`;
+
+ case "original_only":
+ return originalPart;
+
+ case "translated_only":
+ return translationSingle;
+
+ case "translated_only_multi":
+ return translationMulti;
+
+ case "original_translated_multi":
+ return format.translation_first
+ ? `${translationMulti}${format.separator}${originalPart}`
+ : `${originalPart}${format.separator}${translationMulti}`;
+
+ default:
+ throw new Error(`Unexpected id: ${id}`);
+ }
+ };
+
+ const ExampleBox = ({label, example_text_id}) => {
+ return (
+
+
{label}
+
+
{createExampleMessage(example_text_id)}
+
+
+ );
+
+ };
+
+ const svg_class_names = clsx(styles.arrow_left_svg, {
+ [styles.to_down]: example_view_filter_variable[format_id] === "Simplified",
+ [styles.to_up]: example_view_filter_variable[format_id] === "All"
+ });
+
+
+ const FilteredExampleBox = ({format_id, id}) => {
+ if (format_id === "send" && id === "Simplified") {
+ return (
+ <>
+
+
+ >
+ );
+ } else if ( format_id === "send" && id === "All") {
+ return (
+ <>
+
+
+
+
+
+ >
+ );
+
+ } else if (format_id === "received") {
+ return (
+ <>
+
+
+
+ >
+ );
+ }
+ };
+
+
+ return (
+
+
{label_title}
+
+
+
+ { format_id === "send" &&
+
exampleViewFilterToggleFunction(format_id)}>
+
+
+ }
+
+ );
+};
+
+
+const InputComponent = ({id, variable, setFunction, format_id }) => {
+ const { t } = useTranslation();
+
+ const locale_base_path = "config_page.others.message_format_common.settings.";
+ const label_title = t(locale_base_path + "title");
+
+ const LABEL_ORIGINAL = t(locale_base_path + "original");
+ const LABEL_TRANSLATED = t(locale_base_path + "translated");
+ const LABEL_FOR_MULTI_TRANSLATION = t(locale_base_path + "for_multi_translation");
+
+ const replaceValue = (value) => {
+ if (value === "") return "";
+
+ const replaced = value.replace(/\\n/g, "\n");
+ return replaced;
+ };
+
+ const handleChange = (parent_key, child_key) => (e) => {
+ const rawValue = e.target.value;
+ const parsedValue = replaceValue(rawValue);
+
+ if (child_key !== undefined) {
+ setFunction({
+ ...variable,
+ [parent_key]: {
+ ...variable[parent_key],
+ [child_key]: parsedValue
+ }
+ });
+ } else {
+ setFunction({
+ ...variable,
+ [parent_key]: parsedValue
+ });
+ }
+ };
+
+ const toUiValue = (v) => {
+ if (typeof v === "string") {
+ return v.replace(/\n/g, "\\n");
+ }
+ console.log("Empty");
+
+ return v ?? "";
+ };
+
+ const resetFunction = () => {
+ if (format_id === "send") {
+ setFunction(ui_configs.send_message_format_parts);
+ } else if (format_id === "received") {
+ setFunction(ui_configs.received_message_format_parts);
+ }
+ };
+
+ const SwapButton = ({ variable, setFunction }) => {
+ const swapMessageAndTranslate = () => {
+ setFunction({ ...variable, translation_first: !variable.translation_first });
+ };
+
+ return (
+
+
{variable.translation_first ? LABEL_TRANSLATED : LABEL_ORIGINAL}
+

+
{variable.translation_first ? LABEL_ORIGINAL : LABEL_TRANSLATED}
+
+ );
+ };
+
+ return (
+
+
{label_title}
+
+
+
+
+ { !variable.translation_first ?
+
+
+ <_Entry ui_variable={toUiValue(variable.message.prefix)} width={ENTRY_WIDTH} onChange={handleChange("message", "prefix")} />
+
{LABEL_ORIGINAL}
+ <_Entry ui_variable={toUiValue(variable.message.suffix)} width={ENTRY_WIDTH} onChange={handleChange("message", "suffix")} />
+
+
+ <_Entry ui_variable={toUiValue(variable.separator)} width={ENTRY_WIDTH} onChange={handleChange("separator")} />
+
+
+ <_Entry ui_variable={toUiValue(variable.translation.prefix)} width={ENTRY_WIDTH} onChange={handleChange("translation", "prefix")} />
+
{LABEL_TRANSLATED}
+ <_Entry ui_variable={toUiValue(variable.translation.suffix)} width={ENTRY_WIDTH} onChange={handleChange("translation", "suffix")} />
+
+
+ :
+
+
+ <_Entry ui_variable={toUiValue(variable.translation.prefix)} width={ENTRY_WIDTH} onChange={handleChange("translation", "prefix")} />
+
{LABEL_TRANSLATED}
+ <_Entry ui_variable={toUiValue(variable.translation.suffix)} width={ENTRY_WIDTH} onChange={handleChange("translation", "suffix")} />
+
+
+ <_Entry ui_variable={toUiValue(variable.separator)} width={ENTRY_WIDTH} onChange={handleChange("separator")} />
+
+
+ <_Entry ui_variable={toUiValue(variable.message.prefix)} width={ENTRY_WIDTH} onChange={handleChange("message", "prefix")} />
+
{LABEL_ORIGINAL}
+ <_Entry ui_variable={toUiValue(variable.message.suffix)} width={ENTRY_WIDTH} onChange={handleChange("message", "suffix")} />
+
+
+ }
+ { format_id === "send" &&
+
+
{LABEL_FOR_MULTI_TRANSLATION}
+
+
{LABEL_TRANSLATED}
+ <_Entry ui_variable={toUiValue(variable.translation.separator)} width={ENTRY_WIDTH} onChange={handleChange("translation", "separator")} />
+
{LABEL_TRANSLATED}
+
+
+ }
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/src-ui/app/config_page/setting_section/setting_box/_components/message_format/MessageFormat.module.scss b/src-ui/app/config_page/setting_section/setting_box/_components/message_format/MessageFormat.module.scss
new file mode 100644
index 00000000..18244109
--- /dev/null
+++ b/src-ui/app/config_page/setting_section/setting_box/_components/message_format/MessageFormat.module.scss
@@ -0,0 +1,200 @@
+.container {
+ display: flex;
+ justify-content: center;
+ width: 100%;
+ gap: 2.6rem;
+ padding-bottom: 2rem;
+ margin: 1rem 0;
+ &.is_break_point {
+ flex-direction: column;
+ gap: 2.2rem;
+ align-items: center;
+ .border {
+ height: 0.1rem;
+ width: 60%;
+ margin: 0;
+ flex-shrink: 0;
+ }
+ .show_more_container {
+ margin-top: 2rem;
+ }
+ .example_container {
+ gap: 0;
+ }
+ .message_format_settings_container {
+ gap: 0;
+ }
+ }
+}
+
+.border {
+ height: auto;
+ width: 0.1rem;
+ background-color: var(--dark_800_color);
+ margin: 3.2rem 0;
+ flex-shrink: 0;
+}
+
+.section_title {
+ font-size: 1.4rem;
+ text-align: center;
+ width: 100%;
+}
+
+.example_container {
+ display: flex;
+ flex-direction: column;
+ gap: 2rem;
+ min-width: 14rem;
+ max-width: 34rem;
+ width: 100%;
+}
+
+.example_view_container {
+ display: flex;
+ flex-direction: column;
+ gap: 1.2rem;
+}
+
+.example_wrapper {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 0.4rem;
+}
+.example_label {
+ font-size: 1.4rem;
+ text-align: start;
+ width: 100%;
+ color: var(--dark_basic_text_color);
+}
+.example_chatbox {
+ padding: 0.6rem;
+ background-color: #3A4554;
+ border-radius: 1rem;
+ width: 100%;
+ text-align: center;
+}
+
+.example_text {
+ font-size: 1.2rem;
+}
+
+.show_more_container {
+ width: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 0.6rem 0;
+ cursor: pointer;
+ border-radius: 0.6rem;
+ &:hover {
+ background-color: var(--dark_850_color);
+ }
+ &:active {
+ background-color: var(--dark_875_color);
+ }
+}
+
+.arrow_left_svg {
+ width: 2rem;
+ color: var(--dark_450_color);
+ &.to_down {
+ transform: rotate(-90deg);
+ }
+ &.to_up {
+ transform: rotate(90deg);
+ }
+}
+
+.message_format_settings_container {
+ flex-direction: column;
+ display: flex;
+ align-items: center;
+ flex-shrink: 0;
+ gap: 2rem;
+}
+
+.message_format_settings_wrapper {
+ display: flex;
+ flex-direction: column;
+ gap: 3.8rem;
+ width: 34rem;
+ flex-shrink: 0;
+}
+
+.swap_button_container {
+ width: 100%;
+ display: flex;
+ justify-content: end;
+}
+
+.swap_button_wrapper {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 0.8rem;
+ padding: 0.6rem 1.2rem;
+ border-radius: 0.4rem;
+ background-color: var(--dark_850_color);
+ cursor: pointer;
+ &:hover {
+ background-color: var(--dark_800_color);
+ }
+ &:active {
+ background-color: var(--dark_900_color);
+ }
+}
+
+.swap_text {
+ font-size: 1.4rem;
+}
+
+.swap_img {
+ width: 2rem;
+}
+
+
+.input_wrapper {
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ gap: 1.8rem;
+}
+
+.input_contents {
+ width: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 1rem;
+ color: var(--dark_basic_text_color);
+}
+
+.preset_text {
+ font-size: 1.6rem;
+ text-align: center;
+ flex-shrink: 0;
+ color: var(--dark_basic_text_color);
+}
+
+.multi_translation_input_wrapper {
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+ justify-content: center;
+ color: var(--dark_basic_text_color);
+}
+
+.multi_translation_title {
+ font-size: 1.2rem;
+}
+
+.reset_button_wrapper {
+ width: 100%;
+ display: flex;
+ justify-content: end;
+ align-items: center;
+}
\ No newline at end of file
diff --git a/src-ui/app/config_page/setting_section/setting_box/_templates/Templates.jsx b/src-ui/app/config_page/setting_section/setting_box/_templates/Templates.jsx
index b25af8b9..b23f8043 100644
--- a/src-ui/app/config_page/setting_section/setting_box/_templates/Templates.jsx
+++ b/src-ui/app/config_page/setting_section/setting_box/_templates/Templates.jsx
@@ -18,6 +18,7 @@ import {
WordFilter,
WordFilterListToggleComponent,
DownloadModels,
+ MessageFormat,
} from "../_components/";
import { Checkbox } from "@common_components";
@@ -129,4 +130,17 @@ export const WordFilterContainer = (props) => (
export const DownloadModelsContainer = (props) => (
-);
\ No newline at end of file
+);
+
+export const MessageFormatContainer = (props) => {
+ return (
+
+ );
+};
\ No newline at end of file
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 1baf00a5..65027ef3 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
@@ -8,6 +8,7 @@ import {
import {
CheckboxContainer,
+ MessageFormatContainer,
} from "../_templates/Templates";
import {
@@ -39,6 +40,11 @@ export const Others = () => {
+
+
+
+
+
);
};
@@ -151,4 +157,48 @@ const SendReceivedMessageToVrcContainer = () => {
toggleFunction={toggleEnableSendReceivedMessageToVrc}
/>
);
+};
+
+const SendMessageFormatPartsContainer = () => {
+ const { t } = useI18n();
+ const {
+ currentSendMessageFormatParts,
+ setSendMessageFormatParts,
+ currentMessageFormat_ExampleViewFilter,
+ toggleMessageFormat_ExampleViewFilter,
+ } = useOthers();
+
+ return (
+
+ );
+};
+
+const ReceivedMessageFormatPartsContainer = () => {
+ const { t } = useI18n();
+ const {
+ currentReceivedMessageFormatParts,
+ setReceivedMessageFormatParts,
+ currentMessageFormat_ExampleViewFilter,
+ toggleMessageFormat_ExampleViewFilter,
+ } = useOthers();
+
+ return (
+
+ );
};
\ No newline at end of file
diff --git a/src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx b/src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx
index 31c38816..4bd9b6f5 100644
--- a/src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx
+++ b/src-ui/app/config_page/setting_section/setting_box/vr/Vr.jsx
@@ -14,12 +14,12 @@ import {
SectionLabelComponent,
} from "../_components/";
+import { ResetButton } from "@common_components";
+
import {
useVr,
} from "@logics_configs";
-import RedoSvg from "@images/redo.svg?react";
-
import SquareSvg from "@images/square.svg?react";
import TriangleSvg from "@images/triangle.svg?react";
import { randomIntMinMax } from "@utils";
@@ -528,13 +528,6 @@ const CommonSettingsContainer = () => {
);
};
-const ResetButton = ({onClickFunction}) => {
- return (
-
- );
-};
const SendSampleTextToggleButton = () => {
const { t } = useI18n();
diff --git a/src-ui/app/config_page/setting_section/setting_box/vr/Vr.module.scss b/src-ui/app/config_page/setting_section/setting_box/vr/Vr.module.scss
index 9d0963e8..a2a76261 100644
--- a/src-ui/app/config_page/setting_section/setting_box/vr/Vr.module.scss
+++ b/src-ui/app/config_page/setting_section/setting_box/vr/Vr.module.scss
@@ -301,34 +301,6 @@
@include variable-button-wrapper(bottom, 50%, right, -60%, -45deg);
}
-
-
-.slider_reset_button {
- background-color: var(--dark_875_color);
- padding: 0.6rem;
- display: flex;
- justify-content: center;
- align-items: center;
- border-radius: 0.4rem;
- flex-shrink: 0;
- &:hover {
- background-color: var(--dark_825_color);
- & .slider_reset_svg {
- color: var(--dark_200_color);
- }
- }
- &:active {
- background-color: var(--dark_925_color);
- }
-}
-
-.slider_reset_svg {
- width: 1.4rem;
- color: var(--dark_550_color);
-}
-
-
-
.other_controls {
margin-top: 6rem;
display: flex;
diff --git a/src-ui/common_components/index.js b/src-ui/common_components/index.js
index 177161eb..e047306c 100644
--- a/src-ui/common_components/index.js
+++ b/src-ui/common_components/index.js
@@ -1,2 +1,3 @@
export { Checkbox } from "./checkbox/Checkbox";
-export { HomepageLinkButton } from "./homepage_link_button/HomepageLinkButton";
\ No newline at end of file
+export { HomepageLinkButton } from "./homepage_link_button/HomepageLinkButton";
+export { ResetButton } from "./reset_button/ResetButton";
\ No newline at end of file
diff --git a/src-ui/common_components/reset_button/ResetButton.jsx b/src-ui/common_components/reset_button/ResetButton.jsx
new file mode 100644
index 00000000..65974739
--- /dev/null
+++ b/src-ui/common_components/reset_button/ResetButton.jsx
@@ -0,0 +1,10 @@
+import styles from "./ResetButton.module.scss";
+import RedoSvg from "@images/redo.svg?react";
+
+export const ResetButton = ({ onClickFunction }) => {
+ return (
+
+ );
+};
\ No newline at end of file
diff --git a/src-ui/common_components/reset_button/ResetButton.module.scss b/src-ui/common_components/reset_button/ResetButton.module.scss
new file mode 100644
index 00000000..9be83c07
--- /dev/null
+++ b/src-ui/common_components/reset_button/ResetButton.module.scss
@@ -0,0 +1,24 @@
+.reset_button {
+ width: fit-content;
+ background-color: var(--dark_875_color);
+ padding: 0.6rem;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ border-radius: 0.4rem;
+ flex-shrink: 0;
+ &:hover {
+ background-color: var(--dark_825_color);
+ & .reset_svg {
+ color: var(--dark_200_color);
+ }
+ }
+ &:active {
+ background-color: var(--dark_925_color);
+ }
+}
+
+.reset_svg {
+ width: 1.4rem;
+ color: var(--dark_550_color);
+}
\ No newline at end of file
diff --git a/src-ui/logics/configs/others/useOthers.js b/src-ui/logics/configs/others/useOthers.js
index c8a417d6..c2b0179f 100644
--- a/src-ui/logics/configs/others/useOthers.js
+++ b/src-ui/logics/configs/others/useOthers.js
@@ -6,6 +6,9 @@ import {
useStore_EnableSendMessageToVrc,
useStore_EnableNotificationVrcSfx,
useStore_EnableSendReceivedMessageToVrc,
+ useStore_MessageFormat_ExampleViewFilter,
+ useStore_SendMessageFormatParts,
+ useStore_ReceivedMessageFormatParts,
} from "@store";
import { useStdoutToPython } from "@useStdoutToPython";
import { useNotificationStatus } from "@logics_common";
@@ -29,6 +32,12 @@ export const useOthers = () => {
// Speaker2Chatbox
// Send Received Message To VRC
const { currentEnableSendReceivedMessageToVrc, updateEnableSendReceivedMessageToVrc, pendingEnableSendReceivedMessageToVrc } = useStore_EnableSendReceivedMessageToVrc();
+ // Message Formats
+ const { currentMessageFormat_ExampleViewFilter, updateMessageFormat_ExampleViewFilter, pendingMessageFormat_ExampleViewFilter } = useStore_MessageFormat_ExampleViewFilter();
+ // Send
+ const { currentSendMessageFormatParts, updateSendMessageFormatParts, pendingSendMessageFormatParts } = useStore_SendMessageFormatParts();
+ // Received
+ const { currentReceivedMessageFormatParts, updateReceivedMessageFormatParts, pendingReceivedMessageFormatParts } = useStore_ReceivedMessageFormatParts();
const { showNotification_SaveSuccess } = useNotificationStatus();
@@ -178,6 +187,53 @@ export const useOthers = () => {
showNotification_SaveSuccess();
};
+ // Message Formats
+ // Send
+ const getSendMessageFormatParts = () => {
+ pendingSendMessageFormatParts();
+ asyncStdoutToPython("/get/data/send_message_format_parts");
+ };
+
+ const setSendMessageFormatParts = (message_format_parts) => {
+ pendingSendMessageFormatParts();
+ asyncStdoutToPython("/set/data/send_message_format_parts", message_format_parts);
+ };
+
+ const setSuccessSendMessageFormatParts = (message_format_parts) => {
+ updateSendMessageFormatParts(message_format_parts);
+ showNotification_SaveSuccess();
+ };
+
+ // Received
+ const getReceivedMessageFormatParts = () => {
+ pendingReceivedMessageFormatParts();
+ asyncStdoutToPython("/get/data/received_message_format_parts");
+ };
+
+ const setReceivedMessageFormatParts = (message_format_parts) => {
+ pendingReceivedMessageFormatParts();
+ asyncStdoutToPython("/set/data/received_message_format_parts", message_format_parts);
+ };
+
+ const setSuccessReceivedMessageFormatParts = (message_format_parts) => {
+ updateReceivedMessageFormatParts(message_format_parts);
+ showNotification_SaveSuccess();
+ };
+
+
+ const toggleMessageFormat_ExampleViewFilter = (id) => {
+ pendingMessageFormat_ExampleViewFilter();
+ if (["send", "received"].includes(id) === false) return console.error(`id should be small case 'send' or 'received'. got id: ${id}`);
+
+ updateMessageFormat_ExampleViewFilter({
+ ...currentMessageFormat_ExampleViewFilter.data,
+ [id]: currentMessageFormat_ExampleViewFilter.data[id] === "Simplified"
+ ? "All"
+ : "Simplified"
+ });
+ };
+
+
return {
// Auto Clear Message Input Box
currentEnableAutoClearMessageInputBox,
@@ -230,5 +286,22 @@ export const useOthers = () => {
toggleEnableSendReceivedMessageToVrc,
updateEnableSendReceivedMessageToVrc,
setSuccessEnableSendReceivedMessageToVrc,
+
+ // Message Formats
+ currentMessageFormat_ExampleViewFilter,
+ toggleMessageFormat_ExampleViewFilter,
+ // Send
+ currentSendMessageFormatParts,
+ updateSendMessageFormatParts,
+ getSendMessageFormatParts,
+ setSendMessageFormatParts,
+ setSuccessSendMessageFormatParts,
+
+ // Received
+ currentReceivedMessageFormatParts,
+ updateReceivedMessageFormatParts,
+ getReceivedMessageFormatParts,
+ setReceivedMessageFormatParts,
+ setSuccessReceivedMessageFormatParts,
};
};
\ No newline at end of file
diff --git a/src-ui/logics/useReceiveRoutes.js b/src-ui/logics/useReceiveRoutes.js
index 00c48a0b..c9380612 100644
--- a/src-ui/logics/useReceiveRoutes.js
+++ b/src-ui/logics/useReceiveRoutes.js
@@ -275,6 +275,12 @@ export const ROUTE_META_LIST = [
{ endpoint: "/get/data/notification_vrc_sfx", ns: configs, hook_name: "useOthers", method_name: "updateEnableNotificationVrcSfx" },
{ endpoint: "/set/enable/notification_vrc_sfx", ns: configs, hook_name: "useOthers", method_name: "setSuccessEnableNotificationVrcSfx" },
{ endpoint: "/set/disable/notification_vrc_sfx", ns: configs, hook_name: "useOthers", method_name: "setSuccessEnableNotificationVrcSfx" },
+ { endpoint: "/set/disable/notification_vrc_sfx", ns: configs, hook_name: "useOthers", method_name: "setSuccessEnableNotificationVrcSfx" },
+
+ { endpoint: "/get/data/send_message_format_parts", ns: configs, hook_name: "useOthers", method_name: "updateSendMessageFormatParts" },
+ { endpoint: "/set/data/send_message_format_parts", ns: configs, hook_name: "useOthers", method_name: "setSuccessSendMessageFormatParts" },
+ { 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" },
// Hotkeys
{ endpoint: "/get/data/hotkeys", ns: configs, hook_name: "useHotkeys", method_name: "updateHotkeys" },
diff --git a/src-ui/store.js b/src-ui/store.js
index 7d2fac28..9241ad41 100644
--- a/src-ui/store.js
+++ b/src-ui/store.js
@@ -274,6 +274,37 @@ export const { atomInstance: Atom_EnableVrcMicMuteSync, useHook: useStore_Enable
export const { atomInstance: Atom_EnableSendMessageToVrc, useHook: useStore_EnableSendMessageToVrc } = createAtomWithHook(true, "EnableSendMessageToVrc");
export const { atomInstance: Atom_EnableSendReceivedMessageToVrc, useHook: useStore_EnableSendReceivedMessageToVrc } = createAtomWithHook(false, "EnableSendReceivedMessageToVrc");
export const { atomInstance: Atom_EnableNotificationVrcSfx, useHook: useStore_EnableNotificationVrcSfx } = createAtomWithHook(true, "EnableNotificationVrcSfx");
+export const { atomInstance: Atom_MessageFormat_ExampleViewFilter, useHook: useStore_MessageFormat_ExampleViewFilter } = createAtomWithHook({
+ send: "Simplified",
+ received: "Simplified",
+}, "MessageFormat_ExampleViewFilter");
+export const { atomInstance: Atom_SendMessageFormatParts, useHook: useStore_SendMessageFormatParts } = createAtomWithHook({
+ message: {
+ prefix: "",
+ suffix: ""
+ },
+ separator: "\n",
+ translation: {
+ prefix: "",
+ separator: "\n",
+ suffix: ""
+ },
+ translation_first: false,
+}, "SendMessageFormatParts");
+export const { atomInstance: Atom_ReceivedMessageFormatParts, useHook: useStore_ReceivedMessageFormatParts } = createAtomWithHook({
+ message: {
+ prefix: "",
+ suffix: ""
+ },
+ separator: "\n",
+ translation: {
+ prefix: "",
+ separator: "\n",
+ suffix: ""
+ },
+ translation_first: false,
+}, "ReceivedMessageFormatParts");
+
// Hotkeys
export const { atomInstance: Atom_Hotkeys, useHook: useStore_Hotkeys } = createAtomWithHook({
diff --git a/src-ui/ui_configs.js b/src-ui/ui_configs.js
index 915d6a6b..e3bf85f2 100644
--- a/src-ui/ui_configs.js
+++ b/src-ui/ui_configs.js
@@ -49,6 +49,33 @@ export const ui_configs = {
tracker: "LeftHand",
},
+ send_message_format_parts: {
+ message: {
+ prefix: "",
+ suffix: ""
+ },
+ separator: "\n",
+ translation: {
+ prefix: "",
+ separator: "\n",
+ suffix: ""
+ },
+ translation_first: false,
+ },
+ received_message_format_parts: {
+ message: {
+ prefix: "",
+ suffix: ""
+ },
+ separator: "\n",
+ translation: {
+ prefix: "",
+ separator: "\n",
+ suffix: ""
+ },
+ translation_first: false,
+ },
+
selectable_ui_languages: [
{id: "en", label: "English"},
{id: "ja", label: "日本語"},
From 7a6ed850b5dfebc64daa74410872ce7c77851fb7 Mon Sep 17 00:00:00 2001
From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com>
Date: Sat, 30 Aug 2025 21:13:15 +0900
Subject: [PATCH 07/16] [Chore] Localization: Add quotations. (Asked english
localization from this edited version.)
---
locales/en.yml | 20 ++++++++++----------
locales/ja.yml | 22 +++++++++++-----------
2 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/locales/en.yml b/locales/en.yml
index 065d01f6..0b7405e9 100644
--- a/locales/en.yml
+++ b/locales/en.yml
@@ -244,7 +244,7 @@ config_page:
title: "Settings"
original: "Original"
translated: "Translated"
- for_multi_translation: For Multi-Translation
+ for_multi_translation: "For Multi-Translation"
send_message_format:
label: "Message Format (Send)"
desc: "You can change the decoration of the message you want to send."
@@ -294,16 +294,16 @@ config_page:
save_success: "Settings have been saved."
plugin_notifications:
- downloading: Downloading the plugin.
- downloaded_success: Downloaded successfully.
- downloaded_error: Download failed.
+ downloading: "Downloading the plugin."
+ downloaded_success: "Downloaded successfully."
+ downloaded_error: "Download failed."
- updating: Updating the plugin.
- updated_success: Updated successfully.
- updated_error: Update failed.
+ updating: "Updating the plugin."
+ updated_success: "Updated successfully."
+ updated_error: "Update failed."
- disabled_out_of_support: The plugin has been disabled. It's not supported on this VRCT version.
+ disabled_out_of_support: "The plugin has been disabled. It's not supported on this VRCT version."
disabled_due_to_an_error: "An error was detected while running the plugin. Please report this to the plugin developer."
- is_enabled: The plugin has enabled.
- is_disabled: The plugin has disabled.
\ No newline at end of file
+ is_enabled: "The plugin has enabled."
+ is_disabled: "The plugin has disabled."
\ No newline at end of file
diff --git a/locales/ja.yml b/locales/ja.yml
index 978a5b29..d3da554e 100644
--- a/locales/ja.yml
+++ b/locales/ja.yml
@@ -243,7 +243,7 @@ config_page:
title: "設定"
original: "原文"
translated: "翻訳"
- for_multi_translation: 多言語翻訳用
+ for_multi_translation: "多言語翻訳用"
send_message_format:
label: メッセージフォーマット(送信)
desc: VRChatで相手に実際に見えるフォーマットを変更できます。
@@ -293,16 +293,16 @@ config_page:
save_success: "設定を保存しました。"
plugin_notifications:
- downloading: プラグインをダウンロード中。
- downloaded_success: プラグインのダウンロードが完了しました。
- downloaded_error: プラグインのダウンロードに失敗しました。
+ downloading: "プラグインをダウンロード中。"
+ downloaded_success: "プラグインのダウンロードが完了しました。"
+ downloaded_error: "プラグインのダウンロードに失敗しました。"
- updating: プラグインをアップデート中。
- updated_success: プラグインのアップデートが完了しました。
- updated_error: プラグインのアップデートに失敗しました。
+ updating: "プラグインをアップデート中。"
+ updated_success: "プラグインのアップデートが完了しました。"
+ updated_error: "プラグインのアップデートに失敗しました。"
- disabled_out_of_support: 現在のバージョンとの互換性がありません。プラグインを無効にしました。
- disabled_due_to_an_error: プラグイン実行中にエラーを検知しました。プラグイン開発者に報告してください。
+ disabled_out_of_support: "現在のバージョンとの互換性がありません。プラグインを無効にしました。"
+ disabled_due_to_an_error: "プラグイン実行中にエラーを検知しました。プラグイン開発者に報告してください。"
- is_enabled: プラグインを有効にしました。
- is_disabled: プラグインを無効にしました。
\ No newline at end of file
+ is_enabled: "プラグインを有効にしました。"
+ is_disabled: "プラグインを無効にしました。"
\ No newline at end of file
From e7ae70add0942552835dbc0159a1f7d89e1d6890 Mon Sep 17 00:00:00 2001
From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com>
Date: Sat, 30 Aug 2025 22:45:09 +0900
Subject: [PATCH 08/16] [Update] Localization: Add and adjust keys for each
language. (Asked korean localization from this edited version.)
---
locales/en.yml | 1 -
locales/ko.yml | 65 ++++++++++++++++++++++++++++++++++++++++++++-
locales/zh-Hans.yml | 65 ++++++++++++++++++++++++++++++++++++++++++++-
locales/zh-Hant.yml | 65 ++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 192 insertions(+), 4 deletions(-)
diff --git a/locales/en.yml b/locales/en.yml
index 0b7405e9..f311ced3 100644
--- a/locales/en.yml
+++ b/locales/en.yml
@@ -231,7 +231,6 @@ config_page:
send_received_message_to_vrc:
label: "Send Received Message To VRChat"
desc: "Send the message you received from the speaker's voice to VRChat's chatbox."
-
message_format_common:
example_view:
title: "Preview"
diff --git a/locales/ko.yml b/locales/ko.yml
index 39df6d4a..58684102 100644
--- a/locales/ko.yml
+++ b/locales/ko.yml
@@ -24,6 +24,9 @@ common_error:
invalid_value_speaker_phrase_timeout: "0 이상에서 '{{speaker_record_timeout_label}}'보다 작을 수 없습니다."
invalid_value_speaker_max_phrase: "0 이상의 숫자만 설정할 수 있습니다."
+common_warning:
+ unable_to_use_osc_query:
+
main_page:
translation: "번역"
transcription_send: "음성인식 (마이크)"
@@ -79,6 +82,7 @@ config_page:
transcription: "음성인식"
others: "기타"
hotkeys:
+ plugins:
advanced_settings: "고급 설정"
device:
@@ -115,6 +119,9 @@ config_page:
hide: "숨김 (Enter 키를 사용하여 전송)"
show: "표시"
show_and_disable_enter_key: "표시 (Enter 키 전송 비활성화)"
+ show_resend_button:
+ label:
+ desc:
font_family:
label: "폰트"
ui_language:
@@ -204,6 +211,7 @@ config_page:
others:
section_label_sounds:
+ section_label_message_formats:
auto_clear_the_message_box:
label: "챗박스 자동 삭제"
send_only_translated_messages:
@@ -223,6 +231,25 @@ config_page:
send_received_message_to_vrc:
label:
desc:
+ message_format_common:
+ example_view:
+ title:
+ original_translated:
+ original_translated_multi:
+ translated_only_multi:
+ translated_only:
+ original_only:
+ settings:
+ title:
+ original:
+ translated:
+ for_multi_translation:
+ send_message_format:
+ label:
+ desc:
+ received_message_format:
+ label:
+ desc:
hotkeys:
toggle_vrct_visibility:
@@ -234,6 +261,18 @@ config_page:
toggle_transcription_receive:
label:
+ plugins:
+ downloaded_version:
+ latest_version:
+ available_after_updating:
+ unavailable_downloaded:
+ no_latest_info:
+ using_latest_version:
+ available_latest_version:
+ unavailable_latest_version:
+ available_in_latest_vrct_version:
+ unavailable_not_downloaded:
+
advanced_settings:
osc_ip_address:
label: "OSC IP 주소"
@@ -242,4 +281,28 @@ config_page:
open_config_filepath:
label: "설정 파일 열기"
switch_compute_device:
- label:
\ No newline at end of file
+ label:
+ enable_websocket:
+ label:
+ websocket_host:
+ label:
+ websocket_port:
+ label:
+
+ notifications:
+ save_success:
+
+plugin_notifications:
+ downloading:
+ downloaded_success:
+ downloaded_error:
+
+ updating:
+ updated_success:
+ updated_error:
+
+ disabled_out_of_support:
+ disabled_due_to_an_error:
+
+ is_enabled:
+ is_disabled:
\ No newline at end of file
diff --git a/locales/zh-Hans.yml b/locales/zh-Hans.yml
index dd1dafc7..3e2ec51f 100644
--- a/locales/zh-Hans.yml
+++ b/locales/zh-Hans.yml
@@ -24,6 +24,9 @@ common_error:
invalid_value_speaker_phrase_timeout: "转录间隔时间大于0秒且不能小于「{{speaker_record_timeout_label}}」"
invalid_value_speaker_max_phrase: "数值应为 0 以上"
+common_warning:
+ unable_to_use_osc_query:
+
main_page:
translation: "翻译"
transcription_send: "你的语音转文字"
@@ -79,6 +82,7 @@ config_page:
transcription: "转录"
others: "其他"
hotkeys:
+ plugins:
advanced_settings: "高级设置"
device:
@@ -115,6 +119,9 @@ config_page:
hide: "隐藏 (可使用回车发送信息)"
show: "显示"
show_and_disable_enter_key: "显示,并且停用‘回车发送信息’"
+ show_resend_button:
+ label:
+ desc:
font_family:
label: "字体"
ui_language:
@@ -204,6 +211,7 @@ config_page:
others:
section_label_sounds:
+ section_label_message_formats:
auto_clear_the_message_box:
label: "发言后自动清空chatbox"
send_only_translated_messages:
@@ -223,6 +231,25 @@ config_page:
send_received_message_to_vrc:
label:
desc:
+ message_format_common:
+ example_view:
+ title:
+ original_translated:
+ original_translated_multi:
+ translated_only_multi:
+ translated_only:
+ original_only:
+ settings:
+ title:
+ original:
+ translated:
+ for_multi_translation:
+ send_message_format:
+ label:
+ desc:
+ received_message_format:
+ label:
+ desc:
hotkeys:
toggle_vrct_visibility:
@@ -234,6 +261,18 @@ config_page:
toggle_transcription_receive:
label:
+ plugins:
+ downloaded_version:
+ latest_version:
+ available_after_updating:
+ unavailable_downloaded:
+ no_latest_info:
+ using_latest_version:
+ available_latest_version:
+ unavailable_latest_version:
+ available_in_latest_vrct_version:
+ unavailable_not_downloaded:
+
advanced_settings:
osc_ip_address:
label: "OSC IP 地址"
@@ -242,4 +281,28 @@ config_page:
open_config_filepath:
label: "打开设置文件"
switch_compute_device:
- label:
\ No newline at end of file
+ label:
+ enable_websocket:
+ label:
+ websocket_host:
+ label:
+ websocket_port:
+ label:
+
+ notifications:
+ save_success:
+
+plugin_notifications:
+ downloading:
+ downloaded_success:
+ downloaded_error:
+
+ updating:
+ updated_success:
+ updated_error:
+
+ disabled_out_of_support:
+ disabled_due_to_an_error:
+
+ is_enabled:
+ is_disabled:
\ No newline at end of file
diff --git a/locales/zh-Hant.yml b/locales/zh-Hant.yml
index 08210a7d..f091fd03 100644
--- a/locales/zh-Hant.yml
+++ b/locales/zh-Hant.yml
@@ -24,6 +24,9 @@ common_error:
invalid_value_speaker_phrase_timeout: "不能小於「{{speaker_record_timeout_label}}」,應為 0 或更高。"
invalid_value_speaker_max_phrase: "可以設置 0 或更高的數值。"
+common_warning:
+ unable_to_use_osc_query:
+
main_page:
translation: "翻譯"
transcription_send: "麥克風轉文字"
@@ -79,6 +82,7 @@ config_page:
transcription: "轉錄"
others: "其他"
hotkeys:
+ plugins:
advanced_settings: "進階設定"
device:
@@ -115,6 +119,9 @@ config_page:
hide: "隱藏(使用 Enter 鍵發送)"
show: "顯示"
show_and_disable_enter_key: "顯示並停用 Enter 鍵發送"
+ show_resend_button:
+ label:
+ desc:
font_family:
label: "字型"
ui_language:
@@ -204,6 +211,7 @@ config_page:
others:
section_label_sounds:
+ section_label_message_formats:
auto_clear_the_message_box:
label: "自動清除 Chatbox"
send_only_translated_messages:
@@ -223,6 +231,25 @@ config_page:
send_received_message_to_vrc:
label:
desc:
+ message_format_common:
+ example_view:
+ title:
+ original_translated:
+ original_translated_multi:
+ translated_only_multi:
+ translated_only:
+ original_only:
+ settings:
+ title:
+ original:
+ translated:
+ for_multi_translation:
+ send_message_format:
+ label:
+ desc:
+ received_message_format:
+ label:
+ desc:
hotkeys:
toggle_vrct_visibility:
@@ -234,6 +261,18 @@ config_page:
toggle_transcription_receive:
label:
+ plugins:
+ downloaded_version:
+ latest_version:
+ available_after_updating:
+ unavailable_downloaded:
+ no_latest_info:
+ using_latest_version:
+ available_latest_version:
+ unavailable_latest_version:
+ available_in_latest_vrct_version:
+ unavailable_not_downloaded:
+
advanced_settings:
osc_ip_address:
label: "OSC IP 位址"
@@ -242,4 +281,28 @@ config_page:
open_config_filepath:
label: "打開設定文件"
switch_compute_device:
- label:
\ No newline at end of file
+ label:
+ enable_websocket:
+ label:
+ websocket_host:
+ label:
+ websocket_port:
+ label:
+
+ notifications:
+ save_success:
+
+plugin_notifications:
+ downloading:
+ downloaded_success:
+ downloaded_error:
+
+ updating:
+ updated_success:
+ updated_error:
+
+ disabled_out_of_support:
+ disabled_due_to_an_error:
+
+ is_enabled:
+ is_disabled:
\ No newline at end of file
From 8867d180d22a214def354a08307661522439c346 Mon Sep 17 00:00:00 2001
From: Soumt
Date: Wed, 3 Sep 2025 20:03:41 +0900
Subject: [PATCH 09/16] [Update] Localization: Updated Korean localization
---
locales/ko.yml | 216 ++++++++++++++++++++++++-------------------------
1 file changed, 108 insertions(+), 108 deletions(-)
diff --git a/locales/ko.yml b/locales/ko.yml
index 58684102..2294e974 100644
--- a/locales/ko.yml
+++ b/locales/ko.yml
@@ -9,11 +9,11 @@ common:
common_error:
no_device_mic: "마이크 디바이스를 찾지 못했습니다."
no_device_speaker: "스피커 디바이스를 찾지 못했습니다."
- threshold_invalid_value:
- failed_download_weight_ctranslate2:
- failed_download_weight_whisper:
- translation_limit:
- deepl_auth_key_invalid_length:
+ threshold_invalid_value: "{{min}}부터 {{max}}까지의 숫자로 설정할 수 있습니다."
+ failed_download_weight_ctranslate2: "CTranslate2 모델 다운로드에 실패했습니다."
+ failed_download_weight_whisper: "Whisper 모델 다운로드에 실패했습니다."
+ translation_limit: "번역 엔진 사용 제한에 도달했거나 일시적으로 이용 제한이 걸렸습니다."
+ deepl_auth_key_invalid_length: "DeepL 인증 키의 문자 수가 잘못되었습니다."
deepl_auth_key_failed_authentication: "인증키가 잘못되었거나 API 사용 제한이 상한에 도달했습니다."
invalid_value_mic_record_timeout: "0 이상에서 '{{mic_phrase_timeout_label}}'보다 클 수 없습니다."
@@ -25,7 +25,7 @@ common_error:
invalid_value_speaker_max_phrase: "0 이상의 숫자만 설정할 수 있습니다."
common_warning:
- unable_to_use_osc_query:
+ unable_to_use_osc_query: "OSC IP 주소 설정으로 인해 OSC 데이터 수신이 불가능하므로, 아래 기능이 자동으로 비활성화되었습니다."
main_page:
translation: "번역"
@@ -42,7 +42,7 @@ main_page:
translator_label_default: "기본값"
translator_selector:
- is_selected_same_language:
+ is_selected_same_language: "「{{your_language}}」와 「{{target_language}}」에 동일한 언어가 선택되어 있으므로, 「{{ctranslate2}}」만 사용할 수 있습니다."
message_log:
all: "전체"
@@ -50,7 +50,7 @@ main_page:
received: "수신"
system: "시스템"
- resend_button_on_hover_desc:
+ resend_button_on_hover_desc: "길게 눌러서 보내기"
state_text_enabled: "Enabled"
state_text_disabled: "Disabled"
@@ -63,33 +63,33 @@ main_page:
updating: "업데이트 중..."
update_modal:
- cpu_desc:
- cuda_desc:
- cuda_compare_cpu_desc:
- cuda_disk_space_desc:
- close_modal:
- download_latest_and_restart:
- is_latest_version_already:
- is_current_compute_device:
+ cpu_desc: "처리 장치로 CPU만을 사용합니다."
+ cuda_desc: "처리 장치로 CPU와 NVIDIA GPU를 선택할 수 있습니다."
+ cuda_compare_cpu_desc: "GPU 선택 시, CPU에 비해 처리가 빠릅니다."
+ cuda_disk_space_desc: "약 {{size}}의 디스크 용량이 필요합니다."
+ close_modal: "닫기"
+ download_latest_and_restart: "최신 버전이 다운로드되면 앱이 자동으로 재시작됩니다."
+ is_latest_version_already: "이미 최신 버전을 사용 중입니다."
+ is_current_compute_device: "현재 사용 중인 버전"
config_page:
version: "버전 {{version}}"
- model_download_button_label:
+ model_download_button_label: "다운로드"
side_menu_labels:
- device:
+ device: "장치"
appearance: "모양"
translation: "번역"
transcription: "음성인식"
others: "기타"
- hotkeys:
- plugins:
+ hotkeys: "단축키"
+ plugins: "플러그인"
advanced_settings: "고급 설정"
device:
- check_volume:
- label_auto_select:
+ check_volume: "음량 확인"
+ label_auto_select: "자동 선택"
label_host: "호스트/드라이버"
- label_device:
+ label_device: "장치"
mic_host_device:
label: "마이크 장치"
mic_dynamic_energy_threshold:
@@ -120,8 +120,8 @@ config_page:
show: "표시"
show_and_disable_enter_key: "표시 (Enter 키 전송 비활성화)"
show_resend_button:
- label:
- desc:
+ label: "재전송 버튼 표시"
+ desc: "보낸 메시지 로그에 마우스를 올리면 재전송 버튼이 표시됩니다. 클릭하면 편집 모드로 전환되며, 길게 누르면 재전송됩니다."
font_family:
label: "폰트"
ui_language:
@@ -134,19 +134,19 @@ config_page:
small: "일반 모델 ({{capacity}})"
large: "정밀 모델 ({{capacity}})"
ctranslate2_compute_device:
- label:
+ label: "AI 번역 {{ctranslate2}} 처리 장치"
deepl_auth_key:
label: "DeepL 인증키"
desc: "사용시 메인화면에 있는 {{translator}}를 DeepL_API로 변경해 주세요.\n지원하지 않는 언어도 있습니다."
open_auth_key_webpage: "DeepL 계정 페이지 열기"
- save:
- edit:
+ save: "저장"
+ edit: "편집"
auth_key_success: "인증키 갱신이 완료되었습니다."
transcription:
section_label_mic: "마이크"
section_label_speaker: "스피커"
- section_label_transcription_engines:
+ section_label_transcription_engines: "음성 인식 엔진"
mic_record_timeout:
label: "최대 무음 시간"
desc: "무음을 감지하고 설정된 시간(초)만큼의 시간이 지나면 음성 입력이 종료된 것으로 판단합니다."
@@ -171,47 +171,47 @@ config_page:
label: "최대 입력 절(phrases) 수"
desc: "식된 단어 수의 하한값으로, 이 수치를 초과하는 경우에만 결과를 로그에 표시합니다."
select_transcription_engine:
- label:
+ label: "음성 인식에 사용할 엔진"
whisper_weight_type:
label: "Whisper 모델 타입"
- desc:
+ desc: "용량이 큰 모델일수록 정확도는 높지만, 그만큼 CPU나 GPU를 많이 차지합니다. ※ 특히 medium보다 용량이 큰 모델은 CPU/GPU 성능에 따라 사용 자체가 어려울 수 있습니다."
model_template: "{{model_name}} 모델 ({{capacity}})"
recommended_model_template: "{{model_name}} 모델 ({{capacity}}) (권장)"
whisper_compute_device:
- label:
+ label: "Whisper에서 사용할 처리 장치"
vr:
- single_line:
- multi_lines:
- overlay_enable:
- restore_default_settings:
- position:
- rotation:
- x_position:
- y_position:
- z_position:
- x_rotation:
- y_rotation:
- z_rotation:
+ single_line: "한 줄"
+ multi_lines: "여러 줄"
+ overlay_enable: "활성화"
+ restore_default_settings: "초기값으로 되돌리기"
+ position: "위치"
+ rotation: "회전"
+ x_position: "X축 (좌우)"
+ y_position: "Y축 (상하)"
+ z_position: "Z축 (앞뒤)"
+ x_rotation: "X축 회전"
+ y_rotation: "Y축 회전"
+ z_rotation: "Z축 회전"
sample_text_button:
- start:
- stop:
- sample_text:
- opacity:
- ui_scaling:
- display_duration:
- fadeout_duration:
- common_settings:
- tracker:
- hmd:
- left_hand:
- right_hand:
+ start: "샘플 텍스트를 오버레이에 전송"
+ stop: "전송 중지"
+ sample_text: "샘플 텍스트"
+ opacity: "투명도"
+ ui_scaling: "UI 크기 조정"
+ display_duration: "표시 시간"
+ fadeout_duration: "페이드 아웃 시간"
+ common_settings: "공통 설정"
+ tracker: "표시할 트래커의 위치"
+ hmd: "HMD"
+ left_hand: "왼손"
+ right_hand: "오른손"
overlay_show_only_translated_messages:
- label:
+ label: "번역된 메시지만 표시"
others:
- section_label_sounds:
- section_label_message_formats:
+ section_label_sounds: "사운드"
+ section_label_message_formats: "메시지 형식"
auto_clear_the_message_box:
label: "챗박스 자동 삭제"
send_only_translated_messages:
@@ -220,58 +220,58 @@ config_page:
label: "대화 로그 자동 저장"
desc: "logs 폴더에 텍스트 파일로 로그가 저장됩니다."
vrc_mic_mute_sync:
- label:
- desc:
+ label: "VRC 마이크 음소거 동기화"
+ desc: "VRChat의 마이크가 음소거 상태인 동안에는 메시지를 VRChat에 전송하지 않습니다. ※ 약간의 지연이 발생할 수 있습니다. 또한 눌러서 말하기(Push-To-Talk) 기능은 지원되지 않습니다."
send_message_to_vrc:
label: "VRChat에 메시지 전송"
desc: "VRChat에 메시지를 보내지 않고 사용할 수 있는 방법이 있지만 지원되지 않습니다. VRChat에 메시지를 보내려면 이 기능을 활성화하세요."
notification_vrc_sfx:
- label:
- desc:
+ label: "채팅 전송 시 채팅창 알림음 재생"
+ desc: "이 기능을 비활성화하면 다른 사람이 들을 수 있는 채팅창 알림음을 울리지 않고 조용히 전송합니다."
send_received_message_to_vrc:
- label:
- desc:
+ label: "수신한 메시지를 VRChat에 전송"
+ desc: "스피커에서 인식된 내용을 텍스트로 변환한 메시지가 VRChat에 전송됩니다."
message_format_common:
example_view:
- title:
- original_translated:
- original_translated_multi:
- translated_only_multi:
- translated_only:
- original_only:
+ title: "미리 보기"
+ original_translated: "원문 + 번역문"
+ original_translated_multi: "원문 + 번역문 (다국어)"
+ translated_only_multi: "번역문만 (다국어)"
+ translated_only: "번역문만"
+ original_only: "원문만"
settings:
- title:
- original:
- translated:
- for_multi_translation:
+ title: "설정"
+ original: "원문"
+ translated: "\n번역문"
+ for_multi_translation: "다국어 번역용"
send_message_format:
- label:
- desc:
+ label: "메시지 형식 (송신)"
+ desc: "VRChat에서 상대방에게 실제로 보이는 형식을 변경할 수 있습니다."
received_message_format:
- label:
- desc:
+ label: "메시지 형식 (Speaker2Chatbox)"
+ desc: "현재로서는 Speaker2Chatbox로 전송할 때의 표시용으로 사용됩니다."
hotkeys:
toggle_vrct_visibility:
- label:
+ label: "VRCT 최소화/활성화 전환"
toggle_translation:
- label:
+ label: "「{{translation}}」 켜기/끄기 전환"
toggle_transcription_send:
- label:
+ label: "「{{transcription_send}}」 켜기/끄기 전환"
toggle_transcription_receive:
- label:
+ label: "「{{transcription_receive}}」 켜기/끄기 전환"
plugins:
- downloaded_version:
- latest_version:
- available_after_updating:
- unavailable_downloaded:
- no_latest_info:
- using_latest_version:
- available_latest_version:
- unavailable_latest_version:
- available_in_latest_vrct_version:
- unavailable_not_downloaded:
+ downloaded_version: "다운로드된 버전: {{downloaded_version}}"
+ latest_version: "최신 버전: {{latest_version}}"
+ available_after_updating: "최신 버전으로 업데이트 후 이용 가능"
+ unavailable_downloaded: "현재 사용 중인 VRCT 버전과의 호환성 문제로 인해 이용 불가"
+ no_latest_info: "최신 정보를 가져올 수 없습니다"
+ using_latest_version: "최신 버전을 사용 중"
+ available_latest_version: "최신 버전을 이용 가능"
+ unavailable_latest_version: "최신 버전은 현재 이용 불가"
+ available_in_latest_vrct_version: "VRCT 최신 버전에서 이용 가능"
+ unavailable_not_downloaded: "현재 이용 불가"
advanced_settings:
osc_ip_address:
@@ -281,28 +281,28 @@ config_page:
open_config_filepath:
label: "설정 파일 열기"
switch_compute_device:
- label:
+ label: "VRCT CPU/GPU 버전 전환"
enable_websocket:
- label:
+ label: "WebSocket 서버 활성화"
websocket_host:
- label:
+ label: "WebSocket 호스트"
websocket_port:
- label:
+ label: "WebSocket 포트"
notifications:
- save_success:
+ save_success: "설정을 저장했습니다."
plugin_notifications:
- downloading:
- downloaded_success:
- downloaded_error:
+ downloading: "플러그인을 다운로드 중입니다."
+ downloaded_success: "플러그인 다운로드가 완료되었습니다."
+ downloaded_error: "플러그인 다운로드에 실패했습니다."
- updating:
- updated_success:
- updated_error:
+ updating: "플러그인을 업데이트 중입니다."
+ updated_success: "플러그인 업데이트가 완료되었습니다."
+ updated_error: "플러그인 업데이트에 실패했습니다."
- disabled_out_of_support:
- disabled_due_to_an_error:
+ disabled_out_of_support: "현재 버전과 호환되지 않습니다. 플러그인을 비활성화했습니다."
+ disabled_due_to_an_error: "플러그인 실행 중 오류를 감지했습니다. 플러그인 개발자에게 보고해 주세요."
- is_enabled:
- is_disabled:
\ No newline at end of file
+ is_enabled: "플러그인을 활성화했습니다."
+ is_disabled: "플러그인을 비활성화했습니다."
From 9c2123fe31b4980a87ecf5ecdbe413a5d7e0df69 Mon Sep 17 00:00:00 2001
From: Soumt
Date: Wed, 3 Sep 2025 20:38:06 +0900
Subject: [PATCH 10/16] [Chore] Localization: Address minor Korean localization
review feedback
---
locales/ko.yml | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/locales/ko.yml b/locales/ko.yml
index 2294e974..bdbf118e 100644
--- a/locales/ko.yml
+++ b/locales/ko.yml
@@ -42,7 +42,7 @@ main_page:
translator_label_default: "기본값"
translator_selector:
- is_selected_same_language: "「{{your_language}}」와 「{{target_language}}」에 동일한 언어가 선택되어 있으므로, 「{{ctranslate2}}」만 사용할 수 있습니다."
+ is_selected_same_language: "'{{your_language}}'와 '{{target_language}}'에 동일한 언어가 선택되어 있으므로, 「{{ctranslate2}}」만 사용할 수 있습니다."
message_log:
all: "전체"
@@ -174,7 +174,7 @@ config_page:
label: "음성 인식에 사용할 엔진"
whisper_weight_type:
label: "Whisper 모델 타입"
- desc: "용량이 큰 모델일수록 정확도는 높지만, 그만큼 CPU나 GPU를 많이 차지합니다. ※ 특히 medium보다 용량이 큰 모델은 CPU/GPU 성능에 따라 사용 자체가 어려울 수 있습니다."
+ desc: "용량이 큰 모델일수록 정확도는 높지만, 그만큼 CPU나 GPU를 많이 차지합니다. * 특히 medium보다 용량이 큰 모델은 CPU/GPU 성능에 따라 사용 자체가 어려울 수 있습니다."
model_template: "{{model_name}} 모델 ({{capacity}})"
recommended_model_template: "{{model_name}} 모델 ({{capacity}}) (권장)"
whisper_compute_device:
@@ -221,7 +221,7 @@ config_page:
desc: "logs 폴더에 텍스트 파일로 로그가 저장됩니다."
vrc_mic_mute_sync:
label: "VRC 마이크 음소거 동기화"
- desc: "VRChat의 마이크가 음소거 상태인 동안에는 메시지를 VRChat에 전송하지 않습니다. ※ 약간의 지연이 발생할 수 있습니다. 또한 눌러서 말하기(Push-To-Talk) 기능은 지원되지 않습니다."
+ desc: "VRChat의 마이크가 음소거 상태인 동안에는 메시지를 VRChat에 전송하지 않습니다. * 약간의 지연이 발생할 수 있습니다. 또한 눌러서 말하기(Push-To-Talk) 기능은 지원되지 않습니다."
send_message_to_vrc:
label: "VRChat에 메시지 전송"
desc: "VRChat에 메시지를 보내지 않고 사용할 수 있는 방법이 있지만 지원되지 않습니다. VRChat에 메시지를 보내려면 이 기능을 활성화하세요."
@@ -255,11 +255,11 @@ config_page:
toggle_vrct_visibility:
label: "VRCT 최소화/활성화 전환"
toggle_translation:
- label: "「{{translation}}」 켜기/끄기 전환"
+ label: "'{{translation}}' 켜기/끄기 전환"
toggle_transcription_send:
- label: "「{{transcription_send}}」 켜기/끄기 전환"
+ label: "'{{transcription_send}}' 켜기/끄기 전환"
toggle_transcription_receive:
- label: "「{{transcription_receive}}」 켜기/끄기 전환"
+ label: "'{{transcription_receive}}' 켜기/끄기 전환"
plugins:
downloaded_version: "다운로드된 버전: {{downloaded_version}}"
From c9dbd13a3a05f5fbe6631ce8a7693471487db05a Mon Sep 17 00:00:00 2001
From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com>
Date: Thu, 4 Sep 2025 13:49:49 +0900
Subject: [PATCH 11/16] [Chore] Adjust new line codes.
---
locales/ko.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/locales/ko.yml b/locales/ko.yml
index bdbf118e..52594be3 100644
--- a/locales/ko.yml
+++ b/locales/ko.yml
@@ -194,7 +194,7 @@ config_page:
y_rotation: "Y축 회전"
z_rotation: "Z축 회전"
sample_text_button:
- start: "샘플 텍스트를 오버레이에 전송"
+ start: "샘플 텍스트를\n오버레이에 전송"
stop: "전송 중지"
sample_text: "샘플 텍스트"
opacity: "투명도"
@@ -242,7 +242,7 @@ config_page:
settings:
title: "설정"
original: "원문"
- translated: "\n번역문"
+ translated: "번역문"
for_multi_translation: "다국어 번역용"
send_message_format:
label: "메시지 형식 (송신)"
From cad0f796fa4dab21691fa7f0971b5c180bdcf242 Mon Sep 17 00:00:00 2001
From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com>
Date: Fri, 5 Sep 2025 10:44:23 +0900
Subject: [PATCH 12/16] [Update] Transcription: Add UI. The user can config
'mic/speaker avg logprob' and 'mic/speaker no speech prob' that is related
with Whisper's parameter.
---
.../setting_box/appearance/Appearance.jsx | 3 +
.../transcription/Transcription.jsx | 195 ++++++++++++++++++
.../configs/transcription/useTranscription.js | 99 +++++++++
src-ui/logics/useReceiveRoutes.js | 10 +
src-ui/store.js | 5 +
5 files changed, 312 insertions(+)
diff --git a/src-ui/app/config_page/setting_section/setting_box/appearance/Appearance.jsx b/src-ui/app/config_page/setting_section/setting_box/appearance/Appearance.jsx
index 1f2f9eb4..cc7e730f 100644
--- a/src-ui/app/config_page/setting_section/setting_box/appearance/Appearance.jsx
+++ b/src-ui/app/config_page/setting_section/setting_box/appearance/Appearance.jsx
@@ -69,6 +69,7 @@ const UiScalingContainer = () => {
asyncUpdateBreakPoint();
}, [currentUiScaling.data]);
+ // [Duplicated]
const createMarks = (min, max) => {
const marks = [];
for (let value = min; value <= max; value += 10) {
@@ -111,6 +112,7 @@ export const MessageLogUiScalingContainer = () => {
setUiMessageLogUiScaling(currentMessageLogUiScaling.data);
}, [currentMessageLogUiScaling.data]);
+ // [Duplicated]
const createMarks = (min, max) => {
const marks = [];
for (let value = min; value <= max; value += 10) {
@@ -207,6 +209,7 @@ const TransparencyContainer = () => {
setUiTransparency(currentTransparency.data);
}, [currentTransparency.data]);
+ // [Duplicated]
const createMarks = (min, max) => {
const marks = [];
for (let value = min; value <= max; value += 10) {
diff --git a/src-ui/app/config_page/setting_section/setting_box/transcription/Transcription.jsx b/src-ui/app/config_page/setting_section/setting_box/transcription/Transcription.jsx
index 279c1d9d..7416c970 100644
--- a/src-ui/app/config_page/setting_section/setting_box/transcription/Transcription.jsx
+++ b/src-ui/app/config_page/setting_section/setting_box/transcription/Transcription.jsx
@@ -1,3 +1,4 @@
+import { useEffect, useState } from "react";
import { useI18n } from "@useI18n";
import styles from "./Transcription.module.scss";
import { updateLabelsById, genNumObjArray } from "@utils";
@@ -12,6 +13,7 @@ import {
RadioButtonContainer,
DropdownMenuContainer,
ComputeDeviceContainer,
+ SliderContainer,
} from "../_templates/Templates";
import {
@@ -24,6 +26,7 @@ export const Transcription = () => {
+
);
};
@@ -353,4 +356,196 @@ const findKeyByDeviceValue = (devices, target_value) => {
}
}
return null;
+};
+
+
+
+
+
+const Advanced_Container = () => {
+ const { t } = useI18n();
+ return (
+
+
+ {/* */}
+
+
+
+
+
+ );
+
+
+};
+
+export const MicAvgLogprobContainer = () => {
+ const { t } = useI18n();
+ const { currentMicAvgLogprob, setMicAvgLogprob } = useTranscription();
+ const [ui_mic_avg_logprob, setUiMicAvgLogprob] = useState(currentMicAvgLogprob.data);
+
+ const onchangeFunction = (value) => {
+ setUiMicAvgLogprob(value);
+ };
+ const onchangeCommittedFunction = (value) => {
+ setMicAvgLogprob(value);
+ };
+ useEffect(() => {
+ setUiMicAvgLogprob(currentMicAvgLogprob.data);
+ }, [currentMicAvgLogprob.data]);
+
+ // [Duplicated]
+ const createMarks = (min, max) => {
+ const marks = [];
+ for (let value = min; value <= max; value += 0.2) {
+ value = parseFloat(value.toFixed(1));
+ marks.push({ value, label: `${value}` });
+ }
+ return marks;
+ };
+
+ const marks = createMarks(-2, 0);
+
+ return (
+
+ );
+};
+
+export const MicNoSpeechProbContainer = () => {
+ const { t } = useI18n();
+ const { currentMicNoSpeechProb, setMicNoSpeechProb } = useTranscription();
+ const [ui_mic_no_speech_prob, setUiMicNoSpeechProb] = useState(currentMicNoSpeechProb.data);
+
+ const onchangeFunction = (value) => {
+ setUiMicNoSpeechProb(value);
+ };
+ const onchangeCommittedFunction = (value) => {
+ setMicNoSpeechProb(value);
+ };
+ useEffect(() => {
+ setUiMicNoSpeechProb(currentMicNoSpeechProb.data);
+ }, [currentMicNoSpeechProb.data]);
+
+ // [Duplicated]
+ const createMarks = (min, max) => {
+ const marks = [];
+ for (let value = min; value <= max; value += 0.1) {
+ value = parseFloat(value.toFixed(1));
+ marks.push({ value, label: `${value}` });
+ }
+ return marks;
+ };
+
+ const marks = createMarks(0, 1);
+
+ return (
+
+ );
+};
+
+export const SpeakerAvgLogprobContainer = () => {
+ const { t } = useI18n();
+ const { currentSpeakerAvgLogprob, setSpeakerAvgLogprob } = useTranscription();
+ const [ui_speaker_avg_logprob, setUiSpeakerAvgLogprob] = useState(currentSpeakerAvgLogprob.data);
+
+ const onchangeFunction = (value) => {
+ setUiSpeakerAvgLogprob(value);
+ };
+ const onchangeCommittedFunction = (value) => {
+ setSpeakerAvgLogprob(value);
+ };
+ useEffect(() => {
+ setUiSpeakerAvgLogprob(currentSpeakerAvgLogprob.data);
+ }, [currentSpeakerAvgLogprob.data]);
+
+ // [Duplicated]
+ const createMarks = (min, max) => {
+ const marks = [];
+ for (let value = min; value <= max; value += 0.2) {
+ value = parseFloat(value.toFixed(1));
+ marks.push({ value, label: `${value}` });
+ }
+ return marks;
+ };
+
+ const marks = createMarks(-2, 0);
+
+ return (
+
+ );
+};
+
+export const SpeakerNoSpeechProbContainer = () => {
+ const { t } = useI18n();
+ const { currentSpeakerNoSpeechProb, setSpeakerNoSpeechProb } = useTranscription();
+ const [ui_speaker_no_speech_prob, setUiSpeakerNoSpeechProb] = useState(currentSpeakerNoSpeechProb.data);
+
+ const onchangeFunction = (value) => {
+ setUiSpeakerNoSpeechProb(value);
+ };
+ const onchangeCommittedFunction = (value) => {
+ setSpeakerNoSpeechProb(value);
+ };
+ useEffect(() => {
+ setUiSpeakerNoSpeechProb(currentSpeakerNoSpeechProb.data);
+ }, [currentSpeakerNoSpeechProb.data]);
+
+ // [Duplicated]
+ const createMarks = (min, max) => {
+ const marks = [];
+ for (let value = min; value <= max; value += 0.1) {
+ value = parseFloat(value.toFixed(1));
+ marks.push({ value, label: `${value}` });
+ }
+ return marks;
+ };
+
+ const marks = createMarks(0, 1);
+
+ return (
+
+ );
};
\ No newline at end of file
diff --git a/src-ui/logics/configs/transcription/useTranscription.js b/src-ui/logics/configs/transcription/useTranscription.js
index 147aa9e6..294b0473 100644
--- a/src-ui/logics/configs/transcription/useTranscription.js
+++ b/src-ui/logics/configs/transcription/useTranscription.js
@@ -14,6 +14,11 @@ import {
useStore_SelectedWhisperWeightType,
useStore_WhisperWeightTypeStatus,
+
+ useStore_MicAvgLogprob,
+ useStore_MicNoSpeechProb,
+ useStore_SpeakerAvgLogprob,
+ useStore_SpeakerNoSpeechProb,
} from "@store";
import { useStdoutToPython } from "@useStdoutToPython";
import { transformToIndexedArray } from "@utils";
@@ -41,6 +46,13 @@ export const useTranscription = () => {
const { currentSelectableWhisperComputeDeviceList, updateSelectableWhisperComputeDeviceList, pendingSelectableWhisperComputeDeviceList } = useStore_SelectableWhisperComputeDeviceList();
const { currentSelectedWhisperComputeDevice, updateSelectedWhisperComputeDevice, pendingSelectedWhisperComputeDevice } = useStore_SelectedWhisperComputeDevice();
+ // Advanced Settings
+ const { currentMicAvgLogprob, updateMicAvgLogprob, pendingMicAvgLogprob } = useStore_MicAvgLogprob();
+ const { currentMicNoSpeechProb, updateMicNoSpeechProb, pendingMicNoSpeechProb } = useStore_MicNoSpeechProb();
+ const { currentSpeakerAvgLogprob, updateSpeakerAvgLogprob, pendingSpeakerAvgLogprob } = useStore_SpeakerAvgLogprob();
+ const { currentSpeakerNoSpeechProb, updateSpeakerNoSpeechProb, pendingSpeakerNoSpeechProb } = useStore_SpeakerNoSpeechProb();
+
+
// Mic
const getMicRecordTimeout = () => {
pendingMicRecordTimeout();
@@ -276,6 +288,67 @@ export const useTranscription = () => {
showNotification_SaveSuccess();
};
+ // Advanced (Mic Avg Logprob)
+ const getMicAvgLogprob = () => {
+ pendingMicAvgLogprob();
+ asyncStdoutToPython("/get/data/mic_avg_logprob");
+ };
+
+ const setMicAvgLogprob = (selected_mic_avg_logprob) => {
+ pendingMicAvgLogprob();
+ asyncStdoutToPython("/set/data/mic_avg_logprob", selected_mic_avg_logprob);
+ };
+
+ const setSuccessMicAvgLogprob = (selected_mic_avg_logprob) => {
+ updateMicAvgLogprob(selected_mic_avg_logprob);
+ showNotification_SaveSuccess();
+ };
+ // Advanced (Mic No Speech Prob)
+ const getMicNoSpeechProb = () => {
+ pendingMicNoSpeechProb();
+ asyncStdoutToPython("/get/data/mic_no_speech_prob");
+ };
+
+ const setMicNoSpeechProb = (selected_mic_no_speech_prob) => {
+ pendingMicNoSpeechProb();
+ asyncStdoutToPython("/set/data/mic_no_speech_prob", selected_mic_no_speech_prob);
+ };
+
+ const setSuccessMicNoSpeechProb = (selected_mic_no_speech_prob) => {
+ updateMicNoSpeechProb(selected_mic_no_speech_prob);
+ showNotification_SaveSuccess();
+ };
+ // Advanced (Speaker Avg Logprob)
+ const getSpeakerAvgLogprob = () => {
+ pendingSpeakerAvgLogprob();
+ asyncStdoutToPython("/get/data/speaker_avg_logprob");
+ };
+
+ const setSpeakerAvgLogprob = (selected_speaker_avg_logprob) => {
+ pendingSpeakerAvgLogprob();
+ asyncStdoutToPython("/set/data/speaker_avg_logprob", selected_speaker_avg_logprob);
+ };
+
+ const setSuccessSpeakerAvgLogprob = (selected_speaker_avg_logprob) => {
+ updateSpeakerAvgLogprob(selected_speaker_avg_logprob);
+ showNotification_SaveSuccess();
+ };
+ // Advanced (Speaker No Speech Prob)
+ const getSpeakerNoSpeechProb = () => {
+ pendingSpeakerNoSpeechProb();
+ asyncStdoutToPython("/get/data/speaker_no_speech_prob");
+ };
+
+ const setSpeakerNoSpeechProb = (selected_speaker_no_speech_prob) => {
+ pendingSpeakerNoSpeechProb();
+ asyncStdoutToPython("/set/data/speaker_no_speech_prob", selected_speaker_no_speech_prob);
+ };
+
+ const setSuccessSpeakerNoSpeechProb = (selected_speaker_no_speech_prob) => {
+ updateSpeakerNoSpeechProb(selected_speaker_no_speech_prob);
+ showNotification_SaveSuccess();
+ };
+
return {
// Mic
currentMicRecordTimeout,
@@ -353,5 +426,31 @@ export const useTranscription = () => {
updateSelectedWhisperComputeDevice,
setSelectedWhisperComputeDevice,
setSuccessSelectedWhisperComputeDevice,
+
+ // Advanced
+ // Mic Avg Logprob
+ currentMicAvgLogprob,
+ getMicAvgLogprob,
+ updateMicAvgLogprob,
+ setMicAvgLogprob,
+ setSuccessMicAvgLogprob,
+ // Mic No Speech Prob
+ currentMicNoSpeechProb,
+ getMicNoSpeechProb,
+ updateMicNoSpeechProb,
+ setMicNoSpeechProb,
+ setSuccessMicNoSpeechProb,
+ // Speaker Avg Logprob
+ currentSpeakerAvgLogprob,
+ getSpeakerAvgLogprob,
+ updateSpeakerAvgLogprob,
+ setSpeakerAvgLogprob,
+ setSuccessSpeakerAvgLogprob,
+ // Speaker No Speech Prob
+ currentSpeakerNoSpeechProb,
+ getSpeakerNoSpeechProb,
+ updateSpeakerNoSpeechProb,
+ setSpeakerNoSpeechProb,
+ setSuccessSpeakerNoSpeechProb,
};
};
\ No newline at end of file
diff --git a/src-ui/logics/useReceiveRoutes.js b/src-ui/logics/useReceiveRoutes.js
index c9380612..c36b5fa7 100644
--- a/src-ui/logics/useReceiveRoutes.js
+++ b/src-ui/logics/useReceiveRoutes.js
@@ -224,6 +224,16 @@ export const ROUTE_META_LIST = [
{ endpoint: "/get/data/selected_transcription_compute_device", ns: configs, hook_name: "useTranscription", method_name: "updateSelectedWhisperComputeDevice" },
{ endpoint: "/set/data/selected_transcription_compute_device", ns: configs, hook_name: "useTranscription", method_name: "setSuccessSelectedWhisperComputeDevice" },
+ // Transcription (Advanced)
+ { endpoint: "/get/data/mic_avg_logprob", ns: configs, hook_name: "useTranscription", method_name: "updateMicAvgLogprob" },
+ { endpoint: "/set/data/mic_avg_logprob", ns: configs, hook_name: "useTranscription", method_name: "setSuccessMicAvgLogprob" },
+ { endpoint: "/get/data/mic_no_speech_prob", ns: configs, hook_name: "useTranscription", method_name: "updateMicNoSpeechProb" },
+ { endpoint: "/set/data/mic_no_speech_prob", ns: configs, hook_name: "useTranscription", method_name: "setSuccessMicNoSpeechProb" },
+ { endpoint: "/get/data/speaker_avg_logprob", ns: configs, hook_name: "useTranscription", method_name: "updateSpeakerAvgLogprob" },
+ { endpoint: "/set/data/speaker_avg_logprob", ns: configs, hook_name: "useTranscription", method_name: "setSuccessSpeakerAvgLogprob" },
+ { endpoint: "/get/data/speaker_no_speech_prob", ns: configs, hook_name: "useTranscription", method_name: "updateSpeakerNoSpeechProb" },
+ { endpoint: "/set/data/speaker_no_speech_prob", ns: configs, hook_name: "useTranscription", method_name: "setSuccessSpeakerNoSpeechProb" },
+
// VR
{ endpoint: "/get/data/overlay_small_log", ns: configs, hook_name: "useVr", method_name: "updateIsEnabledOverlaySmallLog" },
{ endpoint: "/set/enable/overlay_small_log", ns: configs, hook_name: "useVr", method_name: "setSuccessIsEnabledOverlaySmallLog" },
diff --git a/src-ui/store.js b/src-ui/store.js
index 9241ad41..e36aad46 100644
--- a/src-ui/store.js
+++ b/src-ui/store.js
@@ -238,6 +238,11 @@ export const { atomInstance: Atom_SelectedTranscriptionEngine, useHook: useStore
export const { atomInstance: Atom_SelectableWhisperComputeDeviceList, useHook: useStore_SelectableWhisperComputeDeviceList } = createAtomWithHook({}, "SelectableWhisperComputeDeviceList");
export const { atomInstance: Atom_SelectedWhisperComputeDevice, useHook: useStore_SelectedWhisperComputeDevice } = createAtomWithHook("", "SelectedWhisperComputeDevice");
+export const { atomInstance: Atom_MicAvgLogprob, useHook: useStore_MicAvgLogprob } = createAtomWithHook(-0.8, "MicAvgLogprob");
+export const { atomInstance: Atom_MicNoSpeechProb, useHook: useStore_MicNoSpeechProb } = createAtomWithHook(0.6, "MicNoSpeechProb");
+export const { atomInstance: Atom_SpeakerAvgLogprob, useHook: useStore_SpeakerAvgLogprob } = createAtomWithHook(-0.8, "SpeakerAvgLogprob");
+export const { atomInstance: Atom_SpeakerNoSpeechProb, useHook: useStore_SpeakerNoSpeechProb } = createAtomWithHook(0.6, "SpeakerNoSpeechProb");
+
// VR
export const { atomInstance: Atom_OverlaySmallLogSettings, useHook: useStore_OverlaySmallLogSettings } = createAtomWithHook({
From 7a0913928ea642c2604e7805e3426ae1697eafca Mon Sep 17 00:00:00 2001
From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com>
Date: Fri, 5 Sep 2025 11:45:29 +0900
Subject: [PATCH 13/16] [Update] Localization: Unify the new line code to LF
---
locales/ko.yml | 2 +-
locales/zh-Hans.yml | 614 ++++++++++++++++++++++----------------------
2 files changed, 308 insertions(+), 308 deletions(-)
diff --git a/locales/ko.yml b/locales/ko.yml
index 52594be3..d2e171ac 100644
--- a/locales/ko.yml
+++ b/locales/ko.yml
@@ -305,4 +305,4 @@ plugin_notifications:
disabled_due_to_an_error: "플러그인 실행 중 오류를 감지했습니다. 플러그인 개발자에게 보고해 주세요."
is_enabled: "플러그인을 활성화했습니다."
- is_disabled: "플러그인을 비활성화했습니다."
+ is_disabled: "플러그인을 비활성화했습니다."
\ No newline at end of file
diff --git a/locales/zh-Hans.yml b/locales/zh-Hans.yml
index 3e2ec51f..71a75390 100644
--- a/locales/zh-Hans.yml
+++ b/locales/zh-Hans.yml
@@ -1,308 +1,308 @@
-# =================================
-# IMPORTANT:
-# Please read 'readme_first.txt' before making any changes.
-# =================================
-
-common:
- go_back_button_label: "返回"
-
-common_error:
- no_device_mic: # 未检测到他人语音 ?
- no_device_speaker: # 未检测到他人语音 ?
- threshold_invalid_value: # 数值应为 {{min}} 至 {{max}} 之间。 ? 设定的数值从 {{min}} 到 {{max}} ?
- failed_download_weight_ctranslate2:
- failed_download_weight_whisper:
- translation_limit:
- deepl_auth_key_invalid_length:
- deepl_auth_key_failed_authentication: "授权密匙错误或已达API使用上限"
-
- invalid_value_mic_record_timeout: "数值应为 0 至 「{{mic_phrase_timeout_label}}」"
- invalid_value_mic_phrase_timeout: "转录间隔时间大于0秒且不能小于「{{mic_record_timeout_label}}」"
- invalid_value_mic_max_phrase: "数值应为 0 以上"
-
- invalid_value_speaker_record_timeout: "数值应为 0 至 「{{speaker_phrase_timeout_label}}」"
- invalid_value_speaker_phrase_timeout: "转录间隔时间大于0秒且不能小于「{{speaker_record_timeout_label}}」"
- invalid_value_speaker_max_phrase: "数值应为 0 以上"
-
-common_warning:
- unable_to_use_osc_query:
-
-main_page:
- translation: "翻译"
- transcription_send: "你的语音转文字"
- transcription_receive: "他人语音转文字"
- foreground: "顶层显示"
-
- language_settings: "语言设定"
- your_language: "你的语言"
- translate_each_other_label: "双向翻译"
- swap_button_label: "互换"
- target_language: "目标语言"
- translator: "翻译器"
- translator_label_default: "默认"
-
- translator_selector:
- is_selected_same_language:
-
- message_log:
- all: "全部"
- sent: "发送"
- received: "接受"
- system: "系统"
-
- resend_button_on_hover_desc:
-
- state_text_enabled: "启用"
- state_text_disabled: "停用"
-
- language_selector:
- title_your_language: "你的语言"
- title_target_language: "目标语言"
-
- update_available: "有新版本可供使用!"
- updating: "更新中..."
-
-update_modal:
- cpu_desc:
- cuda_desc:
- cuda_compare_cpu_desc:
- cuda_disk_space_desc:
- close_modal:
- download_latest_and_restart:
- is_latest_version_already:
- is_current_compute_device:
-
-config_page:
- version: "版本 {{version}}"
- model_download_button_label:
- side_menu_labels:
- device:
- appearance: "外观"
- translation: "翻译"
- transcription: "转录"
- others: "其他"
- hotkeys:
- plugins:
- advanced_settings: "高级设置"
-
- device:
- check_volume: "Check Volume"
- label_auto_select: "Auto Select"
- label_host: "Host/Driver"
- label_device: "Device"
- mic_host_device:
- label: "麦克风 (设备)"
- mic_dynamic_energy_threshold:
- label_for_automatic: "麦克风输入阈值(当前设置:自动)"
- desc_for_automatic: "自动调整麦克风输入阈值"
- label_for_manual: "麦克风输入阈值(当前设置:手动)"
- desc_for_manual: "使用滑杆手动确定麦克风输入灵敏度。按下麦克风图标输入语音,并在监控音量的同时调节灵敏度。"
- speaker_device:
- label: "他人语音 (设备)"
- speaker_dynamic_energy_threshold:
- label_for_automatic: "他人语音接收阈值(当前设置:自动)"
- desc_for_automatic: "自动调节他人语音接收阈值"
- label_for_manual: "他人语音接收阈值(当前设置:手动)"
- desc_for_manual: "使用滑杆手动调整他人语音接收阈值.在按下耳机按钮时,请根据实际听到的声音调整该大小"
-
- appearance:
- transparency:
- label: "透明度"
- desc: "更改主视窗透明度"
- ui_size:
- label: "界面大小"
- textbox_ui_size:
- label: "文本框字体大小"
- desc: "你可以根据用户界面大小调整文本框中使用的字体大小。"
- send_message_button_type:
- label: "发送信息按钮"
- hide: "隐藏 (可使用回车发送信息)"
- show: "显示"
- show_and_disable_enter_key: "显示,并且停用‘回车发送信息’"
- show_resend_button:
- label:
- desc:
- font_family:
- label: "字体"
- ui_language:
- label: "界面语言"
-
- translation:
- ctranslate2_weight_type:
- label: "选择离线翻译模型"
- desc: "可以选择用于离线翻译的翻译模型"
- small: "普通模型 ({{capacity}})"
- large: "高精度模型 ({{capacity}})"
- ctranslate2_compute_device:
- label:
- deepl_auth_key:
- label: "DeepL 授权密匙"
- desc: "在使用的时候,使用时请在主屏幕上通过 DeepL_API 选择 {{translator}}\n※某些语言可能不支持"
- open_auth_key_webpage: "打开DeepL账号页面"
- save:
- edit:
- auth_key_success: "授权密匙认证完成。"
-
- transcription:
- section_label_mic: "你的麦克风"
- section_label_speaker: "他人声音"
- section_label_transcription_engines:
- mic_record_timeout:
- label: "语音输入结束后的静音时间"
- desc: "当检测到静音并经过设定的秒数后,语音输入即被视为完成。"
- mic_phrase_timeout:
- label: "转录间隔"
- desc: "在经过设定的时间后执行转录"
- mic_max_phrase:
- label: "麦克风发送时的最小单词数"
- desc: "转录字数的下限,只有超过这个数字,才会记录翻译结果并发送到VRC"
- mic_word_filter:
- label: "单词过滤器"
- desc: "检测出被记录的单词时,不会发送这段话\n如要添加多个单词,可以用逗号来分割\n※不会记录重复的单词"
- add_button_label: "添加"
- count_desc: "现在被记录的单词数: {{count}}"
- speaker_record_timeout:
- label: "语音接收结束后的静音时间"
- desc: "当检测到静音并经过设定的秒数后,语音接收即被视为完成。"
- speaker_phrase_timeout:
- label: "转录间隔"
- desc: "在经过设定的时间后执行转录"
- speaker_max_phrase:
- label: "语音接收时的最小单词数"
- desc: "转录字数的下限,只有超过这个数字,才会记录转录结果"
- select_transcription_engine:
- label:
- whisper_weight_type:
- label: "选择某个Whisper模型"
- desc:
- model_template: "{{model_name}} 模型 ({{capacity}})"
- recommended_model_template: "{{model_name}} 模型 ({{capacity}}) (推荐)"
- whisper_compute_device:
- label:
-
- vr:
- single_line:
- multi_lines:
- overlay_enable:
- restore_default_settings: "恢复默认设置"
- position:
- rotation:
- x_position: "X轴(左右)"
- y_position: "Y轴(上下)"
- z_position: "Z轴(前后)"
- x_rotation: "X轴旋转"
- y_rotation: "Y轴旋转"
- z_rotation: "Z轴旋转"
- sample_text_button:
- start:
- stop:
- sample_text:
- opacity: "透明度"
- ui_scaling: "大小"
- display_duration: "显示持续时间"
- fadeout_duration: "渐隐持续时间"
- common_settings:
- tracker:
- hmd:
- left_hand:
- right_hand:
- overlay_show_only_translated_messages:
- label:
-
- others:
- section_label_sounds:
- section_label_message_formats:
- auto_clear_the_message_box:
- label: "发言后自动清空chatbox"
- send_only_translated_messages:
- label: "只发送翻译后的信息"
- auto_export_message_logs:
- label: "自动导出聊天记录"
- desc: "以文本文件的形式在logs文件夹中保存。"
- vrc_mic_mute_sync:
- label: "与VRC中的麦克风静音同步"
- desc: "当VRChat的麦克风处于静音时,不在VRChat中发送信息\n※存在少许延迟且不支持按键发言."
- send_message_to_vrc:
- label: "发送信息至VRChat"
- desc: "不发送信息至VRChat的情况下也能使用它,但该功能现在并未完成.在想要发送信息时,请不要忘记打开这个功能."
- notification_vrc_sfx:
- label:
- desc:
- send_received_message_to_vrc:
- label:
- desc:
- message_format_common:
- example_view:
- title:
- original_translated:
- original_translated_multi:
- translated_only_multi:
- translated_only:
- original_only:
- settings:
- title:
- original:
- translated:
- for_multi_translation:
- send_message_format:
- label:
- desc:
- received_message_format:
- label:
- desc:
-
- hotkeys:
- toggle_vrct_visibility:
- label:
- toggle_translation:
- label:
- toggle_transcription_send:
- label:
- toggle_transcription_receive:
- label:
-
- plugins:
- downloaded_version:
- latest_version:
- available_after_updating:
- unavailable_downloaded:
- no_latest_info:
- using_latest_version:
- available_latest_version:
- unavailable_latest_version:
- available_in_latest_vrct_version:
- unavailable_not_downloaded:
-
- advanced_settings:
- osc_ip_address:
- label: "OSC IP 地址"
- osc_port:
- label: "OSC 端口"
- open_config_filepath:
- label: "打开设置文件"
- switch_compute_device:
- label:
- enable_websocket:
- label:
- websocket_host:
- label:
- websocket_port:
- label:
-
- notifications:
- save_success:
-
-plugin_notifications:
- downloading:
- downloaded_success:
- downloaded_error:
-
- updating:
- updated_success:
- updated_error:
-
- disabled_out_of_support:
- disabled_due_to_an_error:
-
- is_enabled:
+# =================================
+# IMPORTANT:
+# Please read 'readme_first.txt' before making any changes.
+# =================================
+
+common:
+ go_back_button_label: "返回"
+
+common_error:
+ no_device_mic: # 未检测到他人语音 ?
+ no_device_speaker: # 未检测到他人语音 ?
+ threshold_invalid_value: # 数值应为 {{min}} 至 {{max}} 之间。 ? 设定的数值从 {{min}} 到 {{max}} ?
+ failed_download_weight_ctranslate2:
+ failed_download_weight_whisper:
+ translation_limit:
+ deepl_auth_key_invalid_length:
+ deepl_auth_key_failed_authentication: "授权密匙错误或已达API使用上限"
+
+ invalid_value_mic_record_timeout: "数值应为 0 至 「{{mic_phrase_timeout_label}}」"
+ invalid_value_mic_phrase_timeout: "转录间隔时间大于0秒且不能小于「{{mic_record_timeout_label}}」"
+ invalid_value_mic_max_phrase: "数值应为 0 以上"
+
+ invalid_value_speaker_record_timeout: "数值应为 0 至 「{{speaker_phrase_timeout_label}}」"
+ invalid_value_speaker_phrase_timeout: "转录间隔时间大于0秒且不能小于「{{speaker_record_timeout_label}}」"
+ invalid_value_speaker_max_phrase: "数值应为 0 以上"
+
+common_warning:
+ unable_to_use_osc_query:
+
+main_page:
+ translation: "翻译"
+ transcription_send: "你的语音转文字"
+ transcription_receive: "他人语音转文字"
+ foreground: "顶层显示"
+
+ language_settings: "语言设定"
+ your_language: "你的语言"
+ translate_each_other_label: "双向翻译"
+ swap_button_label: "互换"
+ target_language: "目标语言"
+ translator: "翻译器"
+ translator_label_default: "默认"
+
+ translator_selector:
+ is_selected_same_language:
+
+ message_log:
+ all: "全部"
+ sent: "发送"
+ received: "接受"
+ system: "系统"
+
+ resend_button_on_hover_desc:
+
+ state_text_enabled: "启用"
+ state_text_disabled: "停用"
+
+ language_selector:
+ title_your_language: "你的语言"
+ title_target_language: "目标语言"
+
+ update_available: "有新版本可供使用!"
+ updating: "更新中..."
+
+update_modal:
+ cpu_desc:
+ cuda_desc:
+ cuda_compare_cpu_desc:
+ cuda_disk_space_desc:
+ close_modal:
+ download_latest_and_restart:
+ is_latest_version_already:
+ is_current_compute_device:
+
+config_page:
+ version: "版本 {{version}}"
+ model_download_button_label:
+ side_menu_labels:
+ device:
+ appearance: "外观"
+ translation: "翻译"
+ transcription: "转录"
+ others: "其他"
+ hotkeys:
+ plugins:
+ advanced_settings: "高级设置"
+
+ device:
+ check_volume: "Check Volume"
+ label_auto_select: "Auto Select"
+ label_host: "Host/Driver"
+ label_device: "Device"
+ mic_host_device:
+ label: "麦克风 (设备)"
+ mic_dynamic_energy_threshold:
+ label_for_automatic: "麦克风输入阈值(当前设置:自动)"
+ desc_for_automatic: "自动调整麦克风输入阈值"
+ label_for_manual: "麦克风输入阈值(当前设置:手动)"
+ desc_for_manual: "使用滑杆手动确定麦克风输入灵敏度。按下麦克风图标输入语音,并在监控音量的同时调节灵敏度。"
+ speaker_device:
+ label: "他人语音 (设备)"
+ speaker_dynamic_energy_threshold:
+ label_for_automatic: "他人语音接收阈值(当前设置:自动)"
+ desc_for_automatic: "自动调节他人语音接收阈值"
+ label_for_manual: "他人语音接收阈值(当前设置:手动)"
+ desc_for_manual: "使用滑杆手动调整他人语音接收阈值.在按下耳机按钮时,请根据实际听到的声音调整该大小"
+
+ appearance:
+ transparency:
+ label: "透明度"
+ desc: "更改主视窗透明度"
+ ui_size:
+ label: "界面大小"
+ textbox_ui_size:
+ label: "文本框字体大小"
+ desc: "你可以根据用户界面大小调整文本框中使用的字体大小。"
+ send_message_button_type:
+ label: "发送信息按钮"
+ hide: "隐藏 (可使用回车发送信息)"
+ show: "显示"
+ show_and_disable_enter_key: "显示,并且停用‘回车发送信息’"
+ show_resend_button:
+ label:
+ desc:
+ font_family:
+ label: "字体"
+ ui_language:
+ label: "界面语言"
+
+ translation:
+ ctranslate2_weight_type:
+ label: "选择离线翻译模型"
+ desc: "可以选择用于离线翻译的翻译模型"
+ small: "普通模型 ({{capacity}})"
+ large: "高精度模型 ({{capacity}})"
+ ctranslate2_compute_device:
+ label:
+ deepl_auth_key:
+ label: "DeepL 授权密匙"
+ desc: "在使用的时候,使用时请在主屏幕上通过 DeepL_API 选择 {{translator}}\n※某些语言可能不支持"
+ open_auth_key_webpage: "打开DeepL账号页面"
+ save:
+ edit:
+ auth_key_success: "授权密匙认证完成。"
+
+ transcription:
+ section_label_mic: "你的麦克风"
+ section_label_speaker: "他人声音"
+ section_label_transcription_engines:
+ mic_record_timeout:
+ label: "语音输入结束后的静音时间"
+ desc: "当检测到静音并经过设定的秒数后,语音输入即被视为完成。"
+ mic_phrase_timeout:
+ label: "转录间隔"
+ desc: "在经过设定的时间后执行转录"
+ mic_max_phrase:
+ label: "麦克风发送时的最小单词数"
+ desc: "转录字数的下限,只有超过这个数字,才会记录翻译结果并发送到VRC"
+ mic_word_filter:
+ label: "单词过滤器"
+ desc: "检测出被记录的单词时,不会发送这段话\n如要添加多个单词,可以用逗号来分割\n※不会记录重复的单词"
+ add_button_label: "添加"
+ count_desc: "现在被记录的单词数: {{count}}"
+ speaker_record_timeout:
+ label: "语音接收结束后的静音时间"
+ desc: "当检测到静音并经过设定的秒数后,语音接收即被视为完成。"
+ speaker_phrase_timeout:
+ label: "转录间隔"
+ desc: "在经过设定的时间后执行转录"
+ speaker_max_phrase:
+ label: "语音接收时的最小单词数"
+ desc: "转录字数的下限,只有超过这个数字,才会记录转录结果"
+ select_transcription_engine:
+ label:
+ whisper_weight_type:
+ label: "选择某个Whisper模型"
+ desc:
+ model_template: "{{model_name}} 模型 ({{capacity}})"
+ recommended_model_template: "{{model_name}} 模型 ({{capacity}}) (推荐)"
+ whisper_compute_device:
+ label:
+
+ vr:
+ single_line:
+ multi_lines:
+ overlay_enable:
+ restore_default_settings: "恢复默认设置"
+ position:
+ rotation:
+ x_position: "X轴(左右)"
+ y_position: "Y轴(上下)"
+ z_position: "Z轴(前后)"
+ x_rotation: "X轴旋转"
+ y_rotation: "Y轴旋转"
+ z_rotation: "Z轴旋转"
+ sample_text_button:
+ start:
+ stop:
+ sample_text:
+ opacity: "透明度"
+ ui_scaling: "大小"
+ display_duration: "显示持续时间"
+ fadeout_duration: "渐隐持续时间"
+ common_settings:
+ tracker:
+ hmd:
+ left_hand:
+ right_hand:
+ overlay_show_only_translated_messages:
+ label:
+
+ others:
+ section_label_sounds:
+ section_label_message_formats:
+ auto_clear_the_message_box:
+ label: "发言后自动清空chatbox"
+ send_only_translated_messages:
+ label: "只发送翻译后的信息"
+ auto_export_message_logs:
+ label: "自动导出聊天记录"
+ desc: "以文本文件的形式在logs文件夹中保存。"
+ vrc_mic_mute_sync:
+ label: "与VRC中的麦克风静音同步"
+ desc: "当VRChat的麦克风处于静音时,不在VRChat中发送信息\n※存在少许延迟且不支持按键发言."
+ send_message_to_vrc:
+ label: "发送信息至VRChat"
+ desc: "不发送信息至VRChat的情况下也能使用它,但该功能现在并未完成.在想要发送信息时,请不要忘记打开这个功能."
+ notification_vrc_sfx:
+ label:
+ desc:
+ send_received_message_to_vrc:
+ label:
+ desc:
+ message_format_common:
+ example_view:
+ title:
+ original_translated:
+ original_translated_multi:
+ translated_only_multi:
+ translated_only:
+ original_only:
+ settings:
+ title:
+ original:
+ translated:
+ for_multi_translation:
+ send_message_format:
+ label:
+ desc:
+ received_message_format:
+ label:
+ desc:
+
+ hotkeys:
+ toggle_vrct_visibility:
+ label:
+ toggle_translation:
+ label:
+ toggle_transcription_send:
+ label:
+ toggle_transcription_receive:
+ label:
+
+ plugins:
+ downloaded_version:
+ latest_version:
+ available_after_updating:
+ unavailable_downloaded:
+ no_latest_info:
+ using_latest_version:
+ available_latest_version:
+ unavailable_latest_version:
+ available_in_latest_vrct_version:
+ unavailable_not_downloaded:
+
+ advanced_settings:
+ osc_ip_address:
+ label: "OSC IP 地址"
+ osc_port:
+ label: "OSC 端口"
+ open_config_filepath:
+ label: "打开设置文件"
+ switch_compute_device:
+ label:
+ enable_websocket:
+ label:
+ websocket_host:
+ label:
+ websocket_port:
+ label:
+
+ notifications:
+ save_success:
+
+plugin_notifications:
+ downloading:
+ downloaded_success:
+ downloaded_error:
+
+ updating:
+ updated_success:
+ updated_error:
+
+ disabled_out_of_support:
+ disabled_due_to_an_error:
+
+ is_enabled:
is_disabled:
\ No newline at end of file
From 2efba7247e97e47b6767ac974ae541281fca89af Mon Sep 17 00:00:00 2001
From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com>
Date: Thu, 11 Sep 2025 13:32:32 +0900
Subject: [PATCH 14/16] [Update] Localization: Update English localization.
---
locales/en.yml | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/locales/en.yml b/locales/en.yml
index f311ced3..1faf9639 100644
--- a/locales/en.yml
+++ b/locales/en.yml
@@ -25,7 +25,7 @@ common_error:
invalid_value_speaker_max_phrase: "You can set a number equal to or greater than 0."
common_warning:
- unable_to_use_osc_query: "The functions below have been automatically disabled because receiving OSC data is not possible due to OSC IP Address settings."
+ unable_to_use_osc_query: "The following functions have been automatically disabled due to the OSC IP Address settings preventing OSC data from being received."
main_page:
translation: "Translation"
@@ -234,22 +234,22 @@ config_page:
message_format_common:
example_view:
title: "Preview"
- original_translated: "Original + Translated"
- original_translated_multi: "Original + Translated (Multi-Translation)"
- translated_only_multi: "Translated Only (Multi-Translation)"
- translated_only: "Translated Only"
+ original_translated: "Original + Translation"
+ original_translated_multi: "Original + Translation (Multi-language)"
+ translated_only_multi: "Translation Only (Multi-language)"
+ translated_only: "Translation Only"
original_only: "Original Only"
settings:
title: "Settings"
original: "Original"
- translated: "Translated"
+ translated: "Translation"
for_multi_translation: "For Multi-Translation"
send_message_format:
label: "Message Format (Send)"
- desc: "You can change the decoration of the message you want to send."
+ desc: "This allows you to change the format of the message that others see in VRChat."
received_message_format:
label: "Message Format (Speaker2Chatbox)"
- desc: "It will be used in Speaker2Chatbox for now."
+ desc: "Currently, it is used in Speaker2Chatbox."
hotkeys:
toggle_vrct_visibility:
@@ -265,7 +265,7 @@ config_page:
downloaded_version: "Downloaded version: {{downloaded_version}}"
latest_version: "Latest version: {{latest_version}}"
available_after_updating: "Available after updating to the latest version"
- unavailable_downloaded: "Currently unavailable due to incompatibility with the VRCT version in use"
+ unavailable_downloaded: "Currently Unavailable - Incompatible with the VRCT version in use"
no_latest_info: "Unable to retrieve the latest information"
using_latest_version: "Using the latest version"
available_latest_version: "Latest version available"
@@ -304,5 +304,5 @@ plugin_notifications:
disabled_out_of_support: "The plugin has been disabled. It's not supported on this VRCT version."
disabled_due_to_an_error: "An error was detected while running the plugin. Please report this to the plugin developer."
- is_enabled: "The plugin has enabled."
- is_disabled: "The plugin has disabled."
\ No newline at end of file
+ is_enabled: "The plugin enabled."
+ is_disabled: "The plugin disabled."
\ No newline at end of file
From 9096d05e65f62a5a333099d844bee6d3d473b4d7 Mon Sep 17 00:00:00 2001
From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com>
Date: Thu, 11 Sep 2025 13:51:14 +0900
Subject: [PATCH 15/16] [Update] Update 'readme_first.txt'.
---
locales/readme_first.txt | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/locales/readme_first.txt b/locales/readme_first.txt
index 02323f8f..6d87d7d0 100644
--- a/locales/readme_first.txt
+++ b/locales/readme_first.txt
@@ -1 +1,13 @@
-Thank you for considering translating VRCT's UI. However, please refrain from making any changes at this time. I am currently organizing the files, including reordering, adding, and removing elements, and some parts may change frequently until the UI becomes stable. (Note: This message was updated in February 2025.)
\ No newline at end of file
+Thank you for considering contributing to VRCT's UI translations.
+If you want to edit a language:
+- If it already exists: edit the corresponding [xx].yml file.
+- If it doesn’t exist: please open a GitHub issue or contact us through another channel. (If you know how to add a new language yourself, feel free to do so! Sorry for the complicated structure...)
+
+Languages currently supported:
+- en: English
+- ja: 日本語
+- ko: 한국어
+- zh-Hant: 繁體中文
+- zh-Hans: 简体中文
+
+Last updated: 2025/09
\ No newline at end of file
From 684d9c3283cf5c3afaf4842338be1d0f520186fa Mon Sep 17 00:00:00 2001
From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com>
Date: Thu, 11 Sep 2025 17:00:15 +0900
Subject: [PATCH 16/16] [Update] Version 3.2.1 -> 3.2.2
---
src-python/config.py | 2 +-
src-tauri/tauri.conf.json | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src-python/config.py b/src-python/config.py
index 76638fbe..c544727d 100644
--- a/src-python/config.py
+++ b/src-python/config.py
@@ -1020,7 +1020,7 @@ class Config:
def init_config(self):
# Read Only
- self._VERSION = "3.2.1"
+ self._VERSION = "3.2.2"
if getattr(sys, 'frozen', False):
self._PATH_LOCAL = os_path.dirname(sys.executable)
else:
diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json
index 898312d6..9e2402ef 100644
--- a/src-tauri/tauri.conf.json
+++ b/src-tauri/tauri.conf.json
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "VRCT",
- "version": "3.2.1",
+ "version": "3.2.2",
"identifier": "com.vrct.app",
"build": {
"beforeDevCommand": "",