Skip to content

wuchalejs/wuchale

Repository files navigation

wuchale logo


npm package build status Start new PR in StackBlitz Codeflow discord chat


📜wuchale🪶

wuchale (pronounced /wʊtʃɑleɪ/ or wuh-'CHAH-lay) is a compile-time internationalization toolkit that requires no code changes. Write your components naturally, and wuchale automatically extracts and replaces translatable messages at build time.

  • No extra syntax! - Your normal code is enough, your codebase stays clean
  • Tiny catalogs to bundle - Text catalogs are just arrays, no keys necessary, like Protobuf
  • Zero-effort integration - Add i18n to existing projects without rewriting code
  • Framework agnostic - Works with React, Preact, Svelte(Kit), SolidJS, Astro, and plain JS/TS
  • Full URLs support - E.g. /about to /de/uber-uns
  • LLM translation support - Configurable integration for automatic on-the-fly translations
  • Full, granular HMR - Live updates during development, including LLM translation
  • Tiny footprint - Very few (less than 5) additional dependencies, no bloated node_modules
  • Smart extraction - Uses AST analysis to handle nested markup, conditionals, loops, and complex interpolations
  • Storage agnostic - Standard PO files by default, storage interface to store translations anywhere

A taste

With traditional i18n:

<p>{t('Hello')}</p>
<p><Trans>Welcome {userName}</Trans></p>

With wuchale:

<p>Hello</p>
<p>Welcome {userName}</p>

No imports, no special components, no annotations. wuchale handles everything at compile time by analyzing your code and automatically extracting translatable strings.

Getting started

See the Getting Started guide for instructions specific to your project type.

How it works

  1. Scans your source code using AST and identify translatable text content
  2. Extracts strings into standard .po translation files (or custom storage) for translators
  3. Compiles catalogs into compact modules which export arrays
  4. Replaces strings with translation function calls that access messages by indices from the arrays

Your original code stays clean and readable, while the build output is automatically internationalized.

Example

Let's say you have:

// src/components/Welcome.jsx
function Welcome({ user }) {
  return (
    <div>
      <p><b>Hello, {user}</b>, and welcome!</p>
      <button>Get started</button>
    </div>
  )
}

The messages are extracted into a .po file. for Spanish for example, after translation, it looks like:

#~ src/components/Welcome.jsx
msgid "<0>Hello, {0}</0>, and welcome!"
msgstr "<0>Hola, {0}</0>, y ¡bienvenido!"

#~ src/components/Welcome.jsx
msgid "Get started"
msgstr "Comenzar"

Then they are compiled into a compact form optimized for loading (just an array):

export let c = [[[0, "Hola, ", 0], ", y ¡bienvenido!"], "Comenzar"]

And your code is transformed into a version that accesses them by index:

// src/components/Welcome.jsx
import W_tx_ from "@wuchale/jsx/runtime.jsx"

function Welcome({ user }) {
  const _w_runtime_ = _w_load_rx_();
  return (
    <div>
      <p><W_tx_ t={[_w_ctx_ => <b key="_0"><W_tx_ x={_w_ctx_} n a={[user]} /></b>]} x={_w_runtime_.c(0)} /></p>
      <button>{_w_runtime_(1)}</button>
    </div>
  )
}

Notice the automatic handling of the nested <b>, that's wuchale's full supported for indefinite nesting at play. You can nest as deep as you want, and it still makes it work for i18n. That gives the translator freedom to even reorder placeholders and it gets rendered accordingly.

Check out full working examples for different setups at wuchalejs/examples to see wuchale in action with different frameworks.

Repository structure

This is a monorepo that houses these packages:

Package Description Latest
wuchale Core + CLI + Vanilla adapter wuchale
@wuchale/jsx JSX adapter (for React and SolidJS) @wuchale/jsx
@wuchale/svelte Svelte adapter @wuchale/svelte
@wuchale/astro Astro adapter @wuchale/astro
@wuchale/json JSON storage @wuchale/json

Contributing

Contributions are welcome! Please check out the test suites located inside each package for examples of supported scenarios.

Note: The tests are also written in TypeScript and therefore you should have Node 22+ to run them.

Sponsors

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

Sponsor on GitHub

Sponsors:

mightygroup

Special thanks to our supporters:

hayzamjs p-mercury perdix ZerGo0

And one private donor 🙏.

License

MIT

About

Compile-time i18n toolkit that requires zero code changes and produces the smallest possible bundles. Supports React, Svelte, SolidJS, Astro, and more

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

 

Contributors