# i18n

Enable internationalization in the SvelteKit project.

### Syntax

```
$ vela enable i18n
```

This sets up [Wuchale](https://wuchale.dev) with locale-aware routing. Translatable strings are extracted from the source rather than written into message files by hand, so no keys are maintained separately from the markup.

Has no dependencies — it works with or without a backend, and composes with [content negotiation](/enable/content-negotiation)'s reroute hook.

### What you get

- `wuchale.config.js`, with the locales `en` and `es`. English is the source locale and keeps the unprefixed URLs; Spanish is served under `/es`.
- A `reroute` hook in `src/hooks.ts` that maps localized URLs back to their routes, and the URL helpers it uses in `src/lib/url.ts`. The file is created if the project has none; otherwise the hook is composed with the existing `reroute`.
- A language select in `src/lib/components/language-select.svelte`, added to the root layout.
- A handle in `src/hooks.server.ts` that loads the catalogs on the server and renders each request in its locale. The file is created if the project has none; otherwise the handle is composed with the existing `handle`.
- A `load` in `src/routes/+layout.ts` that loads the locale's catalog in the browser. It is added to a file that has route options of its own; a file that already has a `load` is left alone, with a note on what to merge.
- `lang="%sveltekit.lang%"` on the `<html>` tag in `src/app.html`, which the handle fills in with the locale.
- The Wuchale plugin in the Vite config, and a `$locales` alias for `src/locales`, where the catalogs live. The alias goes in `svelte.config.js`, or in the `sveltekit()` options if the Vite config sets them there.
- The `wuchale` and `@wuchale/svelte` packages, and the `select` component in a project with shadcn-svelte.
- A `.gitignore` entry for `src/locales/.wuchale`.

In a project with shadcn-svelte, the language select is a shadcn `Select`, added as the last item of the navbar in the root layout. Without shadcn-svelte, as in a project from `sv create`, it's a native `<select>` placed above `{@render children()}` in `src/routes/+layout.svelte`.

If `src/routes/+page.svelte` is still the `sv create` welcome page, the command also writes its Spanish translation to `src/locales/es.po`, so switching language visibly changes the page. Any other copy is yours to translate.

A file the command can't safely edit is left as it is, and the change to make is printed instead. The common case is a `src/routes/+layout.ts` that already has a `load`, as the `static` template's does: merge the printed loader into it by hand.

### Working with translations

Once enabled, the [`vela i18n`](/i18n) commands manage the catalogs:

- [`vela i18n extract`](/i18n/extract) - Extract translatable strings
- [`vela i18n watch`](/i18n/watch) - Extract on change
- [`vela i18n status`](/i18n/status) - Show what is translated
- [`vela i18n clean`](/i18n/clean) - Drop strings no longer used

### Reverting

[`vela disable i18n`](/disable/i18n) removes the generated files and undoes the changes above. Your catalogs in `src/locales` are kept.