Feedback

Internationalization

#Translating Elements

The form has an option, called multilingual which is if set true a language selector appears above the form similarly to tabs or wizard. This selector will list all the languages configured at the form or in the global configuration and when clicked, certain elements will display their values in the choosen language.

Let's create a multilingual form in two languages:

<?php

namespace App\Forms;

class MultilingualForm extends \Laraform
{
  public $multilingual = true;

  public $languages = [
    'en' => [
      'code' => 'en',
      'label' => 'English'
    ],
    'de' => [
      'code' => 'de',
      'label' => 'German'
    ]
  ]

  public function schema() {
    return [
      // this will be translated
      'title' => [
        'type' => 't-text',
        'label' => 'Title',
        'rules' => 'required'
      ],

      // this will NOT be translated
      'category' => [
        'type' => 'select',
        'label' => 'Category',
        'items' => [
          'audiobooks' => 'Audiobook',
          'paperback' => 'Paperback',
        ]
      ]
    ]
  }
}

As you can see we're using the t- abbrevation for elements which should be translated. You can still you eg. a simple text type element in a multilingual form, but that will not be translated.

Check out the form real time and also the data structure:

// Form data:

      

Translated Data

As you've seen from the previous example elements with translated data will output an object instead of a single value, which contains different values for each language code.

{
  title: {
    en: '...',
    de: '...'
  },
  category: '...'
}

Validation

When translatable elements are being validated all of their inputs are validated separately. If an input has error in any language which is not the currently selected language it's messages will be shown above the form in the errors list.

Error messages coming from translatable elements will have a (${languageCode}) prefix when shown in the error collector above the form.

errors: [
  "The Title field is required. (en)",
  "The Title field is required. (de)"
]

Check out Validation chapter to see how you can create separate validation rules for languages.

#Translatable Elements

As we've previously mentioned translation does not make sense with all kind of element types. Currently the followings are supported:

  • t-text
  • t-textarea
  • t-trix

#Storing Values

By default if you attempt to insert a translatable element's value into a single column it will be stored as a JSON.

You can also implement your custom storing method or you can use Laraform's built-in translator that supports Astrotomic/laravel-translatable.

To create your custom translator check out vendor/laraform/laraform-laravel/src/Contracts/Translator for the interface or vendor/laraform/laraform-laravel/src/Translator directory for existing implementations.

#Using Laravel Translatable

There is a popular library Astrotomic/laravel-translatable which Laraform supports out of the box. This means that there is a translator class that can be used to make an element compatible with laravel-translatable. To use it, simple add the following class to your element as translator option:

<?php

namespace App\Forms;

use Laraform\Translator\LaravelTranslatable;

class ArticleForm extends \Laraform
{
  public $multilingual = true;

  public function schema() {
    return [
      'title' => [
        'type' => 't-text',
        'label' => 'Title',
        'translator' => LaravelTranslatable::class
      ]
    ];
  }
}

Now when you set up your model using laravel-translatable and make title a translatable attribute you'll see that title will be placed in the translations table.

#Configuring Default Translator

You can set the default translator in configuration to avoid adding it to each element:

/*
|--------------------------------------------------------------------------
| Default translator
|--------------------------------------------------------------------------
|
| The default translator class to be used when using multilingual elements
|
*/
'translator' => Laraform\Translator\LaravelTranslatable::class,

#Locales

A locale file is an object which contains various translation tags in groups like elements, messages, etc. You can check out locale files in @laraform/laraform/src/locales and see what tags are in use.

The form's selected locale object is available in all Laraform components under locale property.


// ./path/to/locales/en_US.js

export default {
  elements: {
    date: {
      format: 'Y-m-d',
      dataFormat: 'YYYY-MM-DD',
    },
    // ...
  },
  messages: {
    accepted: 'The :attribute must be accepted.',
    active_url: 'The :attribute is not a valid URL.',
    after: 'The :attribute must be a date after :date.',
    // ...
  },
  // ...
}

// ./path/to/FormInstance.vue

<script>
  export default {
    mixins: [Laraform],
    data: () => ({
      schema: {
        name: {
          type: 'text',
          created() {
            // Ouputs: 'Y-m-d'
            console.log(this.selectedLocale.elements.date.format)
          }
        }
      }
    }),
    created() {
      // Ouputs: 'Y-m-d'
      console.log(this.selectedLocale.elements.date.format)
    }
  }
</script>
In the main Laraform component the locale is available as selectedLocale because locale is already reserved for choosen locale name.

Each component has a common translation method used as __(tag, params) which accepts the name of the translation tag with dot . syntax and parameters if there's any. Translation tags can define variables starting with : like The :attribute must be accepted..

Based on the previous example the same tags can be reached using __() method:


// ./path/to/FormInstance.vue

<script>
  export default {
    mixins: [Laraform],
    data: () => ({
      schema: {
        name: {
          type: 'text',
          created() {
            // Ouputs: 'Y-m-d'
            console.log(this.__('elements.date.format'))
          }
        }
      }
    }),
    created() {
      // Ouputs: 'Y-m-d'
      console.log(this.__('elements.date.format'))
    }
  }
</script>

#Switching Locale

To choose a locale you may either set a default one in the Configuration or specify it at a form instance, using locale property:

<?php

namespace App\Forms;

class LocalizedForm extends \Laraform
{
  public $locale = 'fr_FR';

  public function schema() {
    // ...
  }
}

#Adding Locale

To add a locale you may call Laraform installer's .locale() method before installing the Laraform plugin:

import Vue from 'vue'
import Laraform from '@laraform/laraform'
import fr_FR from './path/to/fr_FR'

Laraform.locale('fr_FR', fr_FR)

Vue.use(Laraform)

const app = Vue({
  el: '#app'
})

#Extending Locale

You may also extend an existing locale by simply merging two objects:

import Vue from 'vue'
import Laraform from '@laraform/laraform'
import en_US_original from '@laraform/laraform/src/locales/en_US'

var en_US = Object.assign({}, en_US_original, {
  myLocaleTag: '...'
})

Laraform.locale('en_US', en_US)

Vue.use(Laraform)

const app = Vue({
  el: '#app'
})

#Creating Locale

To create a locale check out existing tags at @laraform/laraform/src/locales/en_US/index.js and create your own locale object using the same structure.

#Available Locales

Here's the list of available locales:

  • en_US - English (US)

We are working toward extending are locales and we are happy receiving help. If you would like to participate in translation of Laraform drop up a line at hello@laraform.io.

#Dates

You may notice translation date token tags like in locale files:

date: {
  format: 'Y-m-d',
  dataFormat: 'YYYY-MM-DD',
}

The format refers to the date input's format using flatpickr's formatting tokens, while dataFormat sets the format of the element's value using momentjs tokens.

#Timezones

#App Timezone

You may specify your application's timezone in Configuration under timezone property:

/*
|--------------------------------------------------------------------------
| App timezone
|--------------------------------------------------------------------------
|
| Timezone of the application.
|
*/
'timezone' => 'America/Los_Angeles',

Now if a user enters a date in a datetime element it's value will be transformed from the user's timezone to application's timezone.

For example if user have Europe/Berlin timezone and enters 2019-03-01 18:00:00 the actual value of the element which gets submitted will be 2019-03-01 09:00:00.

#User Timezone

By default the user's timezone is guessed by momentjs, but you may also set a specifiy timezone for your users using userTimezone property in configuration:

/*
|--------------------------------------------------------------------------
| App timezone
|--------------------------------------------------------------------------
|
| Timezone of the application.
|
*/
'timezone' => 'Berlin/Europe',
Be cautious when using userTimezone property and only use it if your application is intended for use only in a specific timezone.

If both timezone and userTimezone are left blank or have the same values no timezone transformation will occur.