locale-resolution
"""Locale Resolution and Field Label Translation
This module demonstrates how the locale resolution system works and how field labels are automatically translated in the Meta API.
Locale Resolution Order
The system resolves the user's locale in the following order:
- Accept-Language header - Browser language preference
- User preference - user.locale field in LocalUser/UserPreferences
- Tenant default - tenant.attributes.default_locale
- System default - DEFAULT_LOCALE setting (defaults to "en")
Usage Examples
1. Frontend: Setting Locale via Accept-Language Header
// Frontend automatically sends Accept-Language header
fetch("http://localhost:8000/api/meta/Invoice", {
headers: {
"Accept-Language": "hi-IN,hi;q=0.9,en;q=0.8",
},
});
// The middleware parses this and resolves locale to 'hi'
2. Backend: User Preference
# Set user's locale preference
user = LocalUser(
email="john@example.com",
password_hash="...",
locale="hi" # Hindi preference
)
# When this user makes requests, locale="hi" takes precedence
# over Accept-Language header
3. Backend: Tenant Default Locale
# Configure tenant with default locale
tenant = TenantContext(
tenant_id="acme-corp",
attributes={
"default_locale": "ta", # Tamil
"plan": "enterprise"
}
)
# All users in this tenant default to Tamil
# unless they have a personal preference
4. Backend: Accessing Resolved Locale
from litestar import get, Request
from framework_m.adapters.web.middleware.locale import provide_locale
@get("/api/greeting")
async def get_greeting(locale: str = provide_locale) -> str:
\"\"\"Greet user in their preferred language.\"\"\"
greetings = {
"en": "Hello!",
"hi": "नमस्ते!",
"ta": "வணக்கம்!",
}
return greetings.get(locale, greetings["en"])
Field Label Translation
Field labels (Field.description and Field.title) are automatically translated in the Meta API response based on the resolved locale.
Example: Creating Translations
# 1. Create Translation entries
from framework_m.core.doctypes.translation import Translation
# English (original)
Translation(
source_text="Customer Name",
translated_text="Customer Name",
locale="en",
context="field_label"
)
# Hindi translation
Translation(
source_text="Customer Name",
translated_text="ग्राहक का नाम",
locale="hi",
context="field_label"
)
# Tamil translation
Translation(
source_text="Customer Name",
translated_text="வாடிக்கையாளர் பெயர்",
locale="ta",
context="field_label"
)
Example: DocType with Translatable Fields
from pydantic import Field
from framework_m.core.domain.base_doctype import BaseDocType
class Invoice(BaseDocType):
\"\"\"Invoice DocType with translatable field labels.\"\"\"
customer: str = Field(
description="Customer Name", # Will be translated
min_length=1,
max_length=200
)
total: float = Field(
description="Total Amount", # Will be translated
ge=0
)
Example: Meta API Response (Hindi locale)
# Request with Hindi locale
curl -H "Accept-Language: hi" http://localhost:8000/api/meta/Invoice
# Response (field labels translated)
{
"doctype": "Invoice",
"locale": "hi",
"schema": {
"properties": {
"customer": {
"type": "string",
"description": "ग्राहक का नाम", # Translated!
"minLength": 1,
"maxLength": 200
},
"total": {
"type": "number",
"description": "कुल राशि", # Translated!
"minimum": 0
}
}
}
}
Middleware Configuration
Add the locale resolution middleware to your Litestar app:
from litestar import Litestar
from framework_m.adapters.web.middleware.locale import create_locale_middleware
app = Litestar(
route_handlers=[...],
middleware=[
create_locale_middleware(),
# ... other middleware
]
)
Translation Context
The context field in Translation DocType allows disambiguation:
# Button label
Translation(
source_text="Save",
translated_text="सहेजें",
locale="hi",
context="button" # Specific to buttons
)
# Field label
Translation(
source_text="Save",
translated_text="बचत",
locale="hi",
context="field_label" # Different meaning for field labels
)
Benefits
- Automatic: No manual translation code needed in endpoints
- Flexible: Multiple fallback levels ensure graceful degradation
- User-friendly: Respects browser language, user preference, and tenant defaults
- Consistent: Same locale resolution logic across all endpoints
- Cacheable: DefaultI18nAdapter caches translations in memory
See Also
framework_m.adapters.web.middleware.locale- Middleware implementationframework_m.adapters.i18n.DefaultI18nAdapter- Translation adapterframework_m.core.doctypes.translation- Translation DocTypeframework_m.core.doctypes.user- User.locale fieldframework_m.core.interfaces.tenant- TenantContext.attributes.default_locale """