From: Sergey Matveev <stargrave@stargrave.org>
Date: Mon, 5 Dec 2022 12:50:18 +0000 (+0300)
Subject: Templates translation
X-Git-Tag: v0.27.0^0
X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=bec350105fae0b0d2719a347c47929817ba57a7d;p=sgblog.git

Templates translation
---

diff --git a/cmd/sgblog/gemini-entry.tmpl b/cmd/sgblog/gemini-entry.tmpl
index 22f7aff..4e234fc 100644
--- a/cmd/sgblog/gemini-entry.tmpl
+++ b/cmd/sgblog/gemini-entry.tmpl
@@ -1,22 +1,22 @@
 {{$CR := printf "\r"}}20 text/gemini{{$CR}}
 # {{.Title}}
-What: {{.Commit.Hash.String}}
-When: {{.When}}
-{{if .Topics}}Topics:{{range .Topics}} {{.}}{{end}}{{end}}
+{{$.T.Get "What"}}: {{.Commit.Hash.String}}
+{{$.T.Get "When"}}: {{.When}}
+{{if .Topics}}{{$.T.Get "Topics"}}:{{range .Topics}} {{.}}{{end}}{{end}}
 ```
 {{.Commit.Message}}```
 {{- if .Note}}
-## Note:
+## {{$.T.Get "Note"}}:
 ```
 {{.Note}}
 ```
 {{end -}}
 {{- if .Cfg.CommentsEmail}}
-=> mailto:{{.Cfg.CommentsEmail}}?subject={{.TitleEscaped}} leave comment
+=> mailto:{{.Cfg.CommentsEmail}}?subject={{.TitleEscaped}} {{$.T.Get "leave a comment"}}
 {{end}}{{range $idx, $comment := .Comments}}
-## comment {{$idx}}:
+## {{$.T.Get "comment"}} {{$idx}}:
 ```
 {{$comment}}
 ```
 {{end}}
-Generated by: SGBlog {{.Version}}
+{{$.T.Get "Generated by"}}: SGBlog {{.Version}}
diff --git a/cmd/sgblog/gemini-menu.tmpl b/cmd/sgblog/gemini-menu.tmpl
index e8f86bc..756b79c 100644
--- a/cmd/sgblog/gemini-menu.tmpl
+++ b/cmd/sgblog/gemini-menu.tmpl
@@ -1,8 +1,8 @@
 {{$CR := printf "\r"}}20 text/gemini{{$CR}}
-# {{.Cfg.Title}} {{if .Topic}}(topic: {{.Topic}}) {{end}}({{.Offset}}-{{.OffsetNext}})
-{{if .Cfg.AboutURL}}=> {{.Cfg.AboutURL}} About{{end}}
-{{if .Offset}}=> /?offset={{.OffsetPrev}}{{if .Topic}}&topic={{.Topic}}{{end}} Prev{{end}}
-{{if not .LogEnded}}=> /?offset={{.OffsetNext}}{{if .Topic}}&topic={{.Topic}}{{end}} Next{{end}}
+# {{.Cfg.Title}} {{if .Topic}}({{$.T.Get "topic"}}: {{.Topic}}) {{end}}({{.Offset}}-{{.OffsetNext}})
+{{if .Cfg.AboutURL}}=> {{.Cfg.AboutURL}} {{$.T.Get "about"}}{{end}}
+{{if .Offset}}=> /?offset={{.OffsetPrev}}{{if .Topic}}&topic={{.Topic}}{{end}} {{$.T.Get "prev"}}{{end}}
+{{if not .LogEnded}}=> /?offset={{.OffsetNext}}{{if .Topic}}&topic={{.Topic}}{{end}} {{$.T.Get "next"}}{{end}}
 
 {{$datePrev := "0001-01-01" -}}
 {{- range .Entries -}}
@@ -14,4 +14,4 @@
 
 {{range .Topics -}}=> /?topic={{.}} Topic: {{.}}
 {{end}}
-Generated by: SGBlog {{.Version}}
+{{$.T.Get "Generated by"}}: SGBlog {{.Version}}
diff --git a/cmd/sgblog/gemini.go b/cmd/sgblog/gemini.go
index 1a7bc57..1d80fde 100644
--- a/cmd/sgblog/gemini.go
+++ b/cmd/sgblog/gemini.go
@@ -32,6 +32,7 @@ import (
 	"github.com/go-git/go-git/v5"
 	"github.com/go-git/go-git/v5/plumbing"
 	"github.com/go-git/go-git/v5/plumbing/object"
+	"github.com/vorlif/spreak"
 	"go.stargrave.org/sgblog"
 )
 
@@ -55,6 +56,7 @@ func serveGemini(cfgPath string) {
 	if err != nil {
 		log.Fatalln(err)
 	}
+	initLocalizer(cfg.Lang)
 
 	headHash, err := initRepo(cfg)
 	if err != nil {
@@ -145,6 +147,7 @@ func serveGemini(cfgPath string) {
 			offsetPrev = 0
 		}
 		err = TmplGemMenu.Execute(os.Stdout, struct {
+			T          *spreak.Localizer
 			Cfg        *Cfg
 			Topic      string
 			Offset     int
@@ -155,6 +158,7 @@ func serveGemini(cfgPath string) {
 			Topics     []string
 			Version    string
 		}{
+			T:          localizer,
 			Cfg:        cfg,
 			Topic:      topic,
 			Offset:     offset,
@@ -175,6 +179,7 @@ func serveGemini(cfgPath string) {
 		}
 		title := msgSplit(commit.Message)[0]
 		err = TmplGemEntry.Execute(os.Stdout, struct {
+			T            *spreak.Localizer
 			Title        string
 			Commit       *object.Commit
 			When         string
@@ -185,6 +190,7 @@ func serveGemini(cfgPath string) {
 			Version      string
 			TitleEscaped string
 		}{
+			T:        localizer,
 			Title:    title,
 			Commit:   commit,
 			When:     commit.Author.When.Format(sgblog.WhenFmt),
diff --git a/cmd/sgblog/gopher-entry.tmpl b/cmd/sgblog/gopher-entry.tmpl
index fa17e3b..164cb6c 100644
--- a/cmd/sgblog/gopher-entry.tmpl
+++ b/cmd/sgblog/gopher-entry.tmpl
@@ -1,20 +1,20 @@
-What: {{.Commit.Hash.String}}
-When: {{.When}}
+{{$.T.Get "What"}}: {{.Commit.Hash.String}}
+{{$.T.Get "When"}}: {{.When}}
 ------------------------------------------------------------------------
-{{if .Topics}}Topics:{{range .Topics}} {{.}}{{end}}{{end}}
+{{if .Topics}}{{$.T.Get "Topics"}}:{{range .Topics}} {{.}}{{end}}{{end}}
 ------------------------------------------------------------------------
 {{.Commit.Message -}}
 {{- if .Note}}
 ------------------------------------------------------------------------
-Note:
+{{$.T.Get "Note"}}:
 {{.Note}}{{end -}}
 {{- if .Cfg.CommentsEmail}}
 ------------------------------------------------------------------------
-leave comment: mailto:{{.Cfg.CommentsEmail}}?subject={{.TitleEscaped}}
+{{$.T.Get "leave a comment"}}: mailto:{{.Cfg.CommentsEmail}}?subject={{.TitleEscaped}}
 {{end}}{{range $idx, $comment := .Comments}}
 ------------------------------------------------------------------------
-comment {{$idx}}:
+{{$.T.Get "comment"}} {{$idx}}:
 {{$comment}}
 {{end}}
 ------------------------------------------------------------------------
-Generated by: SGBlog {{.Version}}
+{{$.T.Get "Generated by"}}: SGBlog {{.Version}}
diff --git a/cmd/sgblog/gopher-menu.tmpl b/cmd/sgblog/gopher-menu.tmpl
index d1cc7eb..f27d4b7 100644
--- a/cmd/sgblog/gopher-menu.tmpl
+++ b/cmd/sgblog/gopher-menu.tmpl
@@ -1,9 +1,9 @@
 {{$CR := printf "\r"}}{{$CRLF := printf "\r\n" -}}
 {{- define "domainPort" }}	{{.GopherDomain}}	70{{end}}{{$Cfg := .Cfg -}}
-i{{.Cfg.Title}} {{if .Topic}}(topic: {{.Topic}}) {{end}}({{.Offset}}-{{.OffsetNext}})	err{{template "domainPort" .Cfg}}{{$CRLF -}}
-{{- if .Cfg.AboutURL}}hAbout	URL:{{.Cfg.AboutURL}}{{template "domainPort" .Cfg}}{{$CRLF}}{{end -}}
-{{- if .Offset}}1Prev	{{if .Topic}}{{.Topic}}/{{end}}offset/{{.OffsetPrev}}{{template "domainPort" .Cfg}}{{$CRLF}}{{end -}}
-{{- if not .LogEnded}}1Next	{{if .Topic}}{{.Topic}}/{{end}}offset/{{.OffsetNext}}{{template "domainPort" .Cfg}}{{$CRLF}}{{end -}}
+i{{.Cfg.Title}} {{if .Topic}}({{$.T.Get "topic"}}: {{.Topic}}) {{end}}({{.Offset}}-{{.OffsetNext}})	err{{template "domainPort" .Cfg}}{{$CRLF -}}
+{{- if .Cfg.AboutURL}}h{{$.T.Get "about"}}	URL:{{.Cfg.AboutURL}}{{template "domainPort" .Cfg}}{{$CRLF}}{{end -}}
+{{- if .Offset}}1{{$.T.Get "prev"}}	{{if .Topic}}{{.Topic}}/{{end}}offset/{{.OffsetPrev}}{{template "domainPort" .Cfg}}{{$CRLF}}{{end -}}
+{{- if not .LogEnded}}1{{$.T.Get "next"}}	{{if .Topic}}{{.Topic}}/{{end}}offset/{{.OffsetNext}}{{template "domainPort" .Cfg}}{{$CRLF}}{{end -}}
 {{- $datePrev := "0001-01-01" -}}
 {{- range .Entries -}}
 {{- $dateCur := .Commit.Author.When.Format "2006-01-02" -}}
@@ -11,6 +11,6 @@ i{{.Cfg.Title}} {{if .Topic}}(topic: {{.Topic}}) {{end}}({{.Offset}}-{{.OffsetNe
 i{{$dateCur}}	err{{template "domainPort" $Cfg}}{{$CR}}{{end}}
 0[{{.Commit.Author.When.Format "15:04"}}] {{.Title}} ({{.LinesNum}}L){{with .CommentsNum}} ({{.}}C){{end}}{{if .Topics}}{{range .Topics}} {{.}}{{end}}{{end}}	/{{.Commit.Hash.String}}{{template "domainPort" $Cfg}}{{$CR}}{{end}}
 {{range .Topics}}
-1Topic: {{.}}	{{.}}/offset/0{{template "domainPort" $Cfg}}{{$CR}}{{end}}
-iGenerated by: SGBlog {{.Version}}	err{{template "domainPort" .Cfg}}{{$CR}}
+1{{$.T.Get "topic"}}: {{.}}	{{.}}/offset/0{{template "domainPort" $Cfg}}{{$CR}}{{end}}
+i{{$.T.Get "Generated by"}}: SGBlog {{.Version}}	err{{template "domainPort" .Cfg}}{{$CR}}
 .{{$CRLF}}
diff --git a/cmd/sgblog/gopher.go b/cmd/sgblog/gopher.go
index 966d94a..2c8578f 100644
--- a/cmd/sgblog/gopher.go
+++ b/cmd/sgblog/gopher.go
@@ -33,6 +33,7 @@ import (
 	"github.com/go-git/go-git/v5"
 	"github.com/go-git/go-git/v5/plumbing"
 	"github.com/go-git/go-git/v5/plumbing/object"
+	"github.com/vorlif/spreak"
 	"go.stargrave.org/sgblog"
 )
 
@@ -62,6 +63,7 @@ func serveGopher(cfgPath string) {
 	if cfg.GopherDomain == "" {
 		log.Fatalln("GopherDomain is not configured")
 	}
+	initLocalizer(cfg.Lang)
 
 	headHash, err := initRepo(cfg)
 	if err != nil {
@@ -96,6 +98,7 @@ Redirecting to <a href="%s">%s</a>...
 			log.Fatalln(err)
 		}
 		err = TmplGopherEntry.Execute(os.Stdout, struct {
+			T            *spreak.Localizer
 			Commit       *object.Commit
 			When         string
 			Cfg          *Cfg
@@ -105,6 +108,7 @@ Redirecting to <a href="%s">%s</a>...
 			Version      string
 			TitleEscaped string
 		}{
+			T:        localizer,
 			Commit:   commit,
 			When:     commit.Author.When.Format(sgblog.WhenFmt),
 			Cfg:      cfg,
@@ -183,6 +187,7 @@ Redirecting to <a href="%s">%s</a>...
 			offsetPrev = 0
 		}
 		err = TmplGopherMenu.Execute(os.Stdout, struct {
+			T          *spreak.Localizer
 			Cfg        *Cfg
 			Topic      string
 			Offset     int
@@ -193,6 +198,7 @@ Redirecting to <a href="%s">%s</a>...
 			Topics     []string
 			Version    string
 		}{
+			T:          localizer,
 			Cfg:        cfg,
 			Topic:      topic,
 			Offset:     offset,
diff --git a/cmd/sgblog/http-entry.tmpl b/cmd/sgblog/http-entry.tmpl
index 55cfd9f..240617a 100644
--- a/cmd/sgblog/http-entry.tmpl
+++ b/cmd/sgblog/http-entry.tmpl
@@ -1,4 +1,4 @@
-{{$Cfg := .Cfg}}<!DOCTYPE html>
+<!DOCTYPE html>
 <html>
 <head>
 	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
@@ -7,42 +7,42 @@
 	{{with .Cfg.CSS}}<link rel="stylesheet" type="text/css" href="{{.}}">{{end}}
 	{{with .Cfg.Webmaster}}<link rev="made" href="mailto:{{.}}">{{end -}}
 	{{- range .Cfg.GitURLs}}
-	<link rel="vcs-git" href="{{.}}" title="Git repository">{{end}}
-	<link rel="top" href="{{.Cfg.URLPrefix}}/" title="top">
-	<link rel="alternate" title="Comments feed" href="{{.AtomCommentsURL}}" type="application/atom+xml">
-	{{if .Parent}}<link rel="prev" href="{{.Cfg.URLPrefix}}/{{.Parent}}" title="prev">{{end}}
+	<link rel="vcs-git" href="{{.}}" title="{{$.T.Get "Git repository"}}">{{end}}
+	<link rel="top" href="{{.Cfg.URLPrefix}}/" title="{{$.T.Get "top"}}">
+	<link rel="alternate" title="{{$.T.Get "Comments feed"}}" href="{{.AtomCommentsURL}}" type="application/atom+xml">
+	{{if .Parent}}<link rel="prev" href="{{.Cfg.URLPrefix}}/{{.Parent}}" title="{{$.T.Get "prev"}}">{{end}}
 </head>
 <body>
-{{with .Cfg.AboutURL}}[<a href="{{.}}">about</a>]{{end}}
+{{with .Cfg.AboutURL}}[<a href="{{.}}">{{$.T.Get "about"}}</a>]{{end}}
 [<a href="{{.Cfg.URLPrefix}}/">index</a>]
-{{if .Parent}}[<a href="{{.Cfg.URLPrefix}}/{{.Parent}}">prev</a>]{{end}}
-[<tt><a title="When">{{.When}}</a></tt>]
-[<tt><a title="What">{{.Commit.Hash.String}}</a></tt>]
+{{if .Parent}}[<a href="{{.Cfg.URLPrefix}}/{{.Parent}}">{{$.T.Get "prev"}}</a>]{{end}}
+[<tt><a title="{{$.T.Get "When"}}">{{.When}}</a></tt>]
+[<tt><a title="{{$.T.Get "What"}}">{{.Commit.Hash.String}}</a></tt>]
 
 {{if .Topics}}
 <hr/>
-Topics: {{range .Topics}}[<tt><a href="{{$Cfg.URLPrefix}}/?topic={{.}}">{{.}}</a></tt>]{{end}}
+{{$.T.Get "Topics"}}: {{range .Topics}}[<tt><a href="{{$.Cfg.URLPrefix}}/?topic={{.}}">{{.}}</a></tt>]{{end}}
 {{end}}
 
 <hr/>
 <h2>{{.Title}}</h2>
 <pre>
-{{range .Lines}}{{. | lineURLize $Cfg.URLPrefix}}
+{{range .Lines}}{{. | lineURLize $.Cfg.URLPrefix}}
 {{end}}</pre>
 <hr/>
 
-{{if .NoteLines}}Note:<pre>
-{{range .NoteLines}}{{. | lineURLize $Cfg.URLPrefix}}
+{{if .NoteLines}}{{$.T.Get "Note"}}:<pre>
+{{range .NoteLines}}{{. | lineURLize $.Cfg.URLPrefix}}
 {{end}}</pre>
 <hr/>{{end}}
 
-{{if .Cfg.CommentsEmail}}[<a href="mailto:{{.Cfg.CommentsEmail}}?subject={{.TitleEscaped}}">leave comment</a>]{{end}}
+{{if .Cfg.CommentsEmail}}[<a href="mailto:{{.Cfg.CommentsEmail}}?subject={{.TitleEscaped}}">{{$.T.Get "leave a comment"}}</a>]{{end}}
 
 <dl>{{range $idx, $comment := .Comments}}
-<dt><a name="comment{{$idx}}"><a href="#comment{{$idx}}">comment {{$idx}}</a>:</dt>
+<dt><a name="comment{{$idx}}"><a href="#comment{{$idx}}">{{$.T.Get "comment"}} {{$idx}}</a>:</dt>
 <dd><pre>
 {{range $comment.HeaderLines}}{{.}}
-{{end}}{{range $comment.BodyLines}}{{. | lineURLize $Cfg.URLPrefix}}
+{{end}}{{range $comment.BodyLines}}{{. | lineURLize $.Cfg.URLPrefix}}
 {{end}}</pre></dd>
 {{end}}</dl>
 
diff --git a/cmd/sgblog/http-index.tmpl b/cmd/sgblog/http-index.tmpl
index 523096d..6056fc7 100644
--- a/cmd/sgblog/http-index.tmpl
+++ b/cmd/sgblog/http-index.tmpl
@@ -6,34 +6,33 @@
     <title>{{.Cfg.Title}} {{if .Topic}}(topic: {{.Topic}}) {{end}}({{.Offset}}-{{.OffsetNext}})</title>
     {{with .Cfg.CSS}}<link rel="stylesheet" type="text/css" href="{{.}}">{{end}}
     {{with .Cfg.Webmaster}}<link rev="made" href="mailto:{{.}}">{{end}}
-    {{range .Cfg.GitURLs}}<link rel="vcs-git" href="{{.}}" title="Git repository">{{end}}
-    <link rel="top" href="{{.Cfg.URLPrefix}}/" title="top">
-    <link rel="alternate" title="Posts feed" href="{{.Cfg.AtomBaseURL}}{{.Cfg.URLPrefix}}/{{.AtomPostsFeed}}{{if .Topic}}?topic={{.Topic}}{{end}}" type="application/atom+xml">
-    {{if .CommentsEnabled}}<link rel="alternate" title="Comments feed" href="{{.Cfg.AtomBaseURL}}{{.Cfg.URLPrefix}}/{{.AtomCommentsFeed}}" type="application/atom+xml">{{end}}
-    {{if .Offset}}<link rel="prev" href="{{.Cfg.URLPrefix}}/?offset={{.OffsetPrev}}{{if .Topic}}&topic={{.Topic}}{{end}}" title="prev">{{end}}
-    {{if not .LogEnded}}<link rel="next" href="{{.Cfg.URLPrefix}}/?offset={{.OffsetNext}}{{if .Topic}}&topic={{.Topic}}{{end}}" title="next">{{end}}
+    {{range .Cfg.GitURLs}}<link rel="vcs-git" href="{{.}}" title="{{$.T.Get "Git repository"}}">{{end}}
+    <link rel="top" href="{{.Cfg.URLPrefix}}/" title="{{$.T.Get "top"}}">
+    <link rel="alternate" title="{{$.T.Get "Posts feed"}}" href="{{.Cfg.AtomBaseURL}}{{.Cfg.URLPrefix}}/{{.AtomPostsFeed}}{{if .Topic}}?topic={{.Topic}}{{end}}" type="application/atom+xml">
+    {{if .CommentsEnabled}}<link rel="alternate" title="{{$.T.Get "Comments feed"}}" href="{{.Cfg.AtomBaseURL}}{{.Cfg.URLPrefix}}/{{.AtomCommentsFeed}}" type="application/atom+xml">{{end}}
+    {{if .Offset}}<link rel="prev" href="{{.Cfg.URLPrefix}}/?offset={{.OffsetPrev}}{{if .Topic}}&topic={{.Topic}}{{end}}" title="{{$.T.Get "prev"}}">{{end}}
+    {{if not .LogEnded}}<link rel="next" href="{{.Cfg.URLPrefix}}/?offset={{.OffsetNext}}{{if .Topic}}&topic={{.Topic}}{{end}}" title="{{$.T.Get "next"}}">{{end}}
 </head>
 <body>
-{{with .Cfg.AboutURL}}[<a href="{{.}}">about</a>]{{end}}
+{{with .Cfg.AboutURL}}[<a href="{{.}}">{{$.T.Get "about"}}</a>]{{end}}
 {{block "links" .}}
-{{if .Offset}}[<a href="{{.Cfg.URLPrefix}}/?offset={{.OffsetPrev}}{{if .Topic}}&topic={{.Topic}}{{end}}">prev</a>]{{end}}
-{{if not .LogEnded}}[<a href="{{.Cfg.URLPrefix}}/?offset={{.OffsetNext}}{{if .Topic}}&topic={{.Topic}}{{end}}">next</a>]{{end}}
+{{if .Offset}}[<a href="{{.Cfg.URLPrefix}}/?offset={{.OffsetPrev}}{{if .Topic}}&topic={{.Topic}}{{end}}">{{$.T.Get "prev"}}</a>]{{end}}
+{{if not .LogEnded}}[<a href="{{.Cfg.URLPrefix}}/?offset={{.OffsetNext}}{{if .Topic}}&topic={{.Topic}}{{end}}">{{$.T.Get "next"}}</a>]{{end}}
 {{end}}
-{{- $Cfg := .Cfg -}}
 {{if .Topics}}<hr/>
-Topics: [<tt><a href="{{$Cfg.URLPrefix}}/">ALL</a></tt>]
-{{range .Topics}}[<tt><a href="{{$Cfg.URLPrefix}}/?topic={{.}}">{{.}}</a></tt>]
+{{$.T.Get "Topics"}}: [<tt><a href="{{$.Cfg.URLPrefix}}/">{{$.T.Get "ALL"}}</a></tt>]
+{{range .Topics}}[<tt><a href="{{$.Cfg.URLPrefix}}/?topic={{.}}">{{.}}</a></tt>]
 {{end}}
 {{end}}
 {{- $TopicsEnabled := .TopicsEnabled -}}
 {{- $datePrev := "0001-01-01" -}}
 <table border=1>
 <tr>
-    <th>N</th><th>When</th><th>Title</th>
-    <th size="5%"><a title="Lines">L</a></th>
-    <th size="5%"><a title="Comments">C</a></th>
-    <th>Linked to</th>
-    {{if .TopicsEnabled}}<th>Topics</th>{{end}}
+    <th>N</th><th>{{$.T.Get "When"}}</th><th>{{$.T.Get "Title"}}</th>
+    <th size="5%"><a title="{{$.T.Get "Lines"}}">L</a></th>
+    <th size="5%"><a title="{{$.T.Get "Comments"}}">C</a></th>
+    <th>{{$.T.Get "Linked to"}}</th>
+    {{if .TopicsEnabled}}<th>{{$.T.Get "Topics"}}</th>{{end}}
 </tr>
 {{range .Entries -}}
 {{- $dateCur := .Commit.Author.When.Format "2006-01-02" -}}
@@ -44,11 +43,11 @@ Topics: [<tt><a href="{{$Cfg.URLPrefix}}/">ALL</a></tt>]
 <tr>
     <td>{{.Num}}</td>
     <td><tt>{{.Commit.Author.When.Format "15:04"}}</tt></td>
-    <td><a href="{{$Cfg.URLPrefix}}/{{.Commit.Hash.String}}">{{.Title}}</a></td>
+    <td><a href="{{$.Cfg.URLPrefix}}/{{.Commit.Hash.String}}">{{.Title}}</a></td>
     <td>{{.LinesNum}}</td>
     <td>{{if .CommentsNum}}{{.CommentsNum}}{{else}}&nbsp;{{end}}</td>
     <td>{{if .DomainURLs}}{{range .DomainURLs}} {{.}} {{end}}{{else}}&nbsp;{{end}}</td>
-    {{if $TopicsEnabled}}<td>{{if .Topics}}{{range .Topics}} <a href="{{$Cfg.URLPrefix}}/?topic={{.}}">{{.}}</a> {{end}}{{else}}&nbsp;{{end}}</td>{{end}}
+    {{if $TopicsEnabled}}<td>{{if .Topics}}{{range .Topics}} <a href="{{$.Cfg.URLPrefix}}/?topic={{.}}">{{.}}</a> {{end}}{{else}}&nbsp;{{end}}</td>{{end}}
 </tr>
 {{end}}</table>
 {{template "links" .}}
diff --git a/cmd/sgblog/http.go b/cmd/sgblog/http.go
index 527f51e..c68f9a9 100644
--- a/cmd/sgblog/http.go
+++ b/cmd/sgblog/http.go
@@ -41,6 +41,7 @@ import (
 	"github.com/go-git/go-git/v5"
 	"github.com/go-git/go-git/v5/plumbing"
 	"github.com/go-git/go-git/v5/plumbing/object"
+	"github.com/vorlif/spreak"
 	"go.stargrave.org/sgblog"
 	"go.stargrave.org/sgblog/cmd/sgblog/atom"
 	"golang.org/x/crypto/blake2b"
@@ -174,6 +175,7 @@ func serveHTTP() {
 	if err != nil {
 		log.Fatalln(err)
 	}
+	initLocalizer(cfg.Lang)
 
 	pathInfo := os.Getenv("PATH_INFO")
 	if len(pathInfo) == 0 {
@@ -349,6 +351,7 @@ func serveHTTP() {
 		}
 		os.Stdout.Write([]byte(startHeader(etagHash, gzipWriter != nil)))
 		err = TmplHTMLIndex.Execute(out, struct {
+			T                *spreak.Localizer
 			Version          string
 			Cfg              *Cfg
 			Topic            string
@@ -363,6 +366,7 @@ func serveHTTP() {
 			LogEnded         bool
 			Entries          []TableEntry
 		}{
+			T:                localizer,
 			Version:          sgblog.Version,
 			Cfg:              cfg,
 			Topic:            topic,
@@ -739,6 +743,7 @@ func serveHTTP() {
 
 		os.Stdout.Write([]byte(startHeader(etagHash, gzipWriter != nil)))
 		err = TmplHTMLEntry.Execute(out, struct {
+			T               *spreak.Localizer
 			Version         string
 			Cfg             *Cfg
 			Title           string
@@ -752,6 +757,7 @@ func serveHTTP() {
 			Comments        []CommentEntry
 			Topics          []string
 		}{
+			T:               localizer,
 			Version:         sgblog.Version,
 			Cfg:             cfg,
 			Title:           title,
diff --git a/cmd/sgblog/locale/messages.pot b/cmd/sgblog/locale/messages.pot
new file mode 100644
index 0000000..e096977
--- /dev/null
+++ b/cmd/sgblog/locale/messages.pot
@@ -0,0 +1,125 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE VERSION package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# 
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2022-12-05 15:23+0300\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../gemini-entry.tmpl:3 ../gopher-entry.tmpl:1 ../http-entry.tmpl:20
+#, go-template
+msgid "What"
+msgstr ""
+
+#: ../gemini-entry.tmpl:4 ../gopher-entry.tmpl:2 ../http-entry.tmpl:19
+#: ../http-index.tmpl:31
+#, go-template
+msgid "When"
+msgstr ""
+
+#: ../gemini-entry.tmpl:5 ../gopher-entry.tmpl:4 ../http-entry.tmpl:24
+#: ../http-index.tmpl:23 ../http-index.tmpl:35
+#, go-template
+msgid "Topics"
+msgstr ""
+
+#: ../gemini-entry.tmpl:9 ../gopher-entry.tmpl:9 ../http-entry.tmpl:34
+#, go-template
+msgid "Note"
+msgstr ""
+
+#: ../gemini-entry.tmpl:15 ../gopher-entry.tmpl:13 ../http-entry.tmpl:39
+#, go-template
+msgid "leave a comment"
+msgstr ""
+
+#: ../gemini-entry.tmpl:17 ../gopher-entry.tmpl:16 ../http-entry.tmpl:42
+#, go-template
+msgid "comment"
+msgstr ""
+
+#: ../gemini-entry.tmpl:22 ../gemini-menu.tmpl:17 ../gopher-entry.tmpl:20
+#: ../gopher-menu.tmpl:15
+#, go-template
+msgid "Generated by"
+msgstr ""
+
+#: ../gemini-menu.tmpl:2 ../gopher-menu.tmpl:3 ../gopher-menu.tmpl:14
+#, go-template
+msgid "topic"
+msgstr ""
+
+#: ../gemini-menu.tmpl:3 ../gopher-menu.tmpl:4 ../http-entry.tmpl:16
+#: ../http-index.tmpl:17
+#, go-template
+msgid "about"
+msgstr ""
+
+#: ../gemini-menu.tmpl:4 ../gopher-menu.tmpl:5 ../http-entry.tmpl:13
+#: ../http-entry.tmpl:18 ../http-index.tmpl:13 ../http-index.tmpl:19
+#, go-template
+msgid "prev"
+msgstr ""
+
+#: ../gemini-menu.tmpl:5 ../gopher-menu.tmpl:6 ../http-index.tmpl:14
+#: ../http-index.tmpl:20
+#, go-template
+msgid "next"
+msgstr ""
+
+#: ../http-entry.tmpl:10 ../http-index.tmpl:9
+#, go-template
+msgid "Git repository"
+msgstr ""
+
+#: ../http-entry.tmpl:11 ../http-index.tmpl:10
+#, go-template
+msgid "top"
+msgstr ""
+
+#: ../http-entry.tmpl:12 ../http-index.tmpl:12
+#, go-template
+msgid "Comments feed"
+msgstr ""
+
+#: ../http-index.tmpl:11
+#, go-template
+msgid "Posts feed"
+msgstr ""
+
+#: ../http-index.tmpl:23
+#, go-template
+msgid "ALL"
+msgstr ""
+
+#: ../http-index.tmpl:31
+#, go-template
+msgid "Title"
+msgstr ""
+
+#: ../http-index.tmpl:32
+#, go-template
+msgid "Lines"
+msgstr ""
+
+#: ../http-index.tmpl:33
+#, go-template
+msgid "Comments"
+msgstr ""
+
+#: ../http-index.tmpl:34
+#, go-template
+msgid "Linked to"
+msgstr ""
+
diff --git a/cmd/sgblog/locale/ru.po b/cmd/sgblog/locale/ru.po
new file mode 100644
index 0000000..baf0f50
--- /dev/null
+++ b/cmd/sgblog/locale/ru.po
@@ -0,0 +1,102 @@
+# SGBlog -- Git-backed CGI/UCSPI blogging/phlogging/gemlogging engine
+# Copyright (C) 2020-2022 Sergey Matveev <stargrave@stargrave.org>
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: sgblog 0.27.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2022-12-05 15:21+0300\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../gemini-entry.tmpl:3 ../gopher-entry.tmpl:1 ../http-entry.tmpl:20
+msgid "What"
+msgstr "Что"
+
+#: ../gemini-entry.tmpl:4 ../gopher-entry.tmpl:2 ../http-entry.tmpl:19
+#: ../http-index.tmpl:31
+msgid "When"
+msgstr "Когда"
+
+#: ../gemini-entry.tmpl:5 ../gopher-entry.tmpl:4 ../http-entry.tmpl:24
+#: ../http-index.tmpl:23 ../http-index.tmpl:35
+msgid "Topics"
+msgstr "Темы"
+
+#: ../gemini-entry.tmpl:9 ../gopher-entry.tmpl:9 ../http-entry.tmpl:34
+msgid "Note"
+msgstr "Заметка"
+
+#: ../gemini-entry.tmpl:15 ../gopher-entry.tmpl:13 ../http-entry.tmpl:39
+msgid "leave a comment"
+msgstr "оставить комментарий"
+
+#: ../gemini-entry.tmpl:17 ../gopher-entry.tmpl:16 ../http-entry.tmpl:42
+msgid "comment"
+msgstr "комментарий"
+
+#: ../gemini-entry.tmpl:22 ../gemini-menu.tmpl:17 ../gopher-entry.tmpl:20
+#: ../gopher-menu.tmpl:15
+msgid "Generated by"
+msgstr "Сгенерирован"
+
+#: ../gemini-menu.tmpl:2 ../gopher-menu.tmpl:3 ../gopher-menu.tmpl:14
+msgid "topic"
+msgstr "тема"
+
+#: ../gemini-menu.tmpl:3 ../gopher-menu.tmpl:4 ../http-entry.tmpl:16
+#: ../http-index.tmpl:17
+msgid "about"
+msgstr "О блоге"
+
+#: ../gemini-menu.tmpl:4 ../gopher-menu.tmpl:5 ../http-entry.tmpl:13
+#: ../http-entry.tmpl:18 ../http-index.tmpl:13 ../http-index.tmpl:19
+msgid "prev"
+msgstr "пред"
+
+#: ../gemini-menu.tmpl:5 ../gopher-menu.tmpl:6 ../http-index.tmpl:14
+#: ../http-index.tmpl:20
+msgid "next"
+msgstr "след"
+
+#: ../http-entry.tmpl:10 ../http-index.tmpl:9
+msgid "Git repository"
+msgstr "Git репозиторий"
+
+#: ../http-entry.tmpl:11 ../http-index.tmpl:10
+msgid "top"
+msgstr "верх"
+
+#: ../http-entry.tmpl:12 ../http-index.tmpl:12
+msgid "Comments feed"
+msgstr "Нить комментариев"
+
+#: ../http-index.tmpl:11
+msgid "Posts feed"
+msgstr "Нить статей"
+
+#: ../http-index.tmpl:23
+msgid "ALL"
+msgstr "ВСЁ"
+
+#: ../http-index.tmpl:31
+msgid "Title"
+msgstr "Название"
+
+#: ../http-index.tmpl:32
+msgid "Lines"
+msgstr "Строк"
+
+#: ../http-index.tmpl:33
+msgid "Comments"
+msgstr "Комментариев"
+
+#: ../http-index.tmpl:34
+msgid "Linked to"
+msgstr "Ссылается на"
diff --git a/cmd/sgblog/main.go b/cmd/sgblog/main.go
index 767850c..a95de7a 100644
--- a/cmd/sgblog/main.go
+++ b/cmd/sgblog/main.go
@@ -20,9 +20,11 @@ package main
 
 import (
 	"crypto/sha1"
+	"embed"
 	"encoding/json"
 	"flag"
 	"fmt"
+	"io/fs"
 	"log"
 	"os"
 	"regexp"
@@ -32,6 +34,8 @@ import (
 	"github.com/go-git/go-git/v5/plumbing"
 	"github.com/go-git/go-git/v5/plumbing/object"
 	"github.com/hjson/hjson-go"
+	"github.com/vorlif/spreak"
+	"golang.org/x/text/language"
 )
 
 const (
@@ -46,12 +50,18 @@ var (
 	commentsTree *object.Tree
 	topicsRef    *plumbing.Reference
 	topicsTree   *object.Tree
+
+	localizer *spreak.Localizer
+
+	//go:embed locale/*
+	locales embed.FS
 )
 
 type Cfg struct {
 	GitPath string
 	Branch  string
 	Title   string
+	Lang    string
 
 	URLPrefix string
 
@@ -145,6 +155,22 @@ func readCfg(cfgPath string) (*Cfg, error) {
 	return cfg, nil
 }
 
+func initLocalizer(lang string) {
+	fsys, _ := fs.Sub(locales, "locale")
+	bundle, err := spreak.NewBundle(
+		spreak.WithSourceLanguage(language.English),
+		spreak.WithDomainFs(spreak.NoDomain, fsys),
+		spreak.WithLanguage(language.Russian),
+	)
+	if err != nil {
+		log.Fatalln(err)
+	}
+	if lang == "" {
+		lang = language.English.String()
+	}
+	localizer = spreak.NewLocalizer(bundle, language.MustParse(lang))
+}
+
 func main() {
 	gopherCfgPath := flag.String("gopher", "", "Path to gopher-related configuration file")
 	geminiCfgPath := flag.String("gemini", "", "Path to gemini-related configuration file")
diff --git a/common.go b/common.go
index 1289dcc..bc0a1f4 100644
--- a/common.go
+++ b/common.go
@@ -15,7 +15,7 @@ import (
 )
 
 const (
-	Version = "0.26.0"
+	Version = "0.27.0"
 	WhenFmt = "2006-01-02 15:04:05Z07:00"
 )
 
diff --git a/go.mod b/go.mod
index ff88ed6..4520f24 100644
--- a/go.mod
+++ b/go.mod
@@ -5,8 +5,10 @@ go 1.17
 require (
 	github.com/go-git/go-git/v5 v5.4.2
 	github.com/hjson/hjson-go v3.3.0+incompatible
+	github.com/vorlif/spreak v0.3.5
 	go.cypherpunks.ru/recfile v0.5.1
-	golang.org/x/crypto v0.1.0
+	golang.org/x/crypto v0.3.0
+	golang.org/x/text v0.5.0
 )
 
 require (
@@ -25,7 +27,7 @@ require (
 	github.com/xanzy/ssh-agent v0.3.2 // indirect
 	golang.org/x/mod v0.6.0 // indirect
 	golang.org/x/net v0.2.0 // indirect
-	golang.org/x/sys v0.2.0 // indirect
+	golang.org/x/sys v0.3.0 // indirect
 	golang.org/x/tools v0.2.0 // indirect
 	gopkg.in/warnings.v0 v0.1.2 // indirect
 )
diff --git a/go.sum b/go.sum
index 45baa47..7ab745a 100644
--- a/go.sum
+++ b/go.sum
@@ -74,31 +74,46 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB
 github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
-github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/vorlif/spreak v0.3.5 h1:mRzp6CCHs9HDxN/TMCY/R4ghjpJmkXrxnJjOrjzhjTQ=
+github.com/vorlif/spreak v0.3.5/go.mod h1:ITHUfZOyQiw65OGWpVatvEZhLljkbtkV4rhQU0F/EG4=
 github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
 github.com/xanzy/ssh-agent v0.3.2 h1:eKj4SX2Fe7mui28ZgnFW5fmTz1EIr7ugo5s6wDxdHBM=
 github.com/xanzy/ssh-agent v0.3.2/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 go.cypherpunks.ru/recfile v0.5.1 h1:Sk9Og/7aybvg4PrZdhyFSeEdS6wvcisvd+1oGf8uFyU=
 go.cypherpunks.ru/recfile v0.5.1/go.mod h1:sR+KajB+vzofL3SFVFwKt3Fke0FaCcN1g3YPNAhU3qI=
 golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
 golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
-golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
+golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A=
+golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
 golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
 golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -112,17 +127,27 @@ golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
-golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
+golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
+golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
 golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -134,5 +159,6 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA=
 gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=