-
Notifications
You must be signed in to change notification settings - Fork 662
feat(cli): add pseudo-localization mode #1629
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ashutoshdebug
wants to merge
7
commits into
lingodotdev:main
Choose a base branch
from
ashutoshdebug:feat/pseudo-localization
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 2 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
5de5959
feat(cli): add pseudo-localization mode
ashutoshdebug cd43006
docs(cli): correct path references in README
ashutoshdebug 0de9d3a
docs(cli): remove unwanted files
ashutoshdebug 9f4ed45
Merge branch 'main' into feat/pseudo-localization
ashutoshdebug 5697402
Merge branch 'main' into feat/pseudo-localization
ashutoshdebug a2bf057
Merge branch 'main' into feat/pseudo-localization
ashutoshdebug b697575
Merge branch 'main' into feat/pseudo-localization
ashutoshdebug File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,243 @@ | ||
| # Pseudo-Localization Mode | ||
|
|
||
| ## Overview | ||
|
|
||
| Pseudo-localization is a testing technique that helps developers verify that their applications are ready for internationalization (i18n) without waiting for actual translations. Instead of using real translated text, pseudo-localization automatically replaces characters with accented versions and adds visual markers. | ||
|
|
||
| This is a standard practice used by Google, Microsoft, and Mozilla in their localization pipelines. | ||
|
|
||
| ## When to Use | ||
|
|
||
| Pseudo-localization is ideal for: | ||
|
|
||
| - **Early UI Testing**: Test your UI before translations are complete | ||
| - **Layout Issue Detection**: Identify truncation, overflow, and text expansion problems | ||
| - **CI/CD Integration**: Validate i18n readiness in continuous integration pipelines | ||
| - **Development Workflow**: Catch i18n issues before deployment | ||
| - **Rapid Iteration**: Quickly test UI changes without external API calls | ||
|
|
||
| ## Usage | ||
|
|
||
| ### Via CLI | ||
|
|
||
| Run the localization pipeline in pseudo-localization mode: | ||
|
|
||
| ```bash | ||
| pnpx lingo.dev run --pseudo | ||
| ``` | ||
|
|
||
| This will: | ||
|
|
||
| 1. Extract all translatable strings from your source code | ||
| 2. Pseudo-translate them by replacing characters with accented versions | ||
| 3. Write the pseudo-translated strings to your target locale files | ||
| 4. Mark each pseudo-translation with a **⚡** symbol for easy identification | ||
|
|
||
| ### Example | ||
|
|
||
| **Input files:** | ||
| ```jsx | ||
| // app.jsx | ||
| <> | ||
| <h1>Submit</h1> | ||
| <p>Welcome back!</p> | ||
| </> | ||
| ``` | ||
|
|
||
| **Output with `--pseudo` flag:** | ||
| ```json | ||
| // en-XA/messages.json | ||
| { | ||
| "submit": "Šûbmíţ⚡", | ||
| "welcome_back": "Ŵèļçømèƀäçķ!⚡" | ||
| } | ||
| ``` | ||
|
|
||
| ## How It Works | ||
|
|
||
| ### Character Replacement | ||
|
|
||
| Each ASCII letter is replaced with a visually similar accented character: | ||
|
|
||
| | Original | Replacement | Original | Replacement | | ||
| |----------|-------------|----------|-------------| | ||
| | a | ã | A | Ã | | ||
| | e | è | E | È | | ||
| | i | í | I | Í | | ||
| | o | ø | O | Ø | | ||
| | u | û | U | Û | | ||
| | s | š | S | Š | | ||
| | t | ţ | T | Ţ | | ||
|
|
||
| And so on for all letters. Non-alphabetic characters (numbers, punctuation, spaces) are preserved as-is. | ||
|
|
||
| ### Visual Marker | ||
|
|
||
| A ⚡ symbol is appended to each pseudo-translated string, making it immediately visible which text has been pseudo-localized. | ||
|
|
||
| ## Configuration | ||
|
|
||
| Currently, pseudo-localization only supports the `--pseudo` CLI flag. Support for configuration in `i18n.json` is planned for a future release. | ||
|
|
||
| ## Key Features | ||
|
|
||
| ✅ **No External API Calls**: Run completely offline | ||
| ✅ **Instant Feedback**: Pseudo-translate instantly without waiting | ||
| ✅ **Character Replacement**: Uses accent-based character mapping (en-XA style) | ||
| ✅ **Visual Markers**: Easy to identify pseudo-translated strings | ||
| ✅ **Recursive Object Handling**: Works with nested structures and arrays | ||
| ✅ **Preserves Structure**: Maintains JSON/object structure and types | ||
|
|
||
| ## What Pseudo-Localization Tests | ||
|
|
||
| ### ✅ Catches These Issues | ||
|
|
||
| - **Text Truncation**: UI elements that cut off text | ||
| - **Layout Overflow**: Components that break with longer text | ||
| - **Font Support**: Missing glyph support for special characters | ||
| - **Text Direction**: Issues with RTL content (though accents don't change direction) | ||
| - **String Concatenation**: Hardcoded text that should be translatable | ||
| - **Placeholder Text**: Missing localization in form fields or labels | ||
|
|
||
| ### ❌ Does NOT Replace | ||
|
|
||
| - **Actual Translation**: Pseudo-localization is for testing, not production use | ||
| - **Translation Memory**: Use Lingo.dev or other providers for real translations | ||
| - **Quality Assurance**: Manual review of actual translations is still needed | ||
| - **Cultural Adaptation**: Different cultures have different needs beyond character replacement | ||
|
|
||
| ## Advanced Usage | ||
|
|
||
| ### Combining with Other Flags | ||
|
|
||
| ```bash | ||
| # Pseudo-localize only specific locales | ||
| pnpx lingo.dev run --pseudo --target-locale es --target-locale fr | ||
|
|
||
| # Pseudo-localize only specific buckets | ||
| pnpx lingo.dev run --pseudo --bucket json --bucket yaml | ||
|
|
||
| # Pseudo-localize specific files | ||
| pnpx lingo.dev run --pseudo --file messages.json --file labels.json | ||
|
|
||
| # Force re-pseudo-translation | ||
| pnpx lingo.dev run --pseudo --force | ||
| ``` | ||
|
|
||
| ### With Watch Mode | ||
|
|
||
| ```bash | ||
| # Automatically pseudo-translate when files change | ||
| pnpx lingo.dev run --pseudo --watch | ||
| ``` | ||
|
|
||
| ## Implementation Details | ||
|
|
||
| ### Locale Code Convention | ||
|
|
||
| Pseudo-localized content uses the special locale code `en-XA` (following Google's convention), where: | ||
| - **en** = English (source language) | ||
| - **XA** = Pseudo-Accents | ||
|
|
||
| This is recognized by many i18n libraries and tools. | ||
|
|
||
| ### API Usage | ||
|
|
||
| For programmatic use, the pseudo-localization functions are available: | ||
|
|
||
| ```typescript | ||
| import { pseudoLocalize, pseudoLocalizeObject } from "lingo.dev/utils"; | ||
|
|
||
| // Pseudo-localize a single string | ||
| const result = pseudoLocalize("Hello World"); | ||
| // Result: "Ĥèļļø Ŵøŕļð⚡" | ||
|
|
||
| // Pseudo-localize an entire object | ||
| const messages = { greeting: "hello", farewell: "goodbye" }; | ||
| const pseudoMessages = pseudoLocalizeObject(messages); | ||
| // Result: { greeting: "ĥèļļø⚡", farewell: "ĝøøðßýè⚡" } | ||
| ``` | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| ### My UI still looks fine with pseudo-localization | ||
|
|
||
| This might indicate: | ||
|
|
||
| - **Hardcoded strings**: Some text might not be extracted properly. Check your extraction configuration. | ||
| - **Flexible layouts**: Your UI might be designed to handle text expansion. Good news for i18n! | ||
| - **Font issues**: Ensure your font supports accented characters. Test with a web-safe font first. | ||
|
|
||
| ### The ⚡ marker is being cut off | ||
|
|
||
| This is exactly what pseudo-localization is meant to catch! It means: | ||
|
|
||
| - Your UI has truncation issues with longer text | ||
| - You need to expand text containers or reduce font size for translations | ||
| - Consider using `max-width` or `line-clamp` CSS properties carefully | ||
|
|
||
| ### I want to customize the character mapping | ||
|
|
||
| Currently, character mapping is fixed to the en-XA style. For custom mappings, you can use the library functions directly and modify the mapping as needed. | ||
|
|
||
| ## Examples | ||
|
|
||
| ### React Component Testing | ||
|
|
||
| ```jsx | ||
| // Before pseudo-localization | ||
| <button>{t("submit")}</button> | ||
|
|
||
| // After pseudo-localization | ||
| <button>Šûbmíţ⚡</button> | ||
|
|
||
| // You'll immediately see if the button is too small! | ||
| ``` | ||
|
|
||
| ### Form Labels | ||
|
|
||
| ```jsx | ||
| // Before | ||
| <label>{t("email")}</label> | ||
|
|
||
| // After (pseudo-localized) | ||
| <label>èmãíļ⚡</label> | ||
|
|
||
| // Check for proper alignment and spacing | ||
| ``` | ||
|
|
||
| ## Performance | ||
|
|
||
| Pseudo-localization is extremely fast: | ||
|
|
||
| - **No network requests**: Everything happens locally | ||
| - **Minimal processing**: Simple character replacement | ||
| - **Instant results**: Suitable for development and CI/CD | ||
|
|
||
| ## Comparison with Alternatives | ||
|
|
||
| | Method | Speed | Accuracy | Cost | Configuration | | ||
| |--------|-------|----------|------|---------------| | ||
| | Pseudo-localization | ⚡ Instant | Simulates expansion | Free | CLI flag only | | ||
| | AI Translation | ⏱️ Seconds | Good (OpenAI, etc.) | $ | API key required | | ||
| | Human Translation | 🐢 Days | Excellent | $$$$ | Translation service | | ||
|
|
||
| ## Related Resources | ||
|
|
||
| - [Google's Pseudo-translation](https://google.github.io/styleguide/tsqm.html) | ||
| - [Mozilla's Pseudo-localization](https://mozilla-l10n.github.io/documentation/tools/pseudo/) | ||
| - [i18n Best Practices](https://www.w3.org/International/questions/qa-i18n) | ||
|
|
||
| ## Next Steps | ||
|
|
||
| After pseudo-localizing: | ||
|
|
||
| 1. **Test your UI**: Navigate your application with pseudo-localized content | ||
| 2. **Identify issues**: Look for truncated text, overflows, or layout problems | ||
| 3. **Fix UI**: Adjust CSS, layouts, or text containers as needed | ||
| 4. **Run actual translations**: Once UI is i18n-ready, use Lingo.dev with real translations | ||
| 5. **Deploy with confidence**: Your app is now ready for international users! | ||
|
|
||
| ## Feedback & Issues | ||
|
|
||
| Found a bug or have a feature request? Open an issue on [GitHub](https://github.com/LingoDotDev/lingo.dev). |
ashutoshdebug marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,146 @@ | ||
| # Pseudo-Localization Quick Start Guide | ||
|
|
||
| ## Installation | ||
|
|
||
| The pseudo-localization feature is built into Lingo.dev CLI. No additional installation needed! | ||
|
|
||
| ## Quick Commands | ||
|
|
||
| ### Test a single locale | ||
| ```bash | ||
| pnpx lingo.dev run --pseudo | ||
| ``` | ||
|
|
||
| ### Test specific locales | ||
| ```bash | ||
| pnpx lingo.dev run --pseudo --target-locale es --target-locale fr | ||
| ``` | ||
|
|
||
| ### Watch mode (auto-pseudo-translate on file changes) | ||
| ```bash | ||
| pnpx lingo.dev run --pseudo --watch | ||
| ``` | ||
|
|
||
| ### Force re-pseudo-translation | ||
| ```bash | ||
| pnpx lingo.dev run --pseudo --force | ||
| ``` | ||
|
|
||
| ### Filter by file pattern | ||
| ```bash | ||
| pnpx lingo.dev run --pseudo --file messages.json | ||
| ``` | ||
|
|
||
| ### Filter by key prefix | ||
| ```bash | ||
| pnpx lingo.dev run --pseudo --key "auth.login" | ||
| ``` | ||
|
|
||
| ## Example Output | ||
|
|
||
| ### Before | ||
| ```json | ||
| { | ||
| "welcome": "Welcome back!", | ||
| "submit": "Submit", | ||
| "cancel": "Cancel" | ||
| } | ||
| ``` | ||
|
|
||
| ### After (with `--pseudo`) | ||
| ```json | ||
| { | ||
| "welcome": "Ŵèļçømèƀãçķ!⚡", | ||
| "submit": "Šûbmíţ⚡", | ||
| "cancel": "Çãñçèļ⚡" | ||
| } | ||
| ``` | ||
|
|
||
| ## What You'll Notice | ||
|
|
||
| ✅ **Text is longer** - Many languages are longer than English (20-30% common) | ||
| ✅ **Characters look weird** - Accented characters help spot untranslated strings | ||
| ✅ **⚡ marker visible** - Easy to see what's pseudo-localized | ||
| ✅ **Spacing issues appear** - Reveals layout problems immediately | ||
|
|
||
| ## Common Use Cases | ||
|
|
||
| ### Before Translations Arrive | ||
| ```bash | ||
| # Start development with pseudo-localization | ||
| pnpx lingo.dev run --pseudo | ||
|
|
||
| # Test your UI with the pseudo-translated files | ||
| npm run dev | ||
|
|
||
| # Fix any layout issues you find | ||
| # When real translations arrive, just switch to real provider | ||
| pnpx lingo.dev run # Uses configured provider | ||
| ``` | ||
|
|
||
| ### In CI/CD | ||
| ```yaml | ||
| # .github/workflows/i18n.yml | ||
| name: Validate i18n | ||
| on: [push] | ||
|
|
||
| jobs: | ||
| validate: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-node@v4 | ||
| - run: npx lingo.dev run --pseudo --frozen | ||
| # --frozen ensures nothing needs translating | ||
| ``` | ||
|
|
||
| ### Testing UI Component Libraries | ||
| ```bash | ||
| # Test components with pseudo-localized strings | ||
| pnpx lingo.dev run --pseudo --bucket json | ||
|
|
||
| # Build Storybook with pseudo-localized strings | ||
| npm run build-storybook | ||
| ``` | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| ### "Pseudo-localization is enabled but I don't see the ⚡" | ||
|
|
||
| Check if your strings are being extracted correctly: | ||
| ```bash | ||
| pnpx lingo.dev run --verbose --pseudo | ||
| ``` | ||
|
|
||
| ### "Text is being truncated badly" | ||
|
|
||
| This is exactly what pseudo-localization should catch! 🎯 | ||
|
|
||
| Solutions: | ||
| - Increase container width/height | ||
| - Use flexible layouts (flexbox, grid) | ||
| - Set `word-wrap: break-word` in CSS | ||
| - Avoid hardcoded width/height values | ||
|
|
||
| ### "Some strings aren't showing up pseudo-localized" | ||
|
|
||
| Possible causes: | ||
| - String not marked for i18n in code | ||
| - String in a component that's not being processed | ||
| - String in a comment or non-extractable location | ||
|
|
||
| Use `--verbose` flag to see what's being extracted. | ||
|
|
||
| ## Next Steps | ||
|
|
||
| 1. **Test your UI** - Navigate your app with pseudo-localized strings | ||
| 2. **Fix issues** - Address any layout or truncation problems | ||
| 3. **Switch to real translations** - Remove `--pseudo` flag when ready | ||
| 4. **Deploy with confidence** - Your app is now ready for international users! | ||
|
|
||
| ## More Information | ||
|
|
||
| - 📖 [Full Documentation](./PSEUDO_LOCALIZATION.md) | ||
| - 🐛 [Report Issues](https://github.com/LingoDotDev/lingo.dev/issues) | ||
| - 💬 [Ask Questions](https://lingo.dev/go/discord) | ||
| - ⭐ [Give us a star!](https://github.com/LingoDotDev/lingo.dev) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.