Locale Parameters API Documentation#
Overview#
The Smokesignal event filtering system provides comprehensive internationalization (i18n) support through locale-aware API endpoints. This document describes how to use locale parameters in filtering endpoints and configure i18n middleware.
Supported Languages#
- en-us: English (United States) - Default
- fr-ca: French (Canada) with gender support
API Endpoints with Locale Support#
Filter Events Endpoint#
URL: GET /events
Locale Detection Priority:
- User profile language settings (authenticated users)
languagecookie valueAccept-LanguageHTTP header- Default fallback to
en-US
Query Parameters#
All standard filtering parameters are supported with locale-aware responses:
GET /events?mode=inperson&status=scheduled&date_range=today
Headers#
Accept-Language Header#
The system parses standard Accept-Language headers with quality values:
Accept-Language: fr-CA,fr;q=0.9,en;q=0.8
Accept-Language: en-US,en;q=0.9
Accept-Language: es-ES,es;q=0.9,en;q=0.8
Examples:
fr-CA,fr;q=0.9,en;q=0.8→ Returns French Canadian interfaceen-US,en;q=0.9→ Returns English interfaceinvalid-locale→ Falls back to English
HTMX Language Headers#
For HTMX requests, language context is preserved:
HX-Request: true
HX-Current-Language: fr-CA
Accept-Language: fr-CA,fr;q=0.9,en;q=0.8
Response Format#
The API returns locale-aware responses with:
- Translated facet labels: Categories, date ranges, status options
- Localized display names: Event modes, status values
- Proper pluralization: Event counts, result summaries
- Currency formatting: Price displays (if applicable)
- Date formatting: Locale-specific date representations
Example Request/Response#
Request:
GET /events?mode=inperson&date_range=today
Accept-Language: fr-CA,fr;q=0.9,en;q=0.8
Response (French Canadian):
{
"events": [...],
"facets": {
"modes": [
{
"value": "inperson",
"count": 15,
"i18n_key": "mode-inperson",
"display_name": "En personne"
}
],
"date_ranges": [
{
"value": "today",
"count": 8,
"i18n_key": "date-range-today",
"display_name": "Aujourd'hui"
}
]
},
"total_count": 15,
"current_locale": "fr-CA"
}
Facets-Only Endpoint#
URL: GET /events/facets
Returns only facet data with translations:
GET /events/facets?mode=online
Accept-Language: fr-CA
Event Suggestions Endpoint#
URL: GET /events/suggestions
Autocomplete suggestions with locale-aware labels:
GET /events/suggestions?q=concert
Accept-Language: fr-CA
Cache Behavior#
The system uses locale-aware caching to ensure optimal performance:
Cache Key Format#
filter:{criteria_hash}:{locale}
Examples:
filter:abc123:en-us- English cache entryfilter:abc123:fr-ca- French Canadian cache entry
Cache Isolation#
Each locale maintains separate cache entries to prevent:
- Translation leakage between languages
- Incorrect facet display names
- Inconsistent user experiences
Error Handling#
Invalid Locale Fallback#
When an unsupported locale is requested:
- Log warning: Invalid locale detected
- Fallback: Automatically use
en-US - Continue processing: No error returned to client
Malformed Headers#
The system gracefully handles:
- Empty Accept-Language headers
- Malformed quality values
- Invalid language tags
- Excessively long header values
Error Response Format#
Error messages respect the user's language preference:
{
"error": "Invalid filter criteria",
"error_code": "INVALID_CRITERIA",
"locale": "fr-CA",
"message": "Critères de filtre invalides"
}
Performance Considerations#
Optimizations#
- Static Translation Loading: Translations compiled into binary
- Locale-Specific Caching: Separate cache entries per locale
- Lazy Loading: Translations loaded on demand
- Memory Efficiency: Shared FluentBundle resources
Benchmarks#
Typical performance impact of i18n features:
- Translation lookup: < 1μs
- Facet calculation with locale: +5-10ms
- Cache key generation: < 100ns
- Accept-Language parsing: < 10μs
Integration Examples#
Frontend JavaScript#
// Set user language preference
fetch('/events?mode=online', {
headers: {
'Accept-Language': navigator.language || 'en-US'
}
});
// HTMX with language context
<div hx-get="/events"
hx-headers='{"Accept-Language": "fr-CA"}'>
</div>
cURL Examples#
# Request with French Canadian preference
curl -H "Accept-Language: fr-CA,fr;q=0.9,en;q=0.8" \
"https://api.example.com/events?mode=inperson"
# Request with quality values
curl -H "Accept-Language: en-US,en;q=0.9,fr;q=0.8" \
"https://api.example.com/events/facets"
# HTMX request with language context
curl -H "HX-Request: true" \
-H "HX-Current-Language: fr-CA" \
-H "Accept-Language: fr-CA" \
"https://api.example.com/events"
Server Integration#
use smokesignal::http::middleware_i18n::Language;
use smokesignal::filtering::FilteringService;
// Handler with automatic locale extraction
pub async fn handle_filter_events(
ctx: UserRequestContext,
Extension(filtering_service): Extension<FilteringService>,
// Language automatically extracted from headers/cookies/profile
language: Language,
query: Query<FilterParams>,
) -> Result<Response, WebError> {
let locale_str = language.to_string();
// Use locale-aware filtering
let results = filtering_service
.filter_events_with_locale(&criteria, &options, &locale_str)
.await?;
// Template rendering with i18n context
let html = renderer.render("events", &context)?;
Ok(html)
}
Security Considerations#
Input Validation#
- Locale strings: Validated against supported languages
- Header parsing: Protected against injection attacks
- Cache keys: Sanitized to prevent cache poisoning
Rate Limiting#
Locale-aware rate limiting considers:
- Language-specific cache effectiveness
- Regional usage patterns
- Translation server load
Migration Guide#
Adding New Languages#
- Create translation files: Add
.ftlfiles ini18n/{locale}/ - Update supported languages: Modify
SUPPORTED_LANGUAGESconstant - Test translation coverage: Run
cargo test i18n - Deploy: Translation files are embedded in binary
Upgrading Existing Code#
// Old: No locale support
let results = filtering_service.filter_events(&criteria).await?;
// New: With locale support
let results = filtering_service
.filter_events_with_locale(&criteria, &options, &locale)
.await?;
Troubleshooting#
Common Issues#
Issue: Translations not appearing
- Check: Translation files in correct directory structure
- Verify: Locale string format (
en-USnoten_US) - Test: Use browser dev tools to inspect Accept-Language header
Issue: Cache inconsistency between languages
- Solution: Clear locale-specific cache entries
- Command:
FLUSHDBor restart Redis/Valkey
Issue: Performance degradation
- Monitor: Cache hit rates per locale
- Optimize: Translation loading patterns
- Scale: Consider translation CDN for high-traffic deployments
Debug Information#
Enable debug logging for i18n operations:
RUST_LOG=smokesignal::i18n=debug,smokesignal::filtering=debug cargo run
Log Examples:
DEBUG smokesignal::i18n: Language detected from header: fr-CA
DEBUG smokesignal::filtering: Cache key generated: filter:abc123:fr-ca
DEBUG smokesignal::i18n: Translation lookup: date-range-today -> Aujourd'hui