feat(i18n): Add full localization support with 40 languages#27
Merged
Conversation
- Add Language section to Settings > General - Support all 40+ macOS languages with native names - Searchable dropdown with English name, native name, and code - System Default option to follow macOS preference - Language override via AppleLanguages UserDefaults - Fix: add termqmcp to .gitignore Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move Language section to bottom of Settings > General - Add "Current" label showing selected language above search - Keeps restart requirement (industry standard) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Expand Strings.swift with ~200 localization keys - Update en.lproj/Localizable.strings with all translations - Add translation template files for 39 additional languages - Create localization management scripts: - generate-translations.sh: Create translation templates - validate-strings.sh: Validate all languages have matching keys - extract-to-json.sh: Export strings for LLM translation - Update .claude/commands/localization.md with full language list - Update CONTRIBUTING.md with localization workflow - Add localization validation to code hygiene checklist Supported languages: English (US/UK/AU), Spanish (ES/LATAM), French (FR/CA), German, Italian, Portuguese (BR/PT), Dutch, Swedish, Danish, Finnish, Norwegian, Polish, Russian, Ukrainian, Czech, Slovak, Hungarian, Romanian, Croatian, Slovenian, Greek, Turkish, Hebrew, Arabic, Thai, Vietnamese, Indonesian, Malay, Chinese (Simplified/Traditional/HK), Japanese, Korean, Hindi, and Catalan. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Reviewed and validated all localization files ensuring consistency and accuracy across Western European, Nordic, Eastern European, Mediterranean, Middle Eastern, Asian, and regional variants. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Extracted language picker into separate view to fix SwiftLint type_body_length violation (was 532 lines, max is 500). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add PRE-PUSH / PRE-PR REQUIREMENTS section - Require local build, format, lint, and test before any push - Document that local/CI discrepancies are bugs to investigate - Reduces wasted CI resources and environmental impact Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Rename CLI from 'termq' to 'termqcli' to fix macOS case-insensitive filesystem collision - Update CLIInstaller paths from termq to termqcli - Localize command palette actions and menu items - Fix 'Open' badge translation (was 'Open Terminal') - Rename L() helper to localized() to fix SwiftLint identifier_name violation - Add DEVELOPER_DIR instructions to CLAUDE.md for local toolchain issues - Update all 40 language files with new keys and CLI description Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
45688b4 to
902c1b2
Compare
5 tasks
eyelock
pushed a commit
that referenced
this pull request
Jan 16, 2026
The original implementation created a Bundle from .lproj folder paths, but Bundle.localizedString() doesn't work on such pseudo-bundles since they lack proper bundle metadata (Info.plist, etc). This fix adds a custom .strings file parser that: - Handles both /* */ and // style comments - Properly parses "key" = "value"; format - Handles escaped characters (\", \n, \\) - Caches parsed strings for the user's preferred language The bug was latent since the original i18n PR (#27) and only manifested when a user explicitly set a non-system-default language preference. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
5 tasks
eyelock
pushed a commit
that referenced
this pull request
Jan 16, 2026
The original implementation created a Bundle from .lproj folder paths, but Bundle.localizedString() doesn't work on such pseudo-bundles since they lack proper bundle metadata (Info.plist, etc). This fix adds a custom .strings file parser that: - Handles both /* */ and // style comments - Properly parses "key" = "value"; format - Handles escaped characters (\", \n, \\) - Caches parsed strings for the user's preferred language The bug was latent since the original i18n PR (#27) and only manifested when a user explicitly set a non-system-default language preference. Also adds comprehensive localization tests to prevent regression: - Parser edge case tests (comments, escaping, empty lines) - English and Danish translation verification - Multi-language file parsing validation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
eyelock
added a commit
that referenced
this pull request
Jan 16, 2026
The original implementation created a Bundle from .lproj folder paths, but Bundle.localizedString() doesn't work on such pseudo-bundles since they lack proper bundle metadata (Info.plist, etc). This fix adds a custom .strings file parser that: - Handles both /* */ and // style comments - Properly parses "key" = "value"; format - Handles escaped characters (\", \n, \\) - Caches parsed strings for the user's preferred language The bug was latent since the original i18n PR (#27) and only manifested when a user explicitly set a non-system-default language preference. Also adds comprehensive localization tests to prevent regression: - Parser edge case tests (comments, escaping, empty lines) - English and Danish translation verification - Multi-language file parsing validation Co-authored-by: David Collie <support@eyelock.net> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
Changes
Core Infrastructure
Languages Supported (40 total)
Arabic, Catalan, Chinese (Simplified, Traditional, Hong Kong), Croatian, Czech, Danish, Dutch, English (US, UK, AU), Finnish, French (France, Canada), German, Greek, Hebrew, Hindi, Hungarian, Indonesian, Italian, Japanese, Korean, Malay, Norwegian, Polish, Portuguese (Brazil, Portugal), Romanian, Russian, Slovak, Slovenian, Spanish (Spain, Latin America), Swedish, Thai, Turkish, Ukrainian, Vietnamese
Developer Tooling
scripts/localization/validate-strings.sh- Validates all language files have matching keysscripts/localization/extract-to-json.sh- Extracts strings for translation servicesscripts/localization/generate-translations.sh- Regenerates .strings files from JSON.claude/commands/localization.md- AI assistant localization guidelinesTest plan
./scripts/localization/validate-strings.sh- all 40 files should match🤖 Generated with Claude Code