diff --git a/README.md b/README.md
index db13342..92b8d54 100644
--- a/README.md
+++ b/README.md
@@ -24,6 +24,7 @@ Originally inspired by a proof of concept from https://github.com/mora9715/hapro
- Maintenance mode page for selected domains.
- Geoip mapping support for alt-svc headers.
- Support simple load balancing to multiple backends per domain dynamically.
+- Multiple language support with locales files (currently en-US and pt-PT).
- Fix multiple security issues.
- Many bugfixes.
diff --git a/docker-compose.yml b/docker-compose.yml
index 36f426f..2c94009 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -17,6 +17,7 @@ services:
- ./src/lua/scripts/:/etc/haproxy/scripts/
- ./src/lua/libs/:/etc/haproxy/libs/
- ./src/js/:/etc/haproxy/js/
+ - ./src/locales/:/etc/haproxy/locales/
environment:
# These are the hcaptcha and recaptcha test keys, not leaking any dont worry :^)
- HCAPTCHA_SITEKEY=20000000-ffff-ffff-ffff-000000000002
diff --git a/src/locales/en-US.json b/src/locales/en-US.json
new file mode 100644
index 0000000..d00ec4a
--- /dev/null
+++ b/src/locales/en-US.json
@@ -0,0 +1,23 @@
+{
+ "Maintenance Mode": "Maintenance Mode",
+ "Under maintenance. Please try again soon!": "Under maintenance. Please try again soon!",
+ "Hold on...": "Hold on...",
+ "Browser does not support Web Workers.": "Browser does not support Web Workers.",
+ "Browser does not support WebAssembly.": "Browser does not support WebAssembly.",
+ "Server rejected your submission.": "Server rejected your submission.",
+ "Server encountered an error.": "Server encountered an error.",
+ "Failed to send request to server.": "Failed to send request to server.",
+ "Working, ≈%ss remaining": "Working, ≈%ss remaining",
+ "Waiting for captcha.": "Waiting for captcha.",
+ "Submitting...": "Submitting...",
+ "Performance & security by BasedFlare": "Performance & security by BasedFlare",
+ "Verifying your connection to %s": "Verifying your connection to %s",
+ "This process is automatic, please wait a moment...": "This process is automatic, please wait a moment...",
+ "Please solve the captcha to continue.": "Please solve the captcha to continue.",
+ "JavaScript is required on this page.": "JavaScript is required on this page.",
+ "No JavaScript?": "No JavaScript?",
+ "Run this in a linux terminal (requires argon2
package installed):": "Run this in a linux terminal (requires argon2
package installed):",
+ "Run this in a linux terminal (requires perl
):": "Run this in a linux terminal (requires perl
):",
+ "Paste the script output into the box and submit:": "Paste the script output into the box and submit:",
+ "submit": "submit"
+}
diff --git a/src/locales/pt-PT.json b/src/locales/pt-PT.json
new file mode 100644
index 0000000..9ece498
--- /dev/null
+++ b/src/locales/pt-PT.json
@@ -0,0 +1,23 @@
+{
+ "Maintenance Mode": "Modo Manutenção",
+ "Under maintenance. Please try again soon!": "Em manutenção. Tenta outra vez em breve!",
+ "Hold on...": "Aguarda...",
+ "Browser does not support Web Workers.": "Navegador não suporta Web Workers.",
+ "Browser does not support WebAssembly.": "Navegador não suporta WebAssembly.",
+ "Server rejected your submission.": "Servidor rejeitou o teu pedido.",
+ "Server encountered an error.": "Servidor encontrou um erro.",
+ "Failed to send request to server.": "Envio de pedido ao servidor falhou.",
+ "Working, ≈%ss remaining": "A trabalhar, ≈%ss para terminar",
+ "Waiting for captcha.": "À espera do captcha.",
+ "Submitting...": "A enviar...",
+ "Performance & security by BasedFlare": "Performance & segurança por BasedFlare",
+ "Verifying your connection to %s": "A verificar a tua ligação a %s",
+ "This process is automatic, please wait a moment...": "Este processo é automático, por favor espera um momento...",
+ "Please solve the captcha to continue.": "Por favor resolve a captcha para continuar.",
+ "JavaScript is required on this page.": "Javascript é necessário nesta página.",
+ "No JavaScript?": "Sem Javascript?",
+ "Run this in a linux terminal (requires argon2
package installed):": "Corre isto num terminal linux (requer package argon2
instalada):",
+ "Run this in a linux terminal (requires perl
):": "Corre isto num terminal linux (requer perl
):",
+ "Paste the script output into the box and submit:": "Cola o output do script na caixa e envia:",
+ "submit": "enviar"
+}
diff --git a/src/lua/scripts/bot-check.lua b/src/lua/scripts/bot-check.lua
index d6690af..3b23cd8 100644
--- a/src/lua/scripts/bot-check.lua
+++ b/src/lua/scripts/bot-check.lua
@@ -11,6 +11,19 @@ local cookie = require("cookie")
local json = require("json")
local randbytes = require("randbytes")
local templates = require("templates")
+local locales_path = "/etc/haproxy/locales/"
+local locales_table = {}
+-- local locales_strings = {}
+for file_name in io.popen('ls "'..locales_path..'"*.json'):lines() do
+ local file_name_with_path = utils.split(file_name, "/")
+ local file_name_without_ext = utils.split(file_name_with_path[#file_name_with_path], ".")[1]
+ local file = io.open(file_name, "r")
+ local json_contents = file:read("*all")
+ local json_object = json.decode(json_contents)
+ file:close()
+ locales_table[file_name_without_ext] = json_object
+ -- locales_strings[file_name_without_ext] = json_contents
+end
-- POW
local pow_type = os.getenv("POW_TYPE") or "argon2"
@@ -74,8 +87,31 @@ function _M.kill_tor_circuit(txn)
utils.send_tor_control_port(circuit_identifier)
end
+-- read first language from accept-language in applet
+local default_lang = "en-US"
+function _M.get_first_language(applet)
+ local accept_language = applet.headers["accept-language"] or {}
+ accept_language = accept_language[0] or ""
+ if #accept_language > 0 and #accept_language < 100 then -- length limit preventing abuse
+ for lang in accept_language:gmatch("[^,%s]+") do
+ if not lang:find(";") then
+ return lang
+ end
+ end
+ end
+end
+
+
function _M.view(applet)
+ -- set the ll language var based off header or default to en-US
+ local lang = _M.get_first_language(applet)
+ local ll = locales_table[lang]
+ if ll == nil then
+ ll = locales_table[default_lang]
+ lang = default_lang
+ end
+
-- set response body and declare status code
local response_body = ""
local response_status_code
@@ -120,27 +156,62 @@ function _M.view(applet)
end
-- pow at least is always enabled when reaching bot-check page
- site_name_body = string.format(templates.site_name_section, host)
+ site_name_body = string.format(
+ templates.site_name_section,
+ string.format(ll["Verifying your connection to %s"], host)
+ )
if captcha_enabled then
- captcha_body = string.format(templates.captcha_section, captcha_classname,
- captcha_sitekey, captcha_script_src)
+ captcha_body = string.format(
+ templates.captcha_section,
+ ll["Please solve the captcha to continue."],
+ captcha_classname,
+ captcha_sitekey,
+ captcha_script_src
+ )
else
- pow_body = templates.pow_section
+ pow_body = string.format(
+ templates.pow_section,
+ ll["This process is automatic, please wait a moment..."]
+ )
local noscript_extra
if pow_type == "argon2" then
noscript_extra = templates.noscript_extra_argon2
else
noscript_extra = templates.noscript_extra_sha256
end
- noscript_extra_body = string.format(noscript_extra, user_key,
- challenge_hash, expiry, signature, math.ceil(pow_difficulty/8),
- argon_time, argon_kb)
+ noscript_extra_body = string.format(
+ noscript_extra,
+ ll["No JavaScript?"],
+ ll["Run this in a linux terminal (requires perl
):"],
+ user_key,
+ challenge_hash,
+ expiry,
+ signature,
+ math.ceil(pow_difficulty/8),
+ argon_time,
+ argon_kb,
+ ll["Paste the script output into the box and submit:"]
+ )
end
-- sub in the body sections
- response_body = string.format(templates.body, combined_challenge,
- pow_difficulty, argon_time, argon_kb, pow_type,
- site_name_body, pow_body, captcha_body, noscript_extra_body, ray_id)
+ response_body = string.format(
+ templates.body,
+ lang,
+ ll["Hold on..."],
+ combined_challenge,
+ pow_difficulty,
+ argon_time,
+ argon_kb,
+ pow_type,
+ site_name_body,
+ pow_body,
+ captcha_body,
+ ll["JavaScript is required on this page."],
+ noscript_extra_body,
+ ray_id,
+ ll["Performance & security by BasedFlare"]
+ )
response_status_code = 403
-- if request is POST, check the answer to the pow/cookie
diff --git a/src/lua/scripts/templates.lua b/src/lua/scripts/templates.lua
index 7b623e1..41efba0 100644
--- a/src/lua/scripts/templates.lua
+++ b/src/lua/scripts/templates.lua
@@ -4,9 +4,9 @@ local _M = {}
_M.body = [[
-