From 7da934fe8b388da0b56239f009715fa2707da97e Mon Sep 17 00:00:00 2001 From: ekko <152005280+EKKOLearnAI@users.noreply.github.com> Date: Thu, 14 May 2026 23:32:33 +0800 Subject: [PATCH] revert: remove i18n lazy loading and highlight.js selective import (#736) Revert the dynamic import() for i18n locales and highlight.js core+ registration from #696. Dynamic imports create separate chunk files that cause 404 errors for users after updating when the browser still references old chunk hashes. Co-authored-by: Claude Opus 4.7 --- .../src/components/hermes/chat/highlight.ts | 58 +------------------ .../src/components/layout/LanguageSwitch.vue | 5 +- packages/client/src/i18n/index.ts | 23 ++------ packages/client/src/i18n/messages.ts | 32 +++++----- packages/client/src/main.ts | 6 +- tests/client/highlight-helper.test.ts | 2 +- tests/client/i18n-coverage.test.ts | 21 ++++--- 7 files changed, 34 insertions(+), 113 deletions(-) diff --git a/packages/client/src/components/hermes/chat/highlight.ts b/packages/client/src/components/hermes/chat/highlight.ts index 0ffffd5a..30a2ae3f 100644 --- a/packages/client/src/components/hermes/chat/highlight.ts +++ b/packages/client/src/components/hermes/chat/highlight.ts @@ -1,62 +1,6 @@ -import hljs from 'highlight.js/lib/core' -import bash from 'highlight.js/lib/languages/bash' -import c from 'highlight.js/lib/languages/c' -import cpp from 'highlight.js/lib/languages/cpp' -import csharp from 'highlight.js/lib/languages/csharp' -import css from 'highlight.js/lib/languages/css' -import diff from 'highlight.js/lib/languages/diff' -import go from 'highlight.js/lib/languages/go' -import xml from 'highlight.js/lib/languages/xml' -import java from 'highlight.js/lib/languages/java' -import javascript from 'highlight.js/lib/languages/javascript' -import json from 'highlight.js/lib/languages/json' -import kotlin from 'highlight.js/lib/languages/kotlin' -import lua from 'highlight.js/lib/languages/lua' -import markdown from 'highlight.js/lib/languages/markdown' -import php from 'highlight.js/lib/languages/php' -import python from 'highlight.js/lib/languages/python' -import r from 'highlight.js/lib/languages/r' -import ruby from 'highlight.js/lib/languages/ruby' -import rust from 'highlight.js/lib/languages/rust' -import scss from 'highlight.js/lib/languages/scss' -import shell from 'highlight.js/lib/languages/shell' -import sql from 'highlight.js/lib/languages/sql' -import swift from 'highlight.js/lib/languages/swift' -import typescript from 'highlight.js/lib/languages/typescript' -import yaml from 'highlight.js/lib/languages/yaml' -import plaintext from 'highlight.js/lib/languages/plaintext' +import hljs from 'highlight.js' import { copyToClipboard } from '@/utils/clipboard' -hljs.registerLanguage('bash', bash) -hljs.registerLanguage('c', c) -hljs.registerLanguage('cpp', cpp) -hljs.registerLanguage('csharp', csharp) -hljs.registerLanguage('css', css) -hljs.registerLanguage('diff', diff) -hljs.registerLanguage('go', go) -hljs.registerLanguage('xml', xml) -hljs.registerLanguage('html', xml) -hljs.registerLanguage('java', java) -hljs.registerLanguage('javascript', javascript) -hljs.registerLanguage('js', javascript) -hljs.registerLanguage('json', json) -hljs.registerLanguage('kotlin', kotlin) -hljs.registerLanguage('lua', lua) -hljs.registerLanguage('markdown', markdown) -hljs.registerLanguage('php', php) -hljs.registerLanguage('python', python) -hljs.registerLanguage('r', r) -hljs.registerLanguage('ruby', ruby) -hljs.registerLanguage('rust', rust) -hljs.registerLanguage('scss', scss) -hljs.registerLanguage('shell', shell) -hljs.registerLanguage('sql', sql) -hljs.registerLanguage('swift', swift) -hljs.registerLanguage('typescript', typescript) -hljs.registerLanguage('ts', typescript) -hljs.registerLanguage('yaml', yaml) -hljs.registerLanguage('plaintext', plaintext) - const LANGUAGE_ALIASES: Record = { shellscript: 'bash', sh: 'bash', diff --git a/packages/client/src/components/layout/LanguageSwitch.vue b/packages/client/src/components/layout/LanguageSwitch.vue index c856d3b0..cb6a572e 100644 --- a/packages/client/src/components/layout/LanguageSwitch.vue +++ b/packages/client/src/components/layout/LanguageSwitch.vue @@ -17,9 +17,8 @@ const options = [ { label: 'Português', value: 'pt' }, ] -async function handleChange(val: string) { - await switchLocale(val) - locale.value = val +function handleChange(val: string) { + switchLocale(val) localStorage.setItem('hermes_locale', val) } diff --git a/packages/client/src/i18n/index.ts b/packages/client/src/i18n/index.ts index 835651b2..b0b6e364 100644 --- a/packages/client/src/i18n/index.ts +++ b/packages/client/src/i18n/index.ts @@ -1,5 +1,5 @@ import { createI18n } from 'vue-i18n' -import { en, loadLocale, supportedLocales } from './messages' +import { messages, supportedLocales } from './messages' import type { SupportedLocale } from './messages' const saved = localStorage.getItem('hermes_locale') @@ -37,24 +37,11 @@ const locale = resolveLocale(saved) export const i18n = createI18n({ legacy: false, - locale: 'en', + locale, fallbackLocale: 'en', - messages: { en }, + messages, }) -export async function setupI18n(): Promise { - if (locale !== 'en') { - const msgs = await loadLocale(locale) - if (msgs) { - i18n.global.setLocaleMessage(locale, msgs as any) - } - ;(i18n.global.locale as any).value = locale - } -} - -export async function switchLocale(newLocale: string): Promise { - const msgs = await loadLocale(newLocale) - if (msgs) { - i18n.global.setLocaleMessage(newLocale, msgs as any) - } +export function switchLocale(newLocale: string): void { + ;(i18n.global.locale as any).value = newLocale } diff --git a/packages/client/src/i18n/messages.ts b/packages/client/src/i18n/messages.ts index 236d4ca2..b1a5e88c 100644 --- a/packages/client/src/i18n/messages.ts +++ b/packages/client/src/i18n/messages.ts @@ -1,4 +1,12 @@ import en from './locales/en' +import zh from './locales/zh' +import zhTW from './locales/zh-TW' +import ja from './locales/ja' +import ko from './locales/ko' +import fr from './locales/fr' +import es from './locales/es' +import de from './locales/de' +import pt from './locales/pt' export type LocaleMessages = Record @@ -25,25 +33,11 @@ export function mergeMessagesWithFallback( return merged } -const localeLoaders: Record Promise<{ default: LocaleMessages }>> = { - 'zh': () => import('./locales/zh'), - 'zh-TW': () => import('./locales/zh-TW'), - 'ja': () => import('./locales/ja'), - 'ko': () => import('./locales/ko'), - 'fr': () => import('./locales/fr'), - 'es': () => import('./locales/es'), - 'de': () => import('./locales/de'), - 'pt': () => import('./locales/pt'), +const rawMessages: Record = { en, zh, 'zh-TW': zhTW, ja, ko, fr, es, de, pt } + +export const messages: Record = {} +for (const [locale, msg] of Object.entries(rawMessages)) { + messages[locale] = locale === 'en' ? msg : mergeMessagesWithFallback(en, msg) } export { en } - -export async function loadLocale(locale: string): Promise { - if (locale === 'en') return en - - const loader = localeLoaders[locale] - if (!loader) return null - - const mod = await loader() - return mergeMessagesWithFallback(en, mod.default) -} diff --git a/packages/client/src/main.ts b/packages/client/src/main.ts index 7641e7b8..2a10cc14 100644 --- a/packages/client/src/main.ts +++ b/packages/client/src/main.ts @@ -1,7 +1,7 @@ import { createApp } from 'vue' import { createPinia } from 'pinia' import router from './router' -import { i18n, setupI18n } from './i18n' +import { i18n } from './i18n' import App from './App.vue' import './styles/global.scss' @@ -36,6 +36,4 @@ const app = createApp(App) app.use(createPinia()) app.use(i18n) app.use(router) -setupI18n().then(() => { - app.mount('#app') -}) +app.mount('#app') diff --git a/tests/client/highlight-helper.test.ts b/tests/client/highlight-helper.test.ts index d241d926..13bc2aa8 100644 --- a/tests/client/highlight-helper.test.ts +++ b/tests/client/highlight-helper.test.ts @@ -8,7 +8,7 @@ const highlightJsMock = vi.hoisted(() => ({ registerLanguage: vi.fn(), })) -vi.mock('highlight.js/lib/core', () => ({ +vi.mock('highlight.js', () => ({ default: highlightJsMock, })) diff --git a/tests/client/i18n-coverage.test.ts b/tests/client/i18n-coverage.test.ts index e50b8426..59f9d1af 100644 --- a/tests/client/i18n-coverage.test.ts +++ b/tests/client/i18n-coverage.test.ts @@ -3,7 +3,7 @@ import { readdirSync, readFileSync } from 'fs' import { join, relative } from 'path' import { changelog } from '@/data/changelog' -import { loadLocale, supportedLocales } from '@/i18n/messages' +import { messages, supportedLocales } from '@/i18n/messages' import en from '@/i18n/locales/en' import { createI18n } from 'vue-i18n' @@ -102,13 +102,12 @@ describe('i18n locale coverage', () => { 'chat.sessionNotFound', ]) - beforeAll(async () => { - const results = await Promise.all( - supportedLocales.filter(l => l !== 'en').map(async l => { - const msgs = await loadLocale(l) - if (msgs) allMessages[l] = msgs - }), - ) + beforeAll(() => { + for (const l of supportedLocales) { + if (l !== 'en' && messages[l]) { + allMessages[l] = messages[l] + } + } }) it('defines every statically referenced translation key in the English source locale', () => { @@ -132,8 +131,8 @@ describe('i18n locale coverage', () => { }) it('localizes Skills Usage page copy in every non-English locale instead of falling back to English', () => { - const englishMessages = rawMessages.en - const untranslated = Object.entries(rawMessages).flatMap(([locale, localeMessages]) => { + const englishMessages = messages.en + const untranslated = Object.entries(messages).flatMap(([locale, localeMessages]) => { if (locale === 'en') return [] return SKILLS_USAGE_LOCALIZED_KEYS.flatMap((key) => { @@ -148,7 +147,7 @@ describe('i18n locale coverage', () => { it('keeps Skills Usage summary and table labels compact across locales', () => { - const oversized = Object.entries(rawMessages).flatMap(([locale, localeMessages]) => + const oversized = Object.entries(messages).flatMap(([locale, localeMessages]) => Object.entries(SKILLS_USAGE_COMPACT_LABEL_LIMITS).flatMap(([key, maxLength]) => { const localeValue = getPath(localeMessages, key) return labelLength(localeValue) > maxLength