soon-i18n-solid
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-solid v2.0
Solid adapter for soon-i18n, providing signal-based i18n integration with full TypeScript support and fine-grained reactivity.
Full Document
Install
npm install soon-i18n-solidFull Example
Solid Demo or
npx degit https://github.com/leafio/soon-i18n/examples/solid-demoInstance Usage
Create an instance
// lang/index.ts
import { createI18n } from "soon-i18n-solid";
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, setLang } = 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
import { Show } from "solid-js";
import { useLocales } from "../lang";
function Content() {
const [t, inited] = useLocales({
zh: { hello: "你好" },
en: { hello: "Hello" }
});
return (
<Show when={inited} fallback={<div>Loading...</div>}>
<div>
<h1>{t("common.title")}</h1>
<p>{t("hello")}</p>
<p>{t("g_welcome", { name: "张三" })}</p>
</div>
</Show>
);
}Lazy Loading
import { Show } from "solid-js";
import { useLocales } from "../lang";
function LazyComponent() {
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
});
return (
<Show when={inited} fallback={<div>Loading translations...</div>}>
<div>
<h2>{t("welcome")}</h2>
<p>{t("common.title")}</p>
</div>
</Show>
);
}Change lang
import { lang, setLang } from "../lang";
function SwitchLang() {
return (
<div>
<p>Current language: {lang()}</p>
<button onClick={() => setLang(lang() === "en" ? "zh" : "en")}>
Switch language
</button>
</div>
);
}API Reference
createI18n(config, globalLocales?)
Creates an i18n instance with Solid-specific signals.
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?): Hook for translations with local resourcestLocales(locales?): Function for translations without signalslang: Signal getter for current languagesetLang(lang): Function to set current language
useLocales(locales?)
Solid hook for using translations with optional local resources.
Parameters:
locales?: Local translation resources (supports sync/async)
Returns: [t, inited] tuple
t: Translation function (reactive signal)inited: Signal indicating if all translations are loaded
tLocales(locales?)
Create translator without Solid signals (for non-component code).
Parameters:
locales?: Local translation resources (only synchronous)
Returns: Translation function
lang()
Get current language value (reactive).
setLang(lang)
Set current language value.
Parameters:
lang: New language value
Type Safety
soon-i18n-solid 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
