言語はliblocale化 + 複数言語対応
このコミットが含まれているのは:
コミット
34bcb6c4ce
|
@ -1,3 +1,7 @@
|
||||||
|
# 1.1.0
|
||||||
|
* 言語はliblocale化
|
||||||
|
* 複数言語対応
|
||||||
|
|
||||||
# 1.0.0
|
# 1.0.0
|
||||||
* PHPからGoに交換しました
|
* PHPからGoに交換しました
|
||||||
* 今度からバージョンを付きます
|
* 今度からバージョンを付きます
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -1,3 +1,5 @@
|
||||||
module 076/hozonsite
|
module 076/hozonsite
|
||||||
|
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
|
require gitler.moe/suwako/goliblocale v1.0.0
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
gitler.moe/suwako/goliblocale v1.0.0 h1:QiQKNzdgpavwmAaYhAb5pth0I6qS8IJ7q2hYAgpXacU=
|
||||||
|
gitler.moe/suwako/goliblocale v1.0.0/go.mod h1:pdv9Go5taevY8ClBOA+oLXjGap7G1RmIVKUMF8HSJmU=
|
39
lang.go
39
lang.go
|
@ -1,39 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getlist (lang string) []byte {
|
|
||||||
var jloc = []byte(`{
|
|
||||||
"top": "トップ",
|
|
||||||
"errfuseiurl": "URLは「http://」又は「https://」で始めます。",
|
|
||||||
"errfusei": "不正なエラー。"
|
|
||||||
}`)
|
|
||||||
var eloc = []byte(`{
|
|
||||||
"top": "Top",
|
|
||||||
"errfuseiurl": "The URL should start with \"http://\" or \"https://\".",
|
|
||||||
"errfusei": "Unknown error."
|
|
||||||
}`)
|
|
||||||
|
|
||||||
if lang == "en" { return eloc }
|
|
||||||
return jloc
|
|
||||||
}
|
|
||||||
|
|
||||||
func getloc (str string, lang string) string {
|
|
||||||
var payload map[string]interface{}
|
|
||||||
err := json.Unmarshal(getlist(lang), &payload)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("loc:", err)
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, v := range payload {
|
|
||||||
if str == k {
|
|
||||||
return v.(string)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"hozonsite": "Hozon Site",
|
||||||
|
"desc": "It is the world's first FOSS web archiver.",
|
||||||
|
"logo": "Logo",
|
||||||
|
"top": "Top",
|
||||||
|
"langchange": "Language change",
|
||||||
|
"totop": "Return to toppage",
|
||||||
|
"tophe": "To toppage.",
|
||||||
|
"topwhatsave": "Which page will you archive?",
|
||||||
|
"hozon": "Archive",
|
||||||
|
"archwhozonsite": "Archived with Hozon Site.",
|
||||||
|
"areadyhozon": "Pages that already got archived:",
|
||||||
|
"willreallyhozon": "This page seems to have been already archived.<br />Do you really want to proceed?",
|
||||||
|
"yesreallyhozon": "Yes, please archive!!",
|
||||||
|
"errfuseiurl": "The URL should start with \"http://\" or \"https://\".",
|
||||||
|
"errfusei": "Unknown error."
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"hozonsite": "保存サイト",
|
||||||
|
"desc": "世界初FOSS系ウエブアーカイバーです。",
|
||||||
|
"logo": "ロゴ",
|
||||||
|
"top": "トップ",
|
||||||
|
"langchange": "言語変更",
|
||||||
|
"totop": "トップページに戻る",
|
||||||
|
"tophe": "トップページへ",
|
||||||
|
"topwhatsave": "どのページを保存しますか?",
|
||||||
|
"hozon": "保存",
|
||||||
|
"archwhozonsite": "保存サイトでアーカイブしました。",
|
||||||
|
"areadyhozon": "既に保存されたページ:",
|
||||||
|
"willreallyhozon": "このページが既に保存されているみたいです。<br />本当に手続きましょうか?",
|
||||||
|
"yesreallyhozon": "はい、保存して下さい!!",
|
||||||
|
"errfuseiurl": "URLは「http://」又は「https://」で始めます。",
|
||||||
|
"errfusei": "不正なエラー。"
|
||||||
|
}
|
2
main.go
2
main.go
|
@ -7,7 +7,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
var version = "1.0.0"
|
var version = "1.1.0"
|
||||||
|
|
||||||
func help () {
|
func help () {
|
||||||
fmt.Println("使い方:");
|
fmt.Println("使い方:");
|
||||||
|
|
40
srv.go
40
srv.go
|
@ -9,11 +9,13 @@ import (
|
||||||
"time"
|
"time"
|
||||||
"os"
|
"os"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"gitler.moe/suwako/goliblocale"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Page struct {
|
Page struct {
|
||||||
Tit, Err, Lan, Ver, Ves, Url, Body string
|
Err, Lan, Ver, Ves, Url, Body string
|
||||||
|
i18n map[string]string
|
||||||
Ext []Exist // 既に存在する場合
|
Ext []Exist // 既に存在する場合
|
||||||
}
|
}
|
||||||
Stat struct { // APIのみ
|
Stat struct { // APIのみ
|
||||||
|
@ -24,6 +26,10 @@ type (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (p Page) T (key string) string {
|
||||||
|
return p.i18n[key]
|
||||||
|
}
|
||||||
|
|
||||||
// 日本語か英語 TODO:複数言語対応
|
// 日本語か英語 TODO:複数言語対応
|
||||||
func initloc (r *http.Request) string {
|
func initloc (r *http.Request) string {
|
||||||
cookie, err := r.Cookie("lang")
|
cookie, err := r.Cookie("lang")
|
||||||
|
@ -52,12 +58,17 @@ func siteHandler (cnf Config) func (http.ResponseWriter, *http.Request) {
|
||||||
data := &Page{Ver: version, Ves: strings.ReplaceAll(version, ".", "")}
|
data := &Page{Ver: version, Ves: strings.ReplaceAll(version, ".", "")}
|
||||||
|
|
||||||
lang := initloc(r)
|
lang := initloc(r)
|
||||||
|
|
||||||
data.Lan = lang
|
data.Lan = lang
|
||||||
|
|
||||||
|
i18n, err := goliblocale.GetLocale("locale/" + lang)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("liblocaleエラー:%v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data.i18n = i18n
|
||||||
ftmpl[0] = cnf.webpath + "/view/index.html"
|
ftmpl[0] = cnf.webpath + "/view/index.html"
|
||||||
tmpl := template.Must(template.ParseFiles(ftmpl[0], ftmpl[1], ftmpl[2]))
|
tmpl := template.Must(template.ParseFiles(ftmpl[0], ftmpl[1], ftmpl[2]))
|
||||||
|
|
||||||
data.Tit = getloc("top", lang)
|
|
||||||
if r.Method == "POST" {
|
if r.Method == "POST" {
|
||||||
err := r.ParseForm()
|
err := r.ParseForm()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -66,14 +77,9 @@ func siteHandler (cnf Config) func (http.ResponseWriter, *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// クッキー
|
// 言語変更
|
||||||
if r.PostForm.Get("langchange") != "" {
|
if lang := r.PostFormValue("lang"); lang != "" {
|
||||||
cookie, err := r.Cookie("lang")
|
http.SetCookie(w, &http.Cookie{Name: "lang", Value: lang, MaxAge: 31536000, Path: "/"})
|
||||||
if err != nil || cookie.Value == "ja" {
|
|
||||||
http.SetCookie(w, &http.Cookie {Name: "lang", Value: "en", MaxAge: 31536000, Path: "/"})
|
|
||||||
} else {
|
|
||||||
http.SetCookie(w, &http.Cookie {Name: "lang", Value: "ja", MaxAge: 31536000, Path: "/"})
|
|
||||||
}
|
|
||||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -84,7 +90,7 @@ func siteHandler (cnf Config) func (http.ResponseWriter, *http.Request) {
|
||||||
url := r.PostForm.Get("hozonsite")
|
url := r.PostForm.Get("hozonsite")
|
||||||
// HTTPかHTTPSじゃない場合
|
// HTTPかHTTPSじゃない場合
|
||||||
if !checkprefix(url) {
|
if !checkprefix(url) {
|
||||||
data.Err = getloc("errfuseiurl", lang)
|
data.Err = i18n["errfuseiurl"]
|
||||||
ftmpl[0] = cnf.webpath + "/view/404.html"
|
ftmpl[0] = cnf.webpath + "/view/404.html"
|
||||||
} else {
|
} else {
|
||||||
eurl := stripurl(url)
|
eurl := stripurl(url)
|
||||||
|
@ -114,7 +120,7 @@ func siteHandler (cnf Config) func (http.ResponseWriter, *http.Request) {
|
||||||
}
|
}
|
||||||
data.Ext = existing
|
data.Ext = existing
|
||||||
} else {
|
} else {
|
||||||
data.Err = getloc("errfusei", lang)
|
data.Err = i18n["errfusei"]
|
||||||
ftmpl[0] = cnf.webpath + "/view/404.html"
|
ftmpl[0] = cnf.webpath + "/view/404.html"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,8 +148,14 @@ func archiveHandler (cnf Config) func (http.ResponseWriter, *http.Request) {
|
||||||
ftmpl := []string{cnf.webpath + "/view/index.html", cnf.webpath + "/view/header.html", cnf.webpath + "/view/footer.html"}
|
ftmpl := []string{cnf.webpath + "/view/index.html", cnf.webpath + "/view/header.html", cnf.webpath + "/view/footer.html"}
|
||||||
data := &Page{Ver: version, Ves: strings.ReplaceAll(version, ".", "")}
|
data := &Page{Ver: version, Ves: strings.ReplaceAll(version, ".", "")}
|
||||||
lang := initloc(r)
|
lang := initloc(r)
|
||||||
|
|
||||||
data.Lan = lang
|
data.Lan = lang
|
||||||
|
|
||||||
|
i18n, err := goliblocale.GetLocale("locale/" + lang)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("liblocaleエラー:%v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data.i18n = i18n
|
||||||
ftmpl[0] = cnf.webpath + "/view/index.html"
|
ftmpl[0] = cnf.webpath + "/view/index.html"
|
||||||
tmpl := template.Must(template.ParseFiles(ftmpl[0], ftmpl[1], ftmpl[2]))
|
tmpl := template.Must(template.ParseFiles(ftmpl[0], ftmpl[1], ftmpl[2]))
|
||||||
path := strings.TrimPrefix(r.URL.Path, "/archive/")
|
path := strings.TrimPrefix(r.URL.Path, "/archive/")
|
||||||
|
|
|
@ -69,10 +69,30 @@ input[type="text"] {
|
||||||
border-color: #ea8181;
|
border-color: #ea8181;
|
||||||
}
|
}
|
||||||
|
|
||||||
.submit, .footer, h1, .switchlang {
|
select {
|
||||||
|
background-color: #600e0e;
|
||||||
|
color: #ea8181;
|
||||||
|
font-size: 18px;
|
||||||
|
border-radius: 4px;
|
||||||
|
max-width: 700px;
|
||||||
|
border: 1px #ff3b3b groove;
|
||||||
|
padding: 8px;
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
select, input.langchange {
|
||||||
|
height: 35px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit, .footer, h1 {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input.langchange {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
.submit, .footer, h1 {
|
.submit, .footer, h1 {
|
||||||
margin-top: 32px;
|
margin-top: 32px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{{template "header" .}}
|
{{template "header" .}}
|
||||||
{{ .Err }}<br />
|
{{ .Err }}<br />
|
||||||
<a href="/">{{if eq .Lan "ja"}}トップページに戻る{{else}}Return to toppage{{end}}</a>
|
<a href="/">{{.T "totop"}}</a>
|
||||||
{{template "footer" .}}
|
{{template "footer" .}}
|
||||||
|
|
|
@ -28,8 +28,8 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="archhead">
|
<div class="archhead">
|
||||||
{{if eq .Lan "ja"}}保存サイトでアーカイブしました。{{else}}Archived with Hozon Site.{{end}} <a class="archlink" href="https://technicalsuwako.moe/blog/hozonsite-{{.Ves}}">hozonsite-{{ .Ver }}</a><br />
|
{{.T "archwhozonsite"}} <a class="archlink" href="https://technicalsuwako.moe/blog/hozonsite-{{.Ves}}">hozonsite-{{ .Ver }}</a><br />
|
||||||
<a class="archlink" href="/">{{if eq .Lan "ja"}}トップページへ{{else}}To toppage{{end}}</a>
|
<a class="archlink" href="/">{{.T "tophe"}}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="archbody">
|
<div class="archbody">
|
||||||
{{ .Body }}
|
{{ .Body }}
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
{{template "header" .}}
|
{{template "header" .}}
|
||||||
<h3>{{.Url}}</h3>
|
<h3>{{.Url}}</h3>
|
||||||
{{if eq .Lan "en"}}
|
{{.T "areadyhozon"}}<br />
|
||||||
Pages that already got archived:
|
|
||||||
{{else}}
|
|
||||||
既に保存されたページ:
|
|
||||||
{{end}}<br />
|
|
||||||
{{range $i, $e := .Ext}}
|
{{range $i, $e := .Ext}}
|
||||||
<a href="{{$e.Url}}">
|
<a href="{{$e.Url}}">
|
||||||
{{$e.Date}}
|
{{$e.Date}}
|
||||||
|
@ -12,17 +8,13 @@
|
||||||
<br />
|
<br />
|
||||||
{{end}}
|
{{end}}
|
||||||
<p>
|
<p>
|
||||||
{{if eq .Lan "en"}}
|
{{.T "willreallyhozon"}}
|
||||||
This page seems to have been already archived.<br />Do you really want to proceed?
|
|
||||||
{{else}}
|
|
||||||
このページが既に保存されているみたいです。<br />本当に手続きましょうか?
|
|
||||||
{{end}}
|
|
||||||
</p>
|
</p>
|
||||||
<form action="/" method="post">
|
<form action="/" method="post">
|
||||||
<input type="hidden" name="hozonsite" value="{{.Url}}" />
|
<input type="hidden" name="hozonsite" value="{{.Url}}" />
|
||||||
<input type="hidden" name="agree" value="1" />
|
<input type="hidden" name="agree" value="1" />
|
||||||
<div class="submit">
|
<div class="submit">
|
||||||
<input type="submit" name="submit" value="{{if eq .Lan "en"}}Yes, please archive!!{{else}}はい、保存して下さい!!{{end}}" />
|
<input type="submit" name="submit" value="{{.T "yesreallyhozon"}}" />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{{template "footer" .}}
|
{{template "footer" .}}
|
||||||
|
|
|
@ -3,24 +3,28 @@
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
|
||||||
<head>
|
<head>
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="content-type" />
|
<meta content="text/html; charset=utf-8" http-equiv="content-type" />
|
||||||
<meta name="title" content="保存サイト" />
|
<meta name="title" content="{{.T "hozonsite"}}" />
|
||||||
<meta name="description" content="世界初FOSS系ウエブアーカイバーです。" />
|
<meta name="description" content="{{.T "desc"}}" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>保存サイト〜{{.Tit}}</title>
|
<title>{{.T "hozonsite"}}〜{{.T "top"}}</title>
|
||||||
<link rel="icon" type="image/x-icon" href="/static/favicon.ico" />
|
<link rel="icon" type="image/x-icon" href="/static/favicon.ico" />
|
||||||
<link rel="stylesheet" type="text/css" href="/static/style.css" />
|
<link rel="stylesheet" type="text/css" href="/static/style.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>
|
<h1>
|
||||||
<img class="headerimg" src="/static/logo.jpg" alt="{{if eq .Lan "ja"}}ロゴ{{else}}Logo{{end}}" />
|
<img class="headerimg" src="/static/logo.jpg" alt="{{.T "logo"}}" />
|
||||||
</h1>
|
</h1>
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<p>
|
<p>
|
||||||
<a href="/">{{if eq .Lan "ja"}}トップ{{else}}Top{{end}}</a>
|
<a href="/">{{.T "top"}}</a>
|
||||||
</p>
|
</p>
|
||||||
<form method="post" action="/">
|
<form method="post" action="/">
|
||||||
<div class="switchlang">
|
<div class="central">
|
||||||
<input class="langchange" type="submit" name="langchange" value="{{if eq .Lan "ja"}}Change to English{{else}}日本語に変更する{{end}}" />
|
<select class="langchange" name="lang">
|
||||||
|
<option value="ja"{{if eq .Lan "ja"}} selected{{end}}>日本語</option>
|
||||||
|
<option value="en"{{if eq .Lan "en"}} selected{{end}}>English</option>
|
||||||
|
</select>
|
||||||
|
<input class="langchange" type="submit" name="chen" value="{{.T "langchange"}}" />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
{{template "header" .}}
|
{{template "header" .}}
|
||||||
{{if eq .Lan "ja"}}どのページを保存しますか?{{else}}Which page will you archive?{{end}}
|
{{.T "topwhatsave"}}
|
||||||
<form action="/" method="post">
|
<form action="/" method="post">
|
||||||
<input type="text" name="hozonsite" value="" />
|
<input type="text" name="hozonsite" value="" />
|
||||||
<div class="submit">
|
<div class="submit">
|
||||||
<input type="submit" name="submit" value="{{if eq .Lan "ja"}}保存{{else}}Archive{{end}}" />
|
<input type="submit" name="submit" value="{{.T "hozon"}}" />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{{template "footer" .}}
|
{{template "footer" .}}
|
||||||
|
|
読み込み中…
新しいイシューから参照