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

@vasakgroup/tauri-plugin-i18n

v2.3.0

Published

Tauri internationalization using rust_i18n

Readme

Tauri Plugin i18n (A simple wrapper around rust_i18n)

this project is a one fork of tauri-plugin-i18n

This plugin does not support macros from rust_i18n.

rust_i18n is only used for parsing the locales.

i18n usage

| Platform | Supported | | -------- | --------- | | Linux | ✓ | | Windows | ✓ | | macOS | ✓ | | Android | Untested | | iOS | Untested |

Install

This plugin requires a Rust version of at least 1.77.2

Install the Core plugin by adding the following to your Cargo.toml file:

src-tauri/Cargo.toml

# Point this to your fork's repository and branch/tag/rev
# Example using a GitHub repo:
[dependencies.tauri-plugin-i18n-vsk]
git = "https://github.com/VasakOS/tauri-plugin-i18n"

# Or use a local path if developing locally:
# path = "../path/to/your/fork/tauri-plugin-i18n"

The package can also be installed by using cargo:

cargo add tauri-plugin-i18n-vsk

You can install the JavaScript Guest bindings using your preferred JavaScript package manager:

Install the JavaScript bindings using your preferred package manager:

# Using bun 
bun add @vasakgroup/tauri-plugin-i18n

# Using pnpm
pnpm add @vasakgroup/tauri-plugin-i18n

# Using npm
npm install @vasakgroup/tauri-plugin-i18n

# Using yarn
yarn add @vasakgroup/tauri-plugin-i18n

Locale file [rust_i18n implementation]

You can use _version key to specify the version (This version is the locale file version, not the rust-i18n version) of the locale file, and the default value is 1.

rust-i18n supports two style of config file, and those versions will always be keeping.

  • _version: 1 - Split each locale into difference files, it is useful when your project wants to split to translate work.
  • _version: 2 - Put all localized text into same file, it is easy to translate quickly by AI (e.g.: GitHub Copilot). When you write original text, just press Enter key, then AI will suggest you the translation text for other languages.

You can choose as you like.

Split Localized Texts into Difference Files

_version: 1

You can also split the each language into difference files, and you can choose (YAML, JSON, TOML), for example: en.json:

.
├── Cargo.lock
├── Cargo.toml
├── locales
│   ├── zh-CN.yml
│   ├── en.yml
└── src
│   └── main.rs
_version: 1
hello: 'Hello world'
mello: 'Mello world'

Or use JSON or TOML format, just rename the file to en.json or en.toml, and the content is like this:

{
  "_version": 1,
  "hello": "Hello world",
  "mello": "Mello world"
}
hello = "Hello world"
mello = "Mello world"

All Localized Texts in One File

_version: 2

Make sure all localized files (containing the localized mappings) are located in the locales/ folder of the project root directory:

.
├── Cargo.lock
├── Cargo.toml
├── locales
│   ├── app.yml
│   ├── some-module.yml
└── src
│   └── main.rs
└── sub_app
│   └── locales
│   │   └── app.yml
│   └── src
│   │   └── main.rs
│   └── Cargo.toml

In the localized files, specify the localization keys and their corresponding values, for example, in app.yml:

_version: 2
hello:
  en: Hello world
  zh-CN: 你好世界

This is useful when you use GitHub Copilot, after you write a first translated text, then Copilot will auto generate other locale's translations for you.

Usage

First you need to register the core plugin with Tauri:

The init method takes two args:

  • The location of the locales dir
  • Default locale (eg: "en")

src-tauri/src/lib.rs

fn main() {
    tauri::Builder::default()
        .plugin(tauri_plugin_i18n::init(None))
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

Afterwards all the plugin's APIs are available through the JavaScript guest bindings and also via tauri::AppHandle:

JS

import I18n from '@vasakgroup/tauri-plugin-i18n';

// Load translations
await I18n.getInstance().load();

// Example
//Get available locales
const locales = await I18n.getAvailableLocales();
console.log('Locales:', locales);

Rust

#[tauri::command]
fn get_locales(app: tauri::AppHandle)-> Vec<String> {
  app.i18n().available_locales()
}

Updating the locale

JS

import I18n from '@vasakgroup/tauri-plugin-i18n';

// Example
// Set the locale
await I18n.setLocale('en');

Rust

#[tauri::command]
fn update_locale(app: tauri::AppHandle, locale: &str) {
  app.i18n().set_locale(locale);
}

Using the locale

Note: The i18n class must be instantiated in order to translate in javascript.

JS

// In javascript, it uses the [data-i18n] attribute to remain framework agnostic

import I18n from '@vasakgroup/tauri-plugin-i18n';

// Load translations
await I18n.getInstance().load();

// Example
// Use a translation
<p data-i18n="hello"> </p>;

Rust

  let translated: Option<&str> = app.i18n().translate("hello");

Call the destroy method in javascript when done to cleanup.

See the examples folder for a working app.


Vue: useI18n()

The composable reads the same state as the I18n class — it does not keep a copy. Loading through either one fills both, so the recommended startup is to load once before mounting and let every component just read:

// main.ts
import I18n from '@vasakgroup/tauri-plugin-i18n';

// One load for the whole app. Every `useI18n()` below sees it already done.
await I18n.getInstance().load();

app.mount('#app');
<script setup>
import { useI18n } from '@vasakgroup/tauri-plugin-i18n'

const { t, locale, setLocale, availableLocales, isLoaded, reload } = useI18n()
</script>

<template>
  <p>{{ t('views.home.title') }}</p>
</template>

load() is safe to call from anywhere and as often as you like: the first call does the work and the rest await that same one. If a component mounts before anything loaded, its onMounted loads for everyone. Use reload() only to re-read the catalogs after the files on disk changed.

Before 2.3.0 the composable kept its own state, so await I18n.getInstance().load() before mounting did not give the components anything: the window showed raw keys (views.home.title) until each component loaded again on its own. Upgrading fixes that without any change in the app.

Watching the state from outside Vue

const i18n = I18n.getInstance();

const unsubscribe = i18n.subscribe(() => {
  console.log(i18n.currentLocale, i18n.catalogs);
});

subscribe() fires when the catalogs or the locale change and returns the function to unsubscribe. catalogs and currentLocale read the state at any moment, which is what lets a late subscriber catch up.

Companion package

Use package rust-i18n-autotranslate to autotranslate locales from a source locale.

Use .taurignore to prevent looping while running build.

This is because tauri tracks all files in the project unless explicitly ignored.

It can be used both at compile time and runtime

Compile time

  //build.rs

  use rust_i18n_autotranslate::{
    TranslationAPI,
    config::{Config, TranslationProvider},
};


  fn main() {

    //run translations
    let target_locales = [
        "es", "zh-CN", "zh-TW", "hi", "ar", "fr", "pt-BR", "de", "ru", "ja", "ko", "it", "tr",
        "id", "vi",
    ];

    let cfg = Config::new()
        .locales_directory("./locales")
        .source_lang("en")
        .add_target_langs(target_locales.to_vec())
        .use_cache(true)
        .translation_provider(TranslationProvider::DEEPL)
        .build();

    TranslationAPI::translate(cfg).unwrap();

    tauri_build::build();
}