> For the complete documentation index, see [llms.txt](https://taffo.gitbook.io/hotcoffee/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://taffo.gitbook.io/hotcoffee/customization-and-logic/multilanguage.md).

# Multilanguage

### Introduction

Thanks to the [spatie/laravel-translatable](https://github.com/spatie/laravel-translatable) package you can translate your models into multiple languages. HotCoffee's own `Article` and `InfoPage` models take advantage of this. Additionally there is a helper method `language_fields()` that will generate the HTML input fields in your forms in separate tabs on the page for each language that you declare in `hotcoffee.php` config file.

### Usage

Define all the locales for the translatable models in the `languages` array in `config/hotcoffee.php`. Each language should be an associative array with this structure`'acronym' => 'full name'`. The first language is going to be the default one.

```php
'languages' => [
        'en' => 'English',
        'bg' => 'Български',
        'de' => 'Deutsche',
],
```

If you have defined more than one language in the array you will be able to see the flag icons above the **title** and **content** fields when creating or editing info pages and articles. Clicking an icon will switch to the tab that contains the fields for that particular locale.

<div align="left"><img src="/files/-M23vAZEjsfaNfhLaG_n" alt=""></div>

These fields and flag icons are generated, because we called the `language_fields()` helper method in the template. Flag images are loaded from the `public/vendor/hotcoffee/img/flags` directory. If the acronym of a locale is 'de', then the loaded image will be `de.svg` from that same directory. Simply put any missing flag svg files that you need there.&#x20;

To make your own models translatable they should use the `Spatie\Translatable\HasTranslations` trait. You need to also define all translatable fields:

```php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Spatie\Translatable\HasTranslations;

class Product extends Model
{

	use HasTranslation;
	
	/**
   * Translatable attributes.
   */
	public $translatable = ['name', 'description'];
	
	/**
   * The attributes that are mass assignable.
   */
  protected $fillable = [
    'name', 'description', 'price'
  ];
}
```

Now in your template:

```markup
<form action="{{ route('products.store') }}" method="post">
  <h6 class="heading-small text-muted mb-4">New Product</h6>
  
  {{ csrf_field() }}
  
  <!-- TRANSLATABLE FIELDS -->
  {!! language_fields([
    'name' => ['type' => 'text', 'title' => 'Product Name'],
    'description' => ['type' => 'textarea', 'title' => 'Content', 'class' => 'tinymce'],
  ], $product ?? null) !!}
  <!-- END TRANSLATABLE FIELDS -->
  
  <!-- NON TRANSLATABLE FIELDS -->
  <input type="text" name="price" />
  <!-- END NON TRANSLATABLE FIELDS -->
  
  <input type="submit" />
</form>
```

The HTML output of `language_fields()` method in this case would look something like this (given, that we have set 3 locales - **en**, **bg** and **de**):

```markup
<!-- Flag Icons -->
<ul class="nav nav-pills nav-pills-circle" role="tablist" id="tabs_2">

    <li class="nav-item">
        <a class="nav-link rounded-circle  active " id="en" data-toggle="tab" href="#tab-en" role="tab" aria-controls="en" aria-selected="true">
            <img src="https://yourapp.com/vendor/hotcoffee/img/flags/en.svg" alt="English" class="flag-img">
        </a>
    </li>

    <li class="nav-item">
        <a class="nav-link rounded-circle " id="bg" data-toggle="tab" href="#tab-bg" role="tab" aria-controls="bg" aria-selected="true">
            <img src="https://yourapp.com/vendor/hotcoffee/img/flags/bg.svg" alt="Български" class="flag-img">
        </a>
    </li>
    
    <li class="nav-item">
        <a class="nav-link rounded-circle " id="de" data-toggle="tab" href="#tab-de" role="tab" aria-controls="bg" aria-selected="true">
            <img src="https://yourapp.com/vendor/hotcoffee/img/flags/de.svg" alt="Deutsche" class="flag-img">
        </a>
    </li>

</ul>

<!-- Tabs with language fields -->
<div class="tab-content" id="lang-tabs">

    <!-- English Fields -->
    <div class="tab-pane fade" id="tab-en" role="tabpanel" aria-labelledby="tab-en">
        <label class="form-control-label" for="input-name">Name</label>
        <input type="text" name="name[en]" class="form-control" />
        
        <label class="form-control-label" for="input-name">Content</label>
        <textarea name="description[en]" class="tinymce form-control"><textarea>
    </div>
    
    <!-- Bulgarian Fields -->
    <div class="tab-pane fade" id="tab-bg" role="tabpanel" aria-labelledby="tab-bg">
        <label class="form-control-label" for="input-name">Name</label>
        <input type="text" name="name[bg]" class="form-control" />
        
        <label class="form-control-label" for="input-name">Content</label>
        <textarea name="description[bg]" class="tinymce form-control"><textarea>
    </div>

    <!-- German Fields -->
    <div class="tab-pane fade" id="tab-de" role="tabpanel" aria-labelledby="tab-de">
        <label class="form-control-label" for="input-name">Name</label>
        <input type="text" name="name[de]" class="form-control" />
        
        <label class="form-control-label" for="input-name">Content</label>
        <textarea name="description[de]" class="tinymce form-control"><textarea>
    </div>
</div>
```

The function will also add "has-danger" class if a validation of a field has failed.

<div align="left"><img src="/files/-M29sio7f4vZTlxHQILC" alt=""></div>

It will also populate the `value=""` attribute (or content of a `<textarea>` field) automatically when editing a model. Hence why you need to specify the variable name of the model as a second parameter:

```markup
{!! language_fields($fields = array(), $product ?? null !!}
```

{% hint style="info" %}
Say you have a method called `edit()` in your `ProductController.php`. In this method we get the product from the database, pass the `$product` variable to the template and return the product.blade.php view. However you may also have a `create()` method, that will return the same view. But this time we don't have to get a product from the database. We will create a new one. Hence the `$product` variable is not defined. To not get an error "***unidentified variable name $product***" when using calling `language_fields()` you can ad&#x64;**`$product ?? null`** as the second parameter.
{% endhint %}

When the form is submitted, the content of the request will be this:

<div align="left"><img src="/files/-M2DV-BwAIS0ZbK2wkN_" alt=""></div>

Now in your `store()` method you can do this:

```php
Product::create($request->all());
```

Of course  when using Eloquent's `create()` or `update()` methods you will need to specify the `fillable` or `guarded` attribute on the model.

```php
public $translatable = ['name', 'description'];
protected $fillable = ['name', 'description', 'price'];
```

Whenever you need to display the content of the product for example you can just do this:

```php
$product->content; // Returns value of content field in the current app locale.
```

If you want to get the content field in a specific locale:

```php
$product->getTranslation('content', 'bg'); // Returns value of content field in Bulgarian.
```

{% hint style="success" %}
To learn more about translating models visit <https://github.com/spatie/laravel-translatable>
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://taffo.gitbook.io/hotcoffee/customization-and-logic/multilanguage.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
