i18next-pseudo
A pseudolocalization post-processor for i18next that stretches and re-letters strings to surface UI and translation bugs before real translations arrive.
Repository Health
Technical Analysis
i18next-pseudo is a lightweight post-processor plugin for i18next that generates pseudolocalized strings on the fly, replacing standard characters with accented look-alikes and stretching text length so developers can catch internationalization bugs long before translators get involved.
Rather than waiting for real translations to reveal truncated UI, broken layouts, or hardcoded strings that were never wrapped for translation, teams register this plugin with their existing i18next configuration and enable pseudolocalization for a chosen locale. It repeats vowels to simulate the length growth typical of translated text, swaps letters for diacritic variants to catch places where character encoding assumptions break, and can optionally wrap every string in brackets to reveal concatenated or hardcoded text that bypassed the translation pipeline entirely.
What You Get
- Drop-in i18next postProcessor - registers as a
pseudopostProcessor viai18n.use(new Pseudo()), with no changes required to existing translation calls. - Configurable letter substitution - a full default alphabet mapping (
uglifiedAlphabet) swaps every letter for an accented look-alike, or supply your own mapping. - Adjustable text expansion -
letterMultiplierrepeats vowels to simulate the length growth of real translations, catching truncated or overflowing UI before translators are involved. - Interpolation-safe processing - detects
{{ }}interpolation braces and skips characters inside them so dynamic values aren’t mangled. - Optional bracket wrapping -
wrapped: truesurrounds every processed string in[ ], making concatenated or hardcoded strings that bypass i18next visually obvious. - Runtime enable/disable - the
enabledflag andconfigurePseudo()method let you toggle pseudolocalization per environment without removing the plugin.
Common Use Cases
- QA catching text overflow before translators start - a QA engineer flips pseudolocalization on in a staging build to see which buttons, labels, and modals break when strings grow 30-50% longer.
- Finding hardcoded, untranslated strings - a frontend developer enables
wrapped: trueso any text without brackets stands out as a string that was never routed through i18next. - CI visual regression testing - a team runs its screenshot test suite against a pseudolocalized build to catch layout regressions caused by variable string length, without maintaining real translation files.
- Verifying encoding and font support end-to-end - a developer uses the accented-character substitution to confirm fonts, encoding, and text rendering handle non-ASCII characters correctly before real localized content ships.
Under The Hood
Architecture
The entire plugin is a single Pseudo class in src/index.js that satisfies i18next’s postProcessor interface (name, type: 'postProcessor', and a process(value, key, options, translator) method), with a small src/utils.js module supplying the default alphabet map, vowel list, and a bracket-wrapping helper. process() walks the input string character by character, tracking a bracket-depth counter so text inside {{ }} interpolation placeholders passes through untouched while every other character is looked up in the letter map (and repeated if it’s a vowel in repeatedLetters). There’s no internal state beyond the constructor-assigned options object, and configurePseudo() merges new options in at runtime — a deliberately minimal, single-responsibility design with nothing to break beyond that one transform function.
Tech Stack
The source is plain ES6 (a single class, no framework), with i18next (^19.1.0) as the only runtime dependency it hooks into. It’s built and packaged with nwb (a zero-config build tool for JS/React modules), which produces es/, lib/ (CommonJS), and umd/ bundles from the src/ directory, alongside a hand-maintained index.d.ts for TypeScript consumers. There’s no bundler config of its own beyond nwb.config.js.
Code Quality
Tests live in tests/index-test.js, run via nwb test (Karma + Mocha under the hood) with the expect assertion library, and cover the default constructor options plus each process() branch — language mismatch, disabled state, standard substitution, non-letter characters, interpolation placeholders, custom letterMultiplier, and bracket wrapping. There’s a tests/.eslintrc scoping a Mocha environment for the test files, but no linting or type-checking is enforced on src/, and no CI configuration (no GitHub Actions workflow or .travis.yml) was found in the repo, so tests aren’t automatically run on push or PR.
API Design
The public surface is intentionally small: instantiate new Pseudo(options), pass it to i18n.use(), and add 'pseudo' to i18next’s postProcess array — no other integration code needed. Defaults are sensible (English source locale, 2x vowel repetition, a full accented-alphabet map) so most consumers can adopt it with zero configuration, and the exported TypeScript declaration gives autocomplete for every option. The one rough edge is that customizing the letter map means providing a full replacement object rather than a partial override.