Index was translated. Also all necessary i18n code was added.
This commit is contained in:
parent
962bddaa0f
commit
e092a34055
@ -1,12 +1,12 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
ihttp "dwelling-radio/internal/http"
|
ihttp "dwelling-radio/internal/http"
|
||||||
"dwelling-radio/internal/radio"
|
"dwelling-radio/internal/radio"
|
||||||
sqlite_stats "dwelling-radio/internal/statistics/db/sqlite"
|
sqlite_stats "dwelling-radio/internal/statistics/db/sqlite"
|
||||||
"dwelling-radio/pkg/utils"
|
"dwelling-radio/pkg/utils"
|
||||||
"dwelling-radio/web"
|
"dwelling-radio/web"
|
||||||
|
"dwelling-radio/web/locales"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
@ -17,6 +17,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"git.arav.su/Arav/httpr"
|
"git.arav.su/Arav/httpr"
|
||||||
|
"github.com/invopop/ctxi18n"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -53,6 +54,10 @@ func main() {
|
|||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := ctxi18n.LoadWithDefault(locales.Content, "en"); err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
|
||||||
r := httpr.New()
|
r := httpr.New()
|
||||||
|
|
||||||
r.Handler(http.MethodGet, "/", func(w http.ResponseWriter, r *http.Request) {
|
r.Handler(http.MethodGet, "/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -63,7 +68,7 @@ func main() {
|
|||||||
|
|
||||||
lstnrs.RLock()
|
lstnrs.RLock()
|
||||||
defer lstnrs.RUnlock()
|
defer lstnrs.RUnlock()
|
||||||
web.Index(¤tSong, lst, *songListLen, lstnrs, r).Render(context.Background(), w)
|
web.Index(version, ¤tSong, lst, *songListLen, lstnrs, r).Render(r.Context(), w)
|
||||||
})
|
})
|
||||||
|
|
||||||
r.Handler(http.MethodGet, "/filelist", func(w http.ResponseWriter, r *http.Request) {
|
r.Handler(http.MethodGet, "/filelist", func(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -94,7 +99,7 @@ func main() {
|
|||||||
s.Handler(http.MethodGet, "/playlist", djh.PlaylistNext)
|
s.Handler(http.MethodGet, "/playlist", djh.PlaylistNext)
|
||||||
s.Handler(http.MethodGet, "/status", djh.Status)
|
s.Handler(http.MethodGet, "/status", djh.Status)
|
||||||
|
|
||||||
srv := ihttp.NewHttpServer(r)
|
srv := ihttp.NewHttpServer(I18nMiddleware(r))
|
||||||
|
|
||||||
if err := srv.Start(*listenAddress); err != nil {
|
if err := srv.Start(*listenAddress); err != nil {
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
@ -130,3 +135,25 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func I18nMiddleware(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
lang := "en"
|
||||||
|
|
||||||
|
if lq := r.URL.Query().Get("lang"); lq != "" {
|
||||||
|
lc := http.Cookie{Name: "lang", Value: lq, HttpOnly: false, MaxAge: 0}
|
||||||
|
http.SetCookie(w, &lc)
|
||||||
|
lang = lq
|
||||||
|
} else if l, err := r.Cookie("lang"); err == nil {
|
||||||
|
lang = l.Value
|
||||||
|
} else if al := r.Header.Get("Accept-Language"); al != "" {
|
||||||
|
lang = r.Header.Get("Accept-Language")
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, err := ctxi18n.WithLocale(r.Context(), lang)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("i18nmw:", err)
|
||||||
|
}
|
||||||
|
next.ServeHTTP(w, r.WithContext(ctx))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -3,12 +3,14 @@ package web
|
|||||||
import "net/http"
|
import "net/http"
|
||||||
import "strconv"
|
import "strconv"
|
||||||
|
|
||||||
|
import "github.com/invopop/ctxi18n/i18n"
|
||||||
|
|
||||||
import "dwelling-radio/internal/radio"
|
import "dwelling-radio/internal/radio"
|
||||||
import "dwelling-radio/pkg/utils"
|
import "dwelling-radio/pkg/utils"
|
||||||
|
|
||||||
templ Index(curSong *radio.Song, sl []radio.Song, slLen int64, lstnrs *radio.ListenerCounter, r *http.Request) {
|
templ Index(prgVer string, curSong *radio.Song, sl []radio.Song, slLen int64, lstnrs *radio.ListenerCounter, r *http.Request) {
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang={ i18n.GetLocale(ctx).Code().String() }>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
@ -16,11 +18,11 @@ templ Index(curSong *radio.Song, sl []radio.Song, slLen int64, lstnrs *radio.Lis
|
|||||||
<meta name="theme-color" content="#cd2682" />
|
<meta name="theme-color" content="#cd2682" />
|
||||||
<meta name="color-scheme" content="light dark" />
|
<meta name="color-scheme" content="light dark" />
|
||||||
|
|
||||||
<title>Arav's dwelling / Radio</title>
|
<title>Arav's dwelling / { i18n.T(ctx, "title") }</title>
|
||||||
|
|
||||||
<meta name="author" content={ "Alexander \"Arav\" Andreev" } />
|
<meta name="author" content={ "Alexander \"Arav\" Andreev" } />
|
||||||
<meta name="description" content="Internet-radio broadcasting from under my desk." />
|
<meta name="description" content={ i18n.T(ctx, "description") } />
|
||||||
<meta name="keywords" content="self-host radio home-radio various music" />
|
<meta name="keywords" content={ i18n.T(ctx, "keywords") } />
|
||||||
|
|
||||||
<link rel="canonical" href={ utils.Site(r.Host) } />
|
<link rel="canonical" href={ utils.Site(r.Host) } />
|
||||||
|
|
||||||
@ -36,8 +38,8 @@ templ Index(curSong *radio.Song, sl []radio.Song, slLen int64, lstnrs *radio.Lis
|
|||||||
<text y="25" textLength="360" lengthAdjust="spacingAndGlyphs">Welcome to my sacred place, wanderer</text>
|
<text y="25" textLength="360" lengthAdjust="spacingAndGlyphs">Welcome to my sacred place, wanderer</text>
|
||||||
</svg>
|
</svg>
|
||||||
<nav>
|
<nav>
|
||||||
<a href={ templ.SafeURL(utils.MainSite(r.Host)) }>Back to home</a>
|
<a href={ templ.SafeURL(utils.MainSite(r.Host)) }>{ i18n.T(ctx, "back-home") }</a>
|
||||||
<h1>Radio</h1>
|
<h1>{ i18n.T(ctx, "title") }</h1>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
<section id="banner">
|
<section id="banner">
|
||||||
@ -47,9 +49,9 @@ templ Index(curSong *radio.Song, sl []radio.Song, slLen int64, lstnrs *radio.Lis
|
|||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<div class="small player-links">
|
<div class="small player-links">
|
||||||
<a href="/filelist">filelist</a>
|
<a href="/filelist">{ i18n.T(ctx, "link.filelist") }</a>
|
||||||
<a href="/playlist">playlist</a>
|
<a href="/playlist">{ i18n.T(ctx, "link.playlist") }</a>
|
||||||
<a href="/live/stream.ogg">direct link</a>
|
<a href="/live/stream.ogg">{ i18n.T(ctx, "link.direct-link") }</a>
|
||||||
(<a href="http://radio.arav.su:8000/stream.ogg">http</a>
|
(<a href="http://radio.arav.su:8000/stream.ogg">http</a>
|
||||||
<a href="http://wsmkgnmhmzqm7kyzv7jnzzafvgm7xlmlfvzhgorpapd5or2arnhuktqd.onion/live/stream.ogg">Tor</a>
|
<a href="http://wsmkgnmhmzqm7kyzv7jnzzafvgm7xlmlfvzhgorpapd5or2arnhuktqd.onion/live/stream.ogg">Tor</a>
|
||||||
<a href="http://radio.arav.i2p/live/stream.ogg">I2P</a>
|
<a href="http://radio.arav.i2p/live/stream.ogg">I2P</a>
|
||||||
@ -64,7 +66,7 @@ templ Index(curSong *radio.Song, sl []radio.Song, slLen int64, lstnrs *radio.Lis
|
|||||||
</div>
|
</div>
|
||||||
<audio preload="none" controls playsinline>
|
<audio preload="none" controls playsinline>
|
||||||
<source src="/live/stream.ogg" type="audio/ogg" />
|
<source src="/live/stream.ogg" type="audio/ogg" />
|
||||||
Seems like your browser doesn't support an audio element, but you can grab the <a href="/playlist">playlist</a>.
|
{ i18n.T(ctx, "no-audio-tag") } <a href="/playlist">{ i18n.T(ctx, "link.playlist") }</a>.
|
||||||
</audio>
|
</audio>
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
@ -92,13 +94,13 @@ templ Index(curSong *radio.Song, sl []radio.Song, slLen int64, lstnrs *radio.Lis
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<h2>Last { strconv.FormatInt(slLen, 10) } songs</h2>
|
<h2>{ i18n.T(ctx, "last-songs.h", i18n.M{"n": strconv.FormatInt(slLen, 10)}) }</h2>
|
||||||
<table id="last-songs">
|
<table id="last-songs">
|
||||||
<thead class="small">
|
<thead class="small">
|
||||||
<tr>
|
<tr>
|
||||||
<td>Start</td>
|
<td>{ i18n.T(ctx, "last-songs.tab-start") }</td>
|
||||||
<td><abbr title="Overall/Peak listeners">O/P</abbr></td>
|
<td><abbr title={ i18n.T(ctx, "last-songs.tab-stat-tip") }>{ i18n.T(ctx, "last-songs.tab-stat") }</abbr></td>
|
||||||
<td>Song</td>
|
<td>{ i18n.T(ctx, "last-songs.tab-song") }</td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -117,7 +119,10 @@ templ Index(curSong *radio.Song, sl []radio.Song, slLen int64, lstnrs *radio.Lis
|
|||||||
</table>
|
</table>
|
||||||
</section>
|
</section>
|
||||||
<footer>
|
<footer>
|
||||||
2017—2024 Alexander "Arav" Andreev <<a href="mailto:me@arav.su">me@arav.su</a>> <a href={ templ.SafeURL(utils.MainSite(r.Host) + "/privacy") }>Privacy statements</a>
|
<a href="?lang=ru">рус</a>
|
||||||
|
<a href="?lang=en">eng</a>
|
||||||
|
<br/>
|
||||||
|
v{ prgVer } 2017—2024 { i18n.T(ctx, "footer.author") } <<a href="mailto:me@arav.su">me@arav.su</a>> <a href={ templ.SafeURL(utils.MainSite(r.Host) + "/privacy") }>{ i18n.T(ctx, "footer.privacy") }</a>
|
||||||
</footer>
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
19
web/locales/en/en.yaml
Normal file
19
web/locales/en/en.yaml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
en:
|
||||||
|
title: Radio
|
||||||
|
description: Internet-radio broadcasting from under my desk.
|
||||||
|
keywords: self-host radio home-radio various music
|
||||||
|
back-home: Back home
|
||||||
|
link:
|
||||||
|
filelist: filelist
|
||||||
|
playlist: playlist
|
||||||
|
direct-link: direct link
|
||||||
|
no-audio-tag: Seems like your browser doesn't support an audio element, but you can grab the
|
||||||
|
last-songs:
|
||||||
|
h: Last %{n} songs
|
||||||
|
tab-start: Start
|
||||||
|
tab-stat: O/P
|
||||||
|
tab-stat-tip: Overall/Peak listeners
|
||||||
|
tab-song: Song
|
||||||
|
footer:
|
||||||
|
author: Alexander ❝Arav❞ Andreev
|
||||||
|
privacy: Privacy statements
|
7
web/locales/locales.go
Normal file
7
web/locales/locales.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package locales
|
||||||
|
|
||||||
|
import "embed"
|
||||||
|
|
||||||
|
//go:embed en
|
||||||
|
//go:embed ru
|
||||||
|
var Content embed.FS
|
19
web/locales/ru/ru.yaml
Normal file
19
web/locales/ru/ru.yaml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
ru:
|
||||||
|
title: Радио
|
||||||
|
description: Интернет-радио вещающееся из-под моего стола.
|
||||||
|
keywords: само-хост селф-хост радио разное музыка
|
||||||
|
back-home: Назад домой
|
||||||
|
link:
|
||||||
|
filelist: список файлов
|
||||||
|
playlist: плейлист
|
||||||
|
direct-link: прямая ссылка
|
||||||
|
no-audio-tag: Похоже на то, что твой браузер не поддерживает audio элемент, хреновенько, но можешь взять
|
||||||
|
last-songs:
|
||||||
|
h: Последние %{n} песен
|
||||||
|
tab-start: Начало
|
||||||
|
tab-stat: В/П
|
||||||
|
tab-stat-tip: Всего/Пиковое кол-во слушателей
|
||||||
|
tab-song: Песня
|
||||||
|
footer:
|
||||||
|
author: Александр «Arav» Андреев
|
||||||
|
privacy: О приватности
|
Loading…
Reference in New Issue
Block a user