Compile-time i18n. Zero code changes. Smallest bundles.

4 min read Original article ↗

Write plain code

Without any need to do anything different:

Transform

Update your code to access the translations by index

Render

Load the desired compiled catalog, and hand it to your framework

Works with your stack!

React Logo

React

Preact Logo

Preact

SolidJS Logo

SolidJS

Svelte Logo

Svelte

Astro Logo

Astro

JavaScript Logo

JavaScript

TypeScript Logo

TypeScript

Python* Logo

Python*

Golang* Logo

Golang*

'use client'

export function Greeting({ username }) {

return (

<div>

<p>Hello!</p>

<p title="Welcome" class="para">

Welcome {username}!

</p>

</div>

)

}

'use client'

import { getRuntimeRx as useW_load_rx_, getRuntime as _w_load_ } from "./main.loader.js"

import W_tx_ from "@wuchale/jsx/runtime.jsx"

export function Greeting({ username }) {

const _w_runtime_ = useW_load_rx_('main')

return (

<div>

<p>{_w_runtime_(0)}</p>

<p title={_w_runtime_(1)} class="para">

<W_tx_ x={_w_runtime_.c(2)} a={[username]} />

</p>

</div>

)

}

// comment

export function Greeting({ username }) {

return (

<div>

<p>Hello!</p>

<p title="Welcome" class="para">

Welcome {username}!

</p>

</div>

)

}

// comment

import { getRuntimeRx as useW_load_rx_, getRuntime as _w_load_ } from "./main.loader.js"

import W_tx_ from "@wuchale/jsx/runtime.jsx"

export function Greeting({ username }) {

const _w_runtime_ = useW_load_rx_('main')

return (

<div>

<p>{_w_runtime_(0)}</p>

<p title={_w_runtime_(1)} class="para">

<W_tx_ x={_w_runtime_.c(2)} a={[username]} />

</p>

</div>

)

}

// comment

export function Greeting({ username }) {

return (

<div>

<p>Hello!</p>

<p title="Welcome" class="para">

Welcome {username}!

</p>

</div>

)

}

// comment

import { getRuntimeRx as useW_load_rx_, getRuntime as _w_load_ } from "./main.loader.js"

import W_tx_ from "@wuchale/jsx/runtime.solid.jsx"

const _w_runtime_ = () => useW_load_rx_('main')

export function Greeting({ username }) {

return (

<div>

<p>{_w_runtime_()(0)}</p>

<p title={_w_runtime_()(1)} class="para">

<W_tx_ x={_w_runtime_().c(2)} a={[username]} />

</p>

</div>

)

}

<script>

const { username } = $props()

</script>

<div>

<p>Hello!</p>

<p title="Welcome" class="para">

Welcome {username}!

</p>

</div>

<script>

import { getRuntimeRx as _w_load_rx_, getRuntime as _w_load_ } from "./main.loader.svelte.js"

import W_tx_ from "@wuchale/svelte/runtime.svelte"

const _w_runtime_ = $derived(_w_load_rx_('main'))

const { username } = $props()

</script>

<div>

<p>{_w_runtime_(0)}</p>

<p title={_w_runtime_(1)} class="para">

<W_tx_ x={_w_runtime_.c(2)} a={[username]} />

</p>

</div>

---

const { username } = Astro.props

---

<div>

<p>Hello!</p>

<p title="Welcome" class="para">

Welcome {username}!

</p>

</div>

---

import {getRuntime as _w_load_, getRuntimeRx as _w_load_rx_} from "./main.loader.js"

import _w_Tx_ from "@wuchale/astro/runtime.js"

const _w_runtime_ = _w_load_('astro')

const { username } = Astro.props

---

<div>

<p>{_w_runtime_(0)}</p>

<p title={_w_runtime_(1)} class="para">

{_w_Tx_({ x: _w_runtime_.c(2), a: [username] })}

</p>

</div>

// comment

export function Greeting(props) {

return {

greeting: `Hello`,

title: 'Welcome',

message: `Welcome ${props.username}!`,

}

}

import { getRuntime as _w_load_ } from "./main.loader.js"

// comment

export function Greeting(props) {

const _w_runtime_ = _w_load_('main')

return {

greeting: _w_runtime_(0),

title: _w_runtime_(1),

message: _w_runtime_(2, [props.username]),

}

}

// comment

export function Greeting(props: { username: string }) {

return {

greeting: `Hello`,

title: 'Welcome',

message: `Welcome ${props.username}!`,

}

}

import { getRuntime as _w_load_ } from "./main.loader.js"

// comment

export function Greeting(props: { username: string }) {

const _w_runtime_ = _w_load_('main')

return {

greeting: _w_runtime_(0),

title: _w_runtime_(1),

message: _w_runtime_(2, [props.username]),

}

}

msgid "Hello!"

msgstr "Hello!"

msgid "Welcome"

msgstr "Welcome"

msgid "Welcome {0}!"

msgstr "Welcome {0}!"

export let c = [

'Hello!',

'Welcome',

[ 'Welcome ', 0, '!' ],

]

Smallest Bundles

Instead of key-value pairs, compilation produces arrays accessed by indices.

Unmatched DX

HMR + optional AI translation for real-time development feedback.

Flexible catalog loading

You decide how the catalog is loaded: Async, Bundled, or custom.

Format agnostic

The default storage is Gettext PO files, widely supported and familiar to translators. But you can use anything else.

Explore more

Used by projects

Blitz Blitz In-game overlays, meta stats, and tier lists for games like League of Legends, VALORANT, and more AlchemillaHQ/Sylve AlchemillaHQ/Sylve Lightweight GUI for managing Bhyve, Jails, ZFS, networking, and more on FreeBSD Nook Nook Run local AI models in your browser for chat, audio transcription, text to speech and background removal CIGALE CIGALE Intelligent Classification and Management of Arthropods and Entomofauna SimAdvisor SimAdvisor Travel eSIM comparison Payqual Payqual A tool for the European payment transparency directive. Svelte-MiniApps Svelte-MiniApps A SvelteKit Progressive Web App containing multiple single-purpose productivity mini-apps Prikkert Prikkert An open-source app for scheduling group events. Always free, no ads. Hopbox Hopbox Run Networks on Autopilot

Do you also use it in your project? Let us know!

Companion tooling

  • vite-plugin-lingo: A Vite plugin that provides a visual editor for .po (Gettext) translation files

Support

This project is supported by the community. Become a sponsor and get your name or logo listed on the README and here on the website!

Sponsor on GitHub

Sponsors
Special thanks to our backers

And one private donor 🙏

Inspiration

This project was inspired by Lingui especially some of its workflow. If you’ve used Lingui before, you’ll find familiar concepts like extraction and compilation.

Where wuchale differs, among other things, is that you don’t need to change your code, catalogs compile smaller than any other tool (including Lingui’s), and it integrates with a wider range of frameworks.