|
| 1 | +--- |
| 2 | +title: Using MF2 with SvelteKit |
| 3 | +sidebar_title: SvelteKit |
| 4 | +--- |
| 5 | + |
| 6 | +This guide explains how to localize SvelteKit applications using the |
| 7 | +`sveltekit-mf2` library. |
| 8 | + |
| 9 | +This library takes care of locale selection, MF2 parsing, and rendering. Because |
| 10 | +it is based on [`@sveltekit-i18n/base`](https://github.com/sveltekit-i18n/base) |
| 11 | +it supports shipping the minimum amount of translations to the client for each |
| 12 | +route. |
| 13 | + |
| 14 | +## Installation and setup |
| 15 | + |
| 16 | +In an existing SvelteKit project, install the SvelteKit integration package |
| 17 | +together with the MF2 engine, and `@sveltekit-i18n/base`. |
| 18 | + |
| 19 | +```bash |
| 20 | +npm install sveltekit-mf2 @sveltekit-i18n/base |
| 21 | +``` |
| 22 | + |
| 23 | +You can also use a different package manager like `yarn`, `pnpm`, or `deno` to |
| 24 | +install the packages. |
| 25 | + |
| 26 | +## Defining translations and locale manifest |
| 27 | + |
| 28 | +In your application's `lib` folder, create a folder for every locale you want to |
| 29 | +support (e.g., `en`, `es`, `fr`). Inside each locale folder, create JSON files |
| 30 | +for different translation namespaces (e.g., `common.json`, `home.json`). You |
| 31 | +will later load one or more of these files for every route in your application. |
| 32 | + |
| 33 | +You should split your translations into namespaces based on the routes where |
| 34 | +they are used. For example, if you have a homepage and an about page, you might |
| 35 | +create `home.json` and `about.json` files, and a `common.json` file for shared |
| 36 | +translations. |
| 37 | + |
| 38 | +``` |
| 39 | +lib/ |
| 40 | + en/ |
| 41 | + common.json |
| 42 | + home.json |
| 43 | + about.json |
| 44 | + es/ |
| 45 | + common.json |
| 46 | + home.json |
| 47 | + about.json |
| 48 | +``` |
| 49 | + |
| 50 | +```json |
| 51 | +// en/common.json |
| 52 | +{ |
| 53 | + "greeting": "Hello, {#bold}{$name}!{/bold}", |
| 54 | + "farewell": "Goodbye!" |
| 55 | +} |
| 56 | +``` |
| 57 | + |
| 58 | +```json |
| 59 | +// es/common.json |
| 60 | +{ |
| 61 | + "greeting": "¡Hola, {#bold}{$name}!{/bold}", |
| 62 | + "farewell": "¡Adiós!" |
| 63 | +} |
| 64 | +``` |
| 65 | + |
| 66 | +> In the JSON files, every translation string can use MF2 syntax for formatting |
| 67 | +> and interpolation. See the [Quick Start](/docs/quick-start/#basic-syntax) for |
| 68 | +> more details on the syntax. |
| 69 | +
|
| 70 | +Then create a `translations.ts` file in your `lib` folder to configure the i18n |
| 71 | +setup. This file will define the translations available for each locale and |
| 72 | +namespace, and set up the parser for MF2. |
| 73 | + |
| 74 | +```ts |
| 75 | +import i18n from "@sveltekit-i18n/base"; |
| 76 | + |
| 77 | +const config = { |
| 78 | + loaders: [ |
| 79 | + { |
| 80 | + locale: "en", |
| 81 | + key: "common", |
| 82 | + loader: async () => (await import("./en/common.json")).default, |
| 83 | + }, |
| 84 | + { |
| 85 | + locale: "es", |
| 86 | + key: "common", |
| 87 | + loader: async () => (await import("./es/common.json")).default, |
| 88 | + }, |
| 89 | + { |
| 90 | + locale: "en", |
| 91 | + key: "home", |
| 92 | + routes: ["/"], |
| 93 | + loader: async () => (await import("./en/home.json")).default, |
| 94 | + }, |
| 95 | + { |
| 96 | + locale: "es", |
| 97 | + key: "home", |
| 98 | + routes: ["/"], |
| 99 | + loader: async () => (await import("./es/home.json")).default, |
| 100 | + }, |
| 101 | + { |
| 102 | + locale: "en", |
| 103 | + key: "about", |
| 104 | + routes: ["/about"], |
| 105 | + loader: async () => (await import("./en/about.json")).default, |
| 106 | + }, |
| 107 | + { |
| 108 | + locale: "es", |
| 109 | + key: "about", |
| 110 | + routes: ["/about"], |
| 111 | + loader: async () => (await import("./es/about.json")).default, |
| 112 | + }, |
| 113 | + ], |
| 114 | + parser: { |
| 115 | + parse(value: string, [props]: Record<string, any>[], locale: string) { |
| 116 | + return { value, props, locale }; |
| 117 | + }, |
| 118 | + }, |
| 119 | +}; |
| 120 | + |
| 121 | +export const { setLocale, t, locale, locales, loading, loadTranslations } = |
| 122 | + new i18n(config); |
| 123 | +``` |
| 124 | + |
| 125 | +Then configure your root layout (`routes/+layout.js`) to load the translations: |
| 126 | + |
| 127 | +```ts |
| 128 | +import { loadTranslations } from "$lib/translations"; |
| 129 | + |
| 130 | +/** @type {import('@sveltejs/kit').Load} */ |
| 131 | +export const load = async ({ url }) => { |
| 132 | + const { pathname } = url; |
| 133 | + |
| 134 | + const initLocale = "en"; // hard code, or get from cookie, user session, ... |
| 135 | + |
| 136 | + await loadTranslations(initLocale, pathname); // keep this just before the `return` |
| 137 | + |
| 138 | + return {}; |
| 139 | +}; |
| 140 | +``` |
| 141 | + |
| 142 | +Finally, wrap your application in the `FormatterProvider` component in |
| 143 | +`routes/+layout.svelte`: |
| 144 | + |
| 145 | +```svelte |
| 146 | +<script lang="ts"> |
| 147 | + import { FormatterProvider } from "sveltekit-mf2"; |
| 148 | + import { t } from "$lib/translations"; |
| 149 | +
|
| 150 | + let { children } = $props(); |
| 151 | +</script> |
| 152 | +
|
| 153 | +<FormatterProvider {t}> |
| 154 | + <!-- You can put other layout content here, wrapping the {@render children()} --> |
| 155 | + {@render children()} |
| 156 | +</FormatterProvider> |
| 157 | +``` |
| 158 | + |
| 159 | +## Using the Formatter component |
| 160 | + |
| 161 | +You can now use the `<Formatter>` component anywhere in your SvelteKit |
| 162 | +application to render localized and formatted strings. |
| 163 | + |
| 164 | +```svelte |
| 165 | +<script lang="ts"> |
| 166 | + import { Formatter } from "sveltekit-mf2"; |
| 167 | +</script> |
| 168 | +
|
| 169 | +<Formatter id="common.greeting" values={{ name: "SvelteKit" }} /> |
| 170 | +<Formatter id="common.farewell" /> |
| 171 | +``` |
| 172 | + |
| 173 | +You can use the `values` prop to pass variables to the MF2 strings. The `id` |
| 174 | +prop should be in the format `namespace.key`, where `namespace` is the key |
| 175 | +defined in the loader configuration, and `key` is the key in the JSON file. |
| 176 | + |
| 177 | +The `values` prop is optional if your MF2 string does not require any variables. |
| 178 | + |
| 179 | +## Switching locales |
| 180 | + |
| 181 | +You can switch locales by calling the `setLocale` function from your |
| 182 | +`translations.ts` file. For example, you can create buttons to switch between |
| 183 | +English and Spanish: |
| 184 | + |
| 185 | +```svelte |
| 186 | +<script lang="ts"> |
| 187 | + import { setLocale } from "$lib/translations"; |
| 188 | +
|
| 189 | + function switchToEnglish() { |
| 190 | + setLocale("en"); |
| 191 | + } |
| 192 | +
|
| 193 | + function switchToSpanish() { |
| 194 | + setLocale("es"); |
| 195 | + } |
| 196 | +</script> |
| 197 | +
|
| 198 | +<div> |
| 199 | + <button onclick={switchToEnglish}>English</button> |
| 200 | + <button onclick={switchToSpanish}>Spanish</button> |
| 201 | +</div> |
| 202 | +``` |
| 203 | + |
| 204 | +## Further reading |
| 205 | + |
| 206 | +- [@sveltekit-i18n/base documentation](https://github.com/sveltekit-i18n/base) |
| 207 | + |
| 208 | +## Reference docs |
| 209 | + |
| 210 | +This package exports two main components: a provider to set up the i18n context, |
| 211 | +and a formatter component to render localized strings. |
| 212 | + |
| 213 | +### `<FormatterProvider>` |
| 214 | + |
| 215 | +Props: |
| 216 | + |
| 217 | +- `t` - The `t` function from the `i18n` object |
| 218 | + |
| 219 | +### `<Formatter>` |
| 220 | + |
| 221 | +Props: |
| 222 | + |
| 223 | +- `id: string` - Translation key (e.g., "common.greeting") |
| 224 | +- `values?: Record<string, any>` - Variables to interpolate into the message |
0 commit comments