# Multilanguage Setup

The blökkli starterkit is built with multilingual support in mind. The frontend and the backend are prepared to handle
multiple languages. We use four pillars to achieve full multilanguage integration in our headless setup.

## 1. Drupal Content Translation

The first and most important part ist the standard Drupal content translation. Drupal provides a powerful translation
system that allows us to translate all content entities, such as nodes, paragraphs, and taxonomy terms.
The content translation is done via Drupal backend or in blökkli via the frontend.

We leverage the GraphQL `routeQuery` to fetch automatically the correct translations based on the current language.
![drupal_translation.png](/content/images/drupal_translation.png)

## 2. Nuxt Language Negotiation

The [Nuxt Language Negotiation](https://github.com/dulnan/nuxt-language-negotiation) provides basic multi-language
support for our Nuxt 3 application. It's minimal by design and tries to do only a few things:

**Features**

* SSR language negotiation/detection based on path prefix, Accept-Language or custom (e.g. via API).
* Single source of truth for "current language" state
* Multi-language routes via languageMapping meta property

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  modules: ['nuxt-language-negotiation'],

  languageNegotiation: {
    // Define the available languages.
    languages: ['en', 'de', 'fr', 'it'],
    // We use two negotiators: Path prefix takes precedence. In cases where no
    // path prefix is available, we fall back to Accept-Language headers.
    negotiators: [
      pathPrefix(),
      query({ keys: ['language', 'langcode'] }),
      acceptLanguage(),
    ],
    debug: false,
  },
})
```

## 3. Nuxt Easy Texts

This module provides a string extractor similar to the famous Drupal `t` function.

It provides a `$texts()` function that can be used in Vue components to translate strings.
The module automatically collects translatable texts with a rollup plugin and loads their translations at runtime (for
example from an API endpoint). The compiled build will only contain the keys and no text values.

```html [components/Carousel.vue]

<nav class="carousel__navigation-container--inner">
  <button :aria-label="$texts('slides.prev', 'Previous')" />
  <button :aria-label="$texts('slides.next', 'Next')" />
</nav>
```

```graphql [queries/translations.graphql]
# This file is automatically generated by the nuxt-easy-texts module.
# Any manual changes will be overwritten.

fragment easyTexts on TextsLoader {
  home: getText(key: "home", default: "Home")
  slides__next: getText(key: "next", context: "slides", default: "Previous")
  slides__prev: getText(key: "prev", context: "slides", default: "Next")
}
```

## 4. Drupal Texts module

This [drupal module is the backend counterpart](https://www.drupal.org/project/texts) to the Nuxt Easy Texts module. It
provides a Drupal UI to manage
key-based
translations.
It allows you to manage your frontend translations within Drupal with ease. The module offers an improved UI to manage
translations in the Drupal backend.

It supports pluralization (singular / plural) and placeholders, like the normal t() function.
The module comes with optional GraphQL support to fetch the translations in a decoupled environment.
![drupal_texts.png](/content/images/drupal_texts.png)
