Skip to content
Development
Skill

/web-i18n-vue-i18n

Type-safe i18n for Vue 3 Composition API — useI18n, pipe-syntax plurals, i18n-t/d/n components, lazy-loaded locales. Load when a project imports vue-i18n.

From plugin
agents-inc-skills
24200 skills
Install
$ npx -y skills add agents-inc/skills --skill web-i18n-vue-i18n --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/web-i18n-vue-i18n

Context preview

The summary Claude sees to decide when to auto-load this skill.

Type-safe i18n for Vue 3 Composition API — useI18n, pipe-syntax plurals, i18n-t/d/n components, lazy-loaded locales. Load when a project imports vue-i18n.

SKILL.md

web-i18n-vue-i18n.SKILL.md
name: web-i18n-vue-i18n
description: Type-safe i18n for Vue 3 Composition API — useI18n, pipe-syntax plurals, i18n-t/d/n components, lazy-loaded locales. Load when a project imports vue-i18n.

vue-i18n Internationalization Patterns

> **Quick Guide:** `createI18n({ legacy: false })` selects Composition API mode, and `useI18n()` > returns `t` for messages, `d` for dates, `n` for numbers and `locale` as a writable ref. Plurals > are pipe-separated rather than ICU. `<i18n-t>`, `<i18n-d>` and `<i18n-n>` put components and > styling inside a formatted result. Version boundary: Legacy API mode, the `v-t` directive and the > Rails `%{var}` format are deprecated in v11 and removed in v12; `$tc()` is already gone.

**Detailed Resources:**

  • [examples/core.md](examples/core.md) — setup, useI18n, interpolation, linked messages, plurals, `<i18n-t>`/`<i18n-d>`, types, locale switching
  • [examples/formatting.md](examples/formatting.md) — datetime and number format configuration, `<i18n-d>`/`<i18n-n>` scoped slots, dynamic currency
  • [examples/lazy-loading.md](examples/lazy-loading.md) — dynamic imports, loading before render, feature splitting, retry and fallback, SSR-safe detection
  • [reference.md](reference.md) — decision trees, anti-pattern code, checklists, plural-rule tables, v8→v9 migration and v11/v12 removals

---

Which path applies

  • **Messages shared across the app** — global scope, the default. `useI18n()` reads the instance

created by `createI18n`. Follow [examples/core.md](examples/core.md).

  • **Messages belonging to one component** — local scope, `useI18n({ messages: { en: { ... } } })`.

Linked messages (`@:key`) resolve against global messages only, so a locally-scoped message cannot reference one.

  • **Locales loaded on demand rather than bundled** — `setLocaleMessage` after a dynamic import, and

the locale is not switched until the import resolves. Follow [examples/lazy-loading.md](examples/lazy-loading.md).

---

<critical_requirements>

Before writing vue-i18n code

**Set `legacy: false` in `createI18n`.** It is what enables `useI18n()`; the default is the Options API mode that v11 deprecates and v12 removes.

**Take everything from one `useI18n()` call per component.** Destructure `t`, `d`, `n` and `locale` together — separate calls can resolve to separate composer instances that then disagree about the current locale.

**Await the message load before assigning `locale.value`.** Switching first renders the raw keys until the import resolves.

**Set `fallbackLocale`.** Without it a key missing from the active locale renders as the key rather than as the default locale's text.

</critical_requirements>

---

**Auto-detection:** vue-i18n, useI18n, createI18n, legacy: false, setLocaleMessage, i18n-t, i18n-d, i18n-n, keypath, pluralRules, datetimeFormats, numberFormats, fallbackLocale, globalInjection

**Applies to:**

  • Message rendering with named interpolation, linked messages and pipe-syntax pluralization
  • Locale-aware date and number formatting through named format definitions
  • Putting components or per-part styling inside a formatted result
  • Loading and swapping locale message sets at runtime
  • Typing message keys and format names so a wrong one fails at compile time

**Handled elsewhere:**

  • Locale-aware routing — this skill settles loading messages before a view renders, not how URLs map

to locales; the hook shape is in [examples/lazy-loading.md](examples/lazy-loading.md)

  • Component authoring and reactivity — `locale` is an ordinary ref and needs nothing special
  • Where the preferred locale is stored and how it is detected — this skill consumes a locale code
  • Bundling and build configuration, beyond the message pre-compilation options in

[reference.md](reference.md)

---

<philosophy>

Messages are plain JSON resolved through a reactive locale ref, so a locale change re-renders every component that read a message — no subscription, no invalidation step. Two consequences shape the API. Because the composer holds that ref, one component wants one composer, which is why repeated `useI18n()` calls are the recurring bug. And because `t()` returns a string rather than a VNode, anything needing markup inside a translation goes through `<i18n-t>` instead — which is also what keeps `v-html` out of translated content.

</philosophy>

---

<patterns>

Core patterns

Pattern 1: Project setup

One instance, registered once on the app.

export const i18n = createI18n({
  legacy: false, // enables useI18n()
  locale: DEFAULT_LOCALE,
  fallbackLocale: DEFAULT_LOCALE,
  messages: { en },
});

app.use(i18n);

`globalInjection` defaults to `true`, which is what puts `$t`, `$d` and `$n` in templates.

Full code: [examples/core.md](examples/core.md)

Pattern 2: useI18n

One call, everything destructured from it.

<script setup lang="ts">
const { t, d, n, locale, availableLocales } = useI18n();
</script>

<template>
  <h1>{{ t("dashboard.title") }}</h1>
  <p>{{ d(updatedAt, "long") }} · {{ n(total, "currency") }}</p>
</template>

Full code: [examples/core.md](examples/core.md)

Pattern 3: Interpolation and linked messages

Named placeholders, `{'@'}` to escape a literal, and `@:key` to reference another message with an optional case modifier.

{
  "app": { "name": "My App" },
  "greeting": "Hello, {name}!",
  "welcome": "Welcome to @:app.name!",
  "shout": "@.upper:app.name"
}

Full code: [examples/core.md](examples/core.md)

Pattern 4: Pluralization

Pipe-separated forms rather than ICU. `{n}` and `{count}` both resolve to the value passed as the second argument.

{
  "car": "car | cars",
  "apple": "no apples | one apple | {count} apples"
}

Languages needing more than three forms take a `pluralRules` function per locale, which returns the index of the form to use.

Full code: [examples/core.md](examples/core.md)

Pattern 5: Component interpolation

`<i18n-t>` puts components into a mes

Read more
Ships withagents-inc-skills

The official skills marketplace for Agents Inc. 150+ skills covering everything from React and Prisma to Redis, ElevenLabs, and infrastructure tooling. Pick the skills that match your stack and install them via Claude Code. Need more control?

Get the whole plugin

Other skills on agents-inc-skills.