feat: implement localization system (#716)
* lib/localization: implement localization system Locale files are placed in lib/localization/locales/. If you add a locale, update manifest.json with available locales. * Exclude locales from check spelling * tests(lib/localization): add comprehensive translations test Signed-off-by: Xe Iaso <me@xeiaso.net> * fix(challenge/metarefresh): enable localization Signed-off-by: Xe Iaso <me@xeiaso.net> * fix: use simple syntax for localization in templ Also localize CELPHASE into French according to the wishes of the artist. Signed-off-by: Xe Iaso <me@xeiaso.net> * chore: spelling Signed-off-by: Xe Iaso <me@xeiaso.net> * chore:(js): fix forbidden patterns Signed-off-by: Xe Iaso <me@xeiaso.net> * chore: add goi18n to tools Signed-off-by: Xe Iaso <me@xeiaso.net> * test(lib/localization): dynamically determine the list of supported languages Signed-off-by: Xe Iaso <me@xeiaso.net> --------- Signed-off-by: Xe Iaso <me@xeiaso.net> Co-authored-by: Xe Iaso <me@xeiaso.net>
This commit is contained in:
parent
c2423d0688
commit
ad5430612f
24 changed files with 1205 additions and 314 deletions
|
|
@ -3,11 +3,12 @@ package web
|
|||
import (
|
||||
"fmt"
|
||||
"github.com/TecharoHQ/anubis"
|
||||
"github.com/TecharoHQ/anubis/lib/localization"
|
||||
"github.com/TecharoHQ/anubis/lib/policy/config"
|
||||
"github.com/TecharoHQ/anubis/xess"
|
||||
)
|
||||
|
||||
templ base(title string, body templ.Component, impressum *config.Impressum, challenge any, ogTags map[string]string) {
|
||||
templ base(title string, body templ.Component, impressum *config.Impressum, challenge any, ogTags map[string]string, localizer *localization.SimpleLocalizer) {
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
|
|
@ -71,14 +72,16 @@ templ base(title string, body templ.Component, impressum *config.Impressum, chal
|
|||
<footer>
|
||||
<center>
|
||||
<p>
|
||||
Protected by <a href="https://github.com/TecharoHQ/anubis">Anubis</a> from <a
|
||||
{ localizer.T("protected_by") } <a href="https://github.com/TecharoHQ/anubis">Anubis</a> from <a
|
||||
href="https://techaro.lol"
|
||||
>Techaro</a>. Made with ❤️ in 🇨🇦.
|
||||
>Techaro</a>. { localizer.T("made_with") }.
|
||||
</p>
|
||||
<p>Mascot design by <a href="https://bsky.app/profile/celphase.bsky.social">CELPHASE</a>.</p>
|
||||
<p>{ localizer.T("mascot_design") } <a href="https://bsky.app/profile/celphase.bsky.social">{ localizer.T("celphase") }</a>.</p>
|
||||
if impressum != nil {
|
||||
<p>@templ.Raw(impressum.Footer)
|
||||
-- <a href={ templ.SafeURL(fmt.Sprintf("%simprint", anubis.APIPrefix)) }>Imprint</a></p>
|
||||
<p>
|
||||
@templ.Raw(impressum.Footer)
|
||||
-- <a href={ templ.SafeURL(fmt.Sprintf("%simprint", anubis.APIPrefix)) }>Imprint</a>
|
||||
</p>
|
||||
}
|
||||
</center>
|
||||
</footer>
|
||||
|
|
@ -87,79 +90,59 @@ templ base(title string, body templ.Component, impressum *config.Impressum, chal
|
|||
</html>
|
||||
}
|
||||
|
||||
templ index() {
|
||||
templ index(localizer *localization.SimpleLocalizer) {
|
||||
<div class="centered-div">
|
||||
<img id="image" style="width:100%;max-width:256px;" src={ anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/img/pensive.webp?cacheBuster=" + anubis.Version }/>
|
||||
<img style="display:none;" style="width:100%;max-width:256px;" src={ anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/img/happy.webp?cacheBuster=" + anubis.Version }/>
|
||||
<p id="status">Loading...</p>
|
||||
<p id="status">{ localizer.T("loading") }</p>
|
||||
<script async type="module" src={ anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/js/main.mjs?cacheBuster=" + anubis.Version }></script>
|
||||
<div id="progress" role="progressbar" aria-labelledby="status">
|
||||
<div class="bar-inner"></div>
|
||||
</div>
|
||||
<details>
|
||||
<summary>Why am I seeing this?</summary>
|
||||
<summary>{ localizer.T("why_am_i_seeing") }</summary>
|
||||
<p>
|
||||
You are seeing this because the administrator of this website has set up <a
|
||||
href="https://github.com/TecharoHQ/anubis"
|
||||
>Anubis</a> to protect the server against the scourge of
|
||||
<a href="https://thelibre.news/foss-infrastructure-is-under-attack-by-ai-companies/">
|
||||
AI companies
|
||||
aggressively scraping websites
|
||||
</a>. This can and does cause downtime for the websites, which makes their
|
||||
resources inaccessible for everyone.
|
||||
{ localizer.T("ai_companies_explanation") }
|
||||
</p>
|
||||
<p>
|
||||
Anubis is a compromise. Anubis uses a <a
|
||||
href="https://anubis.techaro.lol/docs/design/why-proof-of-work"
|
||||
>Proof-of-Work</a>
|
||||
scheme in the vein of <a href="https://en.wikipedia.org/wiki/Hashcash">Hashcash</a>, a proposed
|
||||
proof-of-work scheme for reducing email spam. The idea is that at individual scales the additional load is
|
||||
ignorable, but at mass scraper levels it adds up and makes scraping much more expensive.
|
||||
{ localizer.T("anubis_compromise") }
|
||||
</p>
|
||||
<p>
|
||||
Ultimately, this is a hack whose real purpose is to give a "good enough" placeholder solution so that more
|
||||
time can be spent on fingerprinting and identifying headless browsers (EG: via how they do font rendering)
|
||||
so that the challenge proof of work page doesn't need to be presented to users that are much more likely to
|
||||
be legitimate.
|
||||
{ localizer.T("hack_purpose") }
|
||||
</p>
|
||||
<p>
|
||||
Please note that Anubis requires the use of modern JavaScript features that plugins like <a
|
||||
href="https://jshelter.org/"
|
||||
>JShelter</a> will disable. Please disable JShelter or other such
|
||||
plugins for this domain.
|
||||
{ localizer.T("jshelter_note") }
|
||||
</p>
|
||||
<p>This website is running Anubis version <code>{ anubis.Version }</code>.</p>
|
||||
<p>{ localizer.T("version_info") } <code>{ anubis.Version }</code>.</p>
|
||||
</details>
|
||||
<noscript>
|
||||
<p>
|
||||
Sadly, you must enable JavaScript to get past this challenge. This is required because AI companies have
|
||||
changed
|
||||
the social contract around how website hosting works. A no-JS solution is a work-in-progress.
|
||||
{ localizer.T("javascript_required") }
|
||||
</p>
|
||||
</noscript>
|
||||
<div id="testarea"></div>
|
||||
</div>
|
||||
}
|
||||
|
||||
templ errorPage(message string, mail string) {
|
||||
templ errorPage(message string, mail string, localizer *localization.SimpleLocalizer) {
|
||||
<div class="centered-div">
|
||||
<img id="image" alt="Sad Anubis" style="width:100%;max-width:256px;" src={ anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/img/reject.webp?cacheBuster=" + anubis.Version }/>
|
||||
<p>{ message }.</p>
|
||||
<button onClick="window.location.reload();">Try again</button>
|
||||
<button onClick="window.location.reload();">{ localizer.T("try_again") }</button>
|
||||
if mail != "" {
|
||||
<p>
|
||||
<a href="/">Go home</a> or if you believe you should not be blocked, please contact the webmaster at
|
||||
<a href="/">{ localizer.T("go_home") }</a> { localizer.T("contact_webmaster") }
|
||||
<a href={ "mailto:" + templ.SafeURL(mail) }>
|
||||
{ mail }
|
||||
</a>
|
||||
</p>
|
||||
} else {
|
||||
<p><a href="/">Go home</a></p>
|
||||
<p><a href="/">{ localizer.T("go_home") }</a></p>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
templ StaticHappy() {
|
||||
templ StaticHappy(localizer *localization.SimpleLocalizer) {
|
||||
<div class="centered-div">
|
||||
<img
|
||||
style="display:none;"
|
||||
|
|
@ -167,25 +150,25 @@ templ StaticHappy() {
|
|||
src={ "/.within.website/x/cmd/anubis/static/img/happy.webp?cacheBuster=" +
|
||||
anubis.Version }
|
||||
/>
|
||||
<p>This is just a check endpoint for your reverse proxy to use.</p>
|
||||
<p>{ localizer.T("static_check_endpoint") }</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
templ bench() {
|
||||
templ bench(localizer *localization.SimpleLocalizer) {
|
||||
<div style="height:20rem;display:flex">
|
||||
<table style="margin-top:1rem;display:grid;grid-template:auto 1fr/auto auto;gap:0 0.5rem">
|
||||
<thead
|
||||
style="border-bottom:1px solid black;padding:0.25rem 0;display:grid;grid-template:1fr/subgrid;grid-column:1/-1"
|
||||
>
|
||||
<tr id="table-header" style="display:contents">
|
||||
<th style="width:4.5rem">Time</th>
|
||||
<th style="width:4rem">Iters</th>
|
||||
<th style="width:4.5rem">{ localizer.T("time") }</th>
|
||||
<th style="width:4rem">{ localizer.T("iters") }</th>
|
||||
</tr>
|
||||
<tr id="table-header-compare" style="display:none">
|
||||
<th style="width:4.5rem">Time A</th>
|
||||
<th style="width:4rem">Iters A</th>
|
||||
<th style="width:4.5rem">Time B</th>
|
||||
<th style="width:4rem">Iters B</th>
|
||||
<th style="width:4.5rem">{ localizer.T("time_a") }</th>
|
||||
<th style="width:4rem">{ localizer.T("iters_a") }</th>
|
||||
<th style="width:4.5rem">{ localizer.T("time_b") }</th>
|
||||
<th style="width:4rem">{ localizer.T("iters_b") }</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody
|
||||
|
|
@ -195,25 +178,25 @@ templ bench() {
|
|||
</table>
|
||||
<div class="centered-div">
|
||||
<img id="image" style="width:100%;max-width:256px;" src={ anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/img/pensive.webp?cacheBuster=" + anubis.Version }/>
|
||||
<p id="status" style="max-width:256px">Loading...</p>
|
||||
<p id="status" style="max-width:256px">{ localizer.T("loading") }</p>
|
||||
<script async type="module" src={ anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/js/bench.mjs?cacheBuster=" + anubis.Version }></script>
|
||||
<div id="sparkline"></div>
|
||||
<noscript>
|
||||
<p>Running the benchmark tool requires JavaScript to be enabled.</p>
|
||||
<p>{ localizer.T("benchmark_requires_js") }</p>
|
||||
</noscript>
|
||||
</div>
|
||||
</div>
|
||||
<form id="controls" style="position:fixed;top:0.5rem;right:0.5rem">
|
||||
<div style="display:flex;justify-content:end">
|
||||
<label for="difficulty-input" style="margin-right:0.5rem">Difficulty:</label>
|
||||
<label for="difficulty-input" style="margin-right:0.5rem">{ localizer.T("difficulty") }</label>
|
||||
<input id="difficulty-input" type="number" name="difficulty" style="width:3rem"/>
|
||||
</div>
|
||||
<div style="margin-top:0.25rem;display:flex;justify-content:end">
|
||||
<label for="algorithm-select" style="margin-right:0.5rem">Algorithm:</label>
|
||||
<label for="algorithm-select" style="margin-right:0.5rem">{ localizer.T("algorithm") }</label>
|
||||
<select id="algorithm-select" name="algorithm"></select>
|
||||
</div>
|
||||
<div style="margin-top:0.25rem;display:flex;justify-content:end">
|
||||
<label for="compare-select" style="margin-right:0.5rem">Compare:</label>
|
||||
<label for="compare-select" style="margin-right:0.5rem">{ localizer.T("compare") }</label>
|
||||
<select id="compare-select" name="compare">
|
||||
<option value="NONE">-</option>
|
||||
</select>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue