Framework

Svelte

El paquete oficial de Svelte 5 para Verbaly. Stores idiomáticos sobre el mismo core reactivo, factories de stores para uso a nivel app, y un componente <Trans> para rich text.

Qué puedes lograr:

Instalación

Instala el paquete con tu gestor de paquetes preferido.

 pnpm add @verbaly/svelte

Setup y stores

+layout.svelte · Inbox.svelte
<script>
  // root component / layout:
  import { provideVerbaly } from '@verbaly/svelte';
  import { verbaly } from 'virtual:verbaly';
  provideVerbaly(verbaly);
</script>

<script>
  // any child component:
  import { useT, useLocale } from '@verbaly/svelte';
  const t = useT();
  const locale = useLocale();  // writable store
</script>

<p>{$t('inbox', { count: 3 })}</p>
<select bind:value={$locale}>…</select>

Escribe el texto en su lugar

Desde 0.20.0 el compilador también lee tus archivos .svelte: escribe el texto fuente con el tag del store, en el markup o en el script, y se extrae, recibe su clave y sus tipos al guardar. Sin inventar claves, sin tocar catálogos.

Inbox.svelte
<h1>{$t`Hola ${name}, tienes ${count} mensajes`}</h1>

<!-- extracted on save; the build rewrites it to: -->
<h1>{$t('x7Ka9q2f', { name, count })}</h1>

¿Prefieres claves legibles? $t.id('inbox.title') antes del template extrae bajo tu id en vez de un hash del contenido.

Rich text con <Trans>

Desde 0.10.0 Svelte también tiene componente real: impórtalo del subpath Trans.svelte (componente crudo, lo compila tu bundler):

Title.svelte
<script>
  import Trans from '@verbaly/svelte/Trans.svelte';
  import DocsLink from './DocsLink.svelte';
</script>

<Trans id='home.title' />
<Trans id='greet' values={{ name: 'Aron' }} />

<!-- message: 'Read the <docs>guide</docs>' → your component wraps the tag content -->
<Trans id='cta' components={{ docs: DocsLink }} />

SvelteKit

Las páginas renderizadas en el servidor llegan ya traducidas al idioma del visitante, y el cliente hidrata con el mismo locale y el mismo catálogo, sin flash de texto sin traducir ni mismatch de hidratación.

SvelteKit necesita el paquete de SSR (@verbaly/sveltekit) junto a los bindings de Svelte:

 pnpm add verbaly @verbaly/sveltekit @verbaly/svelte @verbaly/vite

Conéctalo

Tres cables en el servidor, uno en el cliente. Primero el plugin de Vite y el placeholder de lang:

vite.config.ts · src/app.html
// vite.config.ts
import { sveltekit } from '@sveltejs/kit/vite';
import verbaly from '@verbaly/vite';

export default { plugins: [verbaly(), sveltekit()] };

<!-- src/app.html -->
<html lang="%verbaly.lang%">

El hook del servidor resuelve el locale por request (cookie, luego Accept-Language, luego tu fallback) y rellena el placeholder:

src/hooks.server.ts · src/app.d.ts
// src/hooks.server.ts
import { verbalyHandle } from '@verbaly/sveltekit';
import { locales } from 'virtual:verbaly';

export const handle = verbalyHandle({ locales });

// src/app.d.ts
declare namespace App {
  interface Locals { verbalyLocale: string }
}

Pásale el locale al cliente y construye una instancia por render con el catálogo esperado, la garantía sin flash:

src/routes/+layout.server.ts · +layout.ts · +layout.svelte
// +layout.server.ts
export const load = ({ locals }) => ({ locale: locals.verbalyLocale });

// +layout.ts
import { createRequestInstance } from 'virtual:verbaly';

export const load = async ({ data }) => ({
  ...data,
  verbaly: await createRequestInstance(data.locale),  // catalog ready BEFORE render
});

<!-- +layout.svelte -->
<script>
  import { provideVerbaly } from '@verbaly/svelte';
  let { data, children } = $props();
  provideVerbaly(data.verbaly);
</script>

{@render children()}

De aquí en adelante es @verbaly/svelte normal: los stores useT() / useLocale() y Trans.svelte funcionan sin cambios en cada componente.

Cambiar de idioma

switchLocale carga el catálogo primero, cambia en vivo y escribe la cookie que el hook del servidor lee, así el próximo request SSR ya coincide:

LangPicker.svelte
<script>
  import { switchLocale } from '@verbaly/sveltekit';
  import { useVerbaly } from '@verbaly/svelte';

  const verbaly = useVerbaly();
</script>

<button onclick={() => switchLocale(verbaly, 'es')}>Español</button>
Copiado en el portapapeles