Easy-Lang Uses Chinese Strings as i18n Keys to Kill Variable Naming
Naming translation keys is a persistent tax in front-end i18n that most tooling accepts as inevitable. Easy-Lang removes that tax entirely by treating the base-language string as the canonical key, which also restores full-text search across a codebase and collapses multi-file locale management into a single JSON structure.
Traditional i18n forces developers to name every translatable string, then scatter translations across per-locale JSON files. Easy-Lang flips the model: the Chinese (or any base-language) string becomes the key, so `$t('用户登录')` replaces `t('login.title')`. A single `translation.json` holds all locales under each key, which keeps translations co-located and makes the source code searchable by the original text.
The library ships as a zero-dependency TypeScript tool with optional React bindings via Zustand. It supports variable interpolation, module-scoped translation namespaces, runtime reconfiguration, custom storage backends, and a `context` mechanism for handling the same source string that needs different translations in different UI placements. A companion VS Code extension scans the project, lists untranslated keys, and can one-click translate them via Google Translate or an LLM.
Alang, the creator, built Easy-Lang after finding that existing i18n workflows added too much friction: naming fatigue, lost grep-ability, and multi-file editing overhead. The tool is MIT-licensed and designed to work with Vue, React, Angular, or any vanilla JS/TS project.
Making the base-language string the key is a genuinely under-explored design choice in i18n libraries, and it sidesteps the entire class of problems around naming conventions, key collisions, and developer tooling for translation file navigation.
The single-file translation structure aligns well with AI-assisted workflows: an LLM can see all target languages for a given key at once, and tab-completion editors like Cursor can predict translations from surrounding entries.
The `context` mechanism acknowledges a real-world problem—identical source strings needing different translations in different UI contexts—that most i18n libraries handle poorly or not at all.
Defaulting to a page reload on language switch is a pragmatic trade-off that avoids the complexity of making every closure and constant reactive, and the library documents the escape hatch (hooks + `autoReload: false`) for teams that need it.