Skip to main content
Glama

Spec Workflow MCP

i18n-guide.md11.5 kB
# Internationalization (i18n) Guide This project implements comprehensive internationalization support across all components: React frontend, VSCode extension, and backend MCP tools. ## Architecture Overview ### Frontend (React Dashboard) - **Framework**: `react-i18next` with browser language detection - **Location**: `src/dashboard_frontend/src/i18n.ts` - **Translation Files**: `src/dashboard_frontend/src/locales/` ### VSCode Extension - **Framework**: `vscode-nls` compatibility with `react-i18next` for webviews - **Location**: `vscode-extension/src/webview/i18n.ts` - **Translation Files**: `vscode-extension/src/webview/locales/` ### Backend (MCP Tools) - **Framework**: Custom lightweight solution with async loading - **Location**: `src/core/i18n.ts` - **Translation Files**: `src/locales/` ## Using the Translation System ### Backend MCP Tools ```typescript import { translate } from '../core/i18n.js'; import { ToolContext } from '../types.js'; export async function toolHandler(args: any, context: ToolContext): Promise<ToolResponse> { const lang = context.lang || 'en'; return { success: true, message: translate('tools.myTool.success', lang, { name: args.name, count: args.items.length }), nextSteps: [ translate('tools.myTool.nextSteps.first', lang), translate('tools.myTool.nextSteps.second', lang) ] }; } ``` ### React Frontend ```typescript import { useTranslation } from 'react-i18next'; function MyComponent() { const { t } = useTranslation(); return ( <div> <h1>{t('nav.dashboard.title')}</h1> <p>{t('welcome.message', { name: 'User', count: 5 })}</p> </div> ); } ``` ### VSCode Extension Webview ```typescript import { useTranslation } from 'react-i18next'; function WebviewComponent() { const { t } = useTranslation(); return ( <button>{t('actions.approve')}</button> ); } ``` ## Translation File Structure ### JSON Format ```json { "nav": { "dashboard": { "title": "Dashboard", "stats": "Statistics" } }, "tools": { "specStatus": { "description": "Get current status of a specification", "success": "Spec {{specName}} is currently {{status}}" } } } ``` ### Key Naming Convention - Use dot notation for nested keys: `nav.dashboard.title` - Group by functional area: `tools.`, `nav.`, `errors.` - Use descriptive names: `specStatus` not `ss` ## String Interpolation ### Backend ```typescript translate('welcome.message', 'en', { name: 'John', count: 42 }) // Uses {{name}} and {{count}} in translation strings ``` ### Frontend ```typescript t('welcome.message', { name: 'John', count: 42 }) // Uses {{name}} and {{count}} in translation strings ``` ## Language Support ### Currently Supported - **English** (`en`) - Default fallback language - **Japanese** (`ja`) - Complete translations ### Adding New Languages 1. **Backend**: Add new JSON file in `src/locales/` 2. **Frontend**: Add new JSON file in `src/dashboard_frontend/src/locales/` 3. **VSCode Extension**: Add new JSON files in `vscode-extension/src/webview/locales/` 4. **Update validation script**: Add language code to `scripts/validate-i18n.js` ## Error Handling ### Missing Translations - Backend: Returns the translation key as fallback - Frontend: Returns the translation key as fallback - Graceful degradation ensures app continues to work ### File Loading Errors - Backend: Non-blocking async loading with comprehensive error logging - Frontend: React i18next handles missing files gracefully - Build validation prevents deployment with broken translation files ## Performance Considerations ### Backend - **Async Loading**: Translation files load asynchronously on first use - **Caching**: Single loading promise prevents duplicate file reads - **Memory Efficient**: Translations cached in memory after first load ### Frontend - **Static Loading (Default)**: All translations loaded at startup for instant language switching - **Dynamic Loading (Optional)**: Languages loaded on demand to reduce initial bundle size - **Browser Caching**: localStorage persistence for language selection - **Bundle Optimization**: Automatic code splitting available for large translation sets #### Dynamic Import Feature The frontend supports two loading strategies for translations: **1. Static Loading (Default)** - All translations are bundled and loaded at startup - Best for: Small to medium applications, when instant language switching is critical - Usage: Import from `./i18n` in your main entry file **2. Dynamic Loading (Optional)** - Translations are loaded on-demand when needed - Reduces initial bundle size by loading only the detected/selected language - Best for: Large applications with many languages, when initial load time is critical - Trade-off: Small delay when switching languages for the first time **How to Enable Dynamic Loading:** 1. Set the environment variable in your `.env` file: ```env VITE_I18N_DYNAMIC=true ``` 2. Update your main entry file to use the dynamic import: ```typescript // main.tsx or index.tsx import './i18n-dynamic'; // Instead of './i18n' ``` **Performance Comparison:** | Metric | Static Loading | Dynamic Loading | |--------|---------------|-----------------| | Initial Bundle Size | Larger (includes all languages) | Smaller (detected language only) | | Language Switch Speed | Instant | Slight delay on first switch | | Network Requests | None after initial load | One per language on first use | | Best For | <5 languages, <50KB per language | >5 languages, >50KB per language | ## Build Process ### Validation ```bash npm run validate:i18n ``` Checks that all translation files exist and contain valid JSON. ### Testing ```bash npm test # Run all tests including i18n npm run test:watch # Watch mode for development npm run test:coverage # Generate coverage report ``` ## Development Workflow ### Adding New Translation Keys 1. **Add to English files first** (default fallback) 2. **Add to other language files** 3. **Run validation**: `npm run validate:i18n` 4. **Update tests** if needed 5. **Test in all environments** ### Testing Translations ```typescript // Unit test example describe('translate function', () => { it('should handle interpolation', () => { const result = translate('welcome', 'en', { name: 'Test' }); expect(result).toBe('Welcome, Test!'); }); }); ``` ## Best Practices ### Translation Keys - ✅ Use descriptive keys: `tools.specStatus.success` - ❌ Avoid generic keys: `msg1`, `text` - ✅ Group logically: `errors.notFound`, `errors.permission` - ✅ Keep consistent: same structure across languages ### String Interpolation - ✅ Use meaningful parameter names: `{{userName}}` not `{{p1}}` - ✅ Handle pluralization properly - ✅ Keep interpolation simple ### Error Handling - ✅ Always provide fallbacks - ✅ Log missing translations in development - ✅ Never let translation errors break the app ### Performance - ✅ Lazy load translations when possible - ✅ Cache loaded translations - ✅ Validate translations at build time - ✅ Monitor bundle size impact ## Troubleshooting ### Common Issues **Translations not loading in backend tools** - Check that `src/locales/` directory exists - Verify JSON syntax in translation files - Check console for loading errors **Language detection not working in frontend** - Verify browser language settings - Check localStorage for saved preferences - Ensure language selector is working **VSCode extension translations missing** - Check that translation files are included in extension bundle - Verify `package.json` contributes configuration - Test in VSCode extension development host ### Critical Issue: "ReferenceError: t is not defined" This error occurs when components try to use translation functions without properly importing or declaring them. This was a known issue that affected multiple components in version 0.0.30. #### Root Cause Components using `t('translation.key')` without having the `useTranslation` hook declared, causing JavaScript runtime errors that prevent UI functionality. #### Symptoms - Browser console shows `ReferenceError: t is not defined` - UI components fail to render or become non-interactive - Dropdowns, buttons, or forms stop working - Error typically occurs in minified production builds #### Fixed Components (v0.0.30+) The following components were affected and have been fixed: **VSCode Extension:** - `CommentModal.tsx` - Comment editing interface - `comment-modal.tsx` - Modal wrapper component **Dashboard Frontend:** - `VolumeControl.tsx` - Notification volume controls - `AlertModal.tsx` - Alert dialog component - `SearchableSpecDropdown.tsx` - Task management dropdown #### Resolution Steps **For React Components:** 1. **Import the useTranslation hook:** ```typescript import { useTranslation } from 'react-i18next'; ``` 2. **Declare the hook in the component:** ```typescript function MyComponent() { const { t } = useTranslation(); // ... rest of component } ``` 3. **Replace hardcoded strings with translation keys:** ```typescript // Before (causes error) <button>Edit Comment</button> // After (works correctly) <button>{t('commentModal.title.edit')}</button> ``` **For Modal/Standalone Components (like comment-modal.tsx):** 1. **Wrap with I18nextProvider:** ```typescript import { I18nextProvider } from 'react-i18next'; import i18n from './i18n'; return ( <I18nextProvider i18n={i18n}> <YourComponent /> </I18nextProvider> ); ``` 2. **Use i18n.t() for fallback values:** ```typescript const fallbackText = window.initialState?.selectedText || i18n.t('commentModal.noTextSelected'); ``` #### Adding Required Translation Keys After fixing components, ensure all translation keys exist in locale files: **Example for commentModal:** ```json { "commentModal": { "title": { "edit": "Edit Comment", "add": "Add Comment" }, "selectedText": "Selected Text", "cancel": "Cancel", "noTextSelected": "No text selected" } } ``` #### Prevention **Code Review Checklist:** - [ ] Every component using `t()` has `useTranslation()` declared - [ ] All translation keys exist in locale files - [ ] Components wrapped with i18n providers when needed - [ ] Build passes without console errors **Development Tools:** - Run `npm run validate:i18n` before commits - Test components in different languages - Check browser console for runtime errors - Use TypeScript for better error detection **Build Validation:** The build process now includes comprehensive i18n validation that catches missing translation keys and malformed JSON files before deployment. #### Component Template Use this template when creating new components: ```typescript import React from 'react'; import { useTranslation } from 'react-i18next'; function NewComponent() { const { t } = useTranslation(); return ( <div> <h1>{t('newComponent.title')}</h1> <button>{t('newComponent.action')}</button> </div> ); } export default NewComponent; ``` ### Debug Commands ```bash # Validate all translation files npm run validate:i18n # Run i18n tests specifically npm test -- --grep="i18n" # Build with verbose logging npm run build -- --verbose # Check for missing translation function usage grep -r "t(" src/ --include="*.tsx" --include="*.ts" ```

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Pimzino/spec-workflow-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server