Translation Module Documentation¶
Overview¶
The Translation module manages internationalization (i18n) strings for the application. It stores translation keys and their values, organized by language code and optional sections for grouping.
Data Model¶
Translation Entity¶
File: backend/src/modules/translation/models/translation.ts
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| id | string | Yes | Auto-generated | Primary key |
| language_code | string | No | "ar" | Language code (e.g., "ar", "en") |
| key | string | Yes | - | Translation key (unique per language) |
| value | string | Yes | - | Translated text value |
| section | string | No | null | Optional section for grouping keys |
Service Methods¶
TranslationModuleService¶
File: backend/src/modules/translation/service.ts
The service extends MedusaService which automatically provides standard CRUD methods:
- listTranslations(filters, options) - List translations with optional filters
- createTranslations(data) - Create a new translation
- updateTranslations(id, data) - Update an existing translation
- deleteTranslation(id) - Delete a translation
Custom Methods¶
getAllTranslations()¶
Returns all translations across all languages.
Returns: Array of all translation records.
Example:
const translations = await translationModuleService.getAllTranslations()
// Returns: [
// { id: "1", language_code: "ar", key: "welcome", value: "مرحبا", section: "common" },
// { id: "2", language_code: "ar", key: "cart", value: "السلة", section: "common" }
// ]
getTranslationsByLanguage(languageCode)¶
Returns all translations for a specific language.
Parameters:
- languageCode - The language code (e.g., "ar", "en")
Returns: Array of translations for the specified language.
Example:
upsertTranslation(data)¶
Creates or updates a translation.
async upsertTranslation(data: {
language_code?: string
key: string
value: string
section?: string | null
}): Promise<Translation>
Parameters:
- language_code - Language code (defaults to "ar")
- key - Translation key
- value - Translated text
- section - Optional section for grouping
Returns: The created or updated translation.
Example:
const translation = await translationModuleService.upsertTranslation({
language_code: "ar",
key: "checkout",
value: "إتمام الطلب",
section: "checkout",
})
getAllAsBundle()¶
Returns all translations in i18next-compatible bundle format.
async getAllAsBundle(): Promise<{ [languageCode: string]: { translation: Record<string, string> } }>
Returns: Object with language codes as keys, each containing a translation object with key-value pairs.
Example:
const bundle = await translationModuleService.getAllAsBundle()
// Returns: {
// ar: {
// translation: {
// welcome: "مرحبا",
// cart: "السلة",
// checkout: "إتمام الطلب"
// }
// }
// }
This format is directly compatible with i18next frontend libraries.
Usage Examples¶
Getting Arabic Translations for Storefront¶
const bundle = await translationModuleService.getAllAsBundle()
// Pass to i18next init:
i18next.init({
resources: bundle,
lng: "ar",
})
Creating a New Translation¶
await translationModuleService.upsertTranslation({
language_code: "ar",
key: "add_to_cart",
value: "أضف إلى السلة",
section: "product",
})
Updating an Existing Translation¶
await translationModuleService.upsertTranslation({
language_code: "ar",
key: "welcome",
value: "أهلاً وسهلاً",
section: "common",
})
Getting Translations by Section¶
const allTranslations = await translationModuleService.getAllTranslations()
const commonTranslations = allTranslations.filter(t => t.section === "common")
i18next Bundle Format¶
The getAllAsBundle() method returns translations in the exact format expected by i18next:
{
"ar": {
"translation": {
"welcome": "مرحبا",
"cart": "السلة",
"checkout": "إتمام الطلب",
"add_to_cart": "أضف إلى السلة"
}
}
}
This allows direct integration with React i18next or other i18next-based libraries:
import i18next from 'i18next'
// Fetch from API
const response = await fetch('/store/translations')
const bundle = await response.json()
// Initialize i18next
i18next.init({
resources: bundle,
lng: 'ar',
fallbackLng: 'ar',
})
// Use in components
const t = i18next.t
console.log(t('welcome')) // "مرحبا"
Module Registration¶
The module is registered in medusa-config.ts:
Migration¶
Generate and run migrations:
This creates the translation table in PostgreSQL with all defined columns.
API Routes¶
The module is exposed via custom API routes:
- GET /store/translations - Returns i18next bundle for ar locale
- GET /admin/translations - List all translations (admin)
- POST /admin/translations - Create translation (admin)
- PATCH /admin/translations/:id - Update translation (admin)
- DELETE /admin/translations/:id - Delete translation (admin)
See STORE_ENDPOINTS.md and ADMIN_ENDPOINTS.md for API details.
Adding New Languages¶
To add support for additional languages:
-
Create translations with the new
language_code: -
Update
getAllAsBundle()to include the new language if needed - Update the storefront to allow language switching
Translation Key Naming Convention¶
- Use snake_case for keys (e.g.,
add_to_cart,free_delivery) - Group related keys using the
sectionfield - Use descriptive, context-aware names
- Avoid special characters in keys
Recommended sections:
- common - General UI elements
- product - Product-related text
- checkout - Checkout flow text
- account - Account management text
- errors - Error messages