summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortaichan <40626578+tai-cha@users.noreply.github.com>2025-06-26 08:26:44 +0900
committerGitHub <noreply@github.com>2025-06-26 08:26:44 +0900
commitb455e63da75aa71eea00adc9349d7b456664fbcd (patch)
tree3f6f4cb386b6c704dd34cf505a2588f040a69d52
parentUpdate CHANGELOG.md (diff)
downloadmisskey-b455e63da75aa71eea00adc9349d7b456664fbcd.tar.gz
misskey-b455e63da75aa71eea00adc9349d7b456664fbcd.tar.bz2
misskey-b455e63da75aa71eea00adc9349d7b456664fbcd.zip
chore(frontend): 開発モード時に言語ファイルの変更を自動で反映するように (#16215)
* chore(frontend): 開発モード時に言語ファイルの変更を自動で反映するように * fix message * naming * SPDX
-rw-r--r--packages/frontend/lib/vite-plugin-watch-locales.ts36
-rw-r--r--packages/frontend/src/boot/common.ts23
-rw-r--r--packages/frontend/vite.config.ts2
3 files changed, 59 insertions, 2 deletions
diff --git a/packages/frontend/lib/vite-plugin-watch-locales.ts b/packages/frontend/lib/vite-plugin-watch-locales.ts
new file mode 100644
index 0000000000..8e209d27bd
--- /dev/null
+++ b/packages/frontend/lib/vite-plugin-watch-locales.ts
@@ -0,0 +1,36 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import path from 'node:path'
+import locales from '../../../locales/index.js';
+
+const localesDir = path.resolve(__dirname, '../../../locales')
+
+/**
+ * 外部ファイルを監視し、必要に応じてwebSocketでメッセージを送るViteプラグイン
+ * @returns {import('vite').Plugin}
+ */
+export default function pluginWatchLocales() {
+ return {
+ name: 'watch-locales',
+
+ configureServer(server) {
+ const localeYmlPaths = Object.keys(locales).map(locale => path.join(localesDir, `${locale}.yml`));
+
+ // watcherにパスを追加
+ server.watcher.add(localeYmlPaths);
+
+ server.watcher.on('change', (filePath) => {
+ if (localeYmlPaths.includes(filePath)) {
+ server.ws.send({
+ type: 'custom',
+ event: 'locale-update',
+ data: filePath.match(/([^\/]+)\.yml$/)?.[1] || null,
+ })
+ }
+ });
+ },
+ };
+}
diff --git a/packages/frontend/src/boot/common.ts b/packages/frontend/src/boot/common.ts
index c8098b6cf8..992bde9bd1 100644
--- a/packages/frontend/src/boot/common.ts
+++ b/packages/frontend/src/boot/common.ts
@@ -81,8 +81,10 @@ export async function common(createVue: () => Promise<App<Element>>) {
//#region Detect language & fetch translations
const localeVersion = miLocalStorage.getItem('localeVersion');
const localeOutdated = (localeVersion == null || localeVersion !== version || locale == null);
- if (localeOutdated) {
- const res = await window.fetch(`/assets/locales/${lang}.${version}.json`);
+
+ async function fetchAndUpdateLocale({ useCache } = { useCache: true }) {
+ const fetchOptions: RequestInit | undefined = useCache ? undefined : { cache: 'no-store' };
+ const res = await window.fetch(`/assets/locales/${lang}.${version}.json`, fetchOptions);
if (res.status === 200) {
const newLocale = await res.text();
const parsedNewLocale = JSON.parse(newLocale);
@@ -92,6 +94,23 @@ export async function common(createVue: () => Promise<App<Element>>) {
updateI18n(parsedNewLocale);
}
}
+
+ if (localeOutdated) {
+ fetchAndUpdateLocale();
+ }
+
+ if (import.meta.hot) {
+ import.meta.hot.on('locale-update', async (updatedLang: string) => {
+ console.info(`Locale updated: ${updatedLang}`);
+ if (updatedLang === lang) {
+ await new Promise(resolve => {
+ window.setTimeout(resolve, 500);
+ });
+ await fetchAndUpdateLocale({ useCache: false });
+ window.location.reload();
+ }
+ });
+ }
//#endregion
// タッチデバイスでCSSの:hoverを機能させる
diff --git a/packages/frontend/vite.config.ts b/packages/frontend/vite.config.ts
index b0ccbfb65c..77b5b48a18 100644
--- a/packages/frontend/vite.config.ts
+++ b/packages/frontend/vite.config.ts
@@ -13,6 +13,7 @@ import pluginUnwindCssModuleClassName from './lib/rollup-plugin-unwind-css-modul
import pluginJson5 from './vite.json5.js';
import pluginCreateSearchIndex from './lib/vite-plugin-create-search-index.js';
import type { Options as SearchIndexOptions } from './lib/vite-plugin-create-search-index.js';
+import pluginWatchLocales from './lib/vite-plugin-watch-locales.js';
const url = process.env.NODE_ENV === 'development' ? yaml.load(await fsp.readFile('../../.config/default.yml', 'utf-8')).url : null;
const host = url ? (new URL(url)).hostname : undefined;
@@ -102,6 +103,7 @@ export function getConfig(): UserConfig {
},
plugins: [
+ pluginWatchLocales(),
...searchIndexes.map(options => pluginCreateSearchIndex(options)),
pluginVue(),
pluginUnwindCssModuleClassName(),