跪拜 Guibai
← All articles
Frontend · JavaScript · Frontend Framework

Easy-Lang Uses Chinese Strings as i18n Keys to Kill Variable Naming

By Alang ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

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.

Summary

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.

Takeaways
Source-language strings serve directly as translation keys, so `$t('用户登录')` replaces `t('login.title')`.
A single `translation.json` file holds all locales under each key, keeping translations co-located instead of split across per-language files.
TypeScript integration flags untranslated keys at compile time, and `i18n.untranslatedList` collects them at runtime for batch AI translation.
Module-scoped translation namespaces (`$module('billing')`) prevent key collisions in large projects without requiring nested JSON structures.
A `context` option (`$t('模型管理', { context: 'sidebar' })`) handles the same source string needing different translations in different UI placements.
The companion VS Code extension scans the project for translation usage, displays a translated/untranslated list, and offers one-click translation via Google Translate or an LLM.
Runtime `configure()` allows changing the default language, toggling auto-reload, or switching the storage key without rebuilding the i18n instance.
Custom storage backends (e.g., reading the locale from a query parameter or cookie bridge) are supported through a `storage.getLang`/`setLang` interface.
React integration uses Zustand for state; switching languages defaults to a page reload, but setting `autoReload: false` enables reactive re-renders via hooks.
The library is framework-agnostic, dependency-free (except Zustand for React), and MIT-licensed.
Conclusions

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.

Concepts & terms
Source-string-as-key i18n
An internationalization pattern where the text in the base language (e.g., Chinese) is used directly as the lookup key in a translation map, rather than requiring an abstract key like `login.title`.
Translation context
A discriminator passed alongside a translation key to select a different target string when the same source text needs distinct translations in different UI placements (e.g., a sidebar label vs. a page heading).
Module-scoped translation
A namespace mechanism that partitions translation keys by feature module, preventing collisions and allowing different translations for the same source string in different parts of a large application.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗