diff --git a/abrechenbarkeit.lua b/abrechenbarkeit.lua index deaaf34..d29cf20 100755 --- a/abrechenbarkeit.lua +++ b/abrechenbarkeit.lua @@ -15,7 +15,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . -]]-- +]] -- local function escape(s) return s:gsub("<", "<"):gsub("<", "<") @@ -63,17 +63,50 @@ local function load_config() return config end +local function load_translations(langs) + local t = {} + for _, lcode in ipairs(langs) do + local file = io.open(string.format("locale/%s.ini", lcode), "r") + if file ~= nil then + for l in file:lines("l") do + if l ~= "" then + local key, value = string.match(l, "^([^=]+)=([^=]*)") + if key ~= nil and value ~= nil then + t[key] = value + end + end + end + end + end + return t +end + local config = load_config() local path = os.getenv("PATH_INFO") local method = os.getenv("REQUEST_METHOD") local query = parse_query(os.getenv("QUERY_STRING")) +local translations = load_translations({ "en", config.language }) local stylesheet = io.open("style.css"):read("a") local script = io.open("script.js"):read("a") +local function format(template, params) + return string.gsub(template, "{([%w\\.!]+)}", function(n) + local raw = n:sub(1,1) ~= "!" + if raw then n = n:sub(2) end + local s = format(params[n] or translations[n] or "NIL TEMPLATE", params) + return raw and s or escape(s) + end) +end + +local function format_amount(amount, tag, classes) + local s = string.format("%.02f%s", amount / 100, config.unit or "€") + if tag == nil then return s end + return string.format([[<%s class="amount-%s %s">%s"]], tag, amount >= 0 and "pos" or "neg", s, tag, classes or "") +end + local function get_user_theme(username) local c = "" - local js = "" if username == "_jeb" then c = "html { animation: 2s jeb infinite; }" c = c .. "@keyframes jeb {\n" @@ -84,24 +117,29 @@ local function get_user_theme(username) elseif username == "Dinnerbone" then c = "html { transform: scale(-1); } " end - return c, js + return c +end + +local function format_duration(t) + if t > 86400 then return string.format("%d day%s", t / 86400, math.floor(t / 86400) ~= 1 and "s" or "") end + if t > 3600 then return string.format("%d hour%s", t / 3600, math.floor(t / 3600) ~= 1 and "s" or "") end + if t > 60 then return string.format("%d minute%s", t / 60, math.floor(t / 60) ~= 1 and "s" or "") end + return string.format("%d seconds", t) end local function respond(status, title, body) - local themecss, themejs = get_user_theme(path and path:sub(2)) - print(string.format("Status: %d", status)) print("Content-Type: text/html") print("") - print(string.format([[ + print(format([[ - %s + {title} - - - - %s + + + + {head_extra} - ]], - escape(title), - stylesheet, -- style.css - themecss, -- theme for user - script, -- script.js - config.head_extra or "" - )) + ]], { + title = escape(title), + style = stylesheet, + user_style = get_user_theme(path and path:sub(2)), + script = script, + head_extra = config.head_extra or "" + })) body() - print(string.format( - "", - themejs - )) + print("") end local function error_box(message) @@ -149,13 +185,6 @@ local function form_data() return parse_query(io.read()) end -local function format_duration(t) - if t > 86400 then return string.format("%d day%s", t / 86400, math.floor(t / 86400) ~= 1 and "s" or "") end - if t > 3600 then return string.format("%d hour%s", t / 3600, math.floor(t / 3600) ~= 1 and "s" or "") end - if t > 60 then return string.format("%d minute%s", t / 60, math.floor(t / 60) ~= 1 and "s" or "") end - return string.format("%d seconds", t) -end - local function read_log() local log = io.open("log", "r") if log == nil then @@ -285,14 +314,15 @@ local function r_user_post(username) end log:flush() log:close() - return string.format([[ -

Transaction successful: %.02f€ (%s)

- - ]], - amount >= 0 and "pos" or "neg", amount / 100, - escape(comment), - config.transaction_sound or "" - ) + return format([[ +

Transaction successful: {amount} ({!comment})

+ + ]], { + sign = amount >= 0 and "pos" or "neg", + amount = format_amount(amount, "strong"), + comment = escape(comment), + sound = config.transaction_sound or "" + }) end local function r_user(username) @@ -301,24 +331,20 @@ local function r_user(username) notif = r_user_post(username) end return respond(200, string.format("Abrechenbarheit: %s", username), function() - print(string.format("

%s

", username)) + print(format("

{username}

", { username = username })) local balance = balances()[username] local last_txn = last_txns()[username] local new_user = balance == nil balance = balance or 0 if notif then print(notif) end if new_user then - print([[ -

This user account does not exist yet. It will only be created after the first transaction.

- ]]) + print([[

{user.lazy_creation}

]]) else print([[
]]) - print(string.format([[ - Current balance:
%.02f€
- ]], balance >= 0 and "pos" or "neg", balance / 100)) - print(string.format([[ - Last transaction added %s ago. View user log - ]], format_duration(os.time() - last_txn), username)) + print(format([[{user.balance}:
{amount}
]], + { sign = balance >= 0 and "pos" or "neg", amount = format_amount(balance, "span", "balance-value") })) + print(format([[{user.last_txn} {user.view_log}]], + { time = format_duration(os.time() - last_txn), username = urlencode(username) })) print([[
]]) end print([[
]]) @@ -336,35 +362,35 @@ local function r_user(username) end end print("
") - print([[ + print(format([[
-

Create Transaction

+

{user.form.transaction}

- +
-

Buy Product

+

{user.form.buy}

- + - +
-

Restock Product

- +

{user.form.restock}

+ - + - + - +
- ]]) + ]])) print("") end) end diff --git a/locale/en.ini b/locale/en.ini index 33705f5..1deac2a 100644 --- a/locale/en.ini +++ b/locale/en.ini @@ -35,3 +35,4 @@ user.form.transaction.submit=Update user.form.transaction=Create Transaction user.last_txn=Last transaction added %s. user.view_log=View user log +user.lazy_creation=This user account does not exist yet. It will only be created after the first transaction.