# i18n

This page covers defining locales, referencing translations in text and attributes, and switching languages.

## Defining Locales

```html
<div id="app">
  <h1>{{ i18n.title }}</h1>
  <input placeholder="i18n.search" />
  <button @click="toEn">English</button>
</div>

<script>
  const app = new QUI({
    id: "app",
    i18n: {
      zh: { title: "歡迎", search: "搜尋" },
      en: "/i18n/en.json",
    },
    i18nLang: "zh",
    event: {
      toEn: () => app.lang("en"),
    },
  });
</script>
```

| Option | Description |
|---|---|
| `i18n` | Maps a locale code to an object, or to the URL of a JSON file |
| `i18nLang` | Initial locale, defaults to `"zh"` |

String values are fetched before the initial render; when loading fails or the response is not 2xx, that locale becomes an empty object and rendering continues.

## Referencing Translations

| Location | Syntax | Key rules | When missing |
|---|---|---|---|
| Text | `{{ i18n.menu.home }}` | Nested keys with `.` | Shows the key itself (`menu.home`) |
| Attribute value | `placeholder="i18n.search"` | Single-level keys only | Keeps the original string `i18n.search` |

The attribute value must be exactly `i18n.key` with no other text mixed in.

## Switching Languages

`app.lang(code)` updates the current locale and triggers a re-render; it does nothing when `code` is not in `i18n`. Instances created with `once: true` have non-reactive data, so switching does not re-render.

## Reserved Keys

Locale data lives in `app.data.quickui_i18n` and the current locale in `app.data.quickui_i18nLang`. Do not use these two names in your own `data`.
