Localising dates in Ghost themes

Ghost, by default, outputs dates in English using the timezone of the server hosting your blog. Although there are no settings inside of Ghost for changing this, it is possible to change both the language and the timezone used to output dates in your theme using jQuery, moment.js and moment.js timezone.

In the following guide, I'll show you how to switch the locale to German and also how to output dates converted to the 'Europe/Berlin' timezone.

Note: This guide assumes you're comfortable editing a Ghost theme. If you need help getting started with theming for Ghost, there's an editing guide in our support documentation.

Providing dates to moment

For this to work, you'll first need to make sure that your theme is outputting dates in a format that moment can pick up and manipulate. This means using Ghost's date helper to output a complete machine-readable date in an HTML attribute.

For example, if you're using the Casper theme, change the <time></time> HTML blocks to look like this:

<time class="post-date" datetime="{{date format="YYYY-MM-DDTHH:mm:ss.SS\Z"}}"></time>

The format YYYY-MM-DDTHH:mm:ss.SS\Z can be understood by moment.js. Note that we're only outputting it as an attribute, rather than rendering the date on the page. Using an html data attribute would also work here.

Including jQuery

Many Ghost themes, including the default theme Casper, already have jQuery included. If you theme doesn't yet have jQuery you'll need to add it, or see the section on improving performance at the end of this guide for alternatives.

To include jQuery, add the following snippet to the default.hbs file of your theme, somewhere near {{ghost_foot}} or just above the </body> tag:

<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.min.js"></script>

Change your locale

To change your local, you'll need to grab both the moment.js file, and the local you want and include them in your theme.I recommend grabbing these from cdnjs.cloudflare.com, and placing them in your default.hbs underneath where you added jQuery:

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>  
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/locale/de.js"></script>  

Once these are included, you'll need to add a final piece of JavaScript just beneath where you included jQuery and the moment files.

This code first sets the moment locale to 'de'. Then it loops through each date on the page, and replaces the content of the tag with a brand new, correctly localised date using moment:

<script type="text/javascript">  
$(document).ready(function () {
  moment.locale('de');

  $('.post-date').each(function (i, date) {
    var $date = $(date);

    $date.html(
      moment($date.attr('datetime'))
        .format('LLL')
    );
  });
});
</script>  

LLL is a format specific to the locale provided, you can look up how moment will format dates for your local, by visiting the moment locale docs and choosing your locale.

Change your timezone

The majority of Ghost themes don't output the time a post was published. For some blogs with a high volume of posts, distinguishing posts based on time is important and for these blogs, Ghost's use of UTC (or whatever timezone your server runs) isn't ideal.

To change your timezone, you'll need to grab both the moment.js & moment timezone libraries with the timezone data. Again, I recommend grabbing these from cdnjs.cloudflare.com, and placing them in your default.hbs underneath where you added jQuery:

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>  
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.4.1/moment-timezone-with-data-2010-2020.min.js"></script>  

Once you have these included in your theme, you'll need to add a small snippet of JavaScript that will read all of the dates on the page, and replace them with a transformed version.

<script type="text/javascript">  
$(document).ready(function () {
  $('.post-date').each(function (i, date) {
    var $date = $(date); 

    $date.html(
      moment($date.attr('datetime'))
        .tz('Europe/Berlin')
        .format('DD MMMM YYYY HH:mm')
      );
  });
});
</script>  

This snippet calls .tz('Europe/Berlin') to convert the date into the correct timezone for Germany. Use the map in the moment timezone docs to look up the name for your timezone.

This snippet also uses a custom date format to output both the date and time. Moment's formatting documentation has full info on how to design your own custom format.

Combining locale & timezone

Here's a combined version, switching both the locale and the timezone:

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>  
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/locale/de.js"></script>  
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.4.1/moment-timezone-with-data-2010-2020.min.js"></script>

<script type="text/javascript">  
  $(document).ready(function () {
    moment.locale('de');

    $('.post-date').each(function (i, date) {
      var $date = $(date);

      $date.html(
        moment($date.attr('datetime'))
          .tz('Europe/Berlin')
          .format('LLL')
       );
    });
  });
</script>  

Improving performance

If you're keen on keeping your theme super-lightweight, there are some improvements that can be made to the provided examples. The first and most obvious is to remove jQuery as there are plenty of other ways to do $document.ready() without jQuery.

Although moment.js no longer provides a tool for creating a custom build of timezone data, it is relatively straightforward to open the timezone data file to pull out just the data you need. For example, this gist contains just the data for GMT, which will ensure your blog respects time changes during the Summer if you're in the UK.

Note: If you do choose to create custom builds of moment.js that are stored locally, please remember to use the asset helper.

Long term, it is expected that Ghost will add settings to make this easier. Short term, I hope this hack helps you get your blog setup just the way you want.