Write
Dates and languages
Write dates year first, choose how the pages show them, and set the language, or languages, a site is written in.
Write a date
| Written | Statac |
|---|---|
2026-10-04 |
Reads the day. |
2026-10-04 09:30 |
Reads the day and the time, in the site’s time zone. |
2026-10-04T09:30 |
Reads the same: a space or a T parts the day from the time. |
2026-10-04 09:30:15 |
Reads the seconds after the minutes. |
2026-10-04 09:30+01:00 |
Reads the offset from UTC, written Z, +01:00, +0100 or +01, after a space if you like. |
A date in front matter or in statac.yaml is written year first.
You seldom need to type one out:
| Where the date comes from | What is written |
|---|---|
A stamp, such as date: =today |
statac serve or statac stamp writes the day over it: 2026-10-06. A stamp never writes an offset. |
A file named 2026-10-04-post-1.md |
Nothing: the page takes its date from its name. A date: line giving another day wins. |
statac import |
Each old date year first, keeping no more than it held: a day alone stays a day. |
Time zones
In statac.yaml:
timezone: Europe/London
A date with no offset is read in the site’s timezone, which also
decides what today is, for a stamp and for a post waiting for its day.
statac new writes the computer’s own zone.
Without a timezone, such dates are read as UTC, never in the
computer’s zone.
How dates look
In statac.yaml:
date_format: Wed 31 Dec 2025
date_format shows how dates look, by example. Write one moment,
Wednesday 31 December 2025 at 15:04, the way you want every date
written:
date_format |
2026-03-04 09:05 is shown as |
|---|---|
31 December 2025 |
4 March 2026 |
Wed 31 Dec 2025 |
Wed 4 Mar 2026 |
December 31, 2025 |
March 4, 2026 |
31/12/2025 |
04/03/2026 |
2025-12-31 |
2026-03-04 |
Wednesday 31st December 2025 at 3.04pm |
Wednesday 4th March 2026 at 9.05am |
Anything else, such as at or /, is written as it stands.
| You write | Statac writes |
|---|---|
31 |
The day, 4 |
31st |
The day in the language’s words, 4th |
12, Dec or December |
The month, 03, Mar or March |
2025 or 25 |
The year, 2026 or 26 |
Wed or Wednesday |
The weekday |
15:04 |
The time, 09:05 |
3.04pm or 3:04 PM |
The time, 9.05am or 9:05 AM |
- With the month in figures, the day and the month keep a leading zero,
04/03/2026, unlessdate_zeros: falseinstatac.yamlmakes it4/3/2026. - The site’s
date_formatneeds the day, the month and the year in full. - A date with no time is shown without one, and without the words
leading into the time:
Wednesday 4th March 2026. - Write the month and the weekday in the site’s
language:
31 décembre 2025on a site in French.
Without date_format, a date is written as the day, the month in words
and the year: 4 March 2026 in English. German, Spanish, Japanese and
Korean have a usual form of their own.
<p>{{ page.date | date("December 2025") }}</p>
The date filter shows one date in a style of its own, written the
same way. Here any piece may be left out, and the year may be short.
In statac.yaml:
date_short: 31 Dec 2025
<time datetime="{{ post.date | moment }}">{{ post.date | date(site.date_short) }}</time>
The filter’s example can be a value of your own in statac.yaml.
date_short is no setting of Statac’s:
statac new writes three such lines for its
templates.
Languages
In statac.yaml:
language: fr
language names the site’s language by its code, such as en, en-GB
or fr. Dates are written in its words and digits, the writing’s
quotation marks become its own, and templates have it as
page.language. A site that names none is in English, as en.
Statac has the words of eight languages:
| Language | Code |
|---|---|
| Arabic | ar |
| English | en |
| French | fr |
| German | de |
| Japanese | ja |
| Korean | ko |
| Persian | fa |
| Spanish | es |
For the seven besides English, Statac has the months and weekdays, the words for morning and afternoon, the quotation marks, the direction and the digits, from the Unicode CLDR. Anything else comes from the site’s own file.
A code with a region, such as en-GB, uses its language’s words where
Statac has none for the region. In any other language, dates are written
in figures and quotes stay as typed, until you give Statac the words.
Words for another language
In languages/sw.yaml:
months: [Januari, Februari, Machi, Aprili, Mei, Juni,
Julai, Agosti, Septemba, Oktoba, Novemba, Desemba]
weekdays: [Jumatatu, Jumanne, Jumatano, Alhamisi, Ijumaa, Jumamosi, Jumapili]
A file in languages/ named after a code gives a language’s words, for
a language Statac doesn’t know or to change some of its own. With this
one, a site in Swahili writes date_format: 31 Desemba 2025.
Every line is optional. A line the file gives replaces Statac’s, and a line it leaves out keeps Statac’s.
- A line with nothing after its colon takes Statac’s line away:
digits:alone inlanguages/fa.yamlkeeps Persian dates in the digits0to9. - A file for a region adds to its language:
languages/fr-CA.yamladds to Statac’sfr.
| Line | What it holds |
|---|---|
months, months_short |
The months, January first, as a date writes them. |
months_alone, months_short_alone |
The months with no day beside them, where the language writes them differently. |
weekdays, weekdays_short |
The days of the week, Monday first. |
days |
The days of the month as words, 1st to 31st, for a format written with 31st. Statac has them in English alone. |
am_pm |
The words for morning and afternoon: [am, pm] in English. |
digits |
The ten digits, zero first. Dates and a footnote’s number are written in them, and the digits filter writes any other number in them. |
quotes |
The outer pair of quotation marks, then the inner pair: quotes: « » “ ”. Without it, quotes in the writing stay straight. See punctuation. |
inside_quotes |
A space written inside the outer pair, such as inside_quotes: " " for a space a line can’t break at. |
no_break_before, no_break_after |
Marks before which, or after which, a typed space becomes one a line can’t break at: no_break_before: "; : ! ?". None is added where none was typed. |
direction |
rtl for a language written right to left: templates have it as page.direction, and a footnote’s arrow back to the text turns from ↩ to ↪. |
back_to_the_text |
What a screen reader says for a footnote’s link back to the text. Statac writes it as the link’s aria-label, and hands it to a site’s own footnotes.html as label. |
callouts |
The names of the five kinds of callout: note, tip, important, warning and caution, in that order. A site’s own snippets/markdown/callout.html has them as title. |
Statac has back_to_the_text and callouts in English only. For any
other language they come from the site’s own file, which statac new
writes with both lines in English for you to translate.
On a site with no snippet for callouts, Statac’s own callout shows no name in any language.
The words your pages show
The site's own words are in English in `data/words.yaml`, under `fr`, and Statac's in `languages/fr.yaml`. Translate them there.
Every word a new site’s templates and snippets show readers, such as
“Older posts” or a callout’s name, is in data/words.yaml, under each
language’s code. statac new writes them in English for every
language. Translate the lines under a language’s code, and its pages
show them.
The folders’ names in the menu, such as “Notes”, are not among them:
each is the title in the folder’s index.md.
For a language added to language later, copy the English list under
the new code, then translate it.
The starter lists every word in the file.
Templates shows how a template reads them, and
starting a site how --update adds a word a newer
template shows.
A site in several languages
In statac.yaml, the main language first:
language: [ar, en]
content/
index.md
post-1.md
en/
index.md
post-1.md
notes/
post-2.md
A folder at the top of content/ named exactly as language writes a
code holds that language’s pages: here every page under content/en/
is in English. Every page outside the language folders is in the main
language, Arabic here.
- A page can’t choose its language in its front matter: where it stands says.
- The main language may have a folder of its own too, such as
content/ar/. Pages outside every language folder are still in the main language, so a page at/can welcome readers in every language.
Given several languages, statac new makes a folder and a home page for
each besides the main one: see Starting a site.
Lists and feeds in each language
| Arabic, at the top | English, in content/en/ |
|
|---|---|---|
| Home page | / |
/en/ |
post-1.md |
/post-1/ |
/en/post-1/ |
Tag Rust |
/tags/rust/ |
/en/tags/rust/ |
| Feed | /feed.xml |
/en/feed.xml |
Each language has a top: its folder, or content/ for a main language
with no folder. The top is the language’s own list, every post in the
language, and site.posts on its pages. A page in one language is in no
other language’s lists or feeds.
- A top with no
index.mdgets a home page built withtemplates/home.html. Each folder directly inside a top has a page and a feed, as lists and feeds describe. - Tags and series are each language’s own:
Ruston an English page andRuston an Arabic page are two tags. - A post’s previous and next, a list’s later pages,
related(page), aposts:line andeach: site.postsstay within the page’s language.in("blog")names a folder beneath the language’s top. - A feed is built in its list’s language, so it needs a
titlefor that language:titleoren.title. - Where the main language has a folder,
content/itself is no language’s list, and has no feed unless its page asks for one. On its pages,siteanswers for the main language.
Addresses in each language
In statac.yaml:
pages.permalink: /{year}/{slug}/
An Arabic post at the top lands at /2026/post-1/, and an English one
at /en/2026/post-1/. Each address pattern is read from its language’s
top: permalink: on a page or handed down, tags.permalink,
series.permalink, and an each: page’s pattern. So permalink: /about/
on content/en/about.md publishes it at /en/about/.
Addresses written out are read from the top of the site: links in the
writing, redirect_from and redirect_to. An English post that was at
/en/2025/post-1/ writes that whole in redirect_from.
Settings for one language
In statac.yaml:
language: [ar, en]
title: Site 1
en.title: Site 2
en.date_format: Dec 31, 2025
title and date_format can be written for one language: its code, a
dot and the setting, on one line. The plain line covers every language
without one of its own.
A date_format for one language is written in that language’s words.
One for every language may be in any of the site’s languages, and each
page writes its dates in its own: date_format: 31 December 2025 shows
2026-10-04 as 4 October 2026 on English pages and as 4 أكتوبر 2026
on Arabic ones. The date filter reads its examples the same way.
Translations
With Arabic at the top of content/ and English in content/en/:
content/
about.md
blog/
post-1.md
en/
about.md
blog/
post-1.md
| Two pages in different languages are translations where | Such as |
|---|---|
| They stand at the same path below their languages’ tops | content/about.md and content/en/about.md above, and the two blog/post-1.md |
| Only the ending differs | about.md and about.html |
One is a folder’s index.md where the other is a file |
post-1/index.md, a post with its pictures beside it, and post-1.md |
Both have the same translation_key, any text you choose |
content/about.md and content/en/about-us.md, each with translation_key: about |
| They stand at one place below two folders whose own pages share a key | content/ar/books/book-1.md and content/en/book-list/book-1.md, once books/index.md and book-list/index.md share one |
A page with a key is linked by its key alone, and a page outside every language folder is linked only by a key. The pages Statac makes have translations too: each language’s home page, and a tag’s or a series’ page where the same name stands in the other language’s address.
A draft, or a post waiting for its day, is no page’s translation until it is published.
Each language in templates
A new site’s base.html already does everything below. For templates
of your own:
| Name | What it gives |
|---|---|
page.language |
The page’s language, by its code, for lang. |
page.direction |
ltr or rtl, the way the page’s lines run, for dir. |
page.translations |
The same page in the site’s other languages, in the order language lists them. Each has its url, title and language. Empty where there is none. |
site.languages |
Each language’s code, the main one first. Asked by a code, that language’s home page: site.languages.en.url. A site that names no language has en alone. |
site.language, site.title |
Those of the page being built. |
site.posts, site.folders, site.tags, site.series, site.feed |
Those of the page’s language. |
site.pages |
Every page, in every language. Choose one language’s by page.language. |
<html lang="{{ page.language }}" dir="{{ page.direction }}">
For search engines, each page lists in its <head> every language it
is in, itself among them, and names the main language’s page with
x-default:
{% if page.translations and site.url is defined %}
{% set main = site.languages | first %}
<link rel="alternate" hreflang="{{ page.language }}" href="{{ page.url | absolute }}">
{% for other in page.translations %}
<link rel="alternate" hreflang="{{ other.language }}" href="{{ other.url | absolute }}">
{% endfor %}
{% for one in [page] + page.translations if one.language == main %}
<link rel="alternate" hreflang="x-default" href="{{ one.url | absolute }}">
{% endfor %}
{% endif %}
absolute needs the site’s url, so the links are written only where
the site has one.
A switch between languages links each other language to the page’s translation in it, or else to that language’s home page:
<nav aria-label="Languages">
{% for code in site.languages if code != page.language %}
{% set same = page.translations | selectattr("language", "eq", code) | list %}
{% set there = same[0] if same else site.languages[code] %}
<a href="{{ there.url }}" hreflang="{{ code }}" lang="{{ code }}">{{ code }}</a>
{% endfor %}
</nav>
The sitemap can list translations too: sitemaps.
Where next?
- Front matter: stamps, which write a date into a page for you
- Settings:
timezone,date_zerosand every other line ofstatac.yaml - The starter: every file
statac newwrites, and every word indata/words.yaml - Lists, tags and series: the lists each language keeps, and their order
Something unclear or wrong? Open an issue on GitHub.