enhance(dev): 開発モード時にlocaleと型定義が自動的に再生成されるように (#12481)

* enhance: localeを任意のタイミングでリビルドできるように

* enhance: localeも監視し、必要であればlocaleをリビルドするように

* feat: devモードの時のみナビゲーションバーからキャッシュクリアができるように

* refactor: キャッシュクリア部分を共通化

* fix: localesのファイル変更イベントが取れないのを修正

* fix: replaceAllでコケるのを修正

* change: 開発モードに関係なくナビゲーションバーからキャッシュクリアできるように

* refactor: 必要のないリビルドをしないように

* update: CHANGELOG.md

---------

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
This commit is contained in:
yukineko 2023-11-30 14:48:02 +09:00 committed by GitHub
parent 4f6e098542
commit 22d6fa1fdf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 80 additions and 44 deletions

View File

@ -25,6 +25,7 @@
- Enhance: ユーザーのRawデータを表示するページが復活 - Enhance: ユーザーのRawデータを表示するページが復活
- Enhance: リアクション選択時に音を鳴らせるように - Enhance: リアクション選択時に音を鳴らせるように
- Enhance: サウンドにドライブのファイルを使用できるように - Enhance: サウンドにドライブのファイルを使用できるように
- Enhance: ナビゲーションバーに項目「キャッシュを削除」を追加
- Enhance: Shareページで投稿を完了すると、親ウィンドウ親フレームにpostMessageするように - Enhance: Shareページで投稿を完了すると、親ウィンドウ親フレームにpostMessageするように
- Enhance: チャンネル、クリップ、ページ、Play、ギャラリーにURLのコピーボタンを設置 #11305 - Enhance: チャンネル、クリップ、ページ、Play、ギャラリーにURLのコピーボタンを設置 #11305
- Enhance: ノートプレビューに「内容を隠す」が反映されるように - Enhance: ノートプレビューに「内容を隠す」が反映されるように

View File

@ -56,6 +56,18 @@ export default function generateDTS() {
ts.NodeFlags.Const | ts.NodeFlags.Ambient | ts.NodeFlags.ContextFlags, ts.NodeFlags.Const | ts.NodeFlags.Ambient | ts.NodeFlags.ContextFlags,
), ),
), ),
ts.factory.createFunctionDeclaration(
[ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
undefined,
ts.factory.createIdentifier('build'),
undefined,
[],
ts.factory.createTypeReferenceNode(
ts.factory.createIdentifier('Locale'),
undefined,
),
undefined,
),
ts.factory.createExportDefault(ts.factory.createIdentifier('locales')), ts.factory.createExportDefault(ts.factory.createIdentifier('locales')),
]; ];
const printed = ts.createPrinter({ const printed = ts.createPrinter({

1
locales/index.d.ts vendored
View File

@ -2505,4 +2505,5 @@ export interface Locale {
declare const locales: { declare const locales: {
[lang: string]: Locale; [lang: string]: Locale;
}; };
export function build(): Locale;
export default locales; export default locales;

View File

@ -51,33 +51,37 @@ const primaries = {
// 何故か文字列にバックスペース文字が混入することがあり、YAMLが壊れるので取り除く // 何故か文字列にバックスペース文字が混入することがあり、YAMLが壊れるので取り除く
const clean = (text) => text.replace(new RegExp(String.fromCodePoint(0x08), 'g'), ''); const clean = (text) => text.replace(new RegExp(String.fromCodePoint(0x08), 'g'), '');
const locales = languages.reduce((a, c) => (a[c] = yaml.load(clean(fs.readFileSync(new URL(`${c}.yml`, import.meta.url), 'utf-8'))) || {}, a), {}); export function build() {
const locales = languages.reduce((a, c) => (a[c] = yaml.load(clean(fs.readFileSync(new URL(`${c}.yml`, import.meta.url), 'utf-8'))) || {}, a), {});
// 空文字列が入ることがあり、フォールバックが動作しなくなるのでプロパティごと消す // 空文字列が入ることがあり、フォールバックが動作しなくなるのでプロパティごと消す
const removeEmpty = (obj) => { const removeEmpty = (obj) => {
for (const [k, v] of Object.entries(obj)) { for (const [k, v] of Object.entries(obj)) {
if (v === '') { if (v === '') {
delete obj[k]; delete obj[k];
} else if (typeof v === 'object') { } else if (typeof v === 'object') {
removeEmpty(v); removeEmpty(v);
}
} }
} return obj;
return obj; };
}; removeEmpty(locales);
removeEmpty(locales);
export default Object.entries(locales) return Object.entries(locales)
.reduce((a, [k ,v]) => (a[k] = (() => { .reduce((a, [k, v]) => (a[k] = (() => {
const [lang] = k.split('-'); const [lang] = k.split('-');
switch (k) { switch (k) {
case 'ja-JP': return v; case 'ja-JP': return v;
case 'ja-KS': case 'ja-KS':
case 'en-US': return merge(locales['ja-JP'], v); case 'en-US': return merge(locales['ja-JP'], v);
default: return merge( default: return merge(
locales['ja-JP'], locales['ja-JP'],
locales['en-US'], locales['en-US'],
locales[`${lang}-${primaries[lang]}`] ?? {}, locales[`${lang}-${primaries[lang]}`] ?? {},
v v
); );
} }
})(), a), {}); })(), a), {});
}
export default build();

View File

@ -12,6 +12,7 @@ import * as os from '@/os.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { ui } from '@/config.js'; import { ui } from '@/config.js';
import { unisonReload } from '@/scripts/unison-reload.js'; import { unisonReload } from '@/scripts/unison-reload.js';
import { clearCache } from './scripts/clear-cache.js';
export const navbarItemDef = reactive({ export const navbarItemDef = reactive({
notifications: { notifications: {
@ -171,4 +172,11 @@ export const navbarItemDef = reactive({
show: computed(() => $i != null), show: computed(() => $i != null),
to: `/@${$i?.username}`, to: `/@${$i?.username}`,
}, },
cacheClear: {
title: i18n.ts.cacheClear,
icon: 'ti ti-trash',
action: (ev) => {
clearCache();
},
},
}); });

View File

@ -33,13 +33,11 @@ import { i18n } from '@/i18n.js';
import MkInfo from '@/components/MkInfo.vue'; import MkInfo from '@/components/MkInfo.vue';
import MkSuperMenu from '@/components/MkSuperMenu.vue'; import MkSuperMenu from '@/components/MkSuperMenu.vue';
import { signout, $i } from '@/account.js'; import { signout, $i } from '@/account.js';
import { unisonReload } from '@/scripts/unison-reload.js'; import { clearCache } from '@/scripts/clear-cache.js';
import { instance } from '@/instance.js'; import { instance } from '@/instance.js';
import { useRouter } from '@/router.js'; import { useRouter } from '@/router.js';
import { definePageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js'; import { definePageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { miLocalStorage } from '@/local-storage.js';
import { fetchCustomEmojis } from '@/custom-emojis.js';
const indexInfo = { const indexInfo = {
title: i18n.ts.settings, title: i18n.ts.settings,
@ -182,13 +180,7 @@ const menuDef = computed(() => [{
icon: 'ti ti-trash', icon: 'ti ti-trash',
text: i18n.ts.clearCache, text: i18n.ts.clearCache,
action: async () => { action: async () => {
os.waiting(); await clearCache();
miLocalStorage.removeItem('locale');
miLocalStorage.removeItem('theme');
miLocalStorage.removeItem('emojis');
miLocalStorage.removeItem('lastEmojisFetchedAt');
await fetchCustomEmojis(true);
unisonReload();
}, },
}, { }, {
type: 'button', type: 'button',

View File

@ -0,0 +1,14 @@
import { unisonReload } from '@/scripts/unison-reload.js';
import * as os from '@/os.js';
import { miLocalStorage } from '@/local-storage.js';
import { fetchCustomEmojis } from '@/custom-emojis.js';
export async function clearCache() {
os.waiting();
miLocalStorage.removeItem('locale');
miLocalStorage.removeItem('theme');
miLocalStorage.removeItem('emojis');
miLocalStorage.removeItem('lastEmojisFetchedAt');
await fetchCustomEmojis(true);
unisonReload();
}

View File

@ -9,10 +9,12 @@ import cssnano from 'cssnano';
import postcss from 'postcss'; import postcss from 'postcss';
import * as terser from 'terser'; import * as terser from 'terser';
import locales from '../locales/index.js'; import { build as buildLocales } from '../locales/index.js';
import generateDTS from '../locales/generateDTS.js'; import generateDTS from '../locales/generateDTS.js';
import meta from '../package.json' assert { type: "json" }; import meta from '../package.json' assert { type: "json" };
let locales = buildLocales();
async function copyFrontendFonts() { async function copyFrontendFonts() {
await fs.cp('./packages/frontend/node_modules/three/examples/fonts', './built/_frontend_dist_/fonts', { dereference: true, recursive: true }); await fs.cp('./packages/frontend/node_modules/three/examples/fonts', './built/_frontend_dist_/fonts', { dereference: true, recursive: true });
} }
@ -89,10 +91,12 @@ async function build() {
await build(); await build();
if (process.argv.includes("--watch")) { if (process.argv.includes("--watch")) {
const watcher = fs.watch('./packages', { recursive: true }); const watcher = fs.watch('./locales');
for await (const event of watcher) { for await (const event of watcher) {
if (/^[a-z]+\/src/.test(event.filename)) { const filename = event.filename?.replaceAll('\\', '/');
await build(); if (/^[a-z]+-[A-Z]+\.yml/.test(filename)) {
} locales = buildLocales();
} await copyFrontendLocales()
}
}
} }