Skip to content

Commit

Permalink
i18n work, and enable communities to more easily customize about text
Browse files Browse the repository at this point in the history
  • Loading branch information
cblgh committed Sep 19, 2022
1 parent da67000 commit d792585
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 23 deletions.
51 changes: 51 additions & 0 deletions about.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# About

This forum is for and by the [Merveilles](https://wiki.xxiivv.com/site/merveilles.html)
community.

The [forum software](https://github.com/cblgh/cerca) itself was created from scratch by
[cblgh](https://cblgh.org) at the start of 2022, after a long time of pining for a new wave of
forums hangs.

If you are from Merveilles: [register](/register) an account. If you're a passerby, feel free to read the [public threads](/).

## Code of conduct

As with all Merveilles spaces, this forum abides by the compact set out in the [Merveilles Code
of Conduct](https://github.com/merveilles/Resources/blob/master/CONDUCT.md).

## Forum syntax

Posts in the forum are made using [Markdown syntax](https://en.wikipedia.org/wiki/Markdown#Examples).

<b>\*\*Bold text\*\*</b> and <i>\*italics\*</i>

<ul>
<li>* lists</li>
<li>* like </li>
<li>* this </li>
</ul>

<blockquote>&gt; Blockquote</blockquote>

<code>\`typewriter text\`</code>

<!-- leave the <pre><code> blocks from reformatting! they render all their spacing :)-->
<pre><code>```
blocks of
code like
this
```
</code></pre>

Create links like <code>\[this\]\(url\)</code>, and embed images like: <code>!\[description\]\(url\)</code>. Note how the image
syntax's exclamation mark precedes the regular link syntax.

Each post in the thread can be referenced like <code>\[this post\]\(#12\)</code>, where 12 is the post number which can be
found at each post timestamp.

<pre><code>this is one paragraph.
this belongs to the same paragraph.

this is a new paragraph
</code></pre>
7 changes: 7 additions & 0 deletions html/about-template.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{{ template "head" . }}
<main>
<article>
{{ .Data }}
</article>
</main>
{{ template "footer" . }}
8 changes: 4 additions & 4 deletions html/head.html
Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,13 @@
</li>
{{ end }}
{{ if .QuickNav }}
<li><a href="#bottom">bottom</a></li>
<li><a href="#bottom">{{ "Bottom" | translate }}</a></li>
{{end}}
<li><a href="/about">about</a></li>
<li><a href="/about">{{ "About" | translate }}</a></li>
{{ if .LoggedIn }}
<li><a href="/logout">logout</a></li>
<li><a href="/logout">{{"Logout" | translate }}</a></li>
{{ else }}
<li><a href="/login">login</a></li>
<li><a href="/login">{{ "Login" | translate }}</a></li>
{{ end }}
</ul>
</nav>
Expand Down
8 changes: 4 additions & 4 deletions html/login-component.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
<form method="post" action="/login">
<div style="display: grid;">
<div>
<label for="username">Username:</label>
<label for="username">{{ "Username" | translate | capitalize }}:</label>
<input type="text" name="username" id="username">
</div>
<div>
<label for="password">Password:</label>
<label for="password">{{ "Password" | translate | capitalize }}:</label>
<input type="password" name="password" id="password" style="margin-bottom:0;" aria-describedby="password-help">
<div><small id="password-help">Must be at least 9 characters long.</small></div>
<div><small id="password-help">{{ "PasswordMin" | translate }}</small></div>
</div>
<input type="submit" value="Enter" style="margin-top:1rem;">
<input type="submit" value='{{ "Enter" | translate | capitalize }}' style="margin-top:1rem;">
</div>
</form>
{{ end }}
6 changes: 3 additions & 3 deletions html/login.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{{ template "head" . }}
<main>
<h1>Login</h1>
<p>This forum is for the <a href="https://wiki.xxiivv.com/site/merveilles.html">Merveilles</a> community. Don't have an account yet? <a href="/register">Register</a> one. </p>
<h1>{{ "Login" | translate | capitalize }}</h1>
<p>{{ "LoginDescription" | translateWithData | capitalize | tohtml }} {{ "LoginNoAccount" | translate | tohtml }}</p>
<div style="max-width: 20rem">
{{ template "login-component" . }}
<p><a href="/reset">Forgot your password?</a></p>
<p><a href="/reset">{{ "PasswordForgot" | translate }}</a></p>
</div>
{{ if .Data.FailedAttempt }}
<p><b>Failed login attempt:</b> incorrect password, wrong username, or a non-existent user.</p>
Expand Down
16 changes: 7 additions & 9 deletions i18n/i18n.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ package i18n

import (
"cerca/util"
"text/template"
"html/template"
"strings"
"log"
"fmt"
)

var English = map[string]string{
Expand All @@ -31,13 +30,13 @@ var EspanolMexicano = map[string]string{
"Sort": "sort",
"SortPostsRecent": "recent posts",
"SortThreadsRecent": "most recent threads",
"LoginDescription": "Este foro es principalmente para las personas de la comunidad <a href='{{.CommunityLink}}>{{.CommunityName}}</a>.",
"LoginDescription": "Este foro es principalmente para las personas de la comunidad <a href='{{ .CommunityLink }}'>{{ .CommunityName }}</a>.",
"LoginNoAccount": "¿No tienes una cuenta? <a href='/register'>Registra</a> una. ",
"Username": "usuarie",
"Password": "contraseña",
"PasswordMin": "Debe tener por lo menos 9 caracteres.",
"PasswordForgot": "Olvidaste tu contraseña?",
"Enter": "enter",
"Enter": "entrar",
}

var translations = map[string]map[string]string{
Expand Down Expand Up @@ -77,8 +76,7 @@ func Init(lang string) Translator {
return Translator{lang}
}

func main() {
tr := Init("EnglishSwedish")
fmt.Println(tr.Translate("LoginNoAccount"))
fmt.Println(tr.TranslateWithData("LoginDescription", Community{"Merveilles", "https://merveill.es"}))
}
// usage:
// tr := Init("EnglishSwedish")
// fmt.Println(tr.Translate("LoginNoAccount"))
// fmt.Println(tr.TranslateWithData("LoginDescription", Community{"Merveilles", "https://merveill.es"}))
35 changes: 32 additions & 3 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"strings"
"time"

"cerca/i18n"
"cerca/crypto"
"cerca/database"
cercaHTML "cerca/html"
Expand Down Expand Up @@ -108,6 +109,9 @@ func (h RequestHandler) IsLoggedIn(req *http.Request) (bool, int) {
}

var (
translator = i18n.Init("EspañolMexicano")
community = i18n.Community{"Merveilles", "https://wiki.xxiivv.com/site/merveilles.html"}

templateFuncs = template.FuncMap{
"formatDateTime": func(t time.Time) string {
return t.Format("2006-01-02 15:04:05")
Expand All @@ -127,6 +131,23 @@ var (
}
return t.Format("2006-01-02")
},
"translate": func(key string) string {
return translator.Translate(key)
},
"translateWithData": func(key string) string {
return translator.TranslateWithData(key, community)
},
"capitalize": func (s string) string {
return strings.ToUpper(string(s[0])) + s[1:]
},
"tohtml": func (s string) template.HTML {
// use of this function is risky cause it interprets the passed in string and renders it as unescaped html.
// can allow for attacks!
//
// advice: only use on strings that come statically from within cerca code, never on titles that may contain user-submitted data
// :)
return (template.HTML)(s)
},
}

templates = template.Must(generateTemplates())
Expand All @@ -135,6 +156,7 @@ var (
func generateTemplates() (*template.Template, error) {
views := []string{
"about",
"about-template",
"footer",
"generic-message",
"head",
Expand Down Expand Up @@ -264,7 +286,7 @@ func (h RequestHandler) LoginRoute(res http.ResponseWriter, req *http.Request) {
loggedIn, _ := h.IsLoggedIn(req)
switch req.Method {
case "GET":
h.renderView(res, "login", TemplateData{Data: LoginData{}, LoggedIn: loggedIn, Title: ""})
h.renderView(res, "login", TemplateData{Data: LoginData{}, LoggedIn: loggedIn, Title: translator.Translate("Login")})
case "POST":
username := req.PostFormValue("username")
password := req.PostFormValue("password")
Expand All @@ -276,7 +298,7 @@ func (h RequestHandler) LoginRoute(res http.ResponseWriter, req *http.Request) {
}
if err != nil {
fmt.Println(err)
h.renderView(res, "login", TemplateData{Data: LoginData{FailedAttempt: true}, LoggedIn: loggedIn, Title: ""})
h.renderView(res, "login", TemplateData{Data: LoginData{FailedAttempt: true}, LoggedIn: loggedIn, Title: translator.Translate("Login")})
return
}
// save user id in cookie
Expand Down Expand Up @@ -564,7 +586,14 @@ func (h RequestHandler) GenericRoute(res http.ResponseWriter, req *http.Request)

func (h RequestHandler) AboutRoute(res http.ResponseWriter, req *http.Request) {
loggedIn, _ := h.IsLoggedIn(req)
h.renderView(res, "about", TemplateData{LoggedIn: loggedIn})
// TODO (2022-09-19):
// * make sure file exists
// * create function to output a prefilled version, using the Community name and CommunityLink
// * embed the prefilled version in the code using golang's goembed
b, err := os.ReadFile("data/about.md")
util.Check(err, "about route: open about.md")
input := util.Markup(template.HTML(b))
h.renderView(res, "about-template", TemplateData{Data: input, LoggedIn: loggedIn})
}

func (h RequestHandler) RobotsRoute(res http.ResponseWriter, req *http.Request) {
Expand Down

0 comments on commit d792585

Please sign in to comment.