Native Shell
Native Shell:AI 生成的 UI,在你的应用中原生呈现,覆盖每个平台。iOS、Android、macOS、Windows 与 Linux 上的应用、GPUI 应用与网页在运行时加载已签名、沙箱隔离的 TSX 模块并绘制 th
AI 翻译
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Svelte 5 & SvelteKit i18n on MessageFormat 2: runes, SSR-safe per-request locale, URL routing, typed keys, npx sv add
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗Svelte 5 i18n on MessageFormat 2, for SvelteKit and for plain Svelte. The locale is a rune instead of a store, and a small CLI types your message keys. In SvelteKit the locale is negotiated on the server for each request, so concurrent visitors never get each other's language, and it can live in the URL (/de/about). Translations load per namespace when a page asks for them, and markup inside a message renders through your own snippets. MF2 is the only message syntax to learn. Changes are in the changelog.
This README covers the minimal setup: URL routing plus cookie persistence, the combination most apps want. For dynamic loading, rich text, locale strategy, typed keys, the CLI and the full API, see the docs site (in English, German and Russian), where every example is live, working code. (Building it locally works too: npm install && npm run dev.)
npm install svelte-dialect
Requires Svelte 5 (svelte@^5). SvelteKit 3 is an optional peer dependency, and the package has an
entry point for each case:
svelte-dialect/kit for SvelteKit apps, which is what the rest of this README uses. Locale
routing, server-side negotiation and %dialect.lang% go through Kit's handle/reroute; this
entry also picks up paths.base and keeps the locale in step with client-side navigation.svelte-dialect for Svelte without Kit: a Vite SPA, Astro islands, a widget. See
Without SvelteKit.Everything below works without any experimental flags.
The locale is a rune, so the package ships uncompiled Svelte and resolves only under the svelte
export condition. Tooling that reads the package without that condition (a Vitest node environment
set up without the Svelte plugin, say) reports the package as unresolvable. That is the honest
error, and adding the plugin (or resolve.conditions: ['svelte']) is the fix. Type-only imports
need nothing.
In a SvelteKit 3 project, the Svelte CLI can do every step of this section for you:
npx sv add svelte-dialect
It asks for your locales and whether the locale goes in the URL, adds the package, writes
src/lib/i18n.ts and a common.json per locale, and wires handle, reroute and app.html. An
existing handle is wrapped in sequence(), and files you already have are left alone. To skip the
prompts, pass the answers inline: npx sv add svelte-dialect=locales:en,de+routing:yes. The rest of
this section is what it writes, for doing it by hand.
Create the dialect once in src/lib/i18n.ts, from your message files, with the locale routed in
the URL and remembered in a cookie between visits:
import { createDialect } from 'svelte-dialect/kit';
export const { t, handle, reroute, localizeHref, locales } = createDialect({
messages: import.meta.glob('./messages/**/*.json', { eager: true }),
defaultLocale: 'en',
locales: ['en', 'ru'],
routing: true
});
The locale lives in a dialect cookie by default (400-day max age). A URL prefix always wins. On an
unprefixed URL the cookie decides, and without one the server negotiates Accept-Language (on a
static site, the browser language), falling back to defaultLocale.
Wire up handle in src/hooks.server.ts, typed the way SvelteKit expects:
import type { Handle } from '@sveltejs/kit/hooks';
import { handle as dialect } from '#lib/i18n.ts';
export const handle: Handle = dialect;
And reroute in a separate, universal src/hooks.ts — this is what strips the locale prefix
so your route files need no [locale] directory:
import type { Reroute } from '@sveltejs/kit/hooks';
import { reroute as dialect } from '#lib/i18n.ts';
export const reroute: Reroute = dialect;
reroute only picks the route; the URL itself keeps its prefix. event.url, a load function's url
and page.url all read /ru/about, exactly what the browser shows. To compare against a route, use
route.id (/about), which never carries the locale. That goes double for access checks in hooks:
/ru/admin renders the same route as /admin, so a guard on event.url.pathname lets it through.
Finally, in src/app.html, add the two attributes handle fills in on every request; everything
else in the file stays as SvelteKit scaffolded it:
<!-- src/app.html -->
<html lang="%dialect.lang%" dir="%dialect.dir%">
<!-- ...unchanged: <head> with %sveltekit.head%, <body> with %sveltekit.body% -->
</html>
%dialect.dir% resolves to ltr or rtl for the locale from Intl, so right-to-left languages
work with no extra configuration.
Link internally with localizeHref, not a bare href — a bare one would drop the locale prefix on
navigation:
<a href={localizeHref('/about')}>About</a>
Messages live under src/lib/messages/<locale>/<namespace>.json, one flat or nested JSON object per
namespace:
src/lib/messages/
en/
common.json
home.json
ru/
common.json
home.json
Keys are looked up as t('namespace:dot.path', params); nested objects flatten into dot paths, e.g.
{ "nav": { "home": "Home" } } → t('common:nav.home'). A message is just MF2, so plurals, dates,
currencies and markup all work with the same one syntax to learn:
<script lang="ts">
import { t } from '#lib/i18n.ts';
let name = $state('Kat');
</script>
<p>{t('home:greeting', { name })}</p>
See the demo's Message files page for plurals and selectors, number/date/currency formatting, custom MF2 functions and how a broken message degrades instead of throwing, and the Loading messages page for fetching namespaces from a database or an API instead of bundling them.
Import from the root entry and skip the hooks and app.html placeholders — there is nothing else to
wire up:
import { createDialect } from 'svelte-dialect';
export const { t, setLocale, getLocale, locales } = createDialect({
messages: import.meta.glob('./messages/**/*.json', { eager: true }),
defaultLocale: 'en'
});
Messages, t, Rich, lazy namespaces and typed keys work exactly as in a Kit app. The locale comes
from the cookie setLocale writes, then the browser language; switching re-renders every t() and
updates <html lang dir>. What needs a server stays Kit-only: locale routing in the URL,
negotiation from Accept-Language, and server-rendered output in the visitor's language.
The docs site is the rest of the documentation — each page is real, working code, not prose about code:
fetchRich componenttypegen / check / migratecreateDialect option, in one tableMIT © Vladimir Kraikovskii