Skip to main content
Skip table of contents

Language and Translation

Overview

Most of our systems are able to respond to requests for UI and data in multiple languages. There are a number of different mechanisms used to achieve this.

We currently deal with only a single dialect for a language and thus reference the language code “en” to actually represent “en-GB” as such we do not support “en-US” there is work in the backlog to extend all language functionality to support dialects.

Currently, there are resource files in the mono-repo for each of the microservices requiring them and for hub-web and booking-web. There are technical debt tickets in the backlog to rationalise to a single set of language resource files in the root of the mono-repo.

  • Language table - Stores a list of supported languages and provides the mapping between an international language code and an id used as the foreign key in all related database schema.

  • EntityValue table - Stores a single string value in any approved language. Each record is linked to the record in any other table by virtue of the entityId the entityType stores the name of the table that the record links to and entityKey the pseudo “field” that the value represents. At runtime, a dataLoader will be called to enhance the response with all data for the current language and in some cases, the values are also returned in entityList.

  • SystemEnumeration table - Stores language-specific versions of enumeration labels. This is primarily used where the graphQL-API must return enumeration labels in a given language.

  • i18n resource files - The mono repo includes a set of language resource files. These resource files are part of the static build of the interface site. We use a tool known as BabelEdit to manage the resource files. This tool ensures that any property added to the English files will equally be added to all other language-specific files after which time the tool can automatically populate each property with an appropriate machine translation. We are also able to bundle these files and pass them to our external linguists to proofread and correct any machine translation errors. We track in the holibob.babel file which properties in which languages have been proofread and approved.

    • User Interfaces i18n - As the interfaces themself are static then we use the NextI18n package to deliver any string, such as titles, labels and descriptions etc via a set of language-specific resource files. There are some instances where this approach is not appropriate as the graphQL API is also responsible for resolving ”static” values, where this is the case the Enumeration table will be used.

    • Micro services - Services such as the commit and cancel stacks also use resource files to deliver emails, vouchers and other notifications in the appropriate language. Typically these services will determine the appropriate language by reference to the entity in the database for which they are providing service. Thus in the case of Booking the service will take from the Booking record the languageId which will have been placed on the record at the time the booking was made and will indicate the language of the interface that the viewer had set at the time of checkout.

  • Taxonomy Data - All taxonomy records in the database have a translationId which references a record in the Translation table. This table has a column per approved language and essentially acts as a language-aware string resolver.

  • Product Content - Each product will have one or more related records in the ProductContent table FOR EACH LANGUAGE that it is available in. A product will always have a minimum of a ROOT content record (this stores the name and description of the product). Commonly a product will have many other records each providing different types of content (ie Inclusions, Exclusions, Meeting Point, Itinerary etc). The table includes a column lanuageId. When either the productList or productItem queries are executed this table will be filtered by productId and languageId after which the name and description for the Product will be taken from the ProductContent having type=ROOT and, if requested, the contentList will be taken from all other records.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.