diff --git a/config/schema/telephone_formatter.schema.yml b/config/schema/telephone_formatter.schema.yml
new file mode 100644
index 0000000..337e861
--- /dev/null
+++ b/config/schema/telephone_formatter.schema.yml
@@ -0,0 +1,13 @@
+field.formatter.settings.telephone_formatter:
+  type: mapping
+  label: 'Telephone link format settings'
+  mapping:
+    format:
+      type: integer
+      label: 'Telephone format'
+    link:
+      type: boolean
+      label: 'Number as link?'
+    default_country:
+      type: string
+      label: 'Default formatter country'
diff --git a/src/FormatterInterface.php b/src/FormatterInterface.php
index 40df4c7..7ac29a0 100644
--- a/src/FormatterInterface.php
+++ b/src/FormatterInterface.php
@@ -16,12 +16,12 @@ interface FormatterInterface {
    *   Input phone number.
    * @param string $format
    *   Format option.
-   * @param null|string $country
+   * @param null|string $region
    *   Country code.
    *
    * @return string
    *   Formatted string.
    */
-  public function format($input, $format, $country = NULL);
+  public function format($input, $format, $region = NULL);
 
 }
diff --git a/src/Plugin/Field/FieldFormatter/TelephoneFormatter.php b/src/Plugin/Field/FieldFormatter/TelephoneFormatter.php
new file mode 100644
index 0000000..9307a58
--- /dev/null
+++ b/src/Plugin/Field/FieldFormatter/TelephoneFormatter.php
@@ -0,0 +1,202 @@
+<?php
+
+namespace Drupal\telephone_formatter\Plugin\Field\FieldFormatter;
+
+use Drupal\Core\Field\FieldItemInterface;
+use Drupal\Core\Field\FormatterBase;
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Url;
+use libphonenumber\PhoneNumberFormat;
+
+/**
+ * Plugin implementation of the 'telephone_formatter' formatter.
+ *
+ * @FieldFormatter(
+ *   id = "telephone_formatter",
+ *   label = @Translation("Formatted telephone"),
+ *   field_types = {
+ *     "telephone"
+ *   }
+ * )
+ */
+class TelephoneFormatter extends FormatterBase {
+
+  /**
+   * @var \Drupal\telephone_formatter\FormatterInterface
+   */
+  protected $formatter;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function defaultSettings() {
+    return array(
+        'format' => PhoneNumberFormat::INTERNATIONAL,
+        'link' => TRUE,
+        'default_country' => NULL,
+      ) + parent::defaultSettings();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, FormStateInterface $form_state) {
+    $elements['format'] = array(
+      '#type' => 'select',
+      '#title' => $this->t('Format'),
+      '#description' => $this->t('List of available formats'),
+      '#default_value' => $this->getSetting('format'),
+      '#options' => self::availableFormats(),
+    );
+    $elements['link'] = array(
+      '#type' => 'checkbox',
+      '#title' => $this->t('Link'),
+      '#description' => $this->t('Format as link'),
+      '#default_value' => $this->getSetting('link'),
+    );
+    $elements['default_country'] = array(
+      '#type' => 'select',
+      '#title' => $this->t('Default country'),
+      '#description' => $this->t('If field allows internal telephone numbers you can choose which country this number belongs to by default. It is highly advised to enable telephone validation for this field to ensure that telephone number is valid and can be parsed and reformatted.'),
+      '#default_value' => $this->getSetting('default_country'),
+      '#options' => [NULL => $this->t('- Do not use default country -')] + \Drupal::service('country_manager')->getList(),
+    );
+
+    return $elements;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = array();
+
+    $formats = self::availableFormats();
+    $summary[] = $this->t('Format: @format', ['@format' => $formats[$this->getSetting('format')]]);
+    $summary[] = $this->t('Link: @link', ['@link' => $this->getSetting('link') ? $this->t('Yes') : $this->t('No')]);
+    if ($default_country = $this->getSetting('default_country')) {
+      $summary[] = $this->t('Default country: @default_country',
+        ['@default_country' => $default_country]);
+    }
+
+    return $summary;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function viewElements(FieldItemListInterface $items, $langcode) {
+    $element = array();
+    $this->formatter = \Drupal::service('telephone_formatter.formatter');
+    foreach ($items as $delta => $item) {
+      try {
+        if ($this->getSetting('link')) {
+          $element[$delta] = $this->viewLinkValue($item);
+        }
+        else {
+          $element[$delta] = $this->viewFormattedValue($item);
+        }
+      }
+      catch (\Exception $e) {
+        $element[$delta] = $this->viewPlainValue($item);
+      }
+    }
+
+    return $element;
+  }
+
+  /**
+   * Generate the output appropriate for one field item.
+   *
+   * @param string $item
+   *   One field value.
+   *
+   * @return array
+   *   The textual output generated as a render array.
+   */
+  protected function viewPlainValue(FieldItemInterface $item) {
+    // The text value has no text format assigned to it, so the user input
+    // should equal the output, including newlines.
+    return [
+      '#type' => 'inline_template',
+      '#template' => '{{ value }}',
+      '#context' => ['value' => $item->value],
+    ];
+  }
+
+  /**
+   * Generate the output appropriate for one field item.
+   *
+   * @param string $item
+   *   One field value.
+   *
+   * @return array
+   *   The textual output generated as a render array.
+   */
+  protected function viewFormattedValue(FieldItemInterface $item) {
+    // The text value has no text format assigned to it, so the user input
+    // should equal the output, including newlines.
+    return [
+      '#type' => 'inline_template',
+      '#template' => '{{ value }}',
+      '#context' => ['value' => $this->getFormattedValue($item)],
+    ];
+  }
+
+  /**
+   * Generate the output appropriate for one field item.
+   *
+   * @param \Drupal\Core\Field\FieldItemInterface $item
+   *   One field value.
+   *
+   * @return array
+   *   The textual output generated as a render array.
+   */
+  protected function viewLinkValue(FieldItemInterface $item) {
+      // Render each element as link.
+      $element = array(
+        '#type' => 'link',
+        // Use custom title if available, otherwise use the telephone number
+        // itself as title.
+        '#title' => $this->getFormattedValue($item),
+        // Prepend 'tel:' to the telephone number.
+        '#url' => Url::fromUri($this->formatter->format($item->value, PhoneNumberFormat::RFC3966, $this->getSetting('default_country'))),
+        '#options' => array('external' => TRUE),
+      );
+
+      if (!empty($item->_attributes)) {
+        $element['#options'] += array('attributes' => array());
+        $element['#options']['attributes'] += $item->_attributes;
+        // Unset field item attributes since they have been included in the
+        // formatter output and should not be rendered in the field template.
+        unset($item->_attributes);
+      }
+    return $element;
+  }
+
+  /**
+   * @param \Drupal\Core\Field\FieldItemInterface $item
+   * @return string
+   */
+  protected function getFormattedValue(FieldItemInterface $item) {
+    return $this->formatter->format(
+      $item->value,
+      $this->getSetting('format'),
+      $this->getSetting('default_country')
+    );
+  }
+
+  /**
+   * List of available formats.
+   */
+  public static function availableFormats() {
+    return [
+      PhoneNumberFormat::INTERNATIONAL => t('International'),
+      PhoneNumberFormat::E164 => t('E164'),
+      PhoneNumberFormat::NATIONAL => t('National'),
+      PhoneNumberFormat::RFC3966 => t('RFC3966'),
+    ];
+  }
+
+}
