@owlmeans/client-i18n
v0.1.1
Published
The **@owlmeans/client-i18n** package provides React-based internationalization functionality for OwlMeans Common Libraries, designed for fullstack microservices and microclients development with focus on security and proper authentication and authorizati
Readme
@owlmeans/client-i18n
The @owlmeans/client-i18n package provides React-based internationalization functionality for OwlMeans Common Libraries, designed for fullstack microservices and microclients development with focus on security and proper authentication and authorization.
Purpose
This package serves as the client-side React integration layer for the OwlMeans i18n system that:
- Integrates with React applications using React Context and hooks
- Provides React hooks for translations with automatic resource loading
- Supports dynamic resource loading with automatic caching
- Integrates with client context for configuration-driven internationalization
- Offers multi-level translation support (library, app, service levels)
- Enables namespace-based organization for different translation contexts
Core Concepts
I18n Context Provider
A React Context Provider that initializes and manages the i18next instance for the entire React application, integrated with OwlMeans client configuration.
Automatic Resource Loading
Translation resources are automatically loaded and registered with i18next when requested through hooks, with intelligent caching to prevent duplicate loading.
Multi-Level Translation Hooks
Different hooks for accessing translations at different levels:
- Library-level translations (
useI18nLib) - Application-level translations (
useI18nApp) - Service-level translations (
useCommonI18n)
Client Context Integration
Seamless integration with OwlMeans client context system for configuration-driven internationalization setup.
API Reference
Components
I18nContext
React Context Provider component that provides i18n functionality to the entire React application.
import { I18nContext } from '@owlmeans/client-i18n'
import { ClientConfig } from '@owlmeans/client-context'
const App: React.FC = () => {
const config = useClientConfig() // Your client configuration
return (
<I18nContext config={config}>
<AppContent />
</I18nContext>
)
}Props:
config: ClientConfig - The client configuration objectchildren: ReactNode - Child components
Hooks
useCommonI18n(resourceName, ns?, prefix?): TFunction
Main hook for accessing translations with automatic resource loading.
import { useCommonI18n } from '@owlmeans/client-i18n'
const MyComponent: React.FC = () => {
const t = useCommonI18n('user-forms', 'ui', 'profile')
return (
<div>
<h1>{t('title')}</h1>
<p>{t('description')}</p>
</div>
)
}Parameters:
resourceName: string - Name of the translation resource to loadns: string (optional) - Namespace for the translations (defaults to default namespace)prefix: string (optional) - Key prefix for translation lookups
Returns: TFunction - i18next translation function
Behavior:
- Automatically loads translation resources for the current language
- Caches loaded resources to prevent duplicate loading
- Falls back to default language if current language resources are not available
- Supports multi-level translation priority (service > app > library)
useI18nLib(libName, prefix?): TFunction
Hook for accessing library-level translations in the 'lib' namespace.
import { useI18nLib } from '@owlmeans/client-i18n'
const LibraryComponent: React.FC = () => {
const t = useI18nLib('common-ui', 'buttons')
return (
<button>{t('save')}</button>
)
}Parameters:
libName: string - Name of the library translation resourceprefix: string (optional) - Key prefix for translation lookups
Returns: TFunction - i18next translation function configured for library namespace
useI18nApp(appName?, prefix?): TFunction
Hook for accessing application-level translations using the service name from context.
import { useI18nApp } from '@owlmeans/client-i18n'
const AppComponent: React.FC = () => {
const t = useI18nApp(undefined, 'navigation')
return (
<nav>
<a href="/">{t('home')}</a>
<a href="/profile">{t('profile')}</a>
</nav>
)
}Parameters:
appName: string (optional) - Name of the app (defaults to service name from context)prefix: string (optional) - Key prefix for translation lookups
Returns: TFunction - i18next translation function configured for app namespace
Types
I18nContextProps
Props interface for the I18nContext component.
interface I18nContextProps extends PropsWithChildren {
config: ClientConfig
}I18nProps
Generic interface for components that accept i18n properties.
interface I18nProps {
i18n?: I18nBaseProps
}I18nBaseProps
Base properties for i18n configuration.
interface I18nBaseProps {
resource?: string // Resource name override
ns?: string // Namespace override
prefix?: string // Key prefix override
suppress?: boolean // Suppress translation loading
}Utilities
The package also exports utilities under the /utils subpackage:
import { useI18nInstance } from '@owlmeans/client-i18n/utils'useI18nInstance(config): i18n
Hook that creates and configures an i18next instance based on client configuration.
import { useI18nInstance } from '@owlmeans/client-i18n/utils'
const config = useClientConfig()
const i18n = useI18nInstance(config)Usage Examples
Basic Setup
import React from 'react'
import { render } from 'react-dom'
import { I18nContext } from '@owlmeans/client-i18n'
import { makeClientConfig, ClientContext } from '@owlmeans/client-context'
import { AppType } from '@owlmeans/context'
const config = makeClientConfig(AppType.Frontend, 'my-app', {
// Client configuration
defaultLng: 'en',
debug: { i18n: true }
})
const App: React.FC = () => (
<ClientContext.Provider value={context}>
<I18nContext config={config}>
<MainApp />
</I18nContext>
</ClientContext.Provider>
)
render(<App />, document.getElementById('root'))Component with Translations
import React from 'react'
import { useCommonI18n, useI18nLib, useI18nApp } from '@owlmeans/client-i18n'
const UserProfileForm: React.FC = () => {
// Different translation levels
const tLib = useI18nLib('forms') // Library translations
const tApp = useI18nApp() // App-specific translations
const tUser = useCommonI18n('user-profile', 'ui') // Service translations
return (
<form>
<h1>{tApp('profile.title')}</h1>
<label>
{tUser('name.label')}
<input placeholder={tUser('name.placeholder')} />
</label>
<label>
{tUser('email.label')}
<input type="email" placeholder={tUser('email.placeholder')} />
</label>
<div>
<button type="submit">{tLib('save')}</button>
<button type="button">{tLib('cancel')}</button>
</div>
</form>
)
}Custom Hook for Component Translations
import { useCommonI18n } from '@owlmeans/client-i18n'
const useProductTranslations = (prefix?: string) => {
return useCommonI18n('products', 'ecommerce', prefix)
}
const ProductCard: React.FC<{ product: Product }> = ({ product }) => {
const t = useProductTranslations('card')
return (
<div className="product-card">
<h3>{product.name}</h3>
<p>{t('price')}: ${product.price}</p>
<button>{t('addToCart')}</button>
</div>
)
}Dynamic Resource Loading
import React, { useState } from 'react'
import { useCommonI18n } from '@owlmeans/client-i18n'
const DynamicContent: React.FC = () => {
const [selectedModule, setSelectedModule] = useState('dashboard')
// Translations are loaded dynamically based on selected module
const t = useCommonI18n(selectedModule, 'modules')
return (
<div>
<select
value={selectedModule}
onChange={(e) => setSelectedModule(e.target.value)}
>
<option value="dashboard">Dashboard</option>
<option value="analytics">Analytics</option>
<option value="settings">Settings</option>
</select>
<div>
<h2>{t('title')}</h2>
<p>{t('description')}</p>
</div>
</div>
)
}Error Handling and Fallbacks
import React from 'react'
import { useCommonI18n } from '@owlmeans/client-i18n'
const SafeTranslatedComponent: React.FC = () => {
const t = useCommonI18n('user-interface', 'ui')
// Translation function handles missing keys gracefully
return (
<div>
{/* Will show key if translation missing */}
<h1>{t('welcome', 'Welcome')}</h1>
{/* Will use fallback value */}
<p>{t('description', { defaultValue: 'Default description' })}</p>
{/* With interpolation */}
<p>{t('greeting', { name: 'User', defaultValue: 'Hello, {{name}}!' })}</p>
</div>
)
}Multi-Language Support
import React from 'react'
import { useTranslation } from 'react-i18next'
import { useCommonI18n } from '@owlmeans/client-i18n'
const LanguageSwitcher: React.FC = () => {
const { i18n } = useTranslation()
const t = useCommonI18n('language-switcher', 'ui')
const changeLanguage = (lng: string) => {
i18n.changeLanguage(lng)
}
return (
<div>
<h3>{t('selectLanguage')}</h3>
<button onClick={() => changeLanguage('en')}>
{t('languages.english')}
</button>
<button onClick={() => changeLanguage('es')}>
{t('languages.spanish')}
</button>
<button onClick={() => changeLanguage('fr')}>
{t('languages.french')}
</button>
</div>
)
}Integration Patterns
With Component Libraries
// Create a wrapper component for your design system
import React from 'react'
import { useI18nLib } from '@owlmeans/client-i18n'
interface ButtonProps {
variant: 'primary' | 'secondary'
i18nKey: string
children?: React.ReactNode
}
const TranslatedButton: React.FC<ButtonProps> = ({
variant,
i18nKey,
children
}) => {
const t = useI18nLib('ui-components', 'buttons')
return (
<button className={`btn btn-${variant}`}>
{children || t(i18nKey)}
</button>
)
}
// Usage
<TranslatedButton variant="primary" i18nKey="save" />With Forms
import React from 'react'
import { useForm } from 'react-hook-form'
import { useCommonI18n } from '@owlmeans/client-i18n'
const LoginForm: React.FC = () => {
const t = useCommonI18n('auth-forms', 'auth')
const { register, handleSubmit, formState: { errors } } = useForm()
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label>{t('email.label')}</label>
<input
{...register('email', { required: t('email.required') })}
placeholder={t('email.placeholder')}
/>
{errors.email && <span>{errors.email.message}</span>}
</div>
<div>
<label>{t('password.label')}</label>
<input
type="password"
{...register('password', { required: t('password.required') })}
placeholder={t('password.placeholder')}
/>
{errors.password && <span>{errors.password.message}</span>}
</div>
<button type="submit">{t('submit')}</button>
</form>
)
}Performance Considerations
Resource Loading Caching
The package implements intelligent caching:
// Resources are cached per language and resource name
const i18nLoadingCache = new Set<string>()
// Cache key format: "{language}:{resourceName}:{namespace}"
const key = `${i18n.language}:${resourceName}:${ns}`Automatic Resource Management
- Lazy Loading - Resources are only loaded when first requested
- Duplicate Prevention - Multiple components using the same resource won't trigger multiple loads
- Fallback Loading - Default language resources are loaded as fallbacks
Best Practices
- Use specific resource names - Avoid loading large translation bundles
- Leverage namespaces - Organize translations by functional area
- Implement prefixes - Use prefixes to scope translations to specific components
- Cache translation functions - Don't recreate translation functions unnecessarily
Error Handling
The package handles various error scenarios gracefully:
- Missing resources - Falls back to translation keys or default values
- Network failures - Uses cached resources or fallback languages
- Invalid configurations - Provides sensible defaults
- Component unmounting - Prevents memory leaks from resource loading
Dependencies
This package depends on:
@owlmeans/client- Client-side context hooks@owlmeans/client-context- Client context management@owlmeans/i18n- Core i18n functionality and resource managementreact- React framework (peer dependency)react-i18next- React integration for i18nexti18next- Core i18n library
Related Packages
@owlmeans/i18n- Core i18n functionality and resource management@owlmeans/client-context- Client-side context management@owlmeans/client- Client-side utilities and hooks
