Locale specific date in jekyll - jekyll

I am trying out jekyll for website creation. I am using jekyll-bootstrap.
The default configuration has the page archive, where all the posts are listed grouped by year and month of the post date. Currently the months appear in English. I've looked at the code and this is an excerpt which is responsible for putting the date:
{% capture this_month %}{{ post.date | date: "%B" }}{% endcapture %}
I've found a lot of information here, so there is a way to specify the desired locale. But how can you make jekyll respect it? Simply adding
default_locale: "lt"
in _config.yml naturally does not work.

You can overwrite the current month by using Liquid Date Format:
{% assign m = page.date | date: "%-m" %}
{{ page.date | date: "%-d" }}
{% case m %}
{% when '1' %}Januar
{% when '2' %}Februar
{% when '3' %}März
{% when '4' %}April
{% when '5' %}Mai
{% when '6' %}Juni
{% when '7' %}Juli
{% when '8' %}August
{% when '9' %}September
{% when '10' %}Oktober
{% when '11' %}November
{% when '12' %}Dezember
{% endcase %}
{{ page.date | date: "%Y" }}
If your date is, for example 2015-02-20, the output will be 20 Februar 2015

Because i18n is not available on github pages, I built upon answer of #Kleo Petroff and the answer of #Falc, I set up a way to have a date with locale names defined in a YAML file :
The code is almost the same without the whole case statement :
{% capture i18n_date %}
{{ page.date | date: "%-d" }}
{% assign m = page.date | date: "%-m" | minus: 1 %}
{{ site.data.fr.months[m] }}
{{ page.date | date: "%Y" }}
{% endcapture %}
I set the following data-structure (could be in _config.yml, or in some _data/some.yml file), in the above code the file is _data/fr.yml :
months:
- Janvier
- Février
- Mars
- Avril
- Mai
- Juin
- Juillet
- Aout
- Septembre
- Octobre
- Novembre
- Décembre
Note that page.date | date: "%-m" output the month number as a string, ie June number is actually "6" not 6, liquid silently casts that string to a number when piping the minus filter.
During development it was not something I was aware and thus liquid didn't returned anything when passing m with the value "6" to site.data.fr.months[m], I only saw the trick when looking at Falc answer.

Use plugin i18n from jekyll supported plugins page.
Note that github pages does not support local plugins. See the related issue.

My turn to share my solution without plugin inspired by the previous ones:
I've created an include with some parameters like: {% translated_date.html ... %}
The idea is to translate the months and days names respecting the format using the date filter syntax (ex: "%A %-d %B %Y"). The strings used for the translation are in yaml files stores in _data.
Code and usage available on the repo oncleben31/jekyll-date-basic-i18n.
Example of integration in my blog with Jekyll sources available in the repo oncleben31/oncleben31-cc. Look at the layouts post.html and home.html.

I started using the i18n plugin suggested by #mpictas but when Jekyll regenerates a page it starts to print "error" instead of the localized date. So I removed the plugin and started to use this simple code, similar to the "case/when" solution:
{% assign months = "Enero|Febrero|Marzo|Abril|Mayo|Junio|Julio|Agosto|Septiembre|Octubre|Noviembre|Diciembre" | split: "|" %}
{% assign m = page.date | date: "%-m" | minus: 1 %}
{% assign day = page.date | date: "%d" %}
{% assign month = months[m] %}
{% assign year = page.date | date: "%Y" %}
<span class="date">{{ day }}/{{ month }}/{{ year }}</span>

You also could write an own Liquid filter in a Ruby file like following:
module DateFilter
MONTHS = %w(Januar Februar März April Mai Juni July August September Oktober November Dezember)
def german_long_month(input)
MONTHS[input.strftime("%m").to_i - 1]
end
end
Liquid::Template.register_filter(DateFilter)
When you put this file into the _plugins folder of your Jekyll site you can use the filter in your template file like other filter.
{{ post.date | german_long_month }}

You can combine #Falc answer with jekyll-multiple-languages-plugin:
Simply use in template:
{% assign months = "january|february|march|april|may|june|july|august|september|october|november|december" | split: "|" %}
{% assign m = post.date | date: "%-m" | minus: 1 %}
{% assign day = post.date | date: "%d" %}
{% assign month = months[m] %}
{% assign year = post.date | date: "%Y" %}
<span class="post-meta">{{day}} {% t month %} {{year}}</span>
Then in _i18n/en.yml, .../pl.yml, .../any-language.yml:
january: January
february: February
march: March
april: April
may: May
june: June
july: July
august: August
september: September
october: October
november: November
december: December

I am working in a fully automated translations to locale to work on GitHub pages (no plugins), I modified previous answers to this solution as a first approximation of what I need:
{{ page.date | date: "%-d" }}
{% assign m = page.date | date: "%-m" | minus: 1 %}
{{ site.data.ui-text[site.locale].months[m] }}
{{ page.date | date: "%Y" }}
in _config.yml you can set de default site locale as in my case:
locale: "es-ES"
in _data I have a YAML file (ui-text.yaml) containing:
# English (default)
# -----------------
en: &DEFAULT_EN
months:
- January
- February
- March
- April
- May
- June
- July
- August
- September
- October
- November
- December
en-US:
<<: *DEFAULT_EN
# Spanish
# -------
es: &DEFAULT_ES
months:
- Enero
- Febrero
- Marzo
- Abril
- Mayo
- Junio
- Julio
- Agosto
- Septiembre
- Octubre
- Noviembre
- Diciembre
es-ES:
<<: *DEFAULT_ES
# french
# -------
fr: &DEFAULT_FR
months:
- Janvier
- Février
- Mars
- Avril
- Mai
- Juin
- Juillet
- Aout
- Septembre
- Octobre
- Novembre
- Décembre

Based upon the answer of #Brice I came up with this solution to output the month name in Spanish.
<p class="post-meta">
{% assign mes_index = page.date | date: "%-m" | minus: 1 %}
{% assign mes = site.data.spanish.meses[mes_index] %}
<time datetime="{{ page.date | date_to_xmlschema }}">
{{ page.date | date: "%-d" }} de {{ mes }} de {{ page.date | date: "%Y" }}
</time>
</p>
"Mes" means "month" in Spanish.
_data/spanish.yml
meses:
- Enero
- Febrero
- Marzo
- Abril
- Mayo
- Junio
- Julio
- Agosto
- Septiembre
- Octubre
- Noviembre
- Diciembre

Related

Jekyll Liquid Syntax, how to dereference a property

I am grouping the posts on my site using this liquid tag.
{% assign postsForYear = site.posts | group_by_exp:"post", "post.date | date: '%Y'" | where: "name", "2020" %}
When I echo the postForYear out to screen, I see this:
{"name"=>"2020", "items"=>[#, #, #, #, #, #], "size"=>6} 0
Which makes sense, as I have six posts for that year. However, I am trying to dereference that object and get the .size property, which I can see in the output...I can't figure out the syntax!
How to get the .Size property?
None of these work.
{{ postsForYear.size }}
{{ postsForYear.items | size }}
After that, I would love to learn how to foreach my way through the posts...this also seems simple but doesn't work!
Ah, I figured it out. Strangely, the postsForYear array was actually treated like an array itself, so I had to index into the first position to get to the properties.
{% assign postsForYear = site.posts |
group_by_exp:"post", "post.date | date: '%Y'" | where: "name", "2020" %}
###doesn't work
{{ postsForYear.items | size }}
### does work
{{ postsForYear[0].items | size }}
### example
Posts for year {{ postsForYear[0].name }}, total posts {{ postsForYear[0].size }}
>Posts for year 2020, total posts 6
And to answer my other question, how to foreach your way through:
{% for post in postsForYear[0].items %}
<h1>{{post.title}}</h1><br>
{% endfor %}

'where' not finding entries given a parameter to look for in CSV data

jekyll 2.4.0, Mac 10.12.5
{% for year_of_interest in (1997..2017) reversed %}
<large_year>{{year_of_interest}}</large_year>
{% for paper in site.data.publications | where,'site.data.publications.Year',year_of_interest %}
<div class="publication_card">
<a class="article_title" href="../../{{paper.Link}}" title="{{paper.Abstract}}">{{paper.Title}}</a>
</div>
<div class="paper_author_container">
<span class="paper_authors">{{paper.Author | upcase}}</span>
<br>
<span class="journal_info">{{paper.Year}}—{{paper.Journal | upcase}}</span>
<button class="btn" data-clipboard-text="{{paper.BibTex}}">
BIBTEX
</button>
</div>
{% endfor %}
{% endfor %}
The input CSV has this shape and the Year is a simple number:
Title,Link,Abstract,Author,BibTex,Year,Journal,SupplementalLink
background: I'm stuck! I have a CSV where each row represents publication metadata for papers from 1997 to 2016. Some years have many papers, but each year has at least 1 publication. I want a header for each year, and the publications to be posted below. Unfortunately, the where filter does not find any of the articles for a given year in the for loop.
Current functionality: under each header, it shows a list of ALL publications.
Desired: it should only show publications where the paper.Year == year_of_interest.
Thanks in advance!
Three problems here :
You can't filter in a loop
{% for paper in site.data.publications | where,'site.data.publications.Year', year_of_interest %}
Will not work as expected because it always returns all datas.
{% assign filtered = site.data.publications | where,'site.data.publications.Year', year_of_interest %}
{% for paper in filtered %}
Will work, but not now ...
Where filter filters on a key
It's not {% site.data.publications | where,'site.data.publications.Year', year_of_interest %}
but : {% site.data.publications | where,'Year', year_of_interest%}}
Nearly working ...
CSV datas are strings
{{ site.data.publications[0].Year | inspect }} returns "1987" and double quotes around signifies that its a string and that your filter, looking for an integer as "Year" value will never find it. You have to look for a string instead.
To cast an integer into a string you can append an empty string to it.
{% for year_of_interest in (1997..2017) reversed %}
{% comment %} casting an integer to a string {% endcomment %}
{% assign yearAsString = year_of_interest | append:"" %}
{% comment %} filtering datas {% endcomment %}
{% assign selectedEntries = site.data.publications | where: "Year", yearAsString %}
{% for paper in selectedEntries %}
Now, it does the job.
Notes :
1 - Use the | inspect filter to debug, it's useful to determine type of value (string, integer, array, hash).
2 - You can also cast a string to an integer by adding zero to it :
{% assign numberAsString = "1997" %}
{{ numberAsString | inspect }} => "1997"
{% assign numberAsInteger = numberAsString | plus: 0 %}
{{ numberAsInteger | inspect }} => 1997
This is the only documentation for the where filter because it is not a default liquid filter.
https://gist.github.com/smutnyleszek/9803727
site.data.publication.Year is an object of site.data.publications I believe you only need to specify "Year" This is case sensitive by the way.
{% for paper in site.data.publications | where, "Year", year_of_interest %}

Generate category-specific RSS feed using Jekyll using GitHub pages

I am trying to generate a post category-specific RSS feed for a GitHub Pages Jekyll website.
I understand that the jekyll-feed plugin can generate an RSS feed for all posts, but according to this GitHub Issue, category-specific feeds are not yet supported.
Other approaches to generate a category-specific feed (i.e., here and here are not supported by GitHub Pages because it won't support custom plugins.
Is there a way to generate a category-specific RSS feed using Jekyll with GitHub Pages?
You can just create your own XML or RSS file. For this answer I have used this example to build on. I also used Wikipedia for an example RSS feed.
filename: categoryname.rss
---
layout: null
---
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title>{{ site.title }}</title>
<description>{{ site.description }}</description>
<link>{{ site.url }}</link>
<lastBuildDate>{{ site.time | date_to_rfc822 }}</lastBuildDate>
<pubDate>{{ site.time | date_to_rfc822 }}</pubDate>
<ttl>1800</ttl>
{% for post in site.categories.categoryname %}
<item>
<title>{{ post.title }}</title>
<description>{{ post.description }}</description>
<link>{{ post.url }}</link>
<guid isPermaLink="true">{{ site.url }}{{ post.url }}</guid>
<pubDate>{{ post.date | date_to_rfc822 }}</pubDate>
</item>
{% endfor %}
</channel>
</rss>
The title should be something like: 'mysitenames categoryname archive'. The description could be your category description. Link is the link to the category. The 'lastBuildDate' value could be the date of your last post and 'pubDate' could be the same.
Please let me know if you have any questions.
Following I've published for collections hosted on GitHub Pages, however, with modification it might by useful for categories too.
Downloading within another project is facilitated via Git's submodule features...
cd your-project
git checkout gh-pages
mkdir -vp _layouts/modules
git submodule add -b master --name feed-rss2\
https://github.com/liquid-utilities/feed-rss2.git\
_layouts/modules/feed-rss2
Note, https URLs are required for GitHub Pages compatibility.
... which should cause code similar to the following to become available...
_layouts/modules/feed-rss2/feed-rss2.html
---
layout: null
version: 0.0.1
license: AGPL-3.0
author: S0AndS0
---
{% capture workspace__rss2 %}
{% assign date_format = '%a, %d %b %Y %T %z' %}
{% assign collection_name = page.collection_name | default: include.collection_name | default: nil %}
{% assign target_collection = site[collection_name] %}
{% assign collection_home = page.collection_home | default: collection_name %}
{% assign collection_description = page.description | default: site.description %}
{% assign this_time_stamp = page.date | date: '%s' %}
{% assign latest_time_stamp = page.date | date: '%s' %}
{% assign rss_items_has_output = false %}
{% capture workspace__rss2__entries %}
{% for post in target_collection %}
{% if page.relative_path == post.relative_path or post.slug == 'feed' %}
{% continue %}
{% elsif post.slug == collection_name or post.slug == 'index' %}
{% continue %}
{% endif %}
{% assign rss_items_has_output = true %}
{% assign post_synopsis = post.description | default: post.excerpt %}
{% assign post_date_updated = post.date_updated | default: post.date %}
{% assign this_time_stamp = post_date_updated | date: '%s' %}
{% if latest_time_stamp < this_time_stamp %}{% comment %}> Syntax highlighting work-around{% endcomment %}
{% assign latest_time_stamp = this_time_stamp %}
{% endif %}
<item>
<title>{{- post.title | xml_escape -}}</title>
<link>{{- post.url | absolute_url -}}</link>
<guid isPermaLink="true">{{- post.url | absolute_url -}}</guid>
<pubDate>{{- post_date_updated | date: date_format -}}</pubDate>
<description>{{- post_synopsis | xml_escape -}}</description>
</item>
{% assign post_synopsis = nil %}
{% endfor %}
{% endcapture %}
{% assign page_rights = page.copyright | default: collection_home.copyright | default: site.copyright %}
{% assign page_rights = page_rights | default: site.github.license.name | default: 'All rights reserved' %}
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title>{{- page.title | default: 'RSS Title' | xml_escape -}}</title>
<link>{{- page.url | absolute_url -}}</link>
<description>{{ collection_description | xml_escape }}</description>
<copyright>Copyright {{ site.time | date: '%Y' }} {{ page_author | xml_escape }}. {{ page_rights | xml_escape }}</copyright>
<lastBuildDate>{{- site.time | date: date_format -}}</lastBuildDate>
<pubDate>{{- latest_time_stamp | date: date_format -}}</pubDate>
<ttl>{{- page.time_to_live | default: '1800' -}}</ttl>
{% if rss_items_has_output %}
{{ workspace__rss2__entries | strip }}{% assign workspace__rss2__entries = nil %}
{% endif %}
</channel>
</rss>
{% endcapture %}{{ workspace__rss2 | strip }}{% assign workspace__rss2 = nil %}
... Setting a feed file within a collection directory would then look like...
_example-collection/example-collection.rss
---
layout: modules/feed-rss2/feed-rss2
title: Example Collection
collection_name: example-collection
collection_home: /example-collection/
date: 2019-07-23 21:12:13 -0700
content_type: xhtml
permalink: /:collection/:name:output_ext
---
... and minor additions of FrontMatter of each post/page...
_example-collection/something-about-something.markdown
---
layout: post
title: Something About Something
description: Example collection page about something
date: 2019-07-21 11:42:11 -0300
time_to_live: 1800
---
... Which should render results similar to the live demo hosted by GitHub Pages.
Note, check the documentation for updating and cloning tips and caveats.
Regardless of if ya utilize the above project's code I'll suggest looking into the submodule features (hint git help submodule), because such things allow for code reuse in multiple repositories while keeping things version tracked and easily updated. Plus submodules are compatible with GitHub Pages, meaning that submodules are about as close to third-party plugin support as one can get without exploring Continuous Integration solutions.
The other key take-away would be, to try and utilize layouts for these types of solutions.
Feel free to comment if ya get stuck or something from above is confusing.
Expanding on JoostS answer:
---
layout: null
---
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title>{{ site.title }}</title>
<description>{{ site.description }}</description>
<link>{{ site.url }}</link>
<lastBuildDate>{{ site.time | date_to_rfc822 }}</lastBuildDate>
<pubDate>{{ site.time | date_to_rfc822 }}</pubDate>
<ttl>1800</ttl>
{% for post in site.pages %}
{% if post.title %}
<item>
<title>{{ post.title }}</title>
<description>{{ post.description }}</description>
<link>{{ site.url }}{{ post.url }}</link>
<guid isPermaLink="true">{{ site.url }}{{ post.url }}</guid>
<pubDate>{{ post.date | date_to_rfc822 }}</pubDate>
</item>
{% endif %}
{% endfor %}
</channel>
</rss>

Ordinalize date formatting in Liquid/Jekyll (e.g. "1st", "3rd" and "4th")

Is it possible to add day of the month suffixes to a date format in Liquid or Jekyll? For example: January 23rd or May 18th.
I've referred to the Shopify wiki, but I'm shocked to see that there's no formatting there for it. Surely something that simple should be? :/
The Liquid Template Engine that Jekyll uses doesn't offer the ability to ordinalize (e.g. turn "1" into "1st" and "3" into "3rd") out of the box. However, it is possible to use filters and tags to provide that functionality. The snippet below produces the day of month number with an ordanilized string appended. It also removes the leading zero for the first nine days of the month.
{% assign d = page.date | date: "%-d" %}
{% case d %}
{% when "1" or "21" or "31" %}{{ d }}st
{% when "2" or "22" %}{{ d }}nd
{% when "3" or "23" %}{{ d }}rd
{% else %}{{ d }}th
{% endcase %}
For a full date with month, day and year, use this:
{% assign d = page.date | date: "%-d" %}
{{ page.date | date: "%B" }}
{% case d %}{% when "1" or "21" or "31" %}{{ d }}st{% when "2" or "22" %}{{ d }}nd{% when "3" or "23" %}{{ d }}rd{% else %}{{ d }}th{% endcase %},
{{ page.date | date: "%Y" }}
which produces output like:
September 21st, 2013
Note: The code is split onto multiple lines to make it easier to read. It will render fine in HTML but will have extra whitespace in the source code. If that bothers you, simply move everything to one line.
If you are interested in other date formatting options, I create this reference: Jekyll (and GitHub Pages) Liquid Date Formatting Examples

For loops in Liquid: using reversed in conjunction with limit:1

I'm building a simple blog using Jekyll, and I'm pulling my hair out trying to figure out this problem.
The index page of the site is meant to feature a single, most recent article, with the structure looking something like below (pardon the mess):
{% for post in site.posts reversed limit:1 %}
<div class="post">
<div class="post-inner">
<h3 class="posttitle">{{ post.title }}</h3>
<p class="postdate">{{ post.date | date: "%d %B %Y" }}</p>
{{ post.content }}
</div>
</div>
{% endfor %}
The above template works perfectly fine when the limit is not restrictive (i.e does not exist or is set to the length of the array). It seems to only be when the limit is actually restricting the result that the loop ignores reversed.
I've tried clearing the browser cache, which is what got it working without limit:1, but the progress ends there.
Thanks for the help, and I would be happy to provide more detail if this is not enough.
What is Jekyll actually outputting for you?
From what I understand, the reversed filter is applied last. So let assume you posted the first 15 days of Aug, and lets also say you do something like this:
{% for post in site.posts limit:5 %}
{{ post.content }}
{% endfor %}
You post array would be ordered in the following pattern
[Aug 15, Aug 14, Aug 13, Aug 12, Aug 11]
And then if you reversed it
{% for post in site.posts reversed limit:5 %}
{{ post.content }}
{% endfor %}
You post array would be ordered in the following pattern
[Aug 11, Aug 12, Aug 13, Aug 14, Aug 15]
With all that said, I'm a little perplexed as to why you are not using
{% for post in site.posts limit:1 %}
Hack to have custom reversed sorting by custom field with limit:
{% assign items = site.items | sort: 'some_field' | reverse %}
{% for item in items limit:10 %}
<li>{{ item.title }}</li>
{% endfor %}
It's important to assign to some custom var, sort (and reverse) there and only then loop with limit.