Locale Resolution and Field Label Translation
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