#786·MiroFish

meta.title and meta.description are translated but never applied - browser tab stays Chinese in every language

Author: SandroHub013Created Aug 22, 2026Updated Aug 25, 2026
Labelsenhancementgood first issue

Summary

meta.title and meta.description are translated in every locale file but are never read anywhere in the codebase. frontend/index.html hardcodes the Chinese <title> and <meta name="description">, so the browser tab and the SEO description stay Chinese no matter which language the user selects.

Evidence

The keys exist and are translated in every locale:

en  {'title': 'MiroFish - Predict Everything', 'description': 'MiroFish - Social Media Opinion Simulation System'}
zh  {'title': 'MiroFish - 预测万物',            'description': 'MiroFish - 社交媒体舆论模拟系统'}

But nothing consumes them. Grepping the whole repo for meta.title, meta.description, t('meta, document.title, useHead and titleTemplate across frontend/ and backend/ returns no hits — the only meta. matches are Vite's own import.meta.glob (frontend/src/i18n/index.js:4) and import.meta.env (frontend/src/api/index.js:6).

Meanwhile frontend/index.html hardcodes both:

<meta name="description" content="MiroFish - 社交媒体舆论模拟系统" />
<title>MiroFish - 预测万物</title>

Reproduce

  1. npm run dev
  2. Switch the UI language to English with the language switcher
  3. The page content becomes English, but the browser tab still reads MiroFish - 预测万物

Observed on main at 117ed37. It reproduces for any non-Chinese locale, so meta.* is currently two dead keys per locale file.

Impact

  • The browser tab, bookmark name and window title are Chinese for every user, in every language
  • <meta name="description"> is Chinese, which is what search engines and link previews pick up
  • Every locale file carries two translated keys that have no effect, which is misleading for anyone contributing a translation

Suggested fix

index.html already runs an inline script that reads the saved locale before Vue mounts, which is what makes html[lang] correct on first paint:

<script>document.documentElement.lang = localStorage.getItem('locale') || 'zh'</script>

The smallest fix that keeps that no-flash behaviour is to apply the title in App.vue (or main.js) from the existing i18n messages, and re-apply it whenever the locale changes — something along the lines of:

watchEffect(() => {
  document.title = t('meta.title')
  document.querySelector('meta[name="description"]')?.setAttribute('content', t('meta.description'))
})

That reuses the keys already present in every locale and needs no new dependency.

I'm happy to open a PR for this if you'd like — just let me know whether you'd prefer it handled in App.vue, in main.js, or by extending the existing inline script in index.html.

Context

Noticed while adding the Italian locale in #785. Not fixed there, to keep that PR scoped to the translation.


Suggested labels: enhancement, and possibly good first issue since the fix is small and self-contained (I don't have permission to set labels on this repo).