Polskie daty w Hugo

tech • 663 słowa • 4 minuty czytania

Blog ten prowadzony jest w ojczystym języku, zatem dobrze jest zadbać o poprawne polskie zasady językowe, sformułowania, tłumaczenia, zwroty… Dotyczy to także dat i odmian nazw miesięcy. Kiedyś na szybko zrobiłem jakiś hack w szablonie używanym w WordPresie, a teraz muszę coś podobnego ogarnąć na stronie w Hugo.

Generator Hugo mimo iż posiada jakieś wsparcie dla wielojęzycznych stron, to jednak nie dotyczy to samych dat. Póki co język Go, w jakim tworzone jest to narzędzie, nie posiada takiej możliwości. Przy formatowaniu dat z nazwami lub skrótami miesięcy i dni tygodnia dostaniemy standardowe angielskie słówka.

Wiele rozwiązań tego problemu można znaleźć w sieci. Bazują one głównie na idei przedstawionej w dokumentacji - w dodatkowych plikach z danymi (lub w miejscu trzymania tłumaczeń) przechowywane są listy z nazwami miesięcy, do których mamy dostęp w szablonie. W poszczególnych implementacjach, zależnie od struktury i dostępnej wielojęzyczności strony, całość może się nieznacznie różnić w szczegółach.

Ja nie chcę dodawać specjalnie jednego pliku z nazwami miesięcy. No może gdybym miał więcej “jakiś” szablonowych danych na stronie to byłoby inaczej. Zamiast tego mógłbym wrzucić to w dodatkowe parametry w pliku konfiguracyjnym:

params:
  months: [
    unused, stycznia, lutego, marca, kwietnia, maja, czerwca,
    lipca, sierpnia, września, października, listopada, grudnia
  ]

i użyć bezpośrednio w szablonie:

<time>{{ .Date.Day }} {{ index .Site.Params.Months .Date.Month }} {{ .Date.Year }}</time>

Niemniej nie chcę także zaśmiecać sobie “configa” niekonfiguracyjnymi rzeczami, więc pozostaje trzymanie takiej tablicy w szablonie. Żeby się nie powtarzać w szablonach to idealnym miejscem do tego są szablony cząstkowe.

A może iść dalej i zrobić sobie dedykowaną funkcję? W szablonach Go/Hugo nie ma możliwości tworzenia funkcji, ale za pomocą partial, które od jakiegoś czasu wspierają zwracanie wartości można zasymulować taką funkcję.

{{/*
	Get month name in Polish language
	usage: $month := partial "func/GetMonthName" <date-obj>
*/}}

{{ $Months := slice "unused" "stycznia" "lutego" "marca" ... "października" "listopada" "grudnia" }}
{{ return index $Months .Month }}

Powyższy kod zapisany w pliku partials/func/GetMonthName.html można “wywołać” tak:

<time>
	{{- .Date.Day }} {{ partial "func/GetMonthName" .Date }} {{ .Date.Year -}}
</time>

Może mógłbym to tak zostawić. Jednak skoro daty będą prezentowane w tagu <time/> w niestandardowej formie to wypada dołączyć machine-readable znacznik czasu. Idealnie, aby był on formacie zgodnym z ISO 8601. Dodatkowo, przewiduję taką postać daty wyświetlać tylko w kontekście wpisów (posty, listy). To prowadzi mnie do zapakowania wszystkiego inline w dedykowany szablon cząstkowy, który wygeneruje taki oto fragment HTML-a:

<time datetime="2020-06-15T12:00:00+02:00">15 czerwca 2020</time>

Do otrzymania daty w postaci ISO8601/RFC3339 należy użyć taki ciąg formatujący: "2006-01-02T15:04:05Z07:00". Wynika to ze sposobu formatowania dat w Hugo. Bazuje on na pakiecie time z Go, który to używa trochę nienaturalnego zapisu w porównaniu do innych języków i przyzwyczajeń. Opiera się na referencyjnej dacie Jan 2 15:04:05 2006 MST i numerycznych pozycjach w stringu. Szczegóły w dokumentacji, a ciekawostki na stronie “Hugo dateFormat”.

Składając wszystko do kupy, otrzymałem w pliku partials/post-date-tag.html taki kod:

{{/*
	Render <time/> tag with post date in Polish
	usage: partial "post-date-tag.html" <date-obj>
*/}}

{{- $ISO8601 := "2006-01-02T15:04:05Z07:00" -}}
{{- $Months := slice "unused" "stycznia" "lutego" "marca" ... "października" "listopada" "grudnia" -}}

<time {{ .Format $ISO8601 | printf "datetime=%q" | safeHTMLAttr }}>
	{{- .Day }} {{ index $Months .Month }} {{ .Year -}}
</time>

Żeby zapobiec “wy-escape-owaniu” znaku + w wynikowym stringu trzeba go przepuścić przez safeHTMLAttr, a ten działa na pełnym atrybucie (name=value), dlatego taki trochę potworek wychodzi ;)

Taki “partial” zaspokaja moje obecne potrzeby z formatowaniem dat w polskich realiach. Na podobnej zasadzie można spolszczyć dni tygodnia, nie tylko pełne nazwy, ale i skróty. Jeśli jednak takie polskie odpowiedniki używane mają być w wielu miejscach i kontekstach to zdecydowanie lepiej będzie skierować się w stronę wspomnianych plików danych.

Do takich plików z danymi można także wrzucić jakieś “stałe”, które będą widoczne w szablonach. Takie elementy mogą też “naprawiać” napotykane niedociągnięcia - na przykład brak predefiniowanych stałych z formatem dat jakie dostępne są w time.go. Trzeba samemu się posiłkować, co widać było wyżej w moim kodzie ($ISO8601). To na pewno poprawiłoby czytelność i mogło ustrzec przed głupimi błędami, czy literówkami…

Komentarze (0)

Dodaj komentarz

/dozwolony markdown/

/nie zostanie opublikowany/