Vue 3 Translation Integration
Vue 3 Translation Integration Documentation
Section titled âVue 3 Translation Integration DocumentationâOverview
Section titled âOverviewâThis document explains the integration of vue-i18n translation system with the existing Vue 3 application, inspired by the JHipster pattern but adapted for modern Vue 3 with Composition API and Pinia stores.
Architecture Components
Section titled âArchitecture Componentsâ1. Translation Store (stores/translation.ts
)
Section titled â1. Translation Store (stores/translation.ts)âThe Pinia store manages the translation state across the application:
export interface TranslationState { currentLanguage: string; availableLanguages: { code: string; name: string; flag: string }[]; isLoading: boolean;}
Key features:
- Persists language preference in localStorage
- Provides reactive language switching
- Supports multiple languages with metadata (name, flag)
- Loading state management for async language changes
2. Translation Service (services/translation.service.ts
)
Section titled â2. Translation Service (services/translation.service.ts)âHandles the actual translation operations:
Key methods:
refreshTranslation(newLanguage: string)
: Dynamically loads translation filessetLocale(language: string)
: Updates the i18n instance localeisLanguageSupported(language: string)
: Validates language supporttranslate(key: string, params?)
: Direct translation method
Features:
- Dynamic import of translation files from
locales/
directory - Fallback to English if translation loading fails
- Document language attribute updating
- Local storage integration
3. Account Service Integration
Section titled â3. Account Service IntegrationâEnhanced account service with language awareness:
// Language preference handlingconst userLanguage = this.authStore.account?.langKey;await this.changeLanguage(userLanguage);
4. Initialization Service (services/initialization.service.ts
)
Section titled â4. Initialization Service (services/initialization.service.ts)âOrchestrates the startup sequence:
Initialization flow:
- Load language from localStorage
- Determine best language (stored â user profile â browser â fallback)
- Set up reactive watchers for language changes
- Initialize authentication
- Configure router guards
Integration with Vue 3 Main Application
Section titled âIntegration with Vue 3 Main ApplicationâEnhanced main.ts Structure
Section titled âEnhanced main.ts Structureâimport { createI18n } from "vue-i18n";import { i18nConfig } from "@/config/i18n.config";import { InitializationService } from "@/services/initialization.service";
async function bootstrap() { const app = createApp(App); const pinia = createPinia(); const i18n = createI18n(i18nConfig);
// Plugin registration app.use(pinia); app.use(router); app.use(i18n);
// Service initialization const initializationService = new InitializationService({ app, router, i18n: i18n.global, });
await initializationService.initialize();
// Global service provision const translationService = initializationService.getTranslationService(); const accountService = initializationService.getAccountService(); app.provide('translationService', translationService); app.provide('accountService', accountService);
app.mount("#app");}
Key Differences from JHipster Modal-based Auth
Section titled âKey Differences from JHipster Modal-based Authâ- Page-based authentication: Uses Vue Router navigation instead of Bootstrap modals
- shadcn/vue components: Modern UI components instead of Bootstrap
- Composition API: All services use Vue 3 Composition API patterns
- Pinia stores: Modern state management instead of Vuex
- TypeScript-first: Full TypeScript integration with proper typing
Router Integration
Section titled âRouter IntegrationâEnhanced Router Guards
Section titled âEnhanced Router Guardsâimport { useAuthStore } from '@/stores/auth';import { inject } from 'vue';
router.beforeResolve(async (to, from, next) => { const authStore = useAuthStore(); const accountService = inject('accountService');
// Authentication check if (!authStore.authenticated) { await accountService.update(); }
// Authority checking if (to.meta?.authorities?.length > 0) { const hasAuth = await accountService.hasAnyAuthorityAndCheckAuth(to.meta.authorities); if (!hasAuth) { next({ path: authStore.authenticated ? '/forbidden' : '/login' }); return; } }
next();});
Axios Interceptor Enhancements
Section titled âAxios Interceptor EnhancementsâUpdated Request/Response Handling
Section titled âUpdated Request/Response HandlingâRequest interceptor:
- XSRF token handling for non-GET requests
- Bearer token authentication
- Request logging
Response interceptor:
- Enhanced 401/403 error handling
- Token cleanup on logout
- Redirect with query parameters for login flow
- Network error handling
Language Switching Flow
Section titled âLanguage Switching FlowâReactive Language Management
Section titled âReactive Language Managementâ- User changes language â Translation store updated
- Store change detected â Translation service updates i18n instance
- i18n instance updated â DOM language attribute updated
- Components reactive â UI updates automatically
Priority Order for Language Selection
Section titled âPriority Order for Language Selectionâ- Stored language preference (localStorage)
- User account language (
account.langKey
) - Browser language (
navigator.language
) - Fallback to English
Component Integration
Section titled âComponent IntegrationâUsing Translation Service in Components
Section titled âUsing Translation Service in Componentsâ<script setup>import { inject } from 'vue';import { useI18n } from 'vue-i18n';
const { t } = useI18n();const translationService = inject('translationService');
// Direct translationconst message = t('welcome.message');
// Programmatic language changeawait translationService.refreshTranslation('es');</script>
Using Translation Store
Section titled âUsing Translation Storeâ<script setup>import { useTranslationStore } from '@/stores/translation';
const translationStore = useTranslationStore();
// Access current languageconst currentLang = translationStore.currentLanguage;
// Change languagetranslationStore.setCurrentLanguage('es');</script>
Service Injection Pattern
Section titled âService Injection PatternâGlobal Service Provision
Section titled âGlobal Service ProvisionâServices are provided globally in main.ts and can be injected in any component:
// In main.tsconst translationService = initializationService.getTranslationService();const accountService = initializationService.getAccountService();app.provide('translationService', translationService);app.provide('accountService', accountService);
// In any componentconst translationService = inject('translationService');const accountService = inject('accountService');
Error Handling and Fallbacks
Section titled âError Handling and FallbacksâTranslation Loading Errors
Section titled âTranslation Loading Errorsâ- Failed language loads fall back to English
- Error logging for debugging
- Graceful degradation without breaking the app
User Notification Strategy
Section titled âUser Notification StrategyâWhen a translation fails to load or the system falls back to English, users are notified via non-intrusive toast notifications. These notifications appear briefly at the bottom or top of the screen, informing users that their preferred language could not be loaded and that English is being used as a fallback. This approach ensures users are aware of the issue without interrupting their workflow or navigation. The notification system is implemented using a composable toast component (e.g., Vue Toastification or similar), and all error messages are localized where possible. No modal dialogs or blocking UI elements are used, maintaining a smooth and uninterrupted app experience.
Network Errors
Section titled âNetwork Errorsâ- 401: Logout and redirect to login with return URL
- 403: Redirect to forbidden page
- Network errors: Console logging (could be enhanced with toast notifications)
Testing Considerations
Section titled âTesting ConsiderationsâUnit Testing
Section titled âUnit Testingâ// Mock translation serviceconst mockTranslationService = { refreshTranslation: vi.fn(), setLocale: vi.fn(), getCurrentLanguage: () => 'en', translate: (key: string) => key,};
// Mock i18n instanceconst mockI18n = { global: { locale: { value: 'en' }, t: (key: string) => key, }};
Integration Testing
Section titled âIntegration Testingâ- Test language switching flow
- Test authentication with different languages
- Test router guard behavior with auth states
Performance Considerations
Section titled âPerformance ConsiderationsâLazy Loading
Section titled âLazy LoadingâTranslation files are dynamically imported only when needed:
const messages = await import(`../locales/${newLanguage}.json`);
Memory Management
Section titled âMemory Managementâ- Only load required translation files
- Clean up old translations when switching languages
- Efficient reactive watchers that donât cause memory leaks
Future Enhancements
Section titled âFuture Enhancementsâ- Toast notifications for network errors
- Language detection based on user location
- Plural forms and advanced translation features
- Translation management for content creators
- A/B testing for different language versions
Migration from JHipster Pattern
Section titled âMigration from JHipster PatternâKey Changes Made
Section titled âKey Changes Madeâ- Replaced
useLoginModal()
with router-based navigation - Updated store watchers to use Vue 3
watch()
API - Enhanced error handling in axios interceptors
- Integrated with shadcn/vue component library
- Added TypeScript interfaces for better type safety
- Modernized service injection pattern
This integration provides a robust, scalable, and modern approach to internationalization in Vue 3 applications while maintaining the proven patterns from JHipster but adapted for modern frontend architecture.