Appearance
Translations
Overview
Translations allow you to provide menu items, descriptions, and custom content in multiple languages. Translate your menu for international customers.
Key Purpose: Translate menu content for multiple languages.
Purpose
This page lets you view, edit, and auto-translate the names and descriptions of menu items, categories, modifiers, display groups, variant groups, and loyalty rewards into every configured language.
Key Concepts
- Translation Entities: The system supports translating six entity types: Item, DisplayGroup, VariantGroup, Category, Modifier (ModifierGroup), and Loyalty rewards, each resolved via
TranslationEntitiesenum. - Default vs. Translating Language: Every translatable field stores a
defaultvalue plus per-language overrides (e.g.,details.default.nameanddetails.fr.name); the default is the source text. - Google Cloud Translate: Auto-translation uses the Google Cloud Translate V2 API via a
TranslateClientinitialized with theCLOUD_TRANSLATION_API_KEYenvironment variable. - Incompleteness Detection: The
LanguageService.checkTranslationmethod queries each entity repository for records where the translated name is null, empty, or missing for a given language. - Paginated Data Table: Translations are browsed via a paginated pipeline that adds computed fields (
default_name,translating_name, etc.) and supports sorting and search by default name.
Actions
Translate Individual Entity
Select an item, category, or modifier and enter or edit the translation for a specific language; both name and description fields are translatable.
Auto-Translate Missing Content
Trigger the auto-translate function to generate draft translations for all entities that are missing a translation in one or more target languages.
Review Translation Status
View a per-language completeness overview showing how many entities still need translations, broken down by entity type.
Bulk Browse and Edit
Use the paginated translation data table to filter by entity type and language, then edit translations inline.
Location
- Backoffice Route:
/settings/translations - Backend Controller:
app/Http/Controllers/Api/TranslationController.php - Vue Component:
src/views/settings/TranslationsComponent.vue
What Can Be Translated
Menu Items
| Field | Translatable |
|---|---|
| Item Name | ✓ |
| Item Description | ✓ |
| Item Notes | ✓ |
Categories
| Field | Translatable |
|---|---|
| Category Name | ✓ |
| Category Description | ✓ |
Modifiers
| Field | Translatable |
|---|---|
| Group Name | ✓ |
| Option Name | ✓ |
Custom Content
| Field | Translatable |
|---|---|
| Welcome Message | ✓ |
| Footer Text | ✓ |
| Receipt Header | ✓ |
| Receipt Footer | ✓ |
Translation Fields
Source Language
| Property | Value |
|---|---|
| Field ID | source_language |
| Label | Source Language |
| Type | Select |
| Default | Default language |
Description: The original language of your content.
Target Languages
| Property | Value |
|---|---|
| Field ID | target_languages |
| Label | Translate To |
| Type | Multi-select |
Description: Languages to translate content into.
Translation Status
| Property | Value |
|---|---|
| Values | translated, pending, missing |
Description: Status of each translation.
Statuses:
- Translated: Translation complete
- Pending: Needs review
- Missing: No translation yet
Translation Interface
Item Translation View
┌─────────────────────────────────────────────────────────┐
│ Margherita Pizza │
├─────────────────────────────────────────────────────────┤
│ Name │
│ ┌─────────────────────────────────────────────────────┐│
│ │ 🇳🇱 NL: Margherita Pizza ✓ ││
│ │ 🇬🇧 EN: Margherita Pizza ✓ ││
│ │ 🇩🇪 DE: Margherita Pizza ✓ ││
│ │ 🇫🇷 FR: Pizza Margherita ✓ ││
│ └─────────────────────────────────────────────────────┘│
│ │
│ Description │
│ ┌─────────────────────────────────────────────────────┐│
│ │ 🇳🇱 NL: Verse mozzarella, tomaat, basilicum ✓ ││
│ │ 🇬🇧 EN: Fresh mozzarella, tomato, basil ✓ ││
│ │ 🇩🇪 DE: Frischer Mozzarella, Tomate, Basilikum ✓ ││
│ │ 🇫🇷 FR: Mozzarella fraîche, tomate, basilic ✓ ││
│ └─────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────┘Auto-Translation
Enable Auto-Translate
| Property | Value |
|---|---|
| Field ID | auto_translate |
| Label | Auto-Translate |
| Type | Toggle |
| Default | false |
Description: Automatically translate new content using AI.
Business Logic:
- Uses AI translation service
- Creates draft translations
- Should be reviewed for accuracy
Auto-Translate Provider
| Property | Value |
|---|---|
| Field ID | translation_provider |
| Label | Translation Service |
| Type | Select |
| Options | azure, google, deepl |
Description: Which translation service to use.
Business Logic
Translation Storage
Item: Margherita Pizza
├── name: "Margherita Pizza" (default: NL)
├── name_en: "Margherita Pizza"
├── name_de: "Margherita Pizza"
├── name_fr: "Pizza Margherita"
├── description: "Verse mozzarella..." (default: NL)
├── description_en: "Fresh mozzarella..."
├── description_de: "Frischer Mozzarella..."
└── description_fr: "Mozzarella fraîche..."Translation Display
Customer selects language
│
▼
For each text field:
├── Translation exists for language?
│ └── Yes → Show translation
│
└── No → Show default language textBulk Translation
Select items to translate
│
▼
Select target languages
│
▼
For each item:
├── Auto-translate (if enabled)
└── Mark as pending review
│
▼
Review and approve translationsCustomer Impact
Online Ordering
- Menu items in selected language
- Descriptions in selected language
- Category names in selected language
- Modifier options in selected language
Kiosk
- Same as Online Ordering
- All UI text translated
Receipts
- Item names in receipt language
- Custom text translated
Relations
Depends On
- Languages: Which languages are enabled
- Menu Items: Content to translate
- Categories: Content to translate
- Modifiers: Content to translate
Affects
- Online Ordering: Displayed content
- Kiosk: Displayed content
- Receipts: Printed content
Related Features
Business Rules
- Auto-translation uses Google Cloud Translate V2 and requires a valid
CLOUD_TRANSLATION_API_KEYenvironment variable; if the key is missing, auto-translate calls will fail. - Translations are stored inside the entity's
detailsobject as per-language keys (e.g.,details.fr.name); if a language key is missing or empty, the system falls back todetails.default. - The translation data table supports pagination, sorting by any computed field, and search by default name, using MongoDB aggregation pipelines with
$addFields. - Translatable entities include Items, DisplayGroups, VariantGroups, Categories, ModifierGroups, and Loyalty rewards; Notifications and Receipts are planned but not yet implemented in the translation pipeline.
- Child translations (e.g., individual modifiers within a ModifierGroup, or rewards within a Loyalty program) are fetched via the parent's relationship methods and include both default and translating-language values.
FAQs
- "Which translation provider does the system use?" Google Cloud Translate V2 by default; the API key is configured via the
CLOUD_TRANSLATION_API_KEYenvironment variable. - "Are auto-translations final?" No, auto-translations are generated as drafts and should be reviewed manually for accuracy, especially for food and restaurant-specific terminology.
- "What happens if a translation is missing for a language?" The system falls back to the default language text, so the customer still sees content but in the source language.
- "Can I translate receipt text here?" Receipt header and footer text are translated automatically via the Receipt Settings page when you save changes; they are not yet part of the translation data table pipeline.
- "How do I know which translations are incomplete?" The translation status overview checks each entity type per language and flags any records where the translated name is null, empty, or missing.
Troubleshooting
Problem: Translation not showing
Causes:
- Translation not entered
- Language not enabled
- Cache issue
Solutions:
- Add translation
- Enable language in settings
- Clear cache
Problem: Wrong translation showing
Causes:
- Translation incorrect
- Wrong language detected
- Fallback to wrong language
Solutions:
- Update translation
- Check language detection
- Verify fallback settings
Problem: Auto-translate not working
Causes:
- Auto-translate disabled
- API key missing
- Service unavailable
Solutions:
- Enable auto-translate
- Configure API credentials
- Check service status
Examples
Menu Item Translations
json
{
"item": {
"id": "item-123",
"name": "Margherita Pizza",
"name_en": "Margherita Pizza",
"name_nl": "Margherita Pizza",
"name_de": "Margherita Pizza",
"name_fr": "Pizza Margherita",
"description": "Fresh mozzarella, San Marzano tomatoes, basil, extra virgin olive oil",
"description_nl": "Verse mozzarella, San Marzano tomaten, basilicum, extra vierge olijfolie",
"description_de": "Frischer Mozzarella, San Marzano Tomaten, Basilikum, natives Olivenöl extra",
"description_fr": "Mozzarella fraîche, tomates San Marzano, basilic, huile d'olive extra vierge"
}
}Category Translations
json
{
"category": {
"id": "cat-456",
"name": "Starters",
"name_nl": "Voorgerechten",
"name_de": "Vorspeisen",
"name_fr": "Entrées",
"description": "Begin your meal with our delicious starters",
"description_nl": "Begin uw maaltijd met onze heerlijke voorgerechten",
"description_de": "Beginnen Sie Ihre Mahlzeit mit unseren köstlichen Vorspeisen",
"description_fr": "Commencez votre repas avec nos délicieuses entrées"
}
}Modifier Translations
json
{
"modifier_group": {
"name": "Size",
"name_nl": "Grootte",
"name_de": "Größe",
"name_fr": "Taille",
"options": [
{
"name": "Small",
"name_nl": "Klein",
"name_de": "Klein",
"name_fr": "Petit"
},
{
"name": "Medium",
"name_nl": "Medium",
"name_de": "Mittel",
"name_fr": "Moyen"
},
{
"name": "Large",
"name_nl": "Groot",
"name_de": "Groß",
"name_fr": "Grand"
}
]
}
}Translation Status Overview
═══════════════════════════════════════════════════════════
TRANSLATION STATUS
═══════════════════════════════════════════════════════════
Menu Items (45 total)
─────────────────────────────────────────────────────────
🇳🇱 Dutch: 45/45 (100%) ████████████████████ Complete
🇬🇧 English: 45/45 (100%) ████████████████████ Complete
🇩🇪 German: 38/45 (84%) ████████████████░░░░ 7 missing
🇫🇷 French: 32/45 (71%) ██████████████░░░░░░ 13 missing
Categories (8 total)
─────────────────────────────────────────────────────────
🇳🇱 Dutch: 8/8 (100%) ████████████████████ Complete
🇬🇧 English: 8/8 (100%) ████████████████████ Complete
🇩🇪 German: 8/8 (100%) ████████████████████ Complete
🇫🇷 French: 8/8 (100%) ████████████████████ Complete
Modifiers (24 total)
─────────────────────────────────────────────────────────
🇳🇱 Dutch: 24/24 (100%) ████████████████████ Complete
🇬🇧 English: 24/24 (100%) ████████████████████ Complete
🇩🇪 German: 20/24 (83%) ████████████████░░░░ 4 missing
🇫🇷 French: 18/24 (75%) ███████████████░░░░░ 6 missing
[Auto-Translate Missing] [Export] [Import]Translation Best Practices
- Consistency: Use consistent terminology
- Context: Consider food/restaurant context
- Length: Keep translations similar length
- Review: Always review auto-translations
- Updates: Update translations when source changes