[Update/bugfix] Plugins: Add localization system to plugins list(plugin_info.json).

Fix the issue that the i18n didn't work in development environment.
This commit is contained in:
Sakamoto Shiina
2025-04-26 04:13:18 +09:00
parent 819783ea09
commit c665f1d355
7 changed files with 98 additions and 43 deletions

35
package-lock.json generated
View File

@@ -20,7 +20,6 @@
"i18next": "24.1.0", "i18next": "24.1.0",
"jotai": "2.10.3", "jotai": "2.10.3",
"js-base64": "3.7.7", "js-base64": "3.7.7",
"js-yaml": "4.1.0",
"jszip": "3.10.1", "jszip": "3.10.1",
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
@@ -30,10 +29,11 @@
"semver": "7.7.1" "semver": "7.7.1"
}, },
"devDependencies": { "devDependencies": {
"@rollup/plugin-yaml": "^4.1.2",
"@tauri-apps/cli": "1.6.3", "@tauri-apps/cli": "1.6.3",
"npm-run-all": "4.1.5", "npm-run-all": "4.1.5",
"sass": "1.79.4", "sass": "1.79.4",
"source-map": "^0.7.4", "source-map": "0.7.4",
"vite": "6.2.5", "vite": "6.2.5",
"vite-plugin-svgr": "4.3.0" "vite-plugin-svgr": "4.3.0"
} }
@@ -1221,6 +1221,28 @@
"url": "https://opencollective.com/popperjs" "url": "https://opencollective.com/popperjs"
} }
}, },
"node_modules/@rollup/plugin-yaml": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/@rollup/plugin-yaml/-/plugin-yaml-4.1.2.tgz",
"integrity": "sha512-RpupciIeZMUqhgFE97ba0s98mOFS7CWzN3EJNhJkqSv9XLlWYtwVdtE6cDw6ASOF/sZVFS7kRJXftaqM2Vakdw==",
"dev": true,
"dependencies": {
"@rollup/pluginutils": "^5.0.1",
"js-yaml": "^4.1.0",
"tosource": "^2.0.0-alpha.3"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/pluginutils": { "node_modules/@rollup/pluginutils": {
"version": "5.1.3", "version": "5.1.3",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.3.tgz", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.3.tgz",
@@ -5353,6 +5375,15 @@
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
"integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw=="
}, },
"node_modules/tosource": {
"version": "2.0.0-alpha.3",
"resolved": "https://registry.npmjs.org/tosource/-/tosource-2.0.0-alpha.3.tgz",
"integrity": "sha512-KAB2lrSS48y91MzFPFuDg4hLbvDiyTjOVgaK7Erw+5AmZXNq4sFRVn8r6yxSLuNs15PaokrDRpS61ERY9uZOug==",
"dev": true,
"engines": {
"node": ">=10"
}
},
"node_modules/tslib": { "node_modules/tslib": {
"version": "2.8.1", "version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",

View File

@@ -35,7 +35,6 @@
"i18next": "24.1.0", "i18next": "24.1.0",
"jotai": "2.10.3", "jotai": "2.10.3",
"js-base64": "3.7.7", "js-base64": "3.7.7",
"js-yaml": "4.1.0",
"jszip": "3.10.1", "jszip": "3.10.1",
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
@@ -45,6 +44,7 @@
"semver": "7.7.1" "semver": "7.7.1"
}, },
"devDependencies": { "devDependencies": {
"@rollup/plugin-yaml": "^4.1.2",
"@tauri-apps/cli": "1.6.3", "@tauri-apps/cli": "1.6.3",
"npm-run-all": "4.1.5", "npm-run-all": "4.1.5",
"sass": "1.79.4", "sass": "1.79.4",

View File

@@ -26,7 +26,7 @@ export const Plugins = () => {
}; };
const PluginDownloadContainer = () => { const PluginDownloadContainer = () => {
const { t } = useTranslation(); const { t, i18n } = useTranslation();
const { const {
downloadAndExtractPlugin, downloadAndExtractPlugin,
currentPluginsData, currentPluginsData,
@@ -74,35 +74,49 @@ const PluginDownloadContainer = () => {
<div className={styles.plugins_list_container}> <div className={styles.plugins_list_container}>
{is_failed_to_fetch && <p>Failed to fetch plugins data</p>} {is_failed_to_fetch && <p>Failed to fetch plugins data</p>}
{is_fetching && <p>Fetching plugins data...</p>} {is_fetching && <p>Fetching plugins data...</p>}
{sorted_plugins_data.map((plugin) => ( {sorted_plugins_data.map((plugin) => {
<div key={plugin.plugin_id} className={styles.plugin_wrapper}> const target_info = plugin.is_downloaded
<p className={styles.title}> ? plugin.downloaded_plugin_info
{plugin.is_downloaded : plugin.latest_plugin_info;
? plugin.downloaded_plugin_info?.title
: plugin.latest_plugin_info?.title} const target_locale = target_info.locales && target_info.locales[i18n.language]
</p> ? target_info.locales[i18n.language]
<p className={styles.plugin_id}>{plugin.plugin_id}</p> : {
{plugin.is_error ? ( title: target_info.title,
<p style={{ color: "red" }}>Error: {plugin.error_message}</p> desc: target_info.desc || null,
) : ( };
<div className={styles.plugin_info_wrapper}>
<div className={styles.plugin_info}> return (
<p> <div key={plugin.plugin_id} className={styles.plugin_wrapper}>
{plugin.is_downloaded <p className={styles.title}>
? `現在のバージョン: ${plugin.downloaded_plugin_info?.plugin_version}` {target_locale.title}
: null} </p>
</p> <p className={styles.plugin_id}>{plugin.plugin_id}</p>
<p className={styles.desc}>
{target_locale.desc}
</p>
{plugin.is_error ? (
<p style={{ color: "red" }}>Error: {plugin.error_message}</p>
) : (
<div className={styles.plugin_info_wrapper}>
<div className={styles.plugin_info}>
<p>
{plugin.is_downloaded
? `現在のバージョン: ${plugin.downloaded_plugin_info?.plugin_version}`
: null}
</p>
</div>
<PluginsControlComponent
variable_state={variable_state}
toggleFunction={toggleFunction}
downloadStartFunction={downloadStartFunction}
plugin_status={plugin}
/>
</div> </div>
<PluginsControlComponent )}
variable_state={variable_state} </div>
toggleFunction={toggleFunction} );
downloadStartFunction={downloadStartFunction} })}
plugin_status={plugin}
/>
</div>
)}
</div>
))}
</div> </div>
); );
}; };

View File

@@ -4,11 +4,8 @@ import plugin_info from "../plugin_info.json";
export const initI18n = (i18n) => { export const initI18n = (i18n) => {
const ns = plugin_info.plugin_id; const ns = plugin_info.plugin_id;
// parse once
const en_res = en;
const ja_res = ja;
// addResourceBundle will merge into i18ns store // addResourceBundle will merge into i18ns store
i18n.addResourceBundle("en", ns, en_res, /* deep = */ true, /* overwrite = */ true); i18n.addResourceBundle("en", ns, en, /* deep = */ true, /* overwrite = */ true);
i18n.addResourceBundle("ja", ns, ja_res, /* deep = */ true, /* overwrite = */ true); i18n.addResourceBundle("ja", ns, ja, /* deep = */ true, /* overwrite = */ true);
}; };

View File

@@ -1,9 +1,20 @@
{ {
"title": "VRCT Subtitles", "title": "VRCT Subtitles",
"desc": "No description",
"plugin_id": "vrct_plugin_subtitles", "plugin_id": "vrct_plugin_subtitles",
"asset_name": "vrct_plugin_subtitles.zip", "asset_name": "vrct_plugin_subtitles.zip",
"location": "main_section", "location": "main_section",
"plugin_version": "0.0.4", "plugin_version": "0.0.5",
"min_supported_vrct_version": "3.0.5", "min_supported_vrct_version": "3.0.5",
"max_supported_vrct_version": "3.0.5" "max_supported_vrct_version": "3.0.5",
"locales": {
"en": {
"title": "VRCT Subtitles",
"desc": "No description"
},
"ja": {
"title": "VRCT 字幕表示機能",
"desc": "VRCTのオーバーレイ機能を使い、目の前に字幕としてテキストを表示する機能です。ワールドギミックの開始タイミングに合わせて字幕を設定し、同時に表示しているだけではあります。"
}
}
} }

View File

@@ -33,8 +33,6 @@ export const SubtitleSystemContainer = () => {
// // カウントダウンタイマー専用の ref // // カウントダウンタイマー専用の ref
// const countdownIntervalRef = useRef(null); // const countdownIntervalRef = useRef(null);
console.log(t("main_page.title"));
return ( return (
<div className={styles.container}> <div className={styles.container}>
<h1 className={styles.title}>{t("main_page.title")}</h1> <h1 className={styles.title}>{t("main_page.title")}</h1>

View File

@@ -1,6 +1,7 @@
import { defineConfig } from "vite"; import { defineConfig } from "vite";
import react from "@vitejs/plugin-react"; import react from "@vitejs/plugin-react";
import svgr from "vite-plugin-svgr"; import svgr from "vite-plugin-svgr";
import yaml from "@rollup/plugin-yaml";
import path from "path"; import path from "path";
import { dev_plugins } from "./src-ui/plugins/plugins_index.js"; import { dev_plugins } from "./src-ui/plugins/plugins_index.js";
@@ -11,8 +12,11 @@ export default defineConfig(async () => {
const plugin_aliases = await getPluginAliases(); const plugin_aliases = await getPluginAliases();
return { return {
plugins: [react(), svgr()], plugins: [
assetsInclude: ["**/*.yml"], yaml({ include: ["**/*.yml", "**/*.yaml"] }),
react(),
svgr(),
],
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build` // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
// //