]> git.lizzy.rs Git - minetest.git/commitdiff
Translate builtin (#10693)
authorWuzzy <wuzzy2@mail.ru>
Fri, 5 Mar 2021 15:27:33 +0000 (15:27 +0000)
committerSmallJoker <mk939@ymail.com>
Fri, 5 Mar 2021 15:29:48 +0000 (16:29 +0100)
This PR is the second attempt to translate builtin.
Server-sent translation files can be added to `builtin/locale/`, whereas client-side translations depend on gettext.

12 files changed:
.gitignore
builtin/client/chatcommands.lua
builtin/client/death_formspec.lua
builtin/common/chatcommands.lua
builtin/common/information_formspecs.lua
builtin/game/chat.lua
builtin/game/privileges.lua
builtin/game/register.lua
builtin/locale/template.txt [new file with mode: 0644]
builtin/profiler/init.lua
src/server.cpp
util/updatepo.sh

index 52f8bc4f4a52e42730042c1696ab56501cd56538..d951f22228b33176de15f0ad413e4423fa1ebc1b 100644 (file)
@@ -86,8 +86,7 @@ src/test_config.h
 src/cmake_config.h
 src/cmake_config_githash.h
 src/unittest/test_world/world.mt
-src/lua/build/
-locale/
+/locale/
 .directory
 *.cbp
 *.layout
index 0e8d4dd030cbbc3e4df9269162f0f74c6ceb5eae..a563a66276f745f6868bcb1a23464e9dbdb67fe3 100644 (file)
@@ -1,6 +1,5 @@
 -- Minetest: builtin/client/chatcommands.lua
 
-
 core.register_on_sending_chat_message(function(message)
        if message:sub(1,2) == ".." then
                return false
@@ -8,7 +7,7 @@ core.register_on_sending_chat_message(function(message)
 
        local first_char = message:sub(1,1)
        if first_char == "/" or first_char == "." then
-               core.display_chat_message(core.gettext("issued command: ") .. message)
+               core.display_chat_message(core.gettext("Issued command: ") .. message)
        end
 
        if first_char ~= "." then
@@ -19,7 +18,7 @@ core.register_on_sending_chat_message(function(message)
        param = param or ""
 
        if not cmd then
-               core.display_chat_message(core.gettext("-!- Empty command"))
+               core.display_chat_message("-!- " .. core.gettext("Empty command."))
                return true
        end
 
@@ -36,7 +35,7 @@ core.register_on_sending_chat_message(function(message)
                        core.display_chat_message(result)
                end
        else
-               core.display_chat_message(core.gettext("-!- Invalid command: ") .. cmd)
+               core.display_chat_message("-!- " .. core.gettext("Invalid command: ") .. cmd)
        end
 
        return true
@@ -66,7 +65,7 @@ core.register_chatcommand("clear_chat_queue", {
        description = core.gettext("Clear the out chat queue"),
        func = function(param)
                core.clear_out_chat_queue()
-               return true, core.gettext("The out chat queue is now empty")
+               return true, core.gettext("The out chat queue is now empty.")
        end,
 })
 
index e755ac5c16ef7e2f2bfb74bbd5c93bcc3da4cfc8..7df0cbd750c0485aca33acfe4da223cdb09123ef 100644 (file)
@@ -2,7 +2,7 @@
 -- handled by the engine.
 
 core.register_on_death(function()
-       core.display_chat_message("You died.")
+       core.display_chat_message(core.gettext("You died."))
        local formspec = "size[11,5.5]bgcolor[#320000b4;true]" ..
                "label[4.85,1.35;" .. fgettext("You died") ..
                "]button_exit[4,3;3,0.5;btn_respawn;".. fgettext("Respawn") .."]"
index 52edda659baab0a89ede36a09b6c45faf6877641..c945e7bdb2926733dfecb72dbb8f8a979e3118e9 100644 (file)
@@ -1,5 +1,9 @@
 -- Minetest: builtin/common/chatcommands.lua
 
+-- For server-side translations (if INIT == "game")
+-- Otherwise, use core.gettext
+local S = core.get_translator("__builtin")
+
 core.registered_chatcommands = {}
 
 function core.register_chatcommand(cmd, def)
@@ -29,25 +33,12 @@ function core.override_chatcommand(name, redefinition)
        core.registered_chatcommands[name] = chatcommand
 end
 
-local cmd_marker = "/"
-
-local function gettext(...)
-       return ...
-end
-
-local function gettext_replace(text, replace)
-       return text:gsub("$1", replace)
-end
-
-
-if INIT == "client" then
-       cmd_marker = "."
-       gettext = core.gettext
-       gettext_replace = fgettext_ne
-end
-
 local function do_help_cmd(name, param)
        local function format_help_line(cmd, def)
+               local cmd_marker = "/"
+               if INIT == "client" then
+                       cmd_marker = "."
+               end
                local msg = core.colorize("#00ffff", cmd_marker .. cmd)
                if def.params and def.params ~= "" then
                        msg = msg .. " " .. def.params
@@ -65,9 +56,21 @@ local function do_help_cmd(name, param)
                        end
                end
                table.sort(cmds)
-               return true, gettext("Available commands: ") .. table.concat(cmds, " ") .. "\n"
-                               .. gettext_replace("Use '$1help <cmd>' to get more information,"
-                               .. " or '$1help all' to list everything.", cmd_marker)
+               local msg
+               if INIT == "game" then
+                       msg = S("Available commands: @1",
+                               table.concat(cmds, " ")) .. "\n"
+                               .. S("Use '/help <cmd>' to get more "
+                               .. "information, or '/help all' to list "
+                               .. "everything.")
+               else
+                       msg = core.gettext("Available commands: ")
+                               .. table.concat(cmds, " ") .. "\n"
+                               .. core.gettext("Use '.help <cmd>' to get more "
+                               .. "information, or '.help all' to list "
+                               .. "everything.")
+               end
+               return true, msg
        elseif param == "all" then
                local cmds = {}
                for cmd, def in pairs(core.registered_chatcommands) do
@@ -76,19 +79,31 @@ local function do_help_cmd(name, param)
                        end
                end
                table.sort(cmds)
-               return true, gettext("Available commands:").."\n"..table.concat(cmds, "\n")
+               local msg
+               if INIT == "game" then
+                       msg = S("Available commands:")
+               else
+                       msg = core.gettext("Available commands:")
+               end
+               return true, msg.."\n"..table.concat(cmds, "\n")
        elseif INIT == "game" and param == "privs" then
                local privs = {}
                for priv, def in pairs(core.registered_privileges) do
                        privs[#privs + 1] = priv .. ": " .. def.description
                end
                table.sort(privs)
-               return true, "Available privileges:\n"..table.concat(privs, "\n")
+               return true, S("Available privileges:").."\n"..table.concat(privs, "\n")
        else
                local cmd = param
                local def = core.registered_chatcommands[cmd]
                if not def then
-                       return false, gettext("Command not available: ")..cmd
+                       local msg
+                       if INIT == "game" then
+                               msg = S("Command not available: @1", cmd)
+                       else
+                               msg = core.gettext("Command not available: ") .. cmd
+                       end
+                       return false, msg
                else
                        return true, format_help_line(cmd, def)
                end
@@ -97,16 +112,16 @@ end
 
 if INIT == "client" then
        core.register_chatcommand("help", {
-               params = gettext("[all | <cmd>]"),
-               description = gettext("Get help for commands"),
+               params = core.gettext("[all | <cmd>]"),
+               description = core.gettext("Get help for commands"),
                func = function(param)
                        return do_help_cmd(nil, param)
                end,
        })
 else
        core.register_chatcommand("help", {
-               params = "[all | privs | <cmd>]",
-               description = "Get help for commands or list privileges",
+               params = S("[all | privs | <cmd>]"),
+               description = S("Get help for commands or list privileges"),
                func = do_help_cmd,
        })
 end
index 3e2f1f079671e53fc69003182798dd29c6f5c52a..e814b4c43c8e50bba5b1bd435941b1f3461f0fe0 100644 (file)
@@ -20,7 +20,8 @@ local LIST_FORMSPEC_DESCRIPTION = [[
                button_exit[5,7;3,1;quit;%s]
        ]]
 
-local formspec_escape = core.formspec_escape
+local F = core.formspec_escape
+local S = core.get_translator("__builtin")
 local check_player_privs = core.check_player_privs
 
 
@@ -51,22 +52,23 @@ core.after(0, load_mod_command_tree)
 
 local function build_chatcommands_formspec(name, sel, copy)
        local rows = {}
-       rows[1] = "#FFF,0,Command,Parameters"
+       rows[1] = "#FFF,0,"..F(S("Command"))..","..F(S("Parameters"))
 
-       local description = "For more information, click on any entry in the list.\n" ..
-               "Double-click to copy the entry to the chat history."
+       local description = S("For more information, click on "
+               .. "any entry in the list.").. "\n" ..
+               S("Double-click to copy the entry to the chat history.")
 
        for i, data in ipairs(mod_cmds) do
-               rows[#rows + 1] = COLOR_BLUE .. ",0," .. formspec_escape(data[1]) .. ","
+               rows[#rows + 1] = COLOR_BLUE .. ",0," .. F(data[1]) .. ","
                for j, cmds in ipairs(data[2]) do
                        local has_priv = check_player_privs(name, cmds[2].privs)
                        rows[#rows + 1] = ("%s,1,%s,%s"):format(
                                has_priv and COLOR_GREEN or COLOR_GRAY,
-                               cmds[1], formspec_escape(cmds[2].params))
+                               cmds[1], F(cmds[2].params))
                        if sel == #rows then
                                description = cmds[2].description
                                if copy then
-                                       core.chat_send_player(name, ("Command: %s %s"):format(
+                                       core.chat_send_player(name, S("Command: @1 @2",
                                                core.colorize("#0FF", "/" .. cmds[1]), cmds[2].params))
                                end
                        end
@@ -74,9 +76,9 @@ local function build_chatcommands_formspec(name, sel, copy)
        end
 
        return LIST_FORMSPEC_DESCRIPTION:format(
-                       "Available commands: (see also: /help <cmd>)",
+                       F(S("Available commands: (see also: /help <cmd>)")),
                        table.concat(rows, ","), sel or 0,
-                       description, "Close"
+                       F(description), F(S("Close"))
                )
 end
 
@@ -91,19 +93,19 @@ local function build_privs_formspec(name)
        table.sort(privs, function(a, b) return a[1] < b[1] end)
 
        local rows = {}
-       rows[1] = "#FFF,0,Privilege,Description"
+       rows[1] = "#FFF,0,"..F(S("Privilege"))..","..F(S("Description"))
 
        local player_privs = core.get_player_privs(name)
        for i, data in ipairs(privs) do
                rows[#rows + 1] = ("%s,0,%s,%s"):format(
                        player_privs[data[1]] and COLOR_GREEN or COLOR_GRAY,
-                               data[1], formspec_escape(data[2].description))
+                               data[1], F(data[2].description))
        end
 
        return LIST_FORMSPEC:format(
-                       "Available privileges:",
+                       F(S("Available privileges:")),
                        table.concat(rows, ","),
-                       "Close"
+                       F(S("Close"))
                )
 end
 
index ecd413e253e4db4f6e6d53bad927370ff660b8c4..eb3364d60352df5917b1ca161ce968e7f4779dd8 100644 (file)
@@ -1,5 +1,7 @@
 -- Minetest: builtin/game/chat.lua
 
+local S = core.get_translator("__builtin")
+
 -- Helper function that implements search and replace without pattern matching
 -- Returns the string and a boolean indicating whether or not the string was modified
 local function safe_gsub(s, replace, with)
@@ -52,7 +54,7 @@ core.register_on_chat_message(function(name, message)
 
        local cmd, param = string.match(message, "^/([^ ]+) *(.*)")
        if not cmd then
-               core.chat_send_player(name, "-!- Empty command")
+               core.chat_send_player(name, "-!- "..S("Empty command."))
                return true
        end
 
@@ -65,7 +67,7 @@ core.register_on_chat_message(function(name, message)
 
        local cmd_def = core.registered_chatcommands[cmd]
        if not cmd_def then
-               core.chat_send_player(name, "-!- Invalid command: " .. cmd)
+               core.chat_send_player(name, "-!- "..S("Invalid command: @1", cmd))
                return true
        end
        local has_privs, missing_privs = core.check_player_privs(name, cmd_def.privs)
@@ -73,7 +75,7 @@ core.register_on_chat_message(function(name, message)
                core.set_last_run_mod(cmd_def.mod_origin)
                local success, result = cmd_def.func(name, param)
                if success == false and result == nil then
-                       core.chat_send_player(name, "-!- Invalid command usage")
+                       core.chat_send_player(name, "-!- "..S("Invalid command usage."))
                        local help_def = core.registered_chatcommands["help"]
                        if help_def then
                                local _, helpmsg = help_def.func(name, cmd)
@@ -85,9 +87,10 @@ core.register_on_chat_message(function(name, message)
                        core.chat_send_player(name, result)
                end
        else
-               core.chat_send_player(name, "You don't have permission"
-                               .. " to run this command (missing privileges: "
-                               .. table.concat(missing_privs, ", ") .. ")")
+               core.chat_send_player(name,
+                               S("You don't have permission to run this command "
+                               .. "(missing privileges: @1).",
+                               table.concat(missing_privs, ", ")))
        end
        return true  -- Handled chat message
 end)
@@ -107,12 +110,13 @@ local function parse_range_str(player_name, str)
        if args[1] == "here" then
                p1, p2 = core.get_player_radius_area(player_name, tonumber(args[2]))
                if p1 == nil then
-                       return false, "Unable to get player " .. player_name .. " position"
+                       return false, S("Unable to get position of player @1.", player_name)
                end
        else
                p1, p2 = core.string_to_area(str)
                if p1 == nil then
-                       return false, "Incorrect area format. Expected: (x1,y1,z1) (x2,y2,z2)"
+                       return false, S("Incorrect area format. "
+                               .. "Expected: (x1,y1,z1) (x2,y2,z2)")
                end
        end
 
@@ -123,9 +127,9 @@ end
 -- Chat commands
 --
 core.register_chatcommand("me", {
-       params = "<action>",
-       description = "Show chat action (e.g., '/me orders a pizza' displays"
-                       .. " '<player name> orders a pizza')",
+       params = S("<action>"),
+       description = S("Show chat action (e.g., '/me orders a pizza' "
+               .. "displays '<player name> orders a pizza')"),
        privs = {shout=true},
        func = function(name, param)
                core.chat_send_all("* " .. name .. " " .. param)
@@ -134,43 +138,44 @@ core.register_chatcommand("me", {
 })
 
 core.register_chatcommand("admin", {
-       description = "Show the name of the server owner",
+       description = S("Show the name of the server owner"),
        func = function(name)
                local admin = core.settings:get("name")
                if admin then
-                       return true, "The administrator of this server is " .. admin .. "."
+                       return true, S("The administrator of this server is @1.", admin)
                else
-                       return false, "There's no administrator named in the config file."
+                       return false, S("There's no administrator named "
+                               .. "in the config file.")
                end
        end,
 })
 
 core.register_chatcommand("privs", {
-       params = "[<name>]",
-       description = "Show privileges of yourself or another player",
+       params = S("[<name>]"),
+       description = S("Show privileges of yourself or another player"),
        func = function(caller, param)
                param = param:trim()
                local name = (param ~= "" and param or caller)
                if not core.player_exists(name) then
-                       return false, "Player " .. name .. " does not exist."
+                       return false, S("Player @1 does not exist.", name)
                end
-               return true, "Privileges of " .. name .. ": "
-                       .. core.privs_to_string(
-                               core.get_player_privs(name), ", ")
+               return true, S("Privileges of @1: @2", name,
+                               core.privs_to_string(
+                               core.get_player_privs(name), ", "))
        end,
 })
 
 core.register_chatcommand("haspriv", {
-       params = "<privilege>",
-       description = "Return list of all online players with privilege.",
+       params = S("<privilege>"),
+       description = S("Return list of all online players with privilege"),
        privs = {basic_privs = true},
        func = function(caller, param)
                param = param:trim()
                if param == "" then
-                       return false, "Invalid parameters (see /help haspriv)"
+                       return false, S("Invalid parameters (see /help haspriv).")
                end
                if not core.registered_privileges[param] then
-                       return false, "Unknown privilege!"
+                       return false, S("Unknown privilege!")
                end
                local privs = core.string_to_privs(param)
                local players_with_priv = {}
@@ -180,19 +185,20 @@ core.register_chatcommand("haspriv", {
                                table.insert(players_with_priv, player_name)
                        end
                end
-               return true, "Players online with the \"" .. param .. "\" privilege: " ..
-                       table.concat(players_with_priv, ", ")
+               return true, S("Players online with the \"@1\" privilege: @2",
+                               param,
+                               table.concat(players_with_priv, ", "))
        end
 })
 
 local function handle_grant_command(caller, grantname, grantprivstr)
        local caller_privs = core.get_player_privs(caller)
        if not (caller_privs.privs or caller_privs.basic_privs) then
-               return false, "Your privileges are insufficient."
+               return false, S("Your privileges are insufficient.")
        end
 
        if not core.get_auth_handler().get_auth(grantname) then
-               return false, "Player " .. grantname .. " does not exist."
+               return false, S("Player @1 does not exist.", grantname)
        end
        local grantprivs = core.string_to_privs(grantprivstr)
        if grantprivstr == "all" then
@@ -204,10 +210,10 @@ local function handle_grant_command(caller, grantname, grantprivstr)
                core.string_to_privs(core.settings:get("basic_privs") or "interact,shout")
        for priv, _ in pairs(grantprivs) do
                if not basic_privs[priv] and not caller_privs.privs then
-                       return false, "Your privileges are insufficient."
+                       return false, S("Your privileges are insufficient.")
                end
                if not core.registered_privileges[priv] then
-                       privs_unknown = privs_unknown .. "Unknown privilege: " .. priv .. "\n"
+                       privs_unknown = privs_unknown .. S("Unknown privilege: @1", priv) .. "\n"
                end
                privs[priv] = true
        end
@@ -221,33 +227,33 @@ local function handle_grant_command(caller, grantname, grantprivstr)
        core.set_player_privs(grantname, privs)
        core.log("action", caller..' granted ('..core.privs_to_string(grantprivs, ', ')..') privileges to '..grantname)
        if grantname ~= caller then
-               core.chat_send_player(grantname, caller
-                               .. " granted you privileges: "
-                               .. core.privs_to_string(grantprivs, ' '))
+               core.chat_send_player(grantname,
+                               S("@1 granted you privileges: @2", caller,
+                               core.privs_to_string(grantprivs, ' ')))
        end
-       return true, "Privileges of " .. grantname .. ": "
-               .. core.privs_to_string(
-                       core.get_player_privs(grantname), ' ')
+       return true, S("Privileges of @1: @2", grantname,
+                       core.privs_to_string(
+                       core.get_player_privs(grantname), ' '))
 end
 
 core.register_chatcommand("grant", {
-       params = "<name> (<privilege> | all)",
-       description = "Give privileges to player",
+       params = S("<name> (<privilege> | all)"),
+       description = S("Give privileges to player"),
        func = function(name, param)
                local grantname, grantprivstr = string.match(param, "([^ ]+) (.+)")
                if not grantname or not grantprivstr then
-                       return false, "Invalid parameters (see /help grant)"
+                       return false, S("Invalid parameters (see /help grant).")
                end
                return handle_grant_command(name, grantname, grantprivstr)
        end,
 })
 
 core.register_chatcommand("grantme", {
-       params = "<privilege> | all",
-       description = "Grant privileges to yourself",
+       params = S("<privilege> | all"),
+       description = S("Grant privileges to yourself"),
        func = function(name, param)
                if param == "" then
-                       return false, "Invalid parameters (see /help grantme)"
+                       return false, S("Invalid parameters (see /help grantme).")
                end
                return handle_grant_command(name, name, param)
        end,
@@ -256,11 +262,11 @@ core.register_chatcommand("grantme", {
 local function handle_revoke_command(caller, revokename, revokeprivstr)
        local caller_privs = core.get_player_privs(caller)
        if not (caller_privs.privs or caller_privs.basic_privs) then
-               return false, "Your privileges are insufficient."
+               return false, S("Your privileges are insufficient.")
        end
 
        if not core.get_auth_handler().get_auth(revokename) then
-               return false, "Player " .. revokename .. " does not exist."
+               return false, S("Player @1 does not exist.", revokename)
        end
 
        local revokeprivs = core.string_to_privs(revokeprivstr)
@@ -269,7 +275,7 @@ local function handle_revoke_command(caller, revokename, revokeprivstr)
                core.string_to_privs(core.settings:get("basic_privs") or "interact,shout")
        for priv, _ in pairs(revokeprivs) do
                if not basic_privs[priv] and not caller_privs.privs then
-                       return false, "Your privileges are insufficient."
+                       return false, S("Your privileges are insufficient.")
                end
        end
 
@@ -292,43 +298,43 @@ local function handle_revoke_command(caller, revokename, revokeprivstr)
                        ..core.privs_to_string(revokeprivs, ', ')
                        ..') privileges from '..revokename)
        if revokename ~= caller then
-               core.chat_send_player(revokename, caller
-                       .. " revoked privileges from you: "
-                       .. core.privs_to_string(revokeprivs, ' '))
+               core.chat_send_player(revokename,
+                       S("@1 revoked privileges from you: @2", caller,
+                       core.privs_to_string(revokeprivs, ' ')))
        end
-       return true, "Privileges of " .. revokename .. ": "
-               .. core.privs_to_string(
-                       core.get_player_privs(revokename), ' ')
+       return true, S("Privileges of @1: @2", revokename,
+                       core.privs_to_string(
+                       core.get_player_privs(revokename), ' '))
 end
 
 core.register_chatcommand("revoke", {
-       params = "<name> (<privilege> | all)",
-       description = "Remove privileges from player",
+       params = S("<name> (<privilege> | all)"),
+       description = S("Remove privileges from player"),
        privs = {},
        func = function(name, param)
                local revokename, revokeprivstr = string.match(param, "([^ ]+) (.+)")
                if not revokename or not revokeprivstr then
-                       return false, "Invalid parameters (see /help revoke)"
+                       return false, S("Invalid parameters (see /help revoke).")
                end
                return handle_revoke_command(name, revokename, revokeprivstr)
        end,
 })
 
 core.register_chatcommand("revokeme", {
-       params = "<privilege> | all",
-       description = "Revoke privileges from yourself",
+       params = S("<privilege> | all"),
+       description = S("Revoke privileges from yourself"),
        privs = {},
        func = function(name, param)
                if param == "" then
-                       return false, "Invalid parameters (see /help revokeme)"
+                       return false, S("Invalid parameters (see /help revokeme).")
                end
                return handle_revoke_command(name, name, param)
        end,
 })
 
 core.register_chatcommand("setpassword", {
-       params = "<name> <password>",
-       description = "Set player's password",
+       params = S("<name> <password>"),
+       description = S("Set player's password"),
        privs = {password=true},
        func = function(name, param)
                local toname, raw_password = string.match(param, "^([^ ]+) +(.+)$")
@@ -338,83 +344,83 @@ core.register_chatcommand("setpassword", {
                end
 
                if not toname then
-                       return false, "Name field required"
+                       return false, S("Name field required.")
                end
 
-               local act_str_past, act_str_pres
+               local msg_chat, msg_log, msg_ret
                if not raw_password then
                        core.set_player_password(toname, "")
-                       act_str_past = "cleared"
-                       act_str_pres = "clears"
+                       msg_chat = S("Your password was cleared by @1.", name)
+                       msg_log = name .. " clears password of " .. toname .. "."
+                       msg_ret = S("Password of player \"@1\" cleared.", toname)
                else
                        core.set_player_password(toname,
                                        core.get_password_hash(toname,
                                                        raw_password))
-                       act_str_past = "set"
-                       act_str_pres = "sets"
+                       msg_chat = S("Your password was set by @1.", name)
+                       msg_log = name .. " sets password of " .. toname .. "."
+                       msg_ret = S("Password of player \"@1\" set.", toname)
                end
 
                if toname ~= name then
-                       core.chat_send_player(toname, "Your password was "
-                                       .. act_str_past .. " by " .. name)
+                       core.chat_send_player(toname, msg_chat)
                end
 
-               core.log("action", name .. " " .. act_str_pres ..
-                               " password of " .. toname .. ".")
+               core.log("action", msg_log)
 
-               return true, "Password of player \"" .. toname .. "\" " .. act_str_past
+               return true, msg_ret
        end,
 })
 
 core.register_chatcommand("clearpassword", {
-       params = "<name>",
-       description = "Set empty password for a player",
+       params = S("<name>"),
+       description = S("Set empty password for a player"),
        privs = {password=true},
        func = function(name, param)
                local toname = param
                if toname == "" then
-                       return false, "Name field required"
+                       return false, S("Name field required.")
                end
                core.set_player_password(toname, '')
 
                core.log("action", name .. " clears password of " .. toname .. ".")
 
-               return true, "Password of player \"" .. toname .. "\" cleared"
+               return true, S("Password of player \"@1\" cleared.", toname)
        end,
 })
 
 core.register_chatcommand("auth_reload", {
        params = "",
-       description = "Reload authentication data",
+       description = S("Reload authentication data"),
        privs = {server=true},
        func = function(name, param)
                local done = core.auth_reload()
-               return done, (done and "Done." or "Failed.")
+               return done, (done and S("Done.") or S("Failed."))
        end,
 })
 
 core.register_chatcommand("remove_player", {
-       params = "<name>",
-       description = "Remove a player's data",
+       params = S("<name>"),
+       description = S("Remove a player's data"),
        privs = {server=true},
        func = function(name, param)
                local toname = param
                if toname == "" then
-                       return false, "Name field required"
+                       return false, S("Name field required.")
                end
 
                local rc = core.remove_player(toname)
 
                if rc == 0 then
                        core.log("action", name .. " removed player data of " .. toname .. ".")
-                       return true, "Player \"" .. toname .. "\" removed."
+                       return true, S("Player \"@1\" removed.", toname)
                elseif rc == 1 then
-                       return true, "No such player \"" .. toname .. "\" to remove."
+                       return true, S("No such player \"@1\" to remove.", toname)
                elseif rc == 2 then
-                       return true, "Player \"" .. toname .. "\" is connected, cannot remove."
+                       return true, S("Player \"@1\" is connected, cannot remove.", toname)
                end
 
-               return false, "Unhandled remove_player return code " .. rc .. ""
+               return false, S("Unhandled remove_player return code @1.", tostring(rc))
        end,
 })
 
@@ -445,46 +451,46 @@ local function teleport_to_pos(name, p)
        local lm = 31000
        if p.x < -lm or p.x > lm or p.y < -lm or p.y > lm
                        or p.z < -lm or p.z > lm then
-               return false, "Cannot teleport out of map bounds!"
+               return false, S("Cannot teleport out of map bounds!")
        end
        local teleportee = core.get_player_by_name(name)
        if not teleportee then
-               return false, "Cannot get player with name " .. name
+               return false, S("Cannot get player with name @1.", name)
        end
        if teleportee:get_attach() then
-               return false, "Cannot teleport, " .. name ..
-                       " is attached to an object!"
+               return false, S("Cannot teleport, @1 " ..
+                       "is attached to an object!", name)
        end
        teleportee:set_pos(p)
-       return true, "Teleporting " .. name .. " to " .. core.pos_to_string(p, 1)
+       return true, S("Teleporting @1 to @2.", name, core.pos_to_string(p, 1))
 end
 
 -- Teleports player <name> next to player <target_name> if possible
 local function teleport_to_player(name, target_name)
        if name == target_name then
-               return false, "One does not teleport to oneself."
+               return false, S("One does not teleport to oneself.")
        end
        local teleportee = core.get_player_by_name(name)
        if not teleportee then
-               return false, "Cannot get teleportee with name " .. name
+               return false, S("Cannot get teleportee with name @1.", name)
        end
        if teleportee:get_attach() then
-               return false, "Cannot teleport, " .. name ..
-                       " is attached to an object!"
+               return false, S("Cannot teleport, @1 " ..
+                       "is attached to an object!", name)
        end
        local target = core.get_player_by_name(target_name)
        if not target then
-               return false, "Cannot get target player with name " .. target_name
+               return false, S("Cannot get target player with name @1.", target_name)
        end
        local p = find_free_position_near(target:get_pos())
        teleportee:set_pos(p)
-       return true, "Teleporting " .. name .. " to " .. target_name .. " at " ..
-               core.pos_to_string(p, 1)
+       return true, S("Teleporting @1 to @2 at @3.", name, target_name,
+               core.pos_to_string(p, 1))
 end
 
 core.register_chatcommand("teleport", {
-       params = "<X>,<Y>,<Z> | <to_name> | <name> <X>,<Y>,<Z> | <name> <to_name>",
-       description = "Teleport to position or player",
+       params = S("<X>,<Y>,<Z> | <to_name> | <name> <X>,<Y>,<Z> | <name> <to_name>"),
+       description = S("Teleport to position or player"),
        privs = {teleport=true},
        func = function(name, param)
                local p = {}
@@ -500,8 +506,8 @@ core.register_chatcommand("teleport", {
                end
 
                local has_bring_priv = core.check_player_privs(name, {bring=true})
-               local missing_bring_msg = "You don't have permission to teleport " ..
-                       "other players (missing bring privilege)"
+               local missing_bring_msg = S("You don't have permission to teleport " ..
+                       "other players (missing privilege: @1).", "bring")
 
                local teleportee_name
                teleportee_name, p.x, p.y, p.z = param:match(
@@ -527,8 +533,8 @@ core.register_chatcommand("teleport", {
 })
 
 core.register_chatcommand("set", {
-       params = "([-n] <name> <value>) | <name>",
-       description = "Set or read server configuration setting",
+       params = S("([-n] <name> <value>) | <name>"),
+       description = S("Set or read server configuration setting"),
        privs = {server=true},
        func = function(name, param)
                local arg, setname, setvalue = string.match(param, "(-[n]) ([^ ]+) (.+)")
@@ -540,22 +546,23 @@ core.register_chatcommand("set", {
                setname, setvalue = string.match(param, "([^ ]+) (.+)")
                if setname and setvalue then
                        if not core.settings:get(setname) then
-                               return false, "Failed. Use '/set -n <name> <value>' to create a new setting."
+                               return false, S("Failed. Use '/set -n <name> <value>' "
+                                       .. "to create a new setting.")
                        end
                        core.settings:set(setname, setvalue)
-                       return true, setname .. " = " .. setvalue
+                       return true, S("@1 = @2", setname, setvalue)
                end
 
                setname = string.match(param, "([^ ]+)")
                if setname then
                        setvalue = core.settings:get(setname)
                        if not setvalue then
-                               setvalue = "<not set>"
+                               setvalue = S("<not set>")
                        end
-                       return true, setname .. " = " .. setvalue
+                       return true, S("@1 = @2", setname, setvalue)
                end
 
-               return false, "Invalid parameters (see /help set)."
+               return false, S("Invalid parameters (see /help set).")
        end,
 })
 
@@ -568,26 +575,27 @@ local function emergeblocks_callback(pos, action, num_calls_remaining, ctx)
 
        if ctx.current_blocks == ctx.total_blocks then
                core.chat_send_player(ctx.requestor_name,
-                       string.format("Finished emerging %d blocks in %.2fms.",
-                       ctx.total_blocks, (os.clock() - ctx.start_time) * 1000))
+                       S("Finished emerging @1 blocks in @2ms.",
+                               ctx.total_blocks,
+                               string.format("%.2f", (os.clock() - ctx.start_time) * 1000)))
        end
 end
 
 local function emergeblocks_progress_update(ctx)
        if ctx.current_blocks ~= ctx.total_blocks then
                core.chat_send_player(ctx.requestor_name,
-                       string.format("emergeblocks update: %d/%d blocks emerged (%.1f%%)",
+                       S("emergeblocks update: @1/@2 blocks emerged (@3%)",
                        ctx.current_blocks, ctx.total_blocks,
-                       (ctx.current_blocks / ctx.total_blocks) * 100))
+                       string.format("%.1f", (ctx.current_blocks / ctx.total_blocks) * 100)))
 
                core.after(2, emergeblocks_progress_update, ctx)
        end
 end
 
 core.register_chatcommand("emergeblocks", {
-       params = "(here [<radius>]) | (<pos1> <pos2>)",
-       description = "Load (or, if nonexistent, generate) map blocks "
-               .. "contained in area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)",
+       params = S("(here [<radius>]) | (<pos1> <pos2>)"),
+       description = S("Load (or, if nonexistent, generate) map blocks contained in "
+               .. "area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)"),
        privs = {server=true},
        func = function(name, param)
                local p1, p2 = parse_range_str(name, param)
@@ -605,15 +613,15 @@ core.register_chatcommand("emergeblocks", {
                core.emerge_area(p1, p2, emergeblocks_callback, context)
                core.after(2, emergeblocks_progress_update, context)
 
-               return true, "Started emerge of area ranging from " ..
-                       core.pos_to_string(p1, 1) .. " to " .. core.pos_to_string(p2, 1)
+               return true, S("Started emerge of area ranging from @1 to @2.",
+                       core.pos_to_string(p1, 1), core.pos_to_string(p2, 1))
        end,
 })
 
 core.register_chatcommand("deleteblocks", {
-       params = "(here [<radius>]) | (<pos1> <pos2>)",
-       description = "Delete map blocks contained in area pos1 to pos2 "
-               .. "(<pos1> and <pos2> must be in parentheses)",
+       params = S("(here [<radius>]) | (<pos1> <pos2>)"),
+       description = S("Delete map blocks contained in area pos1 to pos2 "
+               .. "(<pos1> and <pos2> must be in parentheses)"),
        privs = {server=true},
        func = function(name, param)
                local p1, p2 = parse_range_str(name, param)
@@ -622,18 +630,20 @@ core.register_chatcommand("deleteblocks", {
                end
 
                if core.delete_area(p1, p2) then
-                       return true, "Successfully cleared area ranging from " ..
-                               core.pos_to_string(p1, 1) .. " to " .. core.pos_to_string(p2, 1)
+                       return true, S("Successfully cleared area "
+                               .. "ranging from @1 to @2.",
+                               core.pos_to_string(p1, 1), core.pos_to_string(p2, 1))
                else
-                       return false, "Failed to clear one or more blocks in area"
+                       return false, S("Failed to clear one or more "
+                               .. "blocks in area.")
                end
        end,
 })
 
 core.register_chatcommand("fixlight", {
-       params = "(here [<radius>]) | (<pos1> <pos2>)",
-       description = "Resets lighting in the area between pos1 and pos2 "
-               .. "(<pos1> and <pos2> must be in parentheses)",
+       params = S("(here [<radius>]) | (<pos1> <pos2>)"),
+       description = S("Resets lighting in the area between pos1 and pos2 "
+               .. "(<pos1> and <pos2> must be in parentheses)"),
        privs = {server = true},
        func = function(name, param)
                local p1, p2 = parse_range_str(name, param)
@@ -642,17 +652,18 @@ core.register_chatcommand("fixlight", {
                end
 
                if core.fix_light(p1, p2) then
-                       return true, "Successfully reset light in the area ranging from " ..
-                               core.pos_to_string(p1, 1) .. " to " .. core.pos_to_string(p2, 1)
+                       return true, S("Successfully reset light in the area "
+                               .. "ranging from @1 to @2.",
+                               core.pos_to_string(p1, 1), core.pos_to_string(p2, 1))
                else
-                       return false, "Failed to load one or more blocks in area"
+                       return false, S("Failed to load one or more blocks in area.")
                end
        end,
 })
 
 core.register_chatcommand("mods", {
        params = "",
-       description = "List mods installed on the server",
+       description = S("List mods installed on the server"),
        privs = {},
        func = function(name, param)
                return true, table.concat(core.get_modnames(), ", ")
@@ -664,117 +675,136 @@ local function handle_give_command(cmd, giver, receiver, stackstring)
                        .. ', stackstring="' .. stackstring .. '"')
        local itemstack = ItemStack(stackstring)
        if itemstack:is_empty() then
-               return false, "Cannot give an empty item"
+               return false, S("Cannot give an empty item.")
        elseif (not itemstack:is_known()) or (itemstack:get_name() == "unknown") then
-               return false, "Cannot give an unknown item"
+               return false, S("Cannot give an unknown item.")
        -- Forbid giving 'ignore' due to unwanted side effects
        elseif itemstack:get_name() == "ignore" then
-               return false, "Giving 'ignore' is not allowed"
+               return false, S("Giving 'ignore' is not allowed.")
        end
        local receiverref = core.get_player_by_name(receiver)
        if receiverref == nil then
-               return false, receiver .. " is not a known player"
+               return false, S("@1 is not a known player.", receiver)
        end
        local leftover = receiverref:get_inventory():add_item("main", itemstack)
        local partiality
        if leftover:is_empty() then
-               partiality = ""
+               partiality = nil
        elseif leftover:get_count() == itemstack:get_count() then
-               partiality = "could not be "
+               partiality = false
        else
-               partiality = "partially "
+               partiality = true
        end
        -- The actual item stack string may be different from what the "giver"
        -- entered (e.g. big numbers are always interpreted as 2^16-1).
        stackstring = itemstack:to_string()
+       local msg
+       if partiality == true then
+               msg = S("@1 partially added to inventory.", stackstring)
+       elseif partiality == false then
+               msg = S("@1 could not be added to inventory.", stackstring)
+       else
+               msg = S("@1 added to inventory.", stackstring)
+       end
        if giver == receiver then
-               local msg = "%q %sadded to inventory."
-               return true, msg:format(stackstring, partiality)
+               return true, msg
        else
-               core.chat_send_player(receiver, ("%q %sadded to inventory.")
-                               :format(stackstring, partiality))
-               local msg = "%q %sadded to %s's inventory."
-               return true, msg:format(stackstring, partiality, receiver)
+               core.chat_send_player(receiver, msg)
+               local msg_other
+               if partiality == true then
+                       msg_other = S("@1 partially added to inventory of @2.",
+                                       stackstring, receiver)
+               elseif partiality == false then
+                       msg_other = S("@1 could not be added to inventory of @2.",
+                                       stackstring, receiver)
+               else
+                       msg_other = S("@1 added to inventory of @2.",
+                                       stackstring, receiver)
+               end
+               return true, msg_other
        end
 end
 
 core.register_chatcommand("give", {
-       params = "<name> <ItemString> [<count> [<wear>]]",
-       description = "Give item to player",
+       params = S("<name> <ItemString> [<count> [<wear>]]"),
+       description = S("Give item to player"),
        privs = {give=true},
        func = function(name, param)
                local toname, itemstring = string.match(param, "^([^ ]+) +(.+)$")
                if not toname or not itemstring then
-                       return false, "Name and ItemString required"
+                       return false, S("Name and ItemString required.")
                end
                return handle_give_command("/give", name, toname, itemstring)
        end,
 })
 
 core.register_chatcommand("giveme", {
-       params = "<ItemString> [<count> [<wear>]]",
-       description = "Give item to yourself",
+       params = S("<ItemString> [<count> [<wear>]]"),
+       description = S("Give item to yourself"),
        privs = {give=true},
        func = function(name, param)
                local itemstring = string.match(param, "(.+)$")
                if not itemstring then
-                       return false, "ItemString required"
+                       return false, S("ItemString required.")
                end
                return handle_give_command("/giveme", name, name, itemstring)
        end,
 })
 
 core.register_chatcommand("spawnentity", {
-       params = "<EntityName> [<X>,<Y>,<Z>]",
-       description = "Spawn entity at given (or your) position",
+       params = S("<EntityName> [<X>,<Y>,<Z>]"),
+       description = S("Spawn entity at given (or your) position"),
        privs = {give=true, interact=true},
        func = function(name, param)
                local entityname, p = string.match(param, "^([^ ]+) *(.*)$")
                if not entityname then
-                       return false, "EntityName required"
+                       return false, S("EntityName required.")
                end
                core.log("action", ("%s invokes /spawnentity, entityname=%q")
                                :format(name, entityname))
                local player = core.get_player_by_name(name)
                if player == nil then
                        core.log("error", "Unable to spawn entity, player is nil")
-                       return false, "Unable to spawn entity, player is nil"
+                       return false, S("Unable to spawn entity, player is nil.")
                end
                if not core.registered_entities[entityname] then
-                       return false, "Cannot spawn an unknown entity"
+                       return false, S("Cannot spawn an unknown entity.")
                end
                if p == "" then
                        p = player:get_pos()
                else
                        p = core.string_to_pos(p)
                        if p == nil then
-                               return false, "Invalid parameters ('" .. param .. "')"
+                               return false, S("Invalid parameters (@1).", param)
                        end
                end
                p.y = p.y + 1
                local obj = core.add_entity(p, entityname)
-               local msg = obj and "%q spawned." or "%q failed to spawn."
-               return true, msg:format(entityname)
+               if obj then
+                       return true, S("@1 spawned.", entityname)
+               else
+                       return true, S("@1 failed to spawn.", entityname)
+               end
        end,
 })
 
 core.register_chatcommand("pulverize", {
        params = "",
-       description = "Destroy item in hand",
+       description = S("Destroy item in hand"),
        func = function(name, param)
                local player = core.get_player_by_name(name)
                if not player then
                        core.log("error", "Unable to pulverize, no player.")
-                       return false, "Unable to pulverize, no player."
+                       return false, S("Unable to pulverize, no player.")
                end
                local wielded_item = player:get_wielded_item()
                if wielded_item:is_empty() then
-                       return false, "Unable to pulverize, no item in hand."
+                       return false, S("Unable to pulverize, no item in hand.")
                end
                core.log("action", name .. " pulverized \"" ..
                        wielded_item:get_name() .. " " .. wielded_item:get_count() .. "\"")
                player:set_wielded_item(nil)
-               return true, "An item was pulverized."
+               return true, S("An item was pulverized.")
        end,
 })
 
@@ -790,14 +820,15 @@ core.register_on_punchnode(function(pos, node, puncher)
 end)
 
 core.register_chatcommand("rollback_check", {
-       params = "[<range>] [<seconds>] [<limit>]",
-       description = "Check who last touched a node or a node near it"
-                       .. " within the time specified by <seconds>. Default: range = 0,"
-                       .. " seconds = 86400 = 24h, limit = 5. Set <seconds> to inf for no time limit",
+       params = S("[<range>] [<seconds>] [<limit>]"),
+       description = S("Check who last touched a node or a node near it "
+               .. "within the time specified by <seconds>. "
+               .. "Default: range = 0, seconds = 86400 = 24h, limit = 5. "
+               .. "Set <seconds> to inf for no time limit"),
        privs = {rollback=true},
        func = function(name, param)
                if not core.settings:get_bool("enable_rollback_recording") then
-                       return false, "Rollback functions are disabled."
+                       return false, S("Rollback functions are disabled.")
                end
                local range, seconds, limit =
                        param:match("(%d+) *(%d*) *(%d*)")
@@ -805,30 +836,30 @@ core.register_chatcommand("rollback_check", {
                seconds = tonumber(seconds) or 86400
                limit = tonumber(limit) or 5
                if limit > 100 then
-                       return false, "That limit is too high!"
+                       return false, S("That limit is too high!")
                end
 
                core.rollback_punch_callbacks[name] = function(pos, node, puncher)
                        local name = puncher:get_player_name()
-                       core.chat_send_player(name, "Checking " .. core.pos_to_string(pos) .. "...")
+                       core.chat_send_player(name, S("Checking @1 ...", core.pos_to_string(pos)))
                        local actions = core.rollback_get_node_actions(pos, range, seconds, limit)
                        if not actions then
-                               core.chat_send_player(name, "Rollback functions are disabled")
+                               core.chat_send_player(name, S("Rollback functions are disabled."))
                                return
                        end
                        local num_actions = #actions
                        if num_actions == 0 then
-                               core.chat_send_player(name, "Nobody has touched"
-                                               .. " the specified location in "
-                                               .. seconds .. " seconds")
+                               core.chat_send_player(name,
+                                               S("Nobody has touched the specified "
+                                               .. "location in @1 seconds.",
+                                               seconds))
                                return
                        end
                        local time = os.time()
                        for i = num_actions, 1, -1 do
                                local action = actions[i]
                                core.chat_send_player(name,
-                                       ("%s %s %s -> %s %d seconds ago.")
-                                               :format(
+                                       S("@1 @2 @3 -> @4 @5 seconds ago.",
                                                        core.pos_to_string(action.pos),
                                                        action.actor,
                                                        action.oldnode.name,
@@ -837,110 +868,123 @@ core.register_chatcommand("rollback_check", {
                        end
                end
 
-               return true, "Punch a node (range=" .. range .. ", seconds="
-                               .. seconds .. "s, limit=" .. limit .. ")"
+               return true, S("Punch a node (range=@1, seconds=@2, limit=@3).",
+                               range, seconds, limit)
        end,
 })
 
 core.register_chatcommand("rollback", {
-       params = "(<name> [<seconds>]) | (:<actor> [<seconds>])",
-       description = "Revert actions of a player. Default for <seconds> is 60. Set <seconds> to inf for no time limit",
+       params = S("(<name> [<seconds>]) | (:<actor> [<seconds>])"),
+       description = S("Revert actions of a player. "
+               .. "Default for <seconds> is 60. "
+               .. "Set <seconds> to inf for no time limit"),
        privs = {rollback=true},
        func = function(name, param)
                if not core.settings:get_bool("enable_rollback_recording") then
-                       return false, "Rollback functions are disabled."
+                       return false, S("Rollback functions are disabled.")
                end
                local target_name, seconds = string.match(param, ":([^ ]+) *(%d*)")
+               local rev_msg
                if not target_name then
                        local player_name
                        player_name, seconds = string.match(param, "([^ ]+) *(%d*)")
                        if not player_name then
-                               return false, "Invalid parameters. See /help rollback"
-                                               .. " and /help rollback_check."
+                               return false, S("Invalid parameters. "
+                                       .. "See /help rollback and "
+                                       .. "/help rollback_check.")
                        end
+                       seconds = tonumber(seconds) or 60
                        target_name = "player:"..player_name
+                       rev_msg = S("Reverting actions of player '@1' since @2 seconds.",
+                               player_name, seconds)
+               else
+                       seconds = tonumber(seconds) or 60
+                       rev_msg = S("Reverting actions of @1 since @2 seconds.",
+                               target_name, seconds)
                end
-               seconds = tonumber(seconds) or 60
-               core.chat_send_player(name, "Reverting actions of "
-                               .. target_name .. " since "
-                               .. seconds .. " seconds.")
+               core.chat_send_player(name, rev_msg)
                local success, log = core.rollback_revert_actions_by(
                                target_name, seconds)
                local response = ""
                if #log > 100 then
-                       response = "(log is too long to show)\n"
+                       response = S("(log is too long to show)").."\n"
                else
                        for _, line in pairs(log) do
                                response = response .. line .. "\n"
                        end
                end
-               response = response .. "Reverting actions "
-                               .. (success and "succeeded." or "FAILED.")
+               if success then
+                       response = response .. S("Reverting actions succeeded.")
+               else
+                       response = response .. S("Reverting actions FAILED.")
+               end
                return success, response
        end,
 })
 
 core.register_chatcommand("status", {
-       description = "Show server status",
+       description = S("Show server status"),
        func = function(name, param)
                local status = core.get_server_status(name, false)
                if status and status ~= "" then
                        return true, status
                end
-               return false, "This command was disabled by a mod or game"
+               return false, S("This command was disabled by a mod or game.")
        end,
 })
 
 core.register_chatcommand("time", {
-       params = "[<0..23>:<0..59> | <0..24000>]",
-       description = "Show or set time of day",
+       params = S("[<0..23>:<0..59> | <0..24000>]"),
+       description = S("Show or set time of day"),
        privs = {},
        func = function(name, param)
                if param == "" then
                        local current_time = math.floor(core.get_timeofday() * 1440)
                        local minutes = current_time % 60
                        local hour = (current_time - minutes) / 60
-                       return true, ("Current time is %d:%02d"):format(hour, minutes)
+                       return true, S("Current time is @1:@2.",
+                                       string.format("%d", hour),
+                                       string.format("%02d", minutes))
                end
                local player_privs = core.get_player_privs(name)
                if not player_privs.settime then
-                       return false, "You don't have permission to run this command " ..
-                               "(missing privilege: settime)."
+                       return false, S("You don't have permission to run "
+                               .. "this command (missing privilege: @1).", "settime")
                end
                local hour, minute = param:match("^(%d+):(%d+)$")
                if not hour then
                        local new_time = tonumber(param)
                        if not new_time then
-                               return false, "Invalid time."
+                               return false, S("Invalid time.")
                        end
                        -- Backward compatibility.
                        core.set_timeofday((new_time % 24000) / 24000)
                        core.log("action", name .. " sets time to " .. new_time)
-                       return true, "Time of day changed."
+                       return true, S("Time of day changed.")
                end
                hour = tonumber(hour)
                minute = tonumber(minute)
                if hour < 0 or hour > 23 then
-                       return false, "Invalid hour (must be between 0 and 23 inclusive)."
+                       return false, S("Invalid hour (must be between 0 and 23 inclusive).")
                elseif minute < 0 or minute > 59 then
-                       return false, "Invalid minute (must be between 0 and 59 inclusive)."
+                       return false, S("Invalid minute (must be between 0 and 59 inclusive).")
                end
                core.set_timeofday((hour * 60 + minute) / 1440)
                core.log("action", ("%s sets time to %d:%02d"):format(name, hour, minute))
-               return true, "Time of day changed."
+               return true, S("Time of day changed.")
        end,
 })
 
 core.register_chatcommand("days", {
-       description = "Show day count since world creation",
+       description = S("Show day count since world creation"),
        func = function(name, param)
-               return true, "Current day is " .. core.get_day_count()
+               return true, S("Current day is @1.", core.get_day_count())
        end
 })
 
 core.register_chatcommand("shutdown", {
-       params = "[<delay_in_seconds> | -1] [reconnect] [<message>]",
-       description = "Shutdown server (-1 cancels a delayed shutdown)",
+       params = S("[<delay_in_seconds> | -1] [reconnect] [<message>]"),
+       description = S("Shutdown server (-1 cancels a delayed shutdown)"),
        privs = {server=true},
        func = function(name, param)
                local delay, reconnect, message
@@ -953,7 +997,7 @@ core.register_chatcommand("shutdown", {
 
                if delay == 0 then
                        core.log("action", name .. " shuts down server")
-                       core.chat_send_all("*** Server shutting down (operator request).")
+                       core.chat_send_all("*** "..S("Server shutting down (operator request)."))
                end
                core.request_shutdown(message:trim(), core.is_yes(reconnect), delay)
                return true
@@ -961,65 +1005,65 @@ core.register_chatcommand("shutdown", {
 })
 
 core.register_chatcommand("ban", {
-       params = "[<name>]",
-       description = "Ban the IP of a player or show the ban list",
+       params = S("[<name>]"),
+       description = S("Ban the IP of a player or show the ban list"),
        privs = {ban=true},
        func = function(name, param)
                if param == "" then
                        local ban_list = core.get_ban_list()
                        if ban_list == "" then
-                               return true, "The ban list is empty."
+                               return true, S("The ban list is empty.")
                        else
-                               return true, "Ban list: " .. ban_list
+                               return true, S("Ban list: @1", ban_list)
                        end
                end
                if not core.get_player_by_name(param) then
-                       return false, "Player is not online."
+                       return false, S("Player is not online.")
                end
                if not core.ban_player(param) then
-                       return false, "Failed to ban player."
+                       return false, S("Failed to ban player.")
                end
                local desc = core.get_ban_description(param)
                core.log("action", name .. " bans " .. desc .. ".")
-               return true, "Banned " .. desc .. "."
+               return true, S("Banned @1.", desc)
        end,
 })
 
 core.register_chatcommand("unban", {
-       params = "<name> | <IP_address>",
-       description = "Remove IP ban belonging to a player/IP",
+       params = S("<name> | <IP_address>"),
+       description = S("Remove IP ban belonging to a player/IP"),
        privs = {ban=true},
        func = function(name, param)
                if not core.unban_player_or_ip(param) then
-                       return false, "Failed to unban player/IP."
+                       return false, S("Failed to unban player/IP.")
                end
                core.log("action", name .. " unbans " .. param)
-               return true, "Unbanned " .. param
+               return true, S("Unbanned @1.", param)
        end,
 })
 
 core.register_chatcommand("kick", {
-       params = "<name> [<reason>]",
-       description = "Kick a player",
+       params = S("<name> [<reason>]"),
+       description = S("Kick a player"),
        privs = {kick=true},
        func = function(name, param)
                local tokick, reason = param:match("([^ ]+) (.+)")
                tokick = tokick or param
                if not core.kick_player(tokick, reason) then
-                       return false, "Failed to kick player " .. tokick
+                       return false, S("Failed to kick player @1.", tokick)
                end
                local log_reason = ""
                if reason then
                        log_reason = " with reason \"" .. reason .. "\""
                end
                core.log("action", name .. " kicks " .. tokick .. log_reason)
-               return true, "Kicked " .. tokick
+               return true, S("Kicked @1.", tokick)
        end,
 })
 
 core.register_chatcommand("clearobjects", {
-       params = "[full | quick]",
-       description = "Clear all objects in world",
+       params = S("[full | quick]"),
+       description = S("Clear all objects in world"),
        privs = {server=true},
        func = function(name, param)
                local options = {}
@@ -1028,45 +1072,42 @@ core.register_chatcommand("clearobjects", {
                elseif param == "full" then
                        options.mode = "full"
                else
-                       return false, "Invalid usage, see /help clearobjects."
+                       return false, S("Invalid usage, see /help clearobjects.")
                end
 
                core.log("action", name .. " clears all objects ("
                                .. options.mode .. " mode).")
-               core.chat_send_all("Clearing all objects. This may take a long time."
-                               .. " You may experience a timeout. (by "
-                               .. name .. ")")
+               core.chat_send_all(S("Clearing all objects. This may take a long time. "
+                       .. "You may experience a timeout. (by @1)", name))
                core.clear_objects(options)
                core.log("action", "Object clearing done.")
-               core.chat_send_all("*** Cleared all objects.")
+               core.chat_send_all("*** "..S("Cleared all objects."))
                return true
        end,
 })
 
 core.register_chatcommand("msg", {
-       params = "<name> <message>",
-       description = "Send a direct message to a player",
+       params = S("<name> <message>"),
+       description = S("Send a direct message to a player"),
        privs = {shout=true},
        func = function(name, param)
                local sendto, message = param:match("^(%S+)%s(.+)$")
                if not sendto then
-                       return false, "Invalid usage, see /help msg."
+                       return false, S("Invalid usage, see /help msg.")
                end
                if not core.get_player_by_name(sendto) then
-                       return false, "The player " .. sendto
-                                       .. " is not online."
+                       return false, S("The player @1 is not online.", sendto)
                end
                core.log("action", "DM from " .. name .. " to " .. sendto
                                .. ": " .. message)
-               core.chat_send_player(sendto, "DM from " .. name .. ": "
-                               .. message)
-               return true, "Message sent."
+               core.chat_send_player(sendto, S("DM from @1: @2", name, message))
+               return true, S("Message sent.")
        end,
 })
 
 core.register_chatcommand("last-login", {
-       params = "[<name>]",
-       description = "Get the last login time of a player or yourself",
+       params = S("[<name>]"),
+       description = S("Get the last login time of a player or yourself"),
        func = function(name, param)
                if param == "" then
                        param = name
@@ -1074,25 +1115,27 @@ core.register_chatcommand("last-login", {
                local pauth = core.get_auth_handler().get_auth(param)
                if pauth and pauth.last_login and pauth.last_login ~= -1 then
                        -- Time in UTC, ISO 8601 format
-                       return true, param.."'s last login time was " ..
-                               os.date("!%Y-%m-%dT%H:%M:%SZ", pauth.last_login)
+                       return true, S("@1's last login time was @2.",
+                               param,
+                               os.date("!%Y-%m-%dT%H:%M:%SZ", pauth.last_login))
                end
-               return false, param.."'s last login time is unknown"
+               return false, S("@1's last login time is unknown.", param)
        end,
 })
 
 core.register_chatcommand("clearinv", {
-       params = "[<name>]",
-       description = "Clear the inventory of yourself or another player",
+       params = S("[<name>]"),
+       description = S("Clear the inventory of yourself or another player"),
        func = function(name, param)
                local player
                if param and param ~= "" and param ~= name then
                        if not core.check_player_privs(name, {server=true}) then
-                               return false, "You don't have permission"
-                                               .. " to clear another player's inventory (missing privilege: server)"
+                               return false, S("You don't have permission to "
+                                       .. "clear another player's inventory "
+                                       .. "(missing privilege: @1).", "server")
                        end
                        player = core.get_player_by_name(param)
-                       core.chat_send_player(param, name.." cleared your inventory.")
+                       core.chat_send_player(param, S("@1 cleared your inventory.", name))
                else
                        player = core.get_player_by_name(name)
                end
@@ -1102,25 +1145,25 @@ core.register_chatcommand("clearinv", {
                        player:get_inventory():set_list("craft", {})
                        player:get_inventory():set_list("craftpreview", {})
                        core.log("action", name.." clears "..player:get_player_name().."'s inventory")
-                       return true, "Cleared "..player:get_player_name().."'s inventory."
+                       return true, S("Cleared @1's inventory.", player:get_player_name())
                else
-                       return false, "Player must be online to clear inventory!"
+                       return false, S("Player must be online to clear inventory!")
                end
        end,
 })
 
 local function handle_kill_command(killer, victim)
        if core.settings:get_bool("enable_damage") == false then
-               return false, "Players can't be killed, damage has been disabled."
+               return false, S("Players can't be killed, damage has been disabled.")
        end
        local victimref = core.get_player_by_name(victim)
        if victimref == nil then
-               return false, string.format("Player %s is not online.", victim)
+               return false, S("Player @1 is not online.", victim)
        elseif victimref:get_hp() <= 0 then
                if killer == victim then
-                       return false, "You are already dead."
+                       return false, S("You are already dead.")
                else
-                       return false, string.format("%s is already dead.", victim)
+                       return false, S("@1 is already dead.", victim)
                end
        end
        if not killer == victim then
@@ -1128,12 +1171,12 @@ local function handle_kill_command(killer, victim)
        end
        -- Kill victim
        victimref:set_hp(0)
-       return true, string.format("%s has been killed.", victim)
+       return true, S("@1 has been killed.", victim)
 end
 
 core.register_chatcommand("kill", {
-       params = "[<name>]",
-       description = "Kill player or yourself",
+       params = S("[<name>]"),
+       description = S("Kill player or yourself"),
        privs = {server=true},
        func = function(name, param)
                return handle_kill_command(name, param == "" and name or param)
index c7417d2f43a54a0c45a2cf000cbb89fee9b9a0fc..aee32a34e62497815efb9a829c6de6a6242f64a9 100644 (file)
@@ -1,5 +1,7 @@
 -- Minetest: builtin/privileges.lua
 
+local S = core.get_translator("__builtin")
+
 --
 -- Privileges
 --
@@ -15,7 +17,7 @@ function core.register_privilege(name, param)
                        def.give_to_admin = def.give_to_singleplayer
                end
                if def.description == nil then
-                       def.description = "(no description)"
+                       def.description = S("(no description)")
                end
        end
        local def
@@ -28,69 +30,69 @@ function core.register_privilege(name, param)
        core.registered_privileges[name] = def
 end
 
-core.register_privilege("interact", "Can interact with things and modify the world")
-core.register_privilege("shout", "Can speak in chat")
-core.register_privilege("basic_privs", "Can modify 'shout' and 'interact' privileges")
-core.register_privilege("privs", "Can modify privileges")
+core.register_privilege("interact", S("Can interact with things and modify the world"))
+core.register_privilege("shout", S("Can speak in chat"))
+core.register_privilege("basic_privs", S("Can modify 'shout' and 'interact' privileges"))
+core.register_privilege("privs", S("Can modify privileges"))
 
 core.register_privilege("teleport", {
-       description = "Can teleport self",
+       description = S("Can teleport self"),
        give_to_singleplayer = false,
 })
 core.register_privilege("bring", {
-       description = "Can teleport other players",
+       description = S("Can teleport other players"),
        give_to_singleplayer = false,
 })
 core.register_privilege("settime", {
-       description = "Can set the time of day using /time",
+       description = S("Can set the time of day using /time"),
        give_to_singleplayer = false,
 })
 core.register_privilege("server", {
-       description = "Can do server maintenance stuff",
+       description = S("Can do server maintenance stuff"),
        give_to_singleplayer = false,
        give_to_admin = true,
 })
 core.register_privilege("protection_bypass", {
-       description = "Can bypass node protection in the world",
+       description = S("Can bypass node protection in the world"),
        give_to_singleplayer = false,
 })
 core.register_privilege("ban", {
-       description = "Can ban and unban players",
+       description = S("Can ban and unban players"),
        give_to_singleplayer = false,
        give_to_admin = true,
 })
 core.register_privilege("kick", {
-       description = "Can kick players",
+       description = S("Can kick players"),
        give_to_singleplayer = false,
        give_to_admin = true,
 })
 core.register_privilege("give", {
-       description = "Can use /give and /giveme",
+       description = S("Can use /give and /giveme"),
        give_to_singleplayer = false,
 })
 core.register_privilege("password", {
-       description = "Can use /setpassword and /clearpassword",
+       description = S("Can use /setpassword and /clearpassword"),
        give_to_singleplayer = false,
        give_to_admin = true,
 })
 core.register_privilege("fly", {
-       description = "Can use fly mode",
+       description = S("Can use fly mode"),
        give_to_singleplayer = false,
 })
 core.register_privilege("fast", {
-       description = "Can use fast mode",
+       description = S("Can use fast mode"),
        give_to_singleplayer = false,
 })
 core.register_privilege("noclip", {
-       description = "Can fly through solid nodes using noclip mode",
+       description = S("Can fly through solid nodes using noclip mode"),
        give_to_singleplayer = false,
 })
 core.register_privilege("rollback", {
-       description = "Can use the rollback functionality",
+       description = S("Can use the rollback functionality"),
        give_to_singleplayer = false,
 })
 core.register_privilege("debug", {
-       description = "Allows enabling various debug options that may affect gameplay",
+       description = S("Allows enabling various debug options that may affect gameplay"),
        give_to_singleplayer = false,
        give_to_admin = true,
 })
index 1cff858135719da9a958d786eba96d0455aec2b6..e01c5033567a4af271e82a3b414fb5592289956e 100644 (file)
@@ -1,5 +1,7 @@
 -- Minetest: builtin/misc_register.lua
 
+local S = core.get_translator("__builtin")
+
 --
 -- Make raw registration functions inaccessible to anyone except this file
 --
@@ -326,7 +328,7 @@ end
 
 core.register_item(":unknown", {
        type = "none",
-       description = "Unknown Item",
+       description = S("Unknown Item"),
        inventory_image = "unknown_item.png",
        on_place = core.item_place,
        on_secondary_use = core.item_secondary_use,
@@ -336,7 +338,7 @@ core.register_item(":unknown", {
 })
 
 core.register_node(":air", {
-       description = "Air",
+       description = S("Air"),
        inventory_image = "air.png",
        wield_image = "air.png",
        drawtype = "airlike",
@@ -353,7 +355,7 @@ core.register_node(":air", {
 })
 
 core.register_node(":ignore", {
-       description = "Ignore",
+       description = S("Ignore"),
        inventory_image = "ignore.png",
        wield_image = "ignore.png",
        drawtype = "airlike",
@@ -370,7 +372,7 @@ core.register_node(":ignore", {
                core.chat_send_player(
                                placer:get_player_name(),
                                core.colorize("#FF0000",
-                               "You can't place 'ignore' nodes!"))
+                               S("You can't place 'ignore' nodes!")))
                return ""
        end,
 })
diff --git a/builtin/locale/template.txt b/builtin/locale/template.txt
new file mode 100644 (file)
index 0000000..c5ace1a
--- /dev/null
@@ -0,0 +1,224 @@
+# textdomain: __builtin
+Empty command.=
+Invalid command: @1=
+Invalid command usage.=
+You don't have permission to run this command (missing privileges: @1).=
+Unable to get position of player @1.=
+Incorrect area format. Expected: (x1,y1,z1) (x2,y2,z2)=
+<action>=
+Show chat action (e.g., '/me orders a pizza' displays '<player name> orders a pizza')=
+Show the name of the server owner=
+The administrator of this server is @1.=
+There's no administrator named in the config file.=
+[<name>]=
+Show privileges of yourself or another player=
+Player @1 does not exist.=
+Privileges of @1: @2=
+<privilege>=
+Return list of all online players with privilege=
+Invalid parameters (see /help haspriv).=
+Unknown privilege!=
+Players online with the "@1" privilege: @2=
+Your privileges are insufficient.=
+Unknown privilege: @1=
+@1 granted you privileges: @2=
+<name> (<privilege> | all)=
+Give privileges to player=
+Invalid parameters (see /help grant).=
+<privilege> | all=
+Grant privileges to yourself=
+Invalid parameters (see /help grantme).=
+@1 revoked privileges from you: @2=
+Remove privileges from player=
+Invalid parameters (see /help revoke).=
+Revoke privileges from yourself=
+Invalid parameters (see /help revokeme).=
+<name> <password>=
+Set player's password=
+Name field required.=
+Your password was cleared by @1.=
+Password of player "@1" cleared.=
+Your password was set by @1.=
+Password of player "@1" set.=
+<name>=
+Set empty password for a player=
+Reload authentication data=
+Done.=
+Failed.=
+Remove a player's data=
+Player "@1" removed.=
+No such player "@1" to remove.=
+Player "@1" is connected, cannot remove.=
+Unhandled remove_player return code @1.=
+Cannot teleport out of map bounds!=
+Cannot get player with name @1.=
+Cannot teleport, @1 is attached to an object!=
+Teleporting @1 to @2.=
+One does not teleport to oneself.=
+Cannot get teleportee with name @1.=
+Cannot get target player with name @1.=
+Teleporting @1 to @2 at @3.=
+<X>,<Y>,<Z> | <to_name> | <name> <X>,<Y>,<Z> | <name> <to_name>=
+Teleport to position or player=
+You don't have permission to teleport other players (missing privilege: @1).=
+([-n] <name> <value>) | <name>=
+Set or read server configuration setting=
+Failed. Use '/set -n <name> <value>' to create a new setting.=
+@1 @= @2=
+<not set>=
+Invalid parameters (see /help set).=
+Finished emerging @1 blocks in @2ms.=
+emergeblocks update: @1/@2 blocks emerged (@3%)=
+(here [<radius>]) | (<pos1> <pos2>)=
+Load (or, if nonexistent, generate) map blocks contained in area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)=
+Started emerge of area ranging from @1 to @2.=
+Delete map blocks contained in area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)=
+Successfully cleared area ranging from @1 to @2.=
+Failed to clear one or more blocks in area.=
+Resets lighting in the area between pos1 and pos2 (<pos1> and <pos2> must be in parentheses)=
+Successfully reset light in the area ranging from @1 to @2.=
+Failed to load one or more blocks in area.=
+List mods installed on the server=
+Cannot give an empty item.=
+Cannot give an unknown item.=
+Giving 'ignore' is not allowed.=
+@1 is not a known player.=
+@1 partially added to inventory.=
+@1 could not be added to inventory.=
+@1 added to inventory.=
+@1 partially added to inventory of @2.=
+@1 could not be added to inventory of @2.=
+@1 added to inventory of @2.=
+<name> <ItemString> [<count> [<wear>]]=
+Give item to player=
+Name and ItemString required.=
+<ItemString> [<count> [<wear>]]=
+Give item to yourself=
+ItemString required.=
+<EntityName> [<X>,<Y>,<Z>]=
+Spawn entity at given (or your) position=
+EntityName required.=
+Unable to spawn entity, player is nil.=
+Cannot spawn an unknown entity.=
+Invalid parameters (@1).=
+@1 spawned.=
+@1 failed to spawn.=
+Destroy item in hand=
+Unable to pulverize, no player.=
+Unable to pulverize, no item in hand.=
+An item was pulverized.=
+[<range>] [<seconds>] [<limit>]=
+Check who last touched a node or a node near it within the time specified by <seconds>. Default: range @= 0, seconds @= 86400 @= 24h, limit @= 5. Set <seconds> to inf for no time limit=
+Rollback functions are disabled.=
+That limit is too high!=
+Checking @1 ...=
+Nobody has touched the specified location in @1 seconds.=
+@1 @2 @3 -> @4 @5 seconds ago.=
+Punch a node (range@=@1, seconds@=@2, limit@=@3).=
+(<name> [<seconds>]) | (:<actor> [<seconds>])=
+Revert actions of a player. Default for <seconds> is 60. Set <seconds> to inf for no time limit=
+Invalid parameters. See /help rollback and /help rollback_check.=
+Reverting actions of player '@1' since @2 seconds.=
+Reverting actions of @1 since @2 seconds.=
+(log is too long to show)=
+Reverting actions succeeded.=
+Reverting actions FAILED.=
+Show server status=
+This command was disabled by a mod or game.=
+[<0..23>:<0..59> | <0..24000>]=
+Show or set time of day=
+Current time is @1:@2.=
+You don't have permission to run this command (missing privilege: @1).=
+Invalid time.=
+Time of day changed.=
+Invalid hour (must be between 0 and 23 inclusive).=
+Invalid minute (must be between 0 and 59 inclusive).=
+Show day count since world creation=
+Current day is @1.=
+[<delay_in_seconds> | -1] [reconnect] [<message>]=
+Shutdown server (-1 cancels a delayed shutdown)=
+Server shutting down (operator request).=
+Ban the IP of a player or show the ban list=
+The ban list is empty.=
+Ban list: @1=
+Player is not online.=
+Failed to ban player.=
+Banned @1.=
+<name> | <IP_address>=
+Remove IP ban belonging to a player/IP=
+Failed to unban player/IP.=
+Unbanned @1.=
+<name> [<reason>]=
+Kick a player=
+Failed to kick player @1.=
+Kicked @1.=
+[full | quick]=
+Clear all objects in world=
+Invalid usage, see /help clearobjects.=
+Clearing all objects. This may take a long time. You may experience a timeout. (by @1)=
+Cleared all objects.=
+<name> <message>=
+Send a direct message to a player=
+Invalid usage, see /help msg.=
+The player @1 is not online.=
+DM from @1: @2=
+Message sent.=
+Get the last login time of a player or yourself=
+@1's last login time was @2.=
+@1's last login time is unknown.=
+Clear the inventory of yourself or another player=
+You don't have permission to clear another player's inventory (missing privilege: @1).=
+@1 cleared your inventory.=
+Cleared @1's inventory.=
+Player must be online to clear inventory!=
+Players can't be killed, damage has been disabled.=
+Player @1 is not online.=
+You are already dead.=
+@1 is already dead.=
+@1 has been killed.=
+Kill player or yourself=
+Available commands: @1=
+Use '/help <cmd>' to get more information, or '/help all' to list everything.=
+Available commands:=
+Command not available: @1=
+[all | privs | <cmd>]=
+Get help for commands or list privileges=
+Available privileges:=
+Command=
+Parameters=
+For more information, click on any entry in the list.=
+Double-click to copy the entry to the chat history.=
+Command: @1 @2=
+Available commands: (see also: /help <cmd>)=
+Close=
+Privilege=
+Description=
+print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset=
+Handle the profiler and profiling data=
+Statistics written to action log.=
+Statistics were reset.=
+Usage: @1=
+Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).=
+(no description)=
+Can interact with things and modify the world=
+Can speak in chat=
+Can modify 'shout' and 'interact' privileges=
+Can modify privileges=
+Can teleport self=
+Can teleport other players=
+Can set the time of day using /time=
+Can do server maintenance stuff=
+Can bypass node protection in the world=
+Can ban and unban players=
+Can kick players=
+Can use /give and /giveme=
+Can use /setpassword and /clearpassword=
+Can use fly mode=
+Can use fast mode=
+Can fly through solid nodes using noclip mode=
+Can use the rollback functionality=
+Allows enabling various debug options that may affect gameplay=
+Unknown Item=
+Air=
+Ignore=
+You can't place 'ignore' nodes!=
index a0033d75209e94aa5516792b5f35fd8d3adc9cd0..7f63dfaead3505cef848a2e4fd91a4ff9756e1b9 100644 (file)
@@ -15,6 +15,8 @@
 --with this program; if not, write to the Free Software Foundation, Inc.,
 --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
+local S = core.get_translator("__builtin")
+
 local function get_bool_default(name, default)
        local val = core.settings:get_bool(name)
        if val == nil then
@@ -40,9 +42,9 @@ function profiler.init_chatcommand()
                instrumentation.init_chatcommand()
        end
 
-       local param_usage = "print [filter] | dump [filter] | save [format [filter]] | reset"
+       local param_usage = S("print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset")
        core.register_chatcommand("profiler", {
-               description = "handle the profiler and profiling data",
+               description = S("Handle the profiler and profiling data"),
                params = param_usage,
                privs = { server=true },
                func = function(name, param)
@@ -51,21 +53,19 @@ function profiler.init_chatcommand()
 
                        if command == "dump" then
                                core.log("action", reporter.print(sampler.profile, arg0))
-                               return true, "Statistics written to action log"
+                               return true, S("Statistics written to action log.")
                        elseif command == "print" then
                                return true, reporter.print(sampler.profile, arg0)
                        elseif command == "save" then
                                return reporter.save(sampler.profile, args[1] or "txt", args[2])
                        elseif command == "reset" then
                                sampler.reset()
-                               return true, "Statistics were reset"
+                               return true, S("Statistics were reset.")
                        end
 
-                       return false, string.format(
-                               "Usage: %s\n" ..
-                               "Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).",
-                               param_usage
-                       )
+                       return false,
+                               S("Usage: @1", param_usage) .. "\n" ..
+                               S("Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).")
                end
        })
 
index 81cdd1f8d1ea6224d93cf66c5c944fe4efe58a1a..a8d45278308b940a5336f0602e0336f861d7bd90 100644 (file)
@@ -2496,7 +2496,9 @@ void Server::fillMediaCache()
 
        // Collect all media file paths
        std::vector<std::string> paths;
-       // The paths are ordered in descending priority
+
+       // ordered in descending priority
+       paths.push_back(getBuiltinLuaPath() + DIR_DELIM + "locale");
        fs::GetRecursiveDirs(paths, porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
        fs::GetRecursiveDirs(paths, m_gamespec.path + DIR_DELIM + "textures");
        m_modmgr->getModsMediaPaths(paths);
index 168483bd44ea2f1370bf55f9534fab21d18d0b85..95acb01eaba39cc7e30990d85e4c3f653863b6a2 100755 (executable)
@@ -58,6 +58,7 @@ xgettext --package-name=minetest \
        --keyword=fgettext_ne \
        --keyword=strgettext \
        --keyword=wstrgettext \
+       --keyword=core.gettext \
        --keyword=showTranslatedStatusText \
        --output $potfile \
        --from-code=utf-8 \