Skip to content

Languages

Overview

Language settings control which languages your vendor offers. You add languages from a fixed supported list, publish them so customers can see them, and pick one published language as the vendor default.

Key Purpose: Configure the set of languages available to customers and choose a default language.

Purpose

This page lets you add, publish, unpublish, delete, and set a default language. Each language you add is created in Unpublished status; only published languages are exposed to customers. The vendor-level default language is used as the fallback throughout the platform.

Key Concepts

  • Language as a record: Each language is a document in the tenant settings collection with model = "language". A language record stores only a name (e.g. "Dutch") and a status (Published or Unpublished). It has no per-channel or toggle fields.
  • Supported language set: Languages are not free text. The selectable names come from a fixed converter map (Constants::$LANGUAGE_CONVERTER): Dutch, French, German, Portuguese, Spanish, English, Italian. Each maps to an ISO code (nl, fr, de, pt, es, en, it). The default-language fallback name is English.
  • Language Status: A language is Published (visible to customers / returned by the options endpoint) or Unpublished (only visible in the back office). Status is the only editable attribute of a language.
  • Default Language: The vendor default is stored on the merchant document as default_language (an ObjectId reference to a language record), not on the language itself. Setting a default also switches the back-office UI locale to that language's ISO code.
  • Location Preferred Language: Each location stores a preferred_language, which is the ObjectId of a language record (not an ISO code). A location's preferred language must reference an existing language in the settings collection.
  • Translation Completeness Check: LanguageService::checkTranslation($language) reports, per entity type, whether any record is still missing a translation in the given language. The GET /check-incomplete endpoint surfaces this per language.
  • Auto-Translate Receipt Settings on Create (queued): Adding a language fires a LanguageCreated event; a queued listener (TranslateReceiptSettingsForLanguage, 3 tries with 30/60/120s backoff) then calls ReceiptSettingService::translateReceiptSettingForCurrentMerchant, which loops the merchant's locations translating each one's receipt custom text. Because it runs on the queue, the translations appear shortly after the language is created rather than instantly, and they can fail independently of the language itself.

Actions

Add a Language

Open the "Add Language" dialog and pick a name from the list of supported languages that have not already been added. The language is created in Unpublished status, and a queued background job then translates every location's receipt custom text into it — so those translations appear shortly after, not the instant the dialog closes. Languages are not visible to customers until published.

Publish a Language

Publish an unpublished language so it becomes visible to customers and is returned by the language-options endpoint. Publishing fires a ReloadMenu event for every location so devices refresh.

Unpublish a Language

Move a published language back to unpublished. Unpublishing is blocked if the language is the vendor default, or if any location uses it as its preferred_language (the error names the affected location). Unpublishing fires a ReloadMenu event for every location.

Set Default Language

Designate a published language as the vendor default. Attempting to set an unpublished language as default returns a 400 error. Setting the default also changes the back-office interface language to that language.

Delete (Remove) a Language

Delete an unpublished language. Deleting is blocked if the language is the vendor default. (Soft delete; the language record is removed from active records.)

Check Translation Coverage

The /check-incomplete endpoint reports which entity types still have missing translations for each language. See the Business Rules section for the exact entities checked.

Location

  • Backoffice Route: /settings/languages
  • Backend Controller: app/Http/Controllers/Api/LanguageController.php
  • Backend Service: app/Services/BackOffice/Settings/LanguageService.php
  • Vue Component: src/views/settings/LanguagesComponent.vue (add dialog: src/components/dialogs/AddLanguageDialog.vue)

API Endpoints

All routes are under the back-office settings prefix (/back-office/settings/languages):

MethodPathAction
GET/back-office/settings/languages/List all languages (all)
GET/back-office/settings/languages/check-incompleteTranslation completeness per language
POST/back-office/settings/languages/Add a language (create)
POST/back-office/settings/languages/set-default/{id}Set default language
POST/back-office/settings/languages/publish/{id}Publish a language
POST/back-office/settings/languages/unpublish/{id}Unpublish a language
DELETE/back-office/settings/languages/delete/{id}Delete a language

The selectable language names for the Add Language dialog come from GET /lang-options (ConstantController::langOptions), which returns the 7 supported names from Constants::$LANGUAGE_CONVERTER as plain strings; the dialog then filters out names that have already been added.

GET /back-office/language-options (LanguageController::options) is a different endpoint: it returns only published languages (id + name) and feeds the location form's preferred_language picker, not the add dialog.

Fields

A language record has only two stored fields. There are no auto-detect, show-selector, per-channel, or "available languages" multi-select fields.

Name

PropertyValue
Field IDname
TypeSelect (from supported list)
RequiredYes

Description: The language name. Must be one of the supported values below. The create endpoint validates language as a required string; the UI restricts the choice to supported, not-yet-added names.

Supported Languages (from Constants::$LANGUAGE_CONVERTER):

NameISO Code
Englishen
Dutchnl
Frenchfr
Germande
Spanishes
Portuguesept
Italianit

Status

PropertyValue
Field IDstatus
TypeEnum
ValuesPublished, Unpublished
DefaultUnpublished (on create)

Description: Whether the language is visible to customers. Changed via the publish / unpublish actions, never edited directly.


Default Language (merchant-level)

PropertyValue
Field IDdefault_language (on the merchant document)
TypeObjectId reference to a language record

Description: The vendor's default language. Not a field on the language record itself; it is stored on the merchant. Only a published language may be set as the default.


Preferred Language (location-level)

PropertyValue
Field IDpreferred_language (on each location)
TypeObjectId reference to a language record (string ID, validated to exist)

Description: A location's own preferred language, referencing a language record by its ObjectId — not an ISO code. Configured on the location, not on this page. Used to block unpublishing a language still in use.

Customer-Facing Display

How published languages are rendered in the customer storefront, Online Ordering, and Kiosk (language selector, menu translation display, receipt language) is handled in those channels and is not verified here. This page only controls which languages exist, their published status, and the vendor default.

Relations

Depends On

  • Locations: Each location references a language via preferred_language (ObjectId).
  • Merchant: Stores the vendor default_language (ObjectId).

Affects

  • Translations: Which languages content can be translated into.
  • Online Ordering / Kiosk: Which languages are offered to customers (rendering not verified here).
  • Receipts: Adding a language auto-translates receipt custom text per location (queued, shortly after creation).

Business Rules

  • A language must be Published before it can be set as the vendor default; setting an unpublished language as default aborts with 400 "The language should be published first before setting it as the default".
  • The default language cannot be unpublished; the request aborts with 400 "Can't unpublish the default language."
  • The default language cannot be deleted; the request aborts with 400 "Can't remove the language since it is the default language".
  • Unpublishing is blocked if any location uses the language as its preferred_language; the error names the affected location (e.g. "Can't unpublish the language since it is used by in <Location>") and appends " and N more" when more than one location is affected.
  • Adding a language with a name that already exists aborts with 400 "Duplicate language" (unless called internally with throw = false, in which case the existing record is returned).
  • Adding a language auto-translates receipt custom text into the new language for every location of the current merchant. This runs asynchronously on the queue (LanguageCreatedTranslateReceiptSettingsForLanguage, 3 tries, 30/60/120s backoff), so it completes shortly after the language is created and can fail without failing the language creation.
  • Publishing and unpublishing each fire a ReloadMenu event for every location so devices refresh; deleting fires ReloadMenu only if the deleted language was published.
  • Translation completeness (check-incomplete) checks these entity types: Items, Display Groups, Variant Groups, Categories, Modifiers (modifier groups and their modifiers), Loyalty rewards, Table Sections, plus order/pager instructions and the upsell screen. Notifications and Receipts are placeholders (TODO) and are not yet checked.

FAQs

  • "Why can't I unpublish a language?" Either it is the vendor default, or a location is using it as its preferred language. Change the default or update the location's preferred language first.
  • "What happens when I add a new language?" It is created in Unpublished status (not yet visible to customers), and a background job then translates receipt custom text for every location into it — those translations show up shortly after, not immediately.
  • "Which languages can I add?" English, Dutch, French, German, Spanish, Portuguese, and Italian. Already-added languages are filtered out of the add dialog.
  • "Why aren't customers seeing a language I added?" New languages are Unpublished by default; publish it to make it visible to customers.
  • "Can each location have a different language?" Each location has its own preferred_language reference, but the vendor-wide default language is the global fallback.
  • "What entities are checked for translation completeness?" Items, display groups, variant groups, categories, modifiers, loyalty rewards, table sections, and order/pager instructions and the upsell screen.

Troubleshooting

Problem: Can't set a language as default

Causes:

  1. The language is still Unpublished.

Solutions:

  1. Publish the language first, then set it as default.

Problem: Can't unpublish or delete a language

Causes:

  1. It is the vendor default language.
  2. (Unpublish only) A location uses it as its preferred language.

Solutions:

  1. Set a different published language as default first.
  2. Change the affected location's preferred language, then retry.

Problem: "Duplicate language" when adding

Causes:

  1. A language with that name already exists.

Solutions:

  1. The language is already added; find it in the published or unpublished list instead.

Examples

A language record (as stored)

json
{
  "_id": "665f1a2b3c4d5e6f70819203",
  "model": "language",
  "name": "Dutch",
  "status": "Published"
}

Language as returned by the list endpoint (LanguageResource)

json
{
  "id": "665f1a2b3c4d5e6f70819203",
  "name": "Dutch",
  "status": "Published",
  "is_default": true,
  "iso": "nl"
}

Published-language option for the location picker (LanguageOptionResource, from /back-office/language-options)

json
{
  "id": "665f1a2b3c4d5e6f70819203",
  "name": "Dutch"
}

Adding a language (request body)

json
{
  "language": "French"
}

Merchant default and location preferred language (references)

json
{
  "merchant": {
    "default_language": "665f1a2b3c4d5e6f70819203"
  },
  "location": {
    "preferred_language": "665f1a2b3c4d5e6f70819203"
  }
}

Both default_language (merchant) and preferred_language (location) hold the ObjectId of a language record, not an ISO code.