npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

vite-vue-internationalization

v1.1.3

Published

A Vite plugin for typed Vue SFC translations with SFC custom blocks and inline locale chunks

Readme

vite-vue-internationalization

A typed internationalization plugin for Vite that lets Vue SFCs own their translations directly.

VVI is the short name for vite-vue-internationalization.

Documentation

Links

It supports <locale> custom blocks, global dictionaries, Volar type completion, and optional locale-specific chunk output.

VVI targets Vite 8 and newer. Builds run on Vite's Rolldown-based pipeline and require Node.js ^20.19.0 || >=22.12.0.

<template>
  <h1>{{ $locale.sfc.title }}</h1>
  <p>{{ $l.sfc.count({ n }) }}</p>
</template>

<script setup lang="ts">
const n = 3;
</script>

<locale locale="ja-JP" lang="yaml">
title: りんご
count: "{n} 個のりんご"
</locale>

<locale locale="en-US" lang="yaml">
title: Apple
count: "one apple | {n} apples"
</locale>

In <script setup>, injected $locale and $l bindings are computed refs. Use .value in script code, while templates keep the direct $locale.sfc.title / $l.sfc.count({ n }) form:

<script setup lang="ts">
const title = $locale.value.sfc.title;
const countText = $l.value.sfc.count({ n: 3 });
</script>

For component-local messages, prefer a <locale> block or top-level defineInternationalization() in the same SFC. For app-wide messages in SFCs that do not own local messages, configure sfcTransform: "all" instead of adding empty dictionaries just to force injection. Plain .ts modules should use useLocale() / useLocalizer() from virtual:vite-vue-internationalization.

Features

  • Write translations as YAML or JSON in Vue SFC <locale> blocks.
  • Get typed $locale and $l completions in templates and TypeScript.
  • Read app-wide global dictionaries through the same API.
  • Opt into injecting $locale and $l for every SFC when global dictionary access is needed outside locale-owning components.
  • Choose between Vue I18n-compatible syntax (vue) and ICU message syntax (icu).
  • Choose either the default virtual build strategy or inline-chunks for locale-specific output chunks.
  • Share the same configuration between the Vite plugin and Vue Language Tools / Volar.

Minimal Setup

// vite.config.ts
import vue from '@vitejs/plugin-vue';
import { defineConfig } from 'vite';
import { vueInternationalization } from 'vite-vue-internationalization';

export default defineConfig({
  plugins: [
    vueInternationalization(),
    vue(),
  ],
});
// tsconfig.json
{
  "vueCompilerOptions": {
    "plugins": [
      {
        "name": "vite-vue-internationalization/volar",
        "primaryLocale": "ja-JP"
      }
    ]
  }
}

Set sfcTransform: "all" when SFCs without <locale> blocks or defineInternationalization() still need $locale.env or $l.env global dictionary access:

{
  "vueCompilerOptions": {
    "plugins": [
      {
        "name": "vite-vue-internationalization/volar",
        "primaryLocale": "ja-JP",
        "sfcTransform": "all"
      }
    ]
  }
}

Vite transform output keeps global env bindings as broad runtime dictionary types to avoid duplicating large global type literals in every transformed SFC. Vue Language Tools / Volar uses detailed global dictionary types by default for editor completion and vue-tsc; set globalType: "runtime" in the Volar plugin config when the global dictionary is too large for type checking.

// src/env.d.ts
/// <reference types="vite-vue-internationalization/virtual" />
// src/main.ts
import { createApp } from 'vue';
import { createInternationalization } from 'virtual:vite-vue-internationalization';
import App from './App.vue';

const app = createApp(App);
const internationalization = createInternationalization();

app.use(internationalization);
await internationalization.ready;
app.mount('#app');

You may import virtual:vite-vue-internationalization from app .ts modules, not only from Vue SFCs. This is the supported way to share createInternationalization(), currentLocale, primaryLocale, and other generated runtime exports across app code.

Plain TypeScript Modules

Plain .ts modules do not receive implicit $locale or $l bindings. Use useLocale() and useLocalizer() from the virtual module instead:

import { useLocale, useLocalizer } from 'virtual:vite-vue-internationalization';

export function useAppMessages() {
  const $locale = useLocale(import.meta.url);
  const $l = useLocalizer(import.meta.url);

  return {
    appName: () => $locale.value.env.appName,
    greeting: (name: string) => $l.value.env.greeting({ name }),
  };
}

Call these helpers after app.use(createInternationalization()), such as inside Vue setup code or functions called from it. In plain .ts modules, sfc points at the module id passed to useLocale() / useLocalizer(); for app-wide dictionaries, prefer env.

Inline Chunks

The default virtual strategy keeps locale payloads in virtual modules and lets Vite split them with dynamic import() calls.

Use buildStrategy: "inline-chunks" when you want build-time locale-specific JavaScript chunks. This strategy duplicates localizable chunks per locale and replaces static $locale / $l references with locale-specific string literals, accessed subtrees, or message formatting expressions.

// vite.config.ts
export default defineConfig({
  plugins: [
    vueInternationalization({
      primaryLocale: 'ja-JP',
      buildStrategy: 'inline-chunks',
    }),
    vue(),
  ],
});

The generated HTML entry script is replaced with a small *.i18n-loader.js file. Existing script attributes such as nonce, crossorigin, and referrerpolicy are preserved. If the original script has integrity, it is replaced with integrity for the generated loader, and the loader verifies the selected locale chunk with modulepreload and per-locale chunk integrity before importing it.

Static references such as $locale.sfc.title and $l.sfc.count({ n }) are fully inlined. Dynamic subtree lookups such as $locale.env.labels[key] keep a runtime lookup against the resolved locale-specific subtree, but bare locale helper objects are not expanded into full dictionaries. Missing values fall back to the primary locale, then to the key string.

Documentation Pages

Examples

To view the documentation locally:

pnpm docs:dev