skip to Main Content

In my Rails 5 app I am using Liquid to let my users generate content.

Based on my users input, I init my template with something like this:

string   = "Order {{ order.id }} was created {{ order.date | date: '%A %d/%m-%Y' }}"
template = Liquid::Template.parse(string)
result   = template.render({'order' => {'id' => '123', 'date' => order.date}})

This would print something a la:

'Order 123 was created Sunday 14/01-2018'

But how do I build Liquid date localization into my Rails app?

It does not seem to be supported in the documentation. However Shopify themselves seems to have build localization into their Liquid implementation.

I suppose I would need to pass my template a locale (en, fr, etc.) and a locale file. My Rails locale file looks like this:

en:
  datetime: &datetime
    month_names:
      [~, January, February, March, April, May, June, July, August, September, October, November, December]
    day_names:
      [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday]
    abbr_day_names:
      [~, Sun, Mon, Thue, Wed, Thu, Fri, Sat]
    formats:
       default: "%d/%m/%Y"
       long: "%A %d/%m-%Y"

And I call it with:

l(order.date, :format => :long, :locale => 'en')

I would love to have access to a similar date localization inside my Liquid template.

4

Answers


  1. Chosen as BEST ANSWER

    I ended up using the link proveded by @Ben, and wrote up this solution:

    # config/initializers/liquid_filters.rb
    module I18nFilters
      def l(date, format)
        I18n.l(date, :format => format.to_sym)
      end
    end
    
    Liquid::Template.register_filter(I18nFilters)
    

    Now, when invoking that new method:

    {{ order.date | l: 'long' }}
    

    it will print out:

    'Sunday 14/01-2018'
    

    with Sunday being whatever is in day_names withing the locale file.


  2. When you pass your date object with order.date

    result   = template.render({'order' => {'id' => '123', 'date' => order.date}})
    

    Can you pass a localized date or localized datetime? Then when it gets rendered it should be correct.

    Otherwise, you could add the date to a span with class name you can target (for fallback) and “fix” it on the client side with a combination of pure Javascript and a library like Moment.js

    # https://stackoverflow.com/a/39161134/793330
    const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
    
    Login or Signup to reply.
  3. It looks like you’re missing only a reference to t method.

    Instead of

    string   = "Order {{ order.id }} was created {{ order.date | date: '%A %d/%m-%Y' }}"
    

    Try with

    string   = "Order {{ order.id }} was created {{ order.date | t: date: '%A %d/%m-%Y' }}"
    
    Login or Signup to reply.
  4. You can do it by using the JavaScript Intl API.

    Add this filter to .eleventy.js:

      eleventyConfig.addFilter("displayDate", function(date, locale) {
        return new Intl.DateTimeFormat(locale, { dateStyle: "long" }).format(date);
      });
    

    Now you can show localized dates by using this in, for example, your Liquid template:

    {{ date | displayDate: locale }}
    

    Here, date contains the date and locale contains the locale.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search