Skip to content

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 TranslationEntities enum.
  • Default vs. Translating Language: Every translatable field stores a default value plus per-language overrides (e.g., details.default.name and details.fr.name); the default is the source text.
  • Google Cloud Translate: Auto-translation uses the Google Cloud Translate V2 API via a TranslateClient initialized with the CLOUD_TRANSLATION_API_KEY environment variable.
  • Incompleteness Detection: The LanguageService.checkTranslation method 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

FieldTranslatable
Item Name
Item Description
Item Notes

Categories

FieldTranslatable
Category Name
Category Description

Modifiers

FieldTranslatable
Group Name
Option Name

Custom Content

FieldTranslatable
Welcome Message
Footer Text
Receipt Header
Receipt Footer

Translation Fields

Source Language

PropertyValue
Field IDsource_language
LabelSource Language
TypeSelect
DefaultDefault language

Description: The original language of your content.


Target Languages

PropertyValue
Field IDtarget_languages
LabelTranslate To
TypeMulti-select

Description: Languages to translate content into.


Translation Status

PropertyValue
Valuestranslated, 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

PropertyValue
Field IDauto_translate
LabelAuto-Translate
TypeToggle
Defaultfalse

Description: Automatically translate new content using AI.

Business Logic:

  • Uses AI translation service
  • Creates draft translations
  • Should be reviewed for accuracy

Auto-Translate Provider

PropertyValue
Field IDtranslation_provider
LabelTranslation Service
TypeSelect
Optionsazure, 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 text

Bulk Translation

Select items to translate


Select target languages


For each item:
├── Auto-translate (if enabled)
└── Mark as pending review


Review and approve translations

Customer 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

Business Rules

  • Auto-translation uses Google Cloud Translate V2 and requires a valid CLOUD_TRANSLATION_API_KEY environment variable; if the key is missing, auto-translate calls will fail.
  • Translations are stored inside the entity's details object as per-language keys (e.g., details.fr.name); if a language key is missing or empty, the system falls back to details.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_KEY environment 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:

  1. Translation not entered
  2. Language not enabled
  3. Cache issue

Solutions:

  1. Add translation
  2. Enable language in settings
  3. Clear cache

Problem: Wrong translation showing

Causes:

  1. Translation incorrect
  2. Wrong language detected
  3. Fallback to wrong language

Solutions:

  1. Update translation
  2. Check language detection
  3. Verify fallback settings

Problem: Auto-translate not working

Causes:

  1. Auto-translate disabled
  2. API key missing
  3. Service unavailable

Solutions:

  1. Enable auto-translate
  2. Configure API credentials
  3. Check service status

Examples

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

  1. Consistency: Use consistent terminology
  2. Context: Consider food/restaurant context
  3. Length: Keep translations similar length
  4. Review: Always review auto-translations
  5. Updates: Update translations when source changes