soon-i18n-vue
v2.0.0
Published
a lightweight nested messages i18n library with smart ts prompt can be used in react , vue , svelte , solid , etc...
Maintainers
Readme
soon-i18n-vue v2.0
Vue adapter for soon-i18n, providing composable-based i18n integration with full TypeScript support and reactive updates.
Full Document
Install
npm install soon-i18n-vueFull Example
Vue Demo or
npx degit https://github.com/leafio/soon-i18n/examples/vue-demoInstance Usage
Create an instance
// lang/index.ts
import { createI18n } from "soon-i18n-vue";
const globalLocales = {
zh: { g_welcome: "全局:欢迎 {name}", common: { title: "标题" } },
en: { g_welcome: "Global: Welcome {name}", common: { title: "Title" } },
} as const;
type Lang = "zh" | "en";
export const { tLocales, useLocales, lang } = createI18n(
{ lang: () => "zh", fallbacks: (curLang, lastLang) => ["en"] },
globalLocales
);Use in JS/TS (Sync only)
import { tLocales } from "../lang";
// tLocales only supports synchronous loading
export const showToast = () => {
const t = tLocales({
zh: { tip: "哈哈,一条中文提醒!!!" },
en: { tip: "Aha, an English tip" },
});
alert(t("tip"));
};
// For lazy loading, use useLocales in componentsUse in components
Synchronous Loading
<template>
<div>
<h1>{{ t("common.title") }}</h1>
<p>{{ t("hello") }}</p>
<p>{{ t("g_welcome", { name: "张三" }) }}</p>
<button @click="handleToggle">Switch Language</button>
</div>
</template>
<script setup>
import { useLocales, lang } from "../lang";
const [t, inited] = useLocales({
zh: { hello: "你好" },
en: { hello: "Hello" }
});
if (!inited.value) {
// Handle loading state
}
const handleToggle = () => {
lang.value = lang.value === "zh" ? "en" : "zh";
};
</script>Lazy Loading
<script setup>
import { useLocales } from "../lang";
const [t, inited] = useLocales({
zh: { welcome: "欢迎" },
en: () => import("./locales/en"), // Dynamic import
ja: () => fetch("/api/translations/ja")
.then(res => res.json())
.then(data => ({ default: data })), // API fetch
});
</script>
<template>
<div v-if="!inited">Loading translations...</div>
<div v-else>
<h2>{{ t("welcome") }}</h2>
<p>{{ t("common.title") }}</p>
</div>
</template>Change lang
<template>
<div>
<p>Current language: {{ lang }}</p>
<button @click="switchLanguage">
Switch language
</button>
</div>
</template>
<script setup>
import { lang } from "../lang";
const switchLanguage = () => {
lang.value = lang.value === "en" ? "zh" : "en";
};
</script>API Reference
createI18n(config, globalLocales?)
Creates an i18n instance with Vue-specific reactivity.
Parameters:
config: Configuration objectlang: () => Lang: Function to get current languagefallbacks?: (curLang, lastLang) => Lang[]: Fallback languages function
globalLocales?: Global translation resources object
Returns: Object with methods:
useLocales(locales?): Composable for translations with local resourcestLocales(locales?): Function for translations without reactivitylang: Reactive computed property for current language (get/set)
useLocales(locales?)
Vue composable for using translations with optional local resources.
Parameters:
locales?: Local translation resources (supports sync/async)
Returns: [t, inited] tuple
t: Translation function (reactive)inited: Ref indicating if all translations are loaded
tLocales(locales?)
Create translator without Vue reactivity (for non-component code).
Parameters:
locales?: Local translation resources (only synchronous)
Returns: Translation function
lang
Reactive computed property for current language.
Get: Returns current language value Set: Updates current language and triggers reactivity
Type Safety
soon-i18n-vue uses SafeLocales type to ensure translation keys exist in all languages. Here are different scenarios:
✅ Case 1: All keys exist in all languages
// Type-safe - all keys exist in both languages
const t = tLocales({
zh: { button: { save: "保存", cancel: "取消" } },
en: { button: { save: "Save", cancel: "Cancel" } }
});
// ✅ This works fine
t("button.save"); // OK
t("button.cancel"); // OK❌ Case 2: Different keys in different languages
// Type error - keys don't match
const t = tLocales({
zh: { button: { save: "保存", cancel: "取消" } },
en: { button: { save: "Save" } } // ❌ Missing cancel in English
});
// ❌ TypeScript will show error
t("button.cancel"); // Type error❌ Case 3: Non-existent key
const t = tLocales({
zh: { button: { save: "保存" } },
en: { button: { save: "Save" } }
});
// ✅ This works
t("button.save"); // OK
// ❌ Type error - key doesn't exist
// t("button.delete"); // Type errorExamples
Check out the example projects:
Documentation
License
MIT
