TsFile Viewer supports multiple languages with Vue I18n.
frontend/src/i18n/
├── index.ts # i18n configuration
└── locales/
├── zh-CN.json # Chinese translations
└── en-US.json # English translations
<script setup lang="ts"> import { useI18n } from "vue-i18n"; const { t, locale } = useI18n(); // Use translation const title = t("app.title"); // Switch language locale.value = "en-US"; </script> <template> <h1>{{ $t("app.title") }}</h1> <p>{{ $t("app.description") }}</p> </template>
<script> export default { computed: { title() { return this.$t("app.title"); }, }, methods: { switchLanguage(lang) { this.$i18n.locale = lang; }, }, }; </script> <template> <h1>{{ $t("app.title") }}</h1> </template>
{ "common": { "loading": "Loading...", "error": "Error", "success": "Success", "cancel": "Cancel", "confirm": "Confirm" } }
{ "file": { "title": "File Management", "uploadFile": "Upload File", "selectFile": "Select File" }, "metadata": { "title": "Metadata", "version": "Version", "timeRange": "Time Range" }, "data": { "title": "Data Preview", "filters": "Filters", "exportCsv": "Export CSV" }, "chart": { "title": "Chart Visualization", "exportPng": "Export PNG" } }
Create a new locale file:
touch frontend/src/i18n/locales/ja-JP.json
Add translations:
{ "app": { "title": "TsFileビューア", "description": "Apache TsFile形式データの表示と分析ツール" } }
Import in i18n/index.ts:
import jaJP from "./locales/ja-JP.json"; const i18n = createI18n({ messages: { "zh-CN": zhCN, "en-US": enUS, "ja-JP": jaJP, // Add new language }, });
Update LanguageSwitcher component:
const languageItems = computed(() => [ [ { label: '中文', click: () => switchLanguage('zh-CN') }, { label: 'English', click: () => switchLanguage('en-US') }, { label: '日本語', click: () => switchLanguage('ja-JP') }, ], ])
English:
Chinese:
Copy existing documentation:
cp README.md README.ja-JP.md cp USER_GUIDE.md USER_GUIDE.ja-JP.md cp DEPLOYMENT.md DEPLOYMENT.ja-JP.md
Translate the content
Add links in main README:
[中文文档](../README.zh-CN.md) | [English](../README.md) | [日本語](README.ja-JP.md)
Use Namespaces: Organize translations by feature
{ "file": { ... }, "metadata": { ... }, "data": { ... } }
Consistent Keys: Use the same key structure across languages
// zh-CN.json { "common": { "save": "保存" } } // en-US.json { "common": { "save": "Save" } }
Pluralization: Use Vue I18n pluralization
{ "items": "no items | one item | {count} items" }
{{ $t("items", 0) }} // "no items" {{ $t("items", 1) }} // "one item" {{ $t("items", 5) }} // "5 items"
Interpolation: Use variables in translations
{ "welcome": "Welcome, {name}!" }
{{ $t("welcome", { name: "John" }) }} // "Welcome, John!"
Date/Time Formatting: Use locale-aware formatting
const date = new Date(); const formatted = date.toLocaleString(locale.value);
Test translations in different languages:
import { createI18n } from "vue-i18n"; import zhCN from "@/i18n/locales/zh-CN.json"; import enUS from "@/i18n/locales/en-US.json"; describe("i18n", () => { it("should have all keys in both languages", () => { const zhKeys = Object.keys(zhCN); const enKeys = Object.keys(enUS); expect(zhKeys).toEqual(enKeys); }); });
import VueI18nPlugin from "@intlify/unplugin-vue-i18n/vite"; export default defineConfig({ plugins: [ VueI18nPlugin({ include: resolve(__dirname, "./src/i18n/locales/**"), }), ], });
import type { MessageSchema } from '@/i18n' // Type-safe translations const i18n = createI18n<[MessageSchema], 'zh-CN' | 'en-US'>({ legacy: false, locale: 'zh-CN', messages: { ... }, })
If a translation key is missing:
If you encounter build errors: