update castles, areas, bakedclay, basic_materials, currency, digistuff,
farming_redo, homedecor, street_signs, technic, and unified inventory removed item_tweaks and teleport_request
@ -2,8 +2,8 @@
|
||||
|
||||
|
||||
# ./init.lua
|
||||
@1 cannot be repaired with an anvil.=
|
||||
@1's anvil=
|
||||
@1 cannot be repaired with an anvil.=@1 ne peut pas être réparé avec une enclume.
|
||||
@1's anvil=enclume de @1
|
||||
A tool for repairing other tools at a blacksmith's anvil.=Un outil pour réparer les autres outils avec une enclume de forgeron.
|
||||
A tool for repairing other tools in conjunction with a blacksmith's hammer.=Un outil pour réparer les autres outils à utiliser avec un marteau de forgeron.
|
||||
Anvil=Enclume
|
||||
@ -11,4 +11,4 @@ Right-click on this anvil with a damaged tool to place the damaged tool upon it.
|
||||
Steel blacksmithing hammer=Marteau de forgeron en acier
|
||||
This anvil is for damaged tools only.=L'enclume s'utilise sur les outils endommagés.
|
||||
Use this hammer to strike blows upon an anvil bearing a damaged tool and you can repair it. It can also be used for smashing stone, but it is not well suited to this task.=Utilisez ce marteau pour frapper une enclume contenant un outil endommagé, ainsi vous pourrez le réparer. Il peut être aussi utilisé pour casser de la pierre, mais il n'est pas adapté à cette tâche.
|
||||
Your @1 has been repaired successfully.=Votre @1 a été réparé avec succès.
|
||||
Your @1 has been repaired successfully.=Votre @1 a été réparé avec succès.
|
||||
|
@ -9,7 +9,6 @@ read_globals = {
|
||||
"VoxelManip", "VoxelArea",
|
||||
"PseudoRandom", "ItemStack",
|
||||
"AreaStore",
|
||||
"intllib",
|
||||
"default",
|
||||
table = { fields = { "copy", "getn" } }
|
||||
}
|
||||
|
@ -1,15 +1,16 @@
|
||||
local S = minetest.get_translator("areas")
|
||||
|
||||
minetest.register_chatcommand("protect", {
|
||||
params = "<AreaName>",
|
||||
description = "Protect your own area",
|
||||
params = S("<AreaName>"),
|
||||
description = S("Protect your own area"),
|
||||
privs = {[areas.config.self_protection_privilege]=true},
|
||||
func = function(name, param)
|
||||
if param == "" then
|
||||
return false, "Invalid usage, see /help protect."
|
||||
return false, S("Invalid usage, see /help @1.", "protect")
|
||||
end
|
||||
local pos1, pos2 = areas:getPos(name)
|
||||
if not (pos1 and pos2) then
|
||||
return false, "You need to select an area first."
|
||||
return false, S("You need to select an area first.")
|
||||
end
|
||||
|
||||
minetest.log("action", "/protect invoked, owner="..name..
|
||||
@ -19,38 +20,37 @@ minetest.register_chatcommand("protect", {
|
||||
|
||||
local canAdd, errMsg = areas:canPlayerAddArea(pos1, pos2, name)
|
||||
if not canAdd then
|
||||
return false, "You can't protect that area: "..errMsg
|
||||
return false, S("You can't protect that area: @1", errMsg)
|
||||
end
|
||||
|
||||
local id = areas:add(name, param, pos1, pos2, nil)
|
||||
areas:save()
|
||||
|
||||
return true, "Area protected. ID: "..id
|
||||
return true, S("Area protected. ID: @1", id)
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
minetest.register_chatcommand("set_owner", {
|
||||
params = "<PlayerName> <AreaName>",
|
||||
description = "Protect an area beetween two positions and give"
|
||||
params = S("<PlayerName>").." "..S("<AreaName>"),
|
||||
description = S("Protect an area between two positions and give"
|
||||
.." a player access to it without setting the parent of the"
|
||||
.." area to any existing area",
|
||||
.." area to any existing area"),
|
||||
privs = areas.adminPrivs,
|
||||
func = function(name, param)
|
||||
local ownerName, areaName = param:match('^(%S+)%s(.+)$')
|
||||
|
||||
if not ownerName then
|
||||
return false, "Incorrect usage, see /help set_owner."
|
||||
return false, S("Invalid usage, see /help @1.", "set_owner")
|
||||
end
|
||||
|
||||
local pos1, pos2 = areas:getPos(name)
|
||||
if not (pos1 and pos2) then
|
||||
return false, "You need to select an area first."
|
||||
return false, S("You need to select an area first.")
|
||||
end
|
||||
|
||||
if not areas:player_exists(ownerName) then
|
||||
return false, "The player \""
|
||||
..ownerName.."\" does not exist."
|
||||
return false, S("The player \"@1\" does not exist.", ownerName)
|
||||
end
|
||||
|
||||
minetest.log("action", name.." runs /set_owner. Owner = "..ownerName..
|
||||
@ -62,34 +62,34 @@ minetest.register_chatcommand("set_owner", {
|
||||
areas:save()
|
||||
|
||||
minetest.chat_send_player(ownerName,
|
||||
"You have been granted control over area #"..
|
||||
id..". Type /list_areas to show your areas.")
|
||||
return true, "Area protected. ID: "..id
|
||||
S("You have been granted control over area #@1. "..
|
||||
"Type /list_areas to show your areas.", id))
|
||||
return true, S("Area protected. ID: @1", id)
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
minetest.register_chatcommand("add_owner", {
|
||||
params = "<ParentID> <Player> <AreaName>",
|
||||
description = "Give a player access to a sub-area beetween two"
|
||||
params = S("<ParentID>").." "..S("<PlayerName>").." "..S("<AreaName>"),
|
||||
description = S("Give a player access to a sub-area beetween two"
|
||||
.." positions that have already been protected,"
|
||||
.." Use set_owner if you don't want the parent to be set.",
|
||||
.." Use set_owner if you don't want the parent to be set."),
|
||||
func = function(name, param)
|
||||
local pid, ownerName, areaName
|
||||
= param:match('^(%d+) ([^ ]+) (.+)$')
|
||||
|
||||
if not pid then
|
||||
minetest.chat_send_player(name, "Incorrect usage, see /help add_owner")
|
||||
minetest.chat_send_player(name, S("Invalid usage, see /help @1.", "add_owner"))
|
||||
return
|
||||
end
|
||||
|
||||
local pos1, pos2 = areas:getPos(name)
|
||||
if not (pos1 and pos2) then
|
||||
return false, "You need to select an area first."
|
||||
return false, S("You need to select an area first.")
|
||||
end
|
||||
|
||||
if not areas:player_exists(ownerName) then
|
||||
return false, "The player \""..ownerName.."\" does not exist."
|
||||
return false, S("The player \"@1\" does not exist.", ownerName)
|
||||
end
|
||||
|
||||
minetest.log("action", name.." runs /add_owner. Owner = "..ownerName..
|
||||
@ -101,52 +101,52 @@ minetest.register_chatcommand("add_owner", {
|
||||
pid = tonumber(pid)
|
||||
if (not areas:isAreaOwner(pid, name)) or
|
||||
(not areas:isSubarea(pos1, pos2, pid)) then
|
||||
return false, "You can't protect that area."
|
||||
return false, S("You can't protect that area.")
|
||||
end
|
||||
|
||||
local id = areas:add(ownerName, areaName, pos1, pos2, pid)
|
||||
areas:save()
|
||||
|
||||
minetest.chat_send_player(ownerName,
|
||||
"You have been granted control over area #"..
|
||||
id..". Type /list_areas to show your areas.")
|
||||
return true, "Area protected. ID: "..id
|
||||
S("You have been granted control over area #@1. "..
|
||||
"Type /list_areas to show your areas.", id))
|
||||
return true, S("Area protected. ID: @1", id)
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
minetest.register_chatcommand("rename_area", {
|
||||
params = "<ID> <newName>",
|
||||
description = "Rename a area that you own",
|
||||
params = S("<ID>").." "..S("<newName>"),
|
||||
description = S("Rename an area that you own"),
|
||||
func = function(name, param)
|
||||
local id, newName = param:match("^(%d+)%s(.+)$")
|
||||
if not id then
|
||||
return false, "Invalid usage, see /help rename_area."
|
||||
return false, S("Invalid usage, see /help @1.", "rename_area")
|
||||
end
|
||||
|
||||
id = tonumber(id)
|
||||
if not id then
|
||||
return false, "That area doesn't exist."
|
||||
return false, S("That area doesn't exist.")
|
||||
end
|
||||
|
||||
if not areas:isAreaOwner(id, name) then
|
||||
return true, "You don't own that area."
|
||||
return true, S("You don't own that area.")
|
||||
end
|
||||
|
||||
areas.areas[id].name = newName
|
||||
areas:save()
|
||||
return true, "Area renamed."
|
||||
return true, S("Area renamed.")
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
minetest.register_chatcommand("find_areas", {
|
||||
params = "<regexp>",
|
||||
description = "Find areas using a Lua regular expression",
|
||||
description = S("Find areas using a Lua regular expression"),
|
||||
privs = areas.adminPrivs,
|
||||
func = function(name, param)
|
||||
if param == "" then
|
||||
return false, "A regular expression is required."
|
||||
return false, S("A regular expression is required.")
|
||||
end
|
||||
|
||||
-- Check expression for validity
|
||||
@ -154,7 +154,7 @@ minetest.register_chatcommand("find_areas", {
|
||||
("Test [1]: Player (0,0,0) (0,0,0)"):find(param)
|
||||
end
|
||||
if not pcall(testRegExp) then
|
||||
return false, "Invalid regular expression."
|
||||
return false, S("Invalid regular expression.")
|
||||
end
|
||||
|
||||
local matches = {}
|
||||
@ -167,14 +167,14 @@ minetest.register_chatcommand("find_areas", {
|
||||
if #matches > 0 then
|
||||
return true, table.concat(matches, "\n")
|
||||
else
|
||||
return true, "No matches found."
|
||||
return true, S("No matches found.")
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
minetest.register_chatcommand("list_areas", {
|
||||
description = "List your areas, or all areas if you are an admin.",
|
||||
description = S("List your areas, or all areas if you are an admin."),
|
||||
func = function(name, param)
|
||||
local admin = minetest.check_player_privs(name, areas.adminPrivs)
|
||||
local areaStrings = {}
|
||||
@ -184,7 +184,7 @@ minetest.register_chatcommand("list_areas", {
|
||||
end
|
||||
end
|
||||
if #areaStrings == 0 then
|
||||
return true, "No visible areas."
|
||||
return true, S("No visible areas.")
|
||||
end
|
||||
return true, table.concat(areaStrings, "\n")
|
||||
end
|
||||
@ -192,154 +192,154 @@ minetest.register_chatcommand("list_areas", {
|
||||
|
||||
|
||||
minetest.register_chatcommand("recursive_remove_areas", {
|
||||
params = "<id>",
|
||||
description = "Recursively remove areas using an id",
|
||||
params = S("<ID>"),
|
||||
description = S("Recursively remove areas using an ID"),
|
||||
func = function(name, param)
|
||||
local id = tonumber(param)
|
||||
if not id then
|
||||
return false, "Invalid usage, see"
|
||||
.." /help recursive_remove_areas"
|
||||
return false, S("Invalid usage, see"
|
||||
.." /help @1.", "recursive_remove_areas")
|
||||
end
|
||||
|
||||
if not areas:isAreaOwner(id, name) then
|
||||
return false, "Area "..id.." does not exist or is"
|
||||
.." not owned by you."
|
||||
return false, S("Area @1 does not exist or is"
|
||||
.." not owned by you.", id)
|
||||
end
|
||||
|
||||
areas:remove(id, true)
|
||||
areas:save()
|
||||
return true, "Removed area "..id.." and it's sub areas."
|
||||
return true, S("Removed area @1 and it's sub areas.", id)
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
minetest.register_chatcommand("remove_area", {
|
||||
params = "<id>",
|
||||
description = "Remove an area using an id",
|
||||
params = S("<ID>"),
|
||||
description = S("Remove an area using an ID"),
|
||||
func = function(name, param)
|
||||
local id = tonumber(param)
|
||||
if not id then
|
||||
return false, "Invalid usage, see /help remove_area"
|
||||
return false, S("Invalid usage, see /help @1.", "remove_area")
|
||||
end
|
||||
|
||||
if not areas:isAreaOwner(id, name) then
|
||||
return false, "Area "..id.." does not exist or"
|
||||
.." is not owned by you."
|
||||
return false, S("Area @1 does not exist or"
|
||||
.." is not owned by you.", id)
|
||||
end
|
||||
|
||||
areas:remove(id)
|
||||
areas:save()
|
||||
return true, "Removed area "..id
|
||||
return true, S("Removed area @1", id)
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
minetest.register_chatcommand("change_owner", {
|
||||
params = "<ID> <NewOwner>",
|
||||
description = "Change the owner of an area using it's ID",
|
||||
params = S("<ID>").." "..S("<NewOwner>"),
|
||||
description = S("Change the owner of an area using its ID"),
|
||||
func = function(name, param)
|
||||
local id, newOwner = param:match("^(%d+)%s(%S+)$")
|
||||
if not id then
|
||||
return false, "Invalid usage, see"
|
||||
.." /help change_owner."
|
||||
return false, S("Invalid usage, see"
|
||||
.." /help @1.", "change_owner")
|
||||
end
|
||||
|
||||
if not areas:player_exists(newOwner) then
|
||||
return false, "The player \""..newOwner
|
||||
.."\" does not exist."
|
||||
return false, S("The player \"@1\" does not exist.", newOwner)
|
||||
end
|
||||
|
||||
id = tonumber(id)
|
||||
if not areas:isAreaOwner(id, name) then
|
||||
return false, "Area "..id.." does not exist"
|
||||
.." or is not owned by you."
|
||||
return false, S("Area @1 does not exist"
|
||||
.." or is not owned by you.", id)
|
||||
end
|
||||
areas.areas[id].owner = newOwner
|
||||
areas:save()
|
||||
minetest.chat_send_player(newOwner,
|
||||
("%s has given you control over the area %q (ID %d).")
|
||||
:format(name, areas.areas[id].name, id))
|
||||
return true, "Owner changed."
|
||||
S("@1 has given you control over the area \"@2\" (ID @3).",
|
||||
name, areas.areas[id].name, id))
|
||||
return true, S("Owner changed.")
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
minetest.register_chatcommand("area_open", {
|
||||
params = "<ID>",
|
||||
description = "Toggle an area open (anyone can interact) or closed",
|
||||
params = S("<ID>"),
|
||||
description = S("Toggle an area open (anyone can interact) or closed"),
|
||||
func = function(name, param)
|
||||
local id = tonumber(param)
|
||||
if not id then
|
||||
return false, "Invalid usage, see /help area_open."
|
||||
return false, S("Invalid usage, see /help @1.", "area_open")
|
||||
end
|
||||
|
||||
if not areas:isAreaOwner(id, name) then
|
||||
return false, "Area "..id.." does not exist"
|
||||
.." or is not owned by you."
|
||||
return false, S("Area @1 does not exist"
|
||||
.." or is not owned by you.", id)
|
||||
end
|
||||
local open = not areas.areas[id].open
|
||||
-- Save false as nil to avoid inflating the DB.
|
||||
areas.areas[id].open = open or nil
|
||||
areas:save()
|
||||
return true, ("Area %s."):format(open and "opened" or "closed")
|
||||
return true, open and S("Area opened.") or S("Area closed.")
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
if areas.factions_available then
|
||||
minetest.register_chatcommand("area_faction_open", {
|
||||
params = "<ID>",
|
||||
description = "Toggle an area open/closed for members in your faction.",
|
||||
params = S("<ID>"),
|
||||
description = S("Toggle an area open/closed for members in your faction."),
|
||||
func = function(name, param)
|
||||
local id = tonumber(param)
|
||||
if not id then
|
||||
return false, "Invalid usage, see /help area_faction_open."
|
||||
return false, S("Invalid usage, see /help @1.", "area_faction_open")
|
||||
end
|
||||
|
||||
if not areas:isAreaOwner(id, name) then
|
||||
return false, "Area "..id.." does not exist"
|
||||
.." or is not owned by you."
|
||||
return false, S("Area @1 does not exist"
|
||||
.." or is not owned by you.", id)
|
||||
end
|
||||
local open = not areas.areas[id].faction_open
|
||||
-- Save false as nil to avoid inflating the DB.
|
||||
areas.areas[id].faction_open = open or nil
|
||||
areas:save()
|
||||
return true, ("Area %s for faction members."):format(open and "opened" or "closed")
|
||||
return true, open and S("Area opened for faction members.")
|
||||
or S("Area closed for faction members.")
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
minetest.register_chatcommand("move_area", {
|
||||
params = "<ID>",
|
||||
description = "Move (or resize) an area to the current positions.",
|
||||
params = S("<ID>"),
|
||||
description = S("Move (or resize) an area to the current positions."),
|
||||
privs = areas.adminPrivs,
|
||||
func = function(name, param)
|
||||
local id = tonumber(param)
|
||||
if not id then
|
||||
return false, "Invalid usage, see /help move_area."
|
||||
return false, S("Invalid usage, see /help @1.", "move_area")
|
||||
end
|
||||
|
||||
local area = areas.areas[id]
|
||||
if not area then
|
||||
return false, "Area does not exist."
|
||||
return false, S("Area does not exist.")
|
||||
end
|
||||
|
||||
local pos1, pos2 = areas:getPos(name)
|
||||
if not pos1 then
|
||||
return false, "You need to select an area first."
|
||||
return false, S("You need to select an area first.")
|
||||
end
|
||||
|
||||
areas:move(id, area, pos1, pos2)
|
||||
areas:save()
|
||||
|
||||
return true, "Area successfully moved."
|
||||
return true, S("Area successfully moved.")
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
minetest.register_chatcommand("area_info", {
|
||||
description = "Get information about area configuration and usage.",
|
||||
description = S("Get information about area configuration and usage."),
|
||||
func = function(name, param)
|
||||
local lines = {}
|
||||
local privs = minetest.get_player_privs(name)
|
||||
@ -361,27 +361,22 @@ minetest.register_chatcommand("area_info", {
|
||||
local max_size = has_high_limit and
|
||||
size_limit_high or size_limit
|
||||
|
||||
-- Privilege information
|
||||
local self_prot_line = ("Self protection is %sabled"):format(
|
||||
self_prot and "en" or "dis")
|
||||
if self_prot and prot_priv then
|
||||
self_prot_line = self_prot_line..
|
||||
(" %s have the neccessary privilege (%q).")
|
||||
:format(
|
||||
has_prot_priv and "and you" or
|
||||
"but you don't",
|
||||
prot_priv)
|
||||
else
|
||||
self_prot_line = self_prot_line.."."
|
||||
end
|
||||
-- Self protection information
|
||||
local self_prot_line = self_prot and S("Self protection is enabled.") or
|
||||
S("Self protection is disabled.")
|
||||
table.insert(lines, self_prot_line)
|
||||
-- Privilege information
|
||||
local priv_line = has_prot_priv and
|
||||
S("You have the necessary privilege (\"@1\").", prot_priv) or
|
||||
S("You don't have the necessary privilege (\"@1\").", prot_priv)
|
||||
table.insert(lines, priv_line)
|
||||
if privs.areas then
|
||||
table.insert(lines, "You are an area"..
|
||||
" administrator (\"areas\" privilege).")
|
||||
table.insert(lines, S("You are an area"..
|
||||
" administrator (\"areas\" privilege)."))
|
||||
elseif has_high_limit then
|
||||
table.insert(lines,
|
||||
"You have extended area protection"..
|
||||
" limits (\"areas_high_limit\" privilege).")
|
||||
S("You have extended area protection"..
|
||||
" limits (\"areas_high_limit\" privilege)."))
|
||||
end
|
||||
|
||||
-- Area count
|
||||
@ -391,26 +386,23 @@ minetest.register_chatcommand("area_info", {
|
||||
area_num = area_num + 1
|
||||
end
|
||||
end
|
||||
local count_line = ("You have %d area%s"):format(
|
||||
area_num, area_num == 1 and "" or "s")
|
||||
if privs.areas then
|
||||
count_line = count_line..
|
||||
" and have no area protection limits."
|
||||
elseif can_prot then
|
||||
count_line = count_line..(", out of a maximum of %d.")
|
||||
:format(max_count)
|
||||
end
|
||||
table.insert(lines, count_line)
|
||||
table.insert(lines, S("You have @1 areas.", area_num))
|
||||
|
||||
-- Area limit
|
||||
local area_limit_line = privs.areas and
|
||||
S("Limit: no area count limit") or
|
||||
S("Limit: @1 areas", max_count)
|
||||
table.insert(lines, area_limit_line)
|
||||
|
||||
-- Area size limits
|
||||
local function size_info(str, size)
|
||||
table.insert(lines, ("%s spanning up to %dx%dx%d.")
|
||||
:format(str, size.x, size.y, size.z))
|
||||
table.insert(lines, S("@1 spanning up to @2x@3x@4.",
|
||||
str, size.x, size.y, size.z))
|
||||
end
|
||||
local function priv_limit_info(lpriv, lmax_count, lmax_size)
|
||||
size_info(("Players with the %q privilege"..
|
||||
" can protect up to %d areas"):format(
|
||||
lpriv, lmax_count), lmax_size)
|
||||
size_info(S("Players with the \"@1\" privilege"..
|
||||
" can protect up to @2 areas", lpriv, lmax_count),
|
||||
lmax_size)
|
||||
end
|
||||
if self_prot then
|
||||
if privs.areas then
|
||||
@ -419,7 +411,7 @@ minetest.register_chatcommand("area_info", {
|
||||
priv_limit_info("areas_high_limit",
|
||||
limit_high, size_limit_high)
|
||||
elseif has_prot_priv then
|
||||
size_info("You can protect areas", max_size)
|
||||
size_info(S("You can protect areas"), max_size)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
-- This is inspired by the landrush mod by Bremaweb
|
||||
|
||||
local S = minetest.get_translator("areas")
|
||||
areas.hud = {}
|
||||
areas.hud.refresh = 0
|
||||
|
||||
@ -26,7 +26,7 @@ minetest.register_globalstep(function(dtime)
|
||||
area.faction_open = faction_info
|
||||
table.insert(areaStrings, ("%s [%u] (%s%s%s)")
|
||||
:format(area.name, id, area.owner,
|
||||
area.open and ":open" or "",
|
||||
area.open and S(":open") or "",
|
||||
faction_info and ":"..faction_info or ""))
|
||||
end
|
||||
|
||||
@ -38,7 +38,7 @@ minetest.register_globalstep(function(dtime)
|
||||
table.insert(areaStrings, str)
|
||||
end
|
||||
|
||||
local areaString = "Areas:"
|
||||
local areaString = S("Areas:")
|
||||
if #areaStrings > 0 then
|
||||
areaString = areaString.."\n"..
|
||||
table.concat(areaStrings, "\n")
|
||||
|
@ -1,3 +1,4 @@
|
||||
local S = minetest.get_translator("areas")
|
||||
|
||||
local old_is_protected = minetest.is_protected
|
||||
function minetest.is_protected(pos, name)
|
||||
@ -11,7 +12,7 @@ minetest.register_on_protection_violation(function(pos, name)
|
||||
if not areas:canInteract(pos, name) then
|
||||
local owners = areas:getNodeOwners(pos)
|
||||
minetest.chat_send_player(name,
|
||||
("%s is protected by %s."):format(
|
||||
S("@1 is protected by @2.",
|
||||
minetest.pos_to_string(pos),
|
||||
table.concat(owners, ", ")))
|
||||
end
|
||||
|
@ -1,3 +1,4 @@
|
||||
local S = minetest.get_translator("areas")
|
||||
|
||||
function areas:player_exists(name)
|
||||
return minetest.get_auth_handler().get_auth(name) ~= nil
|
||||
@ -212,8 +213,8 @@ function areas:canPlayerAddArea(pos1, pos2, name)
|
||||
-- and if the area is too big.
|
||||
if not self.config.self_protection or
|
||||
not privs[areas.config.self_protection_privilege] then
|
||||
return false, "Self protection is disabled or you do not have"
|
||||
.." the necessary privilege."
|
||||
return false, S("Self protection is disabled or you do not have"
|
||||
.." the necessary privilege.")
|
||||
end
|
||||
|
||||
local max_size = privs.areas_high_limit and
|
||||
@ -223,7 +224,7 @@ function areas:canPlayerAddArea(pos1, pos2, name)
|
||||
(pos2.x - pos1.x) > max_size.x or
|
||||
(pos2.y - pos1.y) > max_size.y or
|
||||
(pos2.z - pos1.z) > max_size.z then
|
||||
return false, "Area is too big."
|
||||
return false, S("Area is too big.")
|
||||
end
|
||||
|
||||
-- Check number of areas the user has and make sure it not above the max
|
||||
@ -237,16 +238,16 @@ function areas:canPlayerAddArea(pos1, pos2, name)
|
||||
self.config.self_protection_max_areas_high or
|
||||
self.config.self_protection_max_areas
|
||||
if count >= max_areas then
|
||||
return false, "You have reached the maximum amount of"
|
||||
.." areas that you are allowed to protect."
|
||||
return false, S("You have reached the maximum amount of"
|
||||
.." areas that you are allowed to protect.")
|
||||
end
|
||||
|
||||
-- Check intersecting areas
|
||||
local can, id = self:canInteractInArea(pos1, pos2, name)
|
||||
if not can then
|
||||
local area = self.areas[id]
|
||||
return false, ("The area intersects with %s [%u] (%s).")
|
||||
:format(area.name, id, area.owner)
|
||||
return false, S("The area intersects with @1 [@2] (@3).",
|
||||
area.name, id, area.owner)
|
||||
end
|
||||
|
||||
return true
|
||||
|
@ -1,25 +1,26 @@
|
||||
-- This file contains functions to convert from
|
||||
-- the old areas format and other compatability code.
|
||||
local S = minetest.get_translator("areas")
|
||||
|
||||
minetest.register_chatcommand("legacy_load_areas", {
|
||||
params = "<version>",
|
||||
description = "Loads, converts, and saves the areas from"
|
||||
.." a legacy save file.",
|
||||
params = S("<version>"),
|
||||
description = S("Loads, converts, and saves the areas from"
|
||||
.." a legacy save file."),
|
||||
privs = {areas=true, server=true},
|
||||
func = function(name, param)
|
||||
minetest.chat_send_player(name, "Converting areas...")
|
||||
minetest.chat_send_player(name, S("Converting areas…"))
|
||||
local version = tonumber(param)
|
||||
if version == 0 then
|
||||
local err = areas:node_ownership_load()
|
||||
if err then
|
||||
minetest.chat_send_player(name, "Error loading legacy file: "..err)
|
||||
minetest.chat_send_player(name, S("Error loading legacy file: @1", err))
|
||||
return
|
||||
end
|
||||
else
|
||||
minetest.chat_send_player(name, "Invalid version number. (0 allowed)")
|
||||
minetest.chat_send_player(name, S("Invalid version number. (0 allowed)"))
|
||||
return
|
||||
end
|
||||
minetest.chat_send_player(name, "Legacy file loaded.")
|
||||
minetest.chat_send_player(name, S("Legacy file loaded."))
|
||||
|
||||
for k, area in pairs(areas.areas) do
|
||||
-- New position format
|
||||
@ -34,15 +35,15 @@ minetest.register_chatcommand("legacy_load_areas", {
|
||||
areas:sortPos(area.pos1, area.pos2)
|
||||
|
||||
-- Add name
|
||||
area.name = "unnamed"
|
||||
area.name = S("unnamed")
|
||||
|
||||
-- Remove ID
|
||||
area.id = nil
|
||||
end
|
||||
minetest.chat_send_player(name, "Table format updated.")
|
||||
minetest.chat_send_player(name, S("Table format updated."))
|
||||
|
||||
areas:save()
|
||||
minetest.chat_send_player(name, "Converted areas saved. Done.")
|
||||
minetest.chat_send_player(name, S("Converted areas saved. Done."))
|
||||
end
|
||||
})
|
||||
|
||||
@ -130,7 +131,7 @@ if areas.config.legacy_table then
|
||||
{x=a.x2, y=a.y2, z=a.z2}
|
||||
a.x1, a.y1, a.z1, a.x2, a.y2, a.z2 =
|
||||
nil, nil, nil, nil, nil, nil
|
||||
a.name = a.name or "unnamed"
|
||||
a.name = a.name or S("unnamed")
|
||||
a.id = nil
|
||||
return rawset(areas.areas, key, a)
|
||||
end
|
||||
|
125
areas/locale/areas.fr.tr
Normal file
@ -0,0 +1,125 @@
|
||||
# textdomain: areas
|
||||
|
||||
|
||||
### chatcommands.lua ###
|
||||
|
||||
<AreaName>=<NomZone>
|
||||
<NewOwner>=<NouveauPropriétaire>
|
||||
<ParentID>=<IDZonePrincipale>
|
||||
<PlayerName>=<NomJoueur>
|
||||
<newName>=<NouveauNom>
|
||||
@1 has given you control over the area "@2" (ID @3).=@1 vous a donné le contrôle de la zone "@2" (ID @3).
|
||||
@1 spanning up to @2x@3x@4.=@1 s’étendant jusqu’à @2x@3x@4.
|
||||
A regular expression is required.=Une expression régulière est requise.
|
||||
Area @1 does not exist or is not owned by you.=La zone @1 n’existe pas ou ne vous appartient pas.
|
||||
Area closed for faction members.=Zone fermée aux membres de la faction.
|
||||
Area closed.=Zone fermée.
|
||||
Area does not exist.=La zone n’existe pas.
|
||||
Area opened for faction members.=Zone ouverte aux membres de la faction.
|
||||
Area opened.=Zone ouverte.
|
||||
Area protected. ID: @1=Zone protégée. ID : @1
|
||||
Area renamed.=Zone renommée.
|
||||
Area successfully moved.=Zone déplacée avec succès.
|
||||
Change the owner of an area using its ID=Change le propriétaire d’une zone en utilisant son ID.
|
||||
Find areas using a Lua regular expression=Trouve les zones en utilisant une expression régulière Lua.
|
||||
Get information about area configuration and usage.=Obtient des informations sur la configuration des zones et l’utilisation des zones.
|
||||
|
||||
Give a player access to a sub-area beetween two positions that have already been protected, Use set_owner if you don't want the parent to be set.=Donne au joueur accès aux sous-zones entre deux positions qui ont déjà été protégées ; utilisez set_owner si vous ne voulez pas que la zone pricipale soit définie.
|
||||
|
||||
Invalid regular expression.=Expression régulière invalide.
|
||||
Limit: @1 areas=Limite: @1 zones.
|
||||
Limit: no area count limit=Limite: pas de limite de nombre de zones.
|
||||
List your areas, or all areas if you are an admin.=Liste vos zones, ou toutes les zones si vous êtes administrateur.
|
||||
Move (or resize) an area to the current positions.=Déplace (ou redimensionne) une zone aux positions actuelles.
|
||||
No matches found.=Aucun résultat.
|
||||
No visible areas.=Pas de zone visible.
|
||||
Owner changed.=Propriétaire changé.
|
||||
Players with the "@1" privilege can protect up to @2 areas=Les joueurs avec le privilège "@1" peuvent protéger jusqu’à @2 zones
|
||||
|
||||
Protect an area between two positions and give a player access to it without setting the parent of the area to any existing area=Protège une zone entre deux positions et donne à un joueur accès à cette zone sans définir la zone principale de cette zone ni aucune zone existante.
|
||||
|
||||
Protect your own area=Protège votre zone.
|
||||
Recursively remove areas using an ID=Supprime les zones récursivement en utilisant un ID.
|
||||
Remove an area using an ID=Supprime une zone en utilisant son ID.
|
||||
Removed area @1=Zone @1 supprimée.
|
||||
Removed area @1 and it's sub areas.=Zone @1 et ses sous-zones supprimées.
|
||||
Rename an area that you own=Renomme une zone qui vous appartient.
|
||||
Self protection is disabled.=L’autoprotection est désactivée.
|
||||
Self protection is enabled.=L’autoprotection est activée.
|
||||
That area doesn't exist.=La zone n’existe pas.
|
||||
The player "@1" does not exist.=Le joueur "@1" n’existe pas.
|
||||
Toggle an area open (anyone can interact) or closed=Bascule entre zone ouverte (tout le monde peut intéragir) ou fermée.
|
||||
Toggle an area open/closed for members in your faction.=Bascule entre zone ouverte/fermée pour les membres de votre faction.
|
||||
You are an area administrator ("areas" privilege).=Vous êtes un administrateur de zone (privilège "areas").
|
||||
You can protect areas=Vous pouvez protéger des zones.
|
||||
You can't protect that area.=Vous ne pouvez pas protéger cette zone.
|
||||
You can't protect that area: @1=Vous ne pouvez pas protéger cette zone : @1.
|
||||
You don't have the necessary privilege ("@1").=Vous n’avez pas le privilège nécessaire ("@1").
|
||||
You don't own that area.=Vous ne possédez pas cette zone.
|
||||
You have @1 areas.=Vous avez @1 zones.
|
||||
|
||||
You have been granted control over area #@1. Type /list_areas to show your areas.=Vous avez reçu l’autorisation de contrôler la zone #@1.
|
||||
|
||||
You have extended area protection limits ("areas_high_limit" privilege).=Votre limite de protection de zones est étendue (privilège "areas_high_limit").
|
||||
|
||||
You have the necessary privilege ("@1").=Vous avez le privilège nécessaire ("@1").
|
||||
You need to select an area first.=Vous devez sélectionner une zone d’abord.
|
||||
|
||||
### chatcommands.lua ###
|
||||
### pos.lua ###
|
||||
|
||||
<ID>=<ID>
|
||||
Invalid usage, see /help @1.=Utilisation incorrecte, voir /help @1.
|
||||
|
||||
### hud.lua ###
|
||||
|
||||
:open= : ouverte
|
||||
Areas:=Zones :
|
||||
|
||||
### interact.lua ###
|
||||
|
||||
@1 is protected by @2.=@1 est protégée par @2.
|
||||
|
||||
### internal.lua ###
|
||||
|
||||
Area is too big.=La zone est trop grande.
|
||||
|
||||
Self protection is disabled or you do not have the necessary privilege.=L’autoprotection est désactivée ou vous n’avez pas le privilège nécessaire.
|
||||
|
||||
The area intersects with @1 [@2] (@3).=La zone a une intersection avec @1 [@2] (@3).
|
||||
|
||||
You have reached the maximum amount of areas that you are allowed to protect.=Vous avez atteint le nombre maximum de zones que vous êtes autorisé à protéger.
|
||||
|
||||
|
||||
### legacy.lua ###
|
||||
|
||||
<version>=<version>
|
||||
Converted areas saved. Done.=Zones converties sauvegardées. Fait.
|
||||
Converting areas…=Conversion des zones…
|
||||
Error loading legacy file: @1=Erreur lors du chargement du fichier : @1
|
||||
Invalid version number. (0 allowed)=Numéro de version invalide. (0 autorisé)
|
||||
Legacy file loaded.=Fichier obsolète chargé.
|
||||
|
||||
Loads, converts, and saves the areas from a legacy save file.=Charge, fait la conversion et sauvegarde les zones depuis un fichier de sauvegarde obsolète.
|
||||
|
||||
Table format updated.=Format de tableau mis à jour.
|
||||
unnamed=Non nommé
|
||||
|
||||
### pos.lua ###
|
||||
|
||||
<not set>=<no définie>
|
||||
Area @1 selected.=Zone @1 sélectionnée.
|
||||
Area position @1 set to @2=Position @1 de la zone définie à @2.
|
||||
Position @1 set to @2=Position @1 définie à @2.
|
||||
Position @1: =Position @1 :
|
||||
Select an area by ID.=Sélectionnez une zone par son ID.
|
||||
Select position @1 by punching a node.=Sélectionnez une position en frappant un bloc.
|
||||
Select positions by punching two nodes.=Sélectionnez une position en frappant deux blocs.
|
||||
|
||||
Set area protection region position @1 to your location or the one specified=Définit la position @1 de la région de protection de zone à votre position ou à celle spécifiée.
|
||||
|
||||
Set area protection region, position 1, or position 2 by punching nodes, or display the region=Définit la région de protection de zone, la position 1, ou la position 2 en frappant des blocs, ou en affichant la région.
|
||||
|
||||
The area @1 does not exist.=La zone @1 n’existe pas.
|
||||
Unable to get position.=Impossible d’obtenir la position.
|
||||
Unknown subcommand: @1=Sous-commande inconnue : @1
|
125
areas/locale/template.txt
Normal file
@ -0,0 +1,125 @@
|
||||
# textdomain: areas
|
||||
|
||||
|
||||
### chatcommands.lua ###
|
||||
|
||||
<AreaName>=
|
||||
<NewOwner>=
|
||||
<ParentID>=
|
||||
<PlayerName>=
|
||||
<newName>=
|
||||
@1 has given you control over the area "@2" (ID @3).=
|
||||
@1 spanning up to @2x@3x@4.=
|
||||
A regular expression is required.=
|
||||
Area @1 does not exist or is not owned by you.=
|
||||
Area closed for faction members.=
|
||||
Area closed.=
|
||||
Area does not exist.=
|
||||
Area opened for faction members.=
|
||||
Area opened.=
|
||||
Area protected. ID: @1=
|
||||
Area renamed.=
|
||||
Area successfully moved.=
|
||||
Change the owner of an area using its ID=
|
||||
Find areas using a Lua regular expression=
|
||||
Get information about area configuration and usage.=
|
||||
|
||||
Give a player access to a sub-area beetween two positions that have already been protected, Use set_owner if you don't want the parent to be set.=
|
||||
|
||||
Invalid regular expression.=
|
||||
Limit: @1 areas=
|
||||
Limit: no area count limit=
|
||||
List your areas, or all areas if you are an admin.=
|
||||
Move (or resize) an area to the current positions.=
|
||||
No matches found.=
|
||||
No visible areas.=
|
||||
Owner changed.=
|
||||
Players with the "@1" privilege can protect up to @2 areas=
|
||||
|
||||
Protect an area between two positions and give a player access to it without setting the parent of the area to any existing area=
|
||||
|
||||
Protect your own area=
|
||||
Recursively remove areas using an ID=
|
||||
Remove an area using an ID=
|
||||
Removed area @1=
|
||||
Removed area @1 and it's sub areas.=
|
||||
Rename an area that you own=
|
||||
Self protection is disabled.=
|
||||
Self protection is enabled.=
|
||||
That area doesn't exist.=
|
||||
The player "@1" does not exist.=
|
||||
Toggle an area open (anyone can interact) or closed=
|
||||
Toggle an area open/closed for members in your faction.=
|
||||
You are an area administrator ("areas" privilege).=
|
||||
You can protect areas=
|
||||
You can't protect that area.=
|
||||
You can't protect that area: @1=
|
||||
You don't have the necessary privilege ("@1").=
|
||||
You don't own that area.=
|
||||
You have @1 areas.=
|
||||
|
||||
You have been granted control over area #@1. Type /list_areas to show your areas.=
|
||||
|
||||
You have extended area protection limits ("areas_high_limit" privilege).=
|
||||
|
||||
You have the necessary privilege ("@1").=
|
||||
You need to select an area first.=
|
||||
|
||||
### chatcommands.lua ###
|
||||
### pos.lua ###
|
||||
|
||||
<ID>=
|
||||
Invalid usage, see /help @1.=
|
||||
|
||||
### hud.lua ###
|
||||
|
||||
:open=
|
||||
Areas:=
|
||||
|
||||
### interact.lua ###
|
||||
|
||||
@1 is protected by @2.=
|
||||
|
||||
### internal.lua ###
|
||||
|
||||
Area is too big.=
|
||||
|
||||
Self protection is disabled or you do not have the necessary privilege.=
|
||||
|
||||
The area intersects with @1 [@2] (@3).=
|
||||
|
||||
You have reached the maximum amount of areas that you are allowed to protect.=
|
||||
|
||||
|
||||
### legacy.lua ###
|
||||
|
||||
<version>=
|
||||
Converted areas saved. Done.=
|
||||
Converting areas…=
|
||||
Error loading legacy file: @1=
|
||||
Invalid version number. (0 allowed)=
|
||||
Legacy file loaded.=
|
||||
|
||||
Loads, converts, and saves the areas from a legacy save file.=
|
||||
|
||||
Table format updated.=
|
||||
unnamed=
|
||||
|
||||
### pos.lua ###
|
||||
|
||||
<not set>=
|
||||
Area @1 selected.=
|
||||
Area position @1 set to @2=
|
||||
Position @1 set to @2=
|
||||
Position @1: =
|
||||
Select an area by ID.=
|
||||
Select position @1 by punching a node.=
|
||||
Select positions by punching two nodes.=
|
||||
|
||||
Set area protection region position @1 to your location or the one specified=
|
||||
|
||||
Set area protection region, position 1, or position 2 by punching nodes, or display the region=
|
||||
|
||||
The area @1 does not exist.=
|
||||
Unable to get position.=
|
||||
Unknown subcommand: @1=
|
@ -1,4 +1,4 @@
|
||||
|
||||
local S = minetest.get_translator("areas")
|
||||
-- I could depend on WorldEdit for this, but you need to have the 'worldedit'
|
||||
-- permission to use those commands and you don't have
|
||||
-- /area_pos{1,2} [X Y Z|X,Y,Z].
|
||||
@ -22,27 +22,27 @@ local function posLimit(pos)
|
||||
end
|
||||
|
||||
minetest.register_chatcommand("select_area", {
|
||||
params = "<ID>",
|
||||
description = "Select a area by id.",
|
||||
params = S("<ID>"),
|
||||
description = S("Select an area by ID."),
|
||||
func = function(name, param)
|
||||
local id = tonumber(param)
|
||||
if not id then
|
||||
return false, "Invalid usage, see /help select_area."
|
||||
return false, S("Invalid usage, see /help @1.", "select_area")
|
||||
end
|
||||
if not areas.areas[id] then
|
||||
return false, "The area "..id.." does not exist."
|
||||
return false, S("The area @1 does not exist.", id)
|
||||
end
|
||||
|
||||
areas:setPos1(name, areas.areas[id].pos1)
|
||||
areas:setPos2(name, areas.areas[id].pos2)
|
||||
return true, "Area "..id.." selected."
|
||||
return true, S("Area @1 selected.", id)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("area_pos1", {
|
||||
params = "[X Y Z|X,Y,Z]",
|
||||
description = "Set area protection region position 1 to your"
|
||||
.." location or the one specified",
|
||||
description = S("Set area protection region position @1 to your"
|
||||
.." location or the one specified", "1"),
|
||||
privs = {},
|
||||
func = function(name, param)
|
||||
local pos
|
||||
@ -55,22 +55,22 @@ minetest.register_chatcommand("area_pos1", {
|
||||
if player then
|
||||
pos = player:get_pos()
|
||||
else
|
||||
return false, "Unable to get position."
|
||||
return false, S("Unable to get position.")
|
||||
end
|
||||
else
|
||||
return false, "Invalid usage, see /help area_pos1."
|
||||
return false, S("Invalid usage, see /help @1.", "area_pos1")
|
||||
end
|
||||
pos = posLimit(vector.round(pos))
|
||||
areas:setPos1(name, pos)
|
||||
return true, "Area position 1 set to "
|
||||
..minetest.pos_to_string(pos)
|
||||
return true, S("Area position @1 set to @2", "1",
|
||||
minetest.pos_to_string(pos))
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("area_pos2", {
|
||||
params = "[X Y Z|X,Y,Z]",
|
||||
description = "Set area protection region position 2 to your"
|
||||
.." location or the one specified",
|
||||
description = S("Set area protection region position @1 to your"
|
||||
.." location or the one specified", "2"),
|
||||
func = function(name, param)
|
||||
local pos
|
||||
local found, _, x, y, z = param:find(
|
||||
@ -82,48 +82,48 @@ minetest.register_chatcommand("area_pos2", {
|
||||
if player then
|
||||
pos = player:get_pos()
|
||||
else
|
||||
return false, "Unable to get position."
|
||||
return false, S("Unable to get position.")
|
||||
end
|
||||
else
|
||||
return false, "Invalid usage, see /help area_pos2."
|
||||
return false, S("Invalid usage, see /help @1.", "area_pos2")
|
||||
end
|
||||
pos = posLimit(vector.round(pos))
|
||||
areas:setPos2(name, pos)
|
||||
return true, "Area position 2 set to "
|
||||
..minetest.pos_to_string(pos)
|
||||
return true, S("Area position @1 set to @2", "2",
|
||||
minetest.pos_to_string(pos))
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
minetest.register_chatcommand("area_pos", {
|
||||
params = "set/set1/set2/get",
|
||||
description = "Set area protection region, position 1, or position 2"
|
||||
.." by punching nodes, or display the region",
|
||||
description = S("Set area protection region, position 1, or position 2"
|
||||
.." by punching nodes, or display the region"),
|
||||
func = function(name, param)
|
||||
if param == "set" then -- Set both area positions
|
||||
areas.set_pos[name] = "pos1"
|
||||
return true, "Select positions by punching two nodes."
|
||||
return true, S("Select positions by punching two nodes.")
|
||||
elseif param == "set1" then -- Set area position 1
|
||||
areas.set_pos[name] = "pos1only"
|
||||
return true, "Select position 1 by punching a node."
|
||||
return true, S("Select position @1 by punching a node.", "1")
|
||||
elseif param == "set2" then -- Set area position 2
|
||||
areas.set_pos[name] = "pos2"
|
||||
return true, "Select position 2 by punching a node."
|
||||
return true, S("Select position @1 by punching a node.", "2")
|
||||
elseif param == "get" then -- Display current area positions
|
||||
local pos1str, pos2str = "Position 1: ", "Position 2: "
|
||||
local pos1str, pos2str = S("Position @1: ", "1"), S("Position @1: ", "2")
|
||||
if areas.pos1[name] then
|
||||
pos1str = pos1str..minetest.pos_to_string(areas.pos1[name])
|
||||
else
|
||||
pos1str = pos1str.."<not set>"
|
||||
pos1str = pos1str..S("<not set>")
|
||||
end
|
||||
if areas.pos2[name] then
|
||||
pos2str = pos2str..minetest.pos_to_string(areas.pos2[name])
|
||||
else
|
||||
pos2str = pos2str.."<not set>"
|
||||
pos2str = pos2str..S("<not set>")
|
||||
end
|
||||
return true, pos1str.."\n"..pos2str
|
||||
else
|
||||
return false, "Unknown subcommand: "..param
|
||||
return false, S("Unknown subcommand: @1", param)
|
||||
end
|
||||
end,
|
||||
})
|
||||
@ -159,22 +159,22 @@ minetest.register_on_punchnode(function(pos, node, puncher)
|
||||
areas.markPos1(name)
|
||||
areas.set_pos[name] = "pos2"
|
||||
minetest.chat_send_player(name,
|
||||
"Position 1 set to "
|
||||
..minetest.pos_to_string(pos))
|
||||
S("Position @1 set to @2", "1",
|
||||
minetest.pos_to_string(pos)))
|
||||
elseif areas.set_pos[name] == "pos1only" then
|
||||
areas.pos1[name] = pos
|
||||
areas.markPos1(name)
|
||||
areas.set_pos[name] = nil
|
||||
minetest.chat_send_player(name,
|
||||
"Position 1 set to "
|
||||
..minetest.pos_to_string(pos))
|
||||
S("Position @1 set to @2", "1",
|
||||
minetest.pos_to_string(pos)))
|
||||
elseif areas.set_pos[name] == "pos2" then
|
||||
areas.pos2[name] = pos
|
||||
areas.markPos2(name)
|
||||
areas.set_pos[name] = nil
|
||||
minetest.chat_send_player(name,
|
||||
"Position 2 set to "
|
||||
..minetest.pos_to_string(pos))
|
||||
S("Position @1 set to @2", "2",
|
||||
minetest.pos_to_string(pos)))
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
@ -108,11 +108,14 @@ minetest.register_craft( {
|
||||
recipe = {"dye:black", "dye:black", "dye:white"}
|
||||
})
|
||||
|
||||
-- only add light grey recipe if unifieddye mod isnt present (conflict)
|
||||
if not minetest.get_modpath("unifieddyes") then
|
||||
minetest.register_craft( {
|
||||
type = "shapeless",
|
||||
output = "dye:grey 3",
|
||||
recipe = {"dye:black", "dye:white", "dye:white"}
|
||||
})
|
||||
end
|
||||
|
||||
minetest.register_craft( {
|
||||
type = "shapeless",
|
||||
|
33
basic_materials/locale/basic_materials.de.tr
Normal file
@ -0,0 +1,33 @@
|
||||
# textdomain: basic_materials
|
||||
Silicon lump=Silikonklumpen
|
||||
Simple Integrated Circuit=einfacher Integrierter Schaltkreis
|
||||
Simple Motor=einfacher Motor
|
||||
Heating element=Heizelement
|
||||
Simple energy crystal=einfacher Energiekristall
|
||||
|
||||
Spool of steel wire=Spule mit Stahldraht
|
||||
Spool of copper wire=Spule mit Kupferdraht
|
||||
Spool of silver wire=Spule mit Silberdraht
|
||||
Spool of gold wire=Spule mit Golddraht
|
||||
Steel Strip=Stahlstreifen
|
||||
Copper Strip=Kupferstreifen
|
||||
Steel Bar=Stahlstab
|
||||
Chainlinks (brass)=Messing-Kettenglieder
|
||||
Chainlinks (steel)=Stahl-Kettenglieder
|
||||
Brass Ingot=Messingbarren
|
||||
Steel gear=Stahlzahnrad
|
||||
Padlock=Vorhängeschloss
|
||||
Chain (steel, hanging)=Stahlkette
|
||||
Chain (brass, hanging)=Messingkette
|
||||
Brass Block=Messingblock
|
||||
|
||||
Oil extract=raffiniertes Öl
|
||||
Unprocessed paraffin=unbearbeitetes Paraffin
|
||||
Uncooked Terracotta Base=ungebranntes Terrakotta
|
||||
Wet Cement=nasser Zement
|
||||
Cement=Zement
|
||||
Concrete Block=Betonblock
|
||||
|
||||
Plastic sheet=Kunststoffplatte
|
||||
Plastic strips=Kunststoffstreifen
|
||||
Empty wire spool=leere Drahtspule
|
@ -245,6 +245,18 @@ minetest.register_craft( {
|
||||
},
|
||||
})
|
||||
|
||||
if not minetest.get_modpath("moreores") then
|
||||
-- Without moreores, there still should be a way to create brass.
|
||||
minetest.register_craft( {
|
||||
output = "basic_materials:brass_ingot 9",
|
||||
recipe = {
|
||||
{"default:copper_ingot", "default:tin_ingot", "default:copper_ingot"},
|
||||
{"default:gold_ingot", "default:copper_ingot", "default:gold_ingot"},
|
||||
{"default:copper_ingot", "default:tin_ingot", "default:copper_ingot"},
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
minetest.register_craft( {
|
||||
type = "shapeless",
|
||||
output = "basic_materials:brass_ingot 9",
|
||||
|
@ -1,6 +1,5 @@
|
||||
default
|
||||
farming
|
||||
intllib?
|
||||
wool
|
||||
bucket
|
||||
ropes?
|
@ -1,6 +1,4 @@
|
||||
-- internationalization boilerplate
|
||||
local MP = minetest.get_modpath(minetest.get_current_modname())
|
||||
local S, NS = dofile(MP.."/intllib.lua")
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
minetest.register_alias("castle:hides", "castle_farming:hides")
|
||||
|
||||
|
418
castle_farming/i18n.py
Normal file
@ -0,0 +1,418 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Script to generate the template file and update the translation files.
|
||||
# Copy the script into the mod or modpack root folder and run it there.
|
||||
#
|
||||
# Copyright (C) 2019 Joachim Stolberg, 2020 FaceDeer, 2020 Louis Royer
|
||||
# LGPLv2.1+
|
||||
|
||||
from __future__ import print_function
|
||||
import os, fnmatch, re, shutil, errno
|
||||
from sys import argv as _argv
|
||||
|
||||
# Running params
|
||||
params = {"recursive": False,
|
||||
"help": False,
|
||||
"mods": False,
|
||||
"verbose": False,
|
||||
"folders": []
|
||||
}
|
||||
# Available CLI options
|
||||
options = {"recursive": ['--recursive', '-r'],
|
||||
"help": ['--help', '-h'],
|
||||
"mods": ['--installed-mods'],
|
||||
"verbose": ['--verbose', '-v']
|
||||
}
|
||||
|
||||
# Strings longer than this will have extra space added between
|
||||
# them in the translation files to make it easier to distinguish their
|
||||
# beginnings and endings at a glance
|
||||
doublespace_threshold = 60
|
||||
|
||||
def set_params_folders(tab: list):
|
||||
'''Initialize params["folders"] from CLI arguments.'''
|
||||
# Discarding argument 0 (tool name)
|
||||
for param in tab[1:]:
|
||||
stop_param = False
|
||||
for option in options:
|
||||
if param in options[option]:
|
||||
stop_param = True
|
||||
break
|
||||
if not stop_param:
|
||||
params["folders"].append(os.path.abspath(param))
|
||||
|
||||
def set_params(tab: list):
|
||||
'''Initialize params from CLI arguments.'''
|
||||
for option in options:
|
||||
for option_name in options[option]:
|
||||
if option_name in tab:
|
||||
params[option] = True
|
||||
break
|
||||
|
||||
def print_help(name):
|
||||
'''Prints some help message.'''
|
||||
print(f'''SYNOPSIS
|
||||
{name} [OPTIONS] [PATHS...]
|
||||
DESCRIPTION
|
||||
{', '.join(options["help"])}
|
||||
prints this help message
|
||||
{', '.join(options["recursive"])}
|
||||
run on all subfolders of paths given
|
||||
{', '.join(options["mods"])}
|
||||
run on locally installed modules
|
||||
{', '.join(options["verbose"])}
|
||||
add output information
|
||||
''')
|
||||
|
||||
|
||||
def main():
|
||||
'''Main function'''
|
||||
set_params(_argv)
|
||||
set_params_folders(_argv)
|
||||
if params["help"]:
|
||||
print_help(_argv[0])
|
||||
elif params["recursive"] and params["mods"]:
|
||||
print("Option --installed-mods is incompatible with --recursive")
|
||||
else:
|
||||
# Add recursivity message
|
||||
print("Running ", end='')
|
||||
if params["recursive"]:
|
||||
print("recursively ", end='')
|
||||
# Running
|
||||
if params["mods"]:
|
||||
print(f"on all locally installed modules in {os.path.abspath('~/.minetest/mods/')}")
|
||||
run_all_subfolders("~/.minetest/mods")
|
||||
elif len(params["folders"]) >= 2:
|
||||
print("on folder list:", params["folders"])
|
||||
for f in params["folders"]:
|
||||
if params["recursive"]:
|
||||
run_all_subfolders(f)
|
||||
else:
|
||||
update_folder(f)
|
||||
elif len(params["folders"]) == 1:
|
||||
print("on folder", params["folders"][0])
|
||||
if params["recursive"]:
|
||||
run_all_subfolders(params["folders"][0])
|
||||
else:
|
||||
update_folder(params["folders"][0])
|
||||
else:
|
||||
print("on folder", os.path.abspath("./"))
|
||||
if params["recursive"]:
|
||||
run_all_subfolders(os.path.abspath("./"))
|
||||
else:
|
||||
update_folder(os.path.abspath("./"))
|
||||
|
||||
#group 2 will be the string, groups 1 and 3 will be the delimiters (" or ')
|
||||
#See https://stackoverflow.com/questions/46967465/regex-match-text-in-either-single-or-double-quote
|
||||
pattern_lua = re.compile(r'[\.=^\t,{\(\s]N?S\(\s*(["\'])((?:\\\1|(?:(?!\1)).)*)(\1)[\s,\)]', re.DOTALL)
|
||||
pattern_lua_bracketed = re.compile(r'[\.=^\t,{\(\s]N?S\(\s*\[\[(.*?)\]\][\s,\)]', re.DOTALL)
|
||||
|
||||
# Handles "concatenation" .. " of strings"
|
||||
pattern_concat = re.compile(r'["\'][\s]*\.\.[\s]*["\']', re.DOTALL)
|
||||
|
||||
pattern_tr = re.compile(r'(.+?[^@])=(.*)')
|
||||
pattern_name = re.compile(r'^name[ ]*=[ ]*([^ \n]*)')
|
||||
pattern_tr_filename = re.compile(r'\.tr$')
|
||||
pattern_po_language_code = re.compile(r'(.*)\.po$')
|
||||
|
||||
#attempt to read the mod's name from the mod.conf file. Returns None on failure
|
||||
def get_modname(folder):
|
||||
try:
|
||||
with open(os.path.join(folder, "mod.conf"), "r", encoding='utf-8') as mod_conf:
|
||||
for line in mod_conf:
|
||||
match = pattern_name.match(line)
|
||||
if match:
|
||||
return match.group(1)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
return None
|
||||
|
||||
#If there are already .tr files in /locale, returns a list of their names
|
||||
def get_existing_tr_files(folder):
|
||||
out = []
|
||||
for root, dirs, files in os.walk(os.path.join(folder, 'locale/')):
|
||||
for name in files:
|
||||
if pattern_tr_filename.search(name):
|
||||
out.append(name)
|
||||
return out
|
||||
|
||||
# A series of search and replaces that massage a .po file's contents into
|
||||
# a .tr file's equivalent
|
||||
def process_po_file(text):
|
||||
# The first three items are for unused matches
|
||||
text = re.sub(r'#~ msgid "', "", text)
|
||||
text = re.sub(r'"\n#~ msgstr ""\n"', "=", text)
|
||||
text = re.sub(r'"\n#~ msgstr "', "=", text)
|
||||
# comment lines
|
||||
text = re.sub(r'#.*\n', "", text)
|
||||
# converting msg pairs into "=" pairs
|
||||
text = re.sub(r'msgid "', "", text)
|
||||
text = re.sub(r'"\nmsgstr ""\n"', "=", text)
|
||||
text = re.sub(r'"\nmsgstr "', "=", text)
|
||||
# various line breaks and escape codes
|
||||
text = re.sub(r'"\n"', "", text)
|
||||
text = re.sub(r'"\n', "\n", text)
|
||||
text = re.sub(r'\\"', '"', text)
|
||||
text = re.sub(r'\\n', '@n', text)
|
||||
# remove header text
|
||||
text = re.sub(r'=Project-Id-Version:.*\n', "", text)
|
||||
# remove double-spaced lines
|
||||
text = re.sub(r'\n\n', '\n', text)
|
||||
return text
|
||||
|
||||
# Go through existing .po files and, if a .tr file for that language
|
||||
# *doesn't* exist, convert it and create it.
|
||||
# The .tr file that results will subsequently be reprocessed so
|
||||
# any "no longer used" strings will be preserved.
|
||||
# Note that "fuzzy" tags will be lost in this process.
|
||||
def process_po_files(folder, modname):
|
||||
for root, dirs, files in os.walk(os.path.join(folder, 'locale/')):
|
||||
for name in files:
|
||||
code_match = pattern_po_language_code.match(name)
|
||||
if code_match == None:
|
||||
continue
|
||||
language_code = code_match.group(1)
|
||||
tr_name = modname + "." + language_code + ".tr"
|
||||
tr_file = os.path.join(root, tr_name)
|
||||
if os.path.exists(tr_file):
|
||||
if params["verbose"]:
|
||||
print(f"{tr_name} already exists, ignoring {name}")
|
||||
continue
|
||||
fname = os.path.join(root, name)
|
||||
with open(fname, "r", encoding='utf-8') as po_file:
|
||||
if params["verbose"]:
|
||||
print(f"Importing translations from {name}")
|
||||
text = process_po_file(po_file.read())
|
||||
with open(tr_file, "wt", encoding='utf-8') as tr_out:
|
||||
tr_out.write(text)
|
||||
|
||||
# from https://stackoverflow.com/questions/600268/mkdir-p-functionality-in-python/600612#600612
|
||||
# Creates a directory if it doesn't exist, silently does
|
||||
# nothing if it already exists
|
||||
def mkdir_p(path):
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except OSError as exc: # Python >2.5
|
||||
if exc.errno == errno.EEXIST and os.path.isdir(path):
|
||||
pass
|
||||
else: raise
|
||||
|
||||
# Converts the template dictionary to a text to be written as a file
|
||||
# dKeyStrings is a dictionary of localized string to source file sets
|
||||
# dOld is a dictionary of existing translations and comments from
|
||||
# the previous version of this text
|
||||
def strings_to_text(dkeyStrings, dOld, mod_name):
|
||||
lOut = [f"# textdomain: {mod_name}\n"]
|
||||
|
||||
dGroupedBySource = {}
|
||||
|
||||
for key in dkeyStrings:
|
||||
sourceList = list(dkeyStrings[key])
|
||||
sourceList.sort()
|
||||
sourceString = "\n".join(sourceList)
|
||||
listForSource = dGroupedBySource.get(sourceString, [])
|
||||
listForSource.append(key)
|
||||
dGroupedBySource[sourceString] = listForSource
|
||||
|
||||
lSourceKeys = list(dGroupedBySource.keys())
|
||||
lSourceKeys.sort()
|
||||
for source in lSourceKeys:
|
||||
localizedStrings = dGroupedBySource[source]
|
||||
localizedStrings.sort()
|
||||
lOut.append("")
|
||||
lOut.append(source)
|
||||
lOut.append("")
|
||||
for localizedString in localizedStrings:
|
||||
val = dOld.get(localizedString, {})
|
||||
translation = val.get("translation", "")
|
||||
comment = val.get("comment")
|
||||
if len(localizedString) > doublespace_threshold and not lOut[-1] == "":
|
||||
lOut.append("")
|
||||
if comment != None:
|
||||
lOut.append(comment)
|
||||
lOut.append(f"{localizedString}={translation}")
|
||||
if len(localizedString) > doublespace_threshold:
|
||||
lOut.append("")
|
||||
|
||||
|
||||
unusedExist = False
|
||||
for key in dOld:
|
||||
if key not in dkeyStrings:
|
||||
val = dOld[key]
|
||||
translation = val.get("translation")
|
||||
comment = val.get("comment")
|
||||
# only keep an unused translation if there was translated
|
||||
# text or a comment associated with it
|
||||
if translation != None and (translation != "" or comment):
|
||||
if not unusedExist:
|
||||
unusedExist = True
|
||||
lOut.append("\n\n##### not used anymore #####\n")
|
||||
if len(key) > doublespace_threshold and not lOut[-1] == "":
|
||||
lOut.append("")
|
||||
if comment != None:
|
||||
lOut.append(comment)
|
||||
lOut.append(f"{key}={translation}")
|
||||
if len(key) > doublespace_threshold:
|
||||
lOut.append("")
|
||||
return "\n".join(lOut) + '\n'
|
||||
|
||||
# Writes a template.txt file
|
||||
# dkeyStrings is the dictionary returned by generate_template
|
||||
def write_template(templ_file, dkeyStrings, mod_name):
|
||||
# read existing template file to preserve comments
|
||||
existing_template = import_tr_file(templ_file)
|
||||
|
||||
text = strings_to_text(dkeyStrings, existing_template[0], mod_name)
|
||||
mkdir_p(os.path.dirname(templ_file))
|
||||
with open(templ_file, "wt", encoding='utf-8') as template_file:
|
||||
template_file.write(text)
|
||||
|
||||
|
||||
# Gets all translatable strings from a lua file
|
||||
def read_lua_file_strings(lua_file):
|
||||
lOut = []
|
||||
with open(lua_file, encoding='utf-8') as text_file:
|
||||
text = text_file.read()
|
||||
#TODO remove comments here
|
||||
|
||||
text = re.sub(pattern_concat, "", text)
|
||||
|
||||
strings = []
|
||||
for s in pattern_lua.findall(text):
|
||||
strings.append(s[1])
|
||||
for s in pattern_lua_bracketed.findall(text):
|
||||
strings.append(s)
|
||||
|
||||
for s in strings:
|
||||
s = re.sub(r'"\.\.\s+"', "", s)
|
||||
s = re.sub("@[^@=0-9]", "@@", s)
|
||||
s = s.replace('\\"', '"')
|
||||
s = s.replace("\\'", "'")
|
||||
s = s.replace("\n", "@n")
|
||||
s = s.replace("\\n", "@n")
|
||||
s = s.replace("=", "@=")
|
||||
lOut.append(s)
|
||||
return lOut
|
||||
|
||||
# Gets strings from an existing translation file
|
||||
# returns both a dictionary of translations
|
||||
# and the full original source text so that the new text
|
||||
# can be compared to it for changes.
|
||||
def import_tr_file(tr_file):
|
||||
dOut = {}
|
||||
text = None
|
||||
if os.path.exists(tr_file):
|
||||
with open(tr_file, "r", encoding='utf-8') as existing_file :
|
||||
# save the full text to allow for comparison
|
||||
# of the old version with the new output
|
||||
text = existing_file.read()
|
||||
existing_file.seek(0)
|
||||
# a running record of the current comment block
|
||||
# we're inside, to allow preceeding multi-line comments
|
||||
# to be retained for a translation line
|
||||
latest_comment_block = None
|
||||
for line in existing_file.readlines():
|
||||
line = line.rstrip('\n')
|
||||
if line[:3] == "###":
|
||||
# Reset comment block if we hit a header
|
||||
latest_comment_block = None
|
||||
continue
|
||||
if line[:1] == "#":
|
||||
# Save the comment we're inside
|
||||
if not latest_comment_block:
|
||||
latest_comment_block = line
|
||||
else:
|
||||
latest_comment_block = latest_comment_block + "\n" + line
|
||||
continue
|
||||
match = pattern_tr.match(line)
|
||||
if match:
|
||||
# this line is a translated line
|
||||
outval = {}
|
||||
outval["translation"] = match.group(2)
|
||||
if latest_comment_block:
|
||||
# if there was a comment, record that.
|
||||
outval["comment"] = latest_comment_block
|
||||
latest_comment_block = None
|
||||
dOut[match.group(1)] = outval
|
||||
return (dOut, text)
|
||||
|
||||
# Walks all lua files in the mod folder, collects translatable strings,
|
||||
# and writes it to a template.txt file
|
||||
# Returns a dictionary of localized strings to source file sets
|
||||
# that can be used with the strings_to_text function.
|
||||
def generate_template(folder, mod_name):
|
||||
dOut = {}
|
||||
for root, dirs, files in os.walk(folder):
|
||||
for name in files:
|
||||
if fnmatch.fnmatch(name, "*.lua"):
|
||||
fname = os.path.join(root, name)
|
||||
found = read_lua_file_strings(fname)
|
||||
if params["verbose"]:
|
||||
print(f"{fname}: {str(len(found))} translatable strings")
|
||||
|
||||
for s in found:
|
||||
sources = dOut.get(s, set())
|
||||
sources.add(f"### {os.path.basename(fname)} ###")
|
||||
dOut[s] = sources
|
||||
|
||||
if len(dOut) == 0:
|
||||
return None
|
||||
templ_file = os.path.join(folder, "locale/template.txt")
|
||||
write_template(templ_file, dOut, mod_name)
|
||||
return dOut
|
||||
|
||||
# Updates an existing .tr file, copying the old one to a ".old" file
|
||||
# if any changes have happened
|
||||
# dNew is the data used to generate the template, it has all the
|
||||
# currently-existing localized strings
|
||||
def update_tr_file(dNew, mod_name, tr_file):
|
||||
if params["verbose"]:
|
||||
print(f"updating {tr_file}")
|
||||
|
||||
tr_import = import_tr_file(tr_file)
|
||||
dOld = tr_import[0]
|
||||
textOld = tr_import[1]
|
||||
|
||||
textNew = strings_to_text(dNew, dOld, mod_name)
|
||||
|
||||
if textOld and textOld != textNew:
|
||||
print(f"{tr_file} has changed.")
|
||||
shutil.copyfile(tr_file, f"{tr_file}.old")
|
||||
|
||||
with open(tr_file, "w", encoding='utf-8') as new_tr_file:
|
||||
new_tr_file.write(textNew)
|
||||
|
||||
# Updates translation files for the mod in the given folder
|
||||
def update_mod(folder):
|
||||
modname = get_modname(folder)
|
||||
if modname is not None:
|
||||
process_po_files(folder, modname)
|
||||
print(f"Updating translations for {modname}")
|
||||
data = generate_template(folder, modname)
|
||||
if data == None:
|
||||
print(f"No translatable strings found in {modname}")
|
||||
else:
|
||||
for tr_file in get_existing_tr_files(folder):
|
||||
update_tr_file(data, modname, os.path.join(folder, "locale/", tr_file))
|
||||
else:
|
||||
print("Unable to find modname in folder " + folder)
|
||||
|
||||
# Determines if the folder being pointed to is a mod or a mod pack
|
||||
# and then runs update_mod accordingly
|
||||
def update_folder(folder):
|
||||
is_modpack = os.path.exists(os.path.join(folder, "modpack.txt")) or os.path.exists(os.path.join(folder, "modpack.conf"))
|
||||
if is_modpack:
|
||||
subfolders = [f.path for f in os.scandir(folder) if f.is_dir()]
|
||||
for subfolder in subfolders:
|
||||
update_mod(subfolder + "/")
|
||||
else:
|
||||
update_mod(folder)
|
||||
print("Done.")
|
||||
|
||||
def run_all_subfolders(folder):
|
||||
for modfolder in [f.path for f in os.scandir(folder) if f.is_dir()]:
|
||||
update_folder(modfolder + "/")
|
||||
|
||||
|
||||
main()
|
@ -1,45 +0,0 @@
|
||||
|
||||
-- Fallback functions for when `intllib` is not installed.
|
||||
-- Code released under Unlicense <http://unlicense.org>.
|
||||
|
||||
-- Get the latest version of this file at:
|
||||
-- https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua
|
||||
|
||||
local function format(str, ...)
|
||||
local args = { ... }
|
||||
local function repl(escape, open, num, close)
|
||||
if escape == "" then
|
||||
local replacement = tostring(args[tonumber(num)])
|
||||
if open == "" then
|
||||
replacement = replacement..close
|
||||
end
|
||||
return replacement
|
||||
else
|
||||
return "@"..open..num..close
|
||||
end
|
||||
end
|
||||
return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl))
|
||||
end
|
||||
|
||||
local gettext, ngettext
|
||||
if minetest.get_modpath("intllib") then
|
||||
if intllib.make_gettext_pair then
|
||||
-- New method using gettext.
|
||||
gettext, ngettext = intllib.make_gettext_pair()
|
||||
else
|
||||
-- Old method using text files.
|
||||
gettext = intllib.Getter()
|
||||
end
|
||||
end
|
||||
|
||||
-- Fill in missing functions.
|
||||
|
||||
gettext = gettext or function(msgid, ...)
|
||||
return format(msgid, ...)
|
||||
end
|
||||
|
||||
ngettext = ngettext or function(msgid, msgid_plural, n, ...)
|
||||
return format(n==1 and msgid or msgid_plural, ...)
|
||||
end
|
||||
|
||||
return gettext, ngettext
|
11
castle_farming/locale/castle_farming.es.tr
Normal file
@ -0,0 +1,11 @@
|
||||
# textdomain: castle_farming
|
||||
|
||||
|
||||
### hides.lua ###
|
||||
|
||||
Hides=Escondite
|
||||
|
||||
### straw.lua ###
|
||||
|
||||
Bound Straw=Paja amarrada
|
||||
Training Dummy=Maniqui de Entrenamiento
|
11
castle_farming/locale/castle_farming.pt_br.tr
Normal file
@ -0,0 +1,11 @@
|
||||
# textdomain: castle_farming
|
||||
|
||||
|
||||
### hides.lua ###
|
||||
|
||||
Hides=Esconde-se
|
||||
|
||||
### straw.lua ###
|
||||
|
||||
Bound Straw=Palha Amarrada
|
||||
Training Dummy=Vaca Parada de Madeira (para Laço)
|
@ -1,30 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-02-27 00:59-0700\n"
|
||||
"PO-Revision-Date: 2017-04-21 19:47-0500\n"
|
||||
"Last-Translator: Carlos Barraza <carlosbarrazaes@gmail.com>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: Español\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: hides.lua:9
|
||||
msgid "Hides"
|
||||
msgstr "Escondite"
|
||||
|
||||
#: straw.lua:13
|
||||
msgid "Bound Straw"
|
||||
msgstr "Paja amarrada"
|
||||
|
||||
#: straw.lua:22
|
||||
msgid "Training Dummy"
|
||||
msgstr "Maniqui de Entrenamiento"
|
@ -1,30 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) 2017
|
||||
# This file is distributed under the same license as the castle_farming package.
|
||||
# Caio Roberto <caiorrs@gmail.com>, 2017.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-02-27 00:59-0700\n"
|
||||
"PO-Revision-Date: 2017-06-29 13:00-0330\n"
|
||||
"Last-Translator: Caio Roberto <caiorrs@gmail.com>\n"
|
||||
"Language-Team: Paulo Slomp FACED UFRGS <00009228@ufrgs.br>\n"
|
||||
"Language: Brazilian Portuguese\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: hides.lua:9
|
||||
msgid "Hides"
|
||||
msgstr "Esconde-se"
|
||||
|
||||
#: straw.lua:13
|
||||
msgid "Bound Straw"
|
||||
msgstr "Palha Amarrada"
|
||||
|
||||
#: straw.lua:22
|
||||
msgid "Training Dummy"
|
||||
msgstr "Vaca Parada de Madeira (para Laço)"
|
@ -1,30 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-02-27 00:59-0700\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: hides.lua:9
|
||||
msgid "Hides"
|
||||
msgstr ""
|
||||
|
||||
#: straw.lua:13
|
||||
msgid "Bound Straw"
|
||||
msgstr ""
|
||||
|
||||
#: straw.lua:22
|
||||
msgid "Training Dummy"
|
||||
msgstr ""
|
11
castle_farming/locale/template.txt
Normal file
@ -0,0 +1,11 @@
|
||||
# textdomain: castle_farming
|
||||
|
||||
|
||||
### hides.lua ###
|
||||
|
||||
Hides=
|
||||
|
||||
### straw.lua ###
|
||||
|
||||
Bound Straw=
|
||||
Training Dummy=
|
@ -1 +1,4 @@
|
||||
name = castle_farming
|
||||
depends = default, farming, wool, bucket
|
||||
optional_depends = ropes
|
||||
description = Contains farming products useful for decorating a castle
|
@ -5,9 +5,7 @@ minetest.register_alias_force("cottages:straw_bale", "castle_farming:bound_straw
|
||||
minetest.register_alias_force("darkage:straw_bale", "castle_farming:bound_straw")
|
||||
minetest.register_alias_force("castle:bound_straw", "castle_farming:bound_straw")
|
||||
|
||||
-- internationalization boilerplate
|
||||
local MP = minetest.get_modpath(minetest.get_current_modname())
|
||||
local S, NS = dofile(MP.."/intllib.lua")
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
minetest.register_node("castle_farming:bound_straw", {
|
||||
description = S("Bound Straw"),
|
||||
|
Before Width: | Height: | Size: 618 B After Width: | Height: | Size: 614 B |
Before Width: | Height: | Size: 756 B After Width: | Height: | Size: 732 B |
Before Width: | Height: | Size: 803 B After Width: | Height: | Size: 798 B |
@ -1,8 +1,6 @@
|
||||
if not minetest.get_modpath("fire") then return end
|
||||
|
||||
-- internationalization boilerplate
|
||||
local MP = minetest.get_modpath(minetest.get_current_modname())
|
||||
local S, NS = dofile(MP.."/intllib.lua")
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
local brasier_longdesc = S("A brasier for producing copious amounts of light and heat.")
|
||||
local brasier_usagehelp = S("To ignite the brasier place a flammable fuel in its inventory slot. A lump of coal will burn for about half an hour.")
|
||||
|
@ -1,5 +1,4 @@
|
||||
default
|
||||
intllib?
|
||||
fire?
|
||||
castle_masonry?
|
||||
hopper?
|
||||
|
418
castle_lighting/i18n.py
Normal file
@ -0,0 +1,418 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Script to generate the template file and update the translation files.
|
||||
# Copy the script into the mod or modpack root folder and run it there.
|
||||
#
|
||||
# Copyright (C) 2019 Joachim Stolberg, 2020 FaceDeer, 2020 Louis Royer
|
||||
# LGPLv2.1+
|
||||
|
||||
from __future__ import print_function
|
||||
import os, fnmatch, re, shutil, errno
|
||||
from sys import argv as _argv
|
||||
|
||||
# Running params
|
||||
params = {"recursive": False,
|
||||
"help": False,
|
||||
"mods": False,
|
||||
"verbose": False,
|
||||
"folders": []
|
||||
}
|
||||
# Available CLI options
|
||||
options = {"recursive": ['--recursive', '-r'],
|
||||
"help": ['--help', '-h'],
|
||||
"mods": ['--installed-mods'],
|
||||
"verbose": ['--verbose', '-v']
|
||||
}
|
||||
|
||||
# Strings longer than this will have extra space added between
|
||||
# them in the translation files to make it easier to distinguish their
|
||||
# beginnings and endings at a glance
|
||||
doublespace_threshold = 60
|
||||
|
||||
def set_params_folders(tab: list):
|
||||
'''Initialize params["folders"] from CLI arguments.'''
|
||||
# Discarding argument 0 (tool name)
|
||||
for param in tab[1:]:
|
||||
stop_param = False
|
||||
for option in options:
|
||||
if param in options[option]:
|
||||
stop_param = True
|
||||
break
|
||||
if not stop_param:
|
||||
params["folders"].append(os.path.abspath(param))
|
||||
|
||||
def set_params(tab: list):
|
||||
'''Initialize params from CLI arguments.'''
|
||||
for option in options:
|
||||
for option_name in options[option]:
|
||||
if option_name in tab:
|
||||
params[option] = True
|
||||
break
|
||||
|
||||
def print_help(name):
|
||||
'''Prints some help message.'''
|
||||
print(f'''SYNOPSIS
|
||||
{name} [OPTIONS] [PATHS...]
|
||||
DESCRIPTION
|
||||
{', '.join(options["help"])}
|
||||
prints this help message
|
||||
{', '.join(options["recursive"])}
|
||||
run on all subfolders of paths given
|
||||
{', '.join(options["mods"])}
|
||||
run on locally installed modules
|
||||
{', '.join(options["verbose"])}
|
||||
add output information
|
||||
''')
|
||||
|
||||
|
||||
def main():
|
||||
'''Main function'''
|
||||
set_params(_argv)
|
||||
set_params_folders(_argv)
|
||||
if params["help"]:
|
||||
print_help(_argv[0])
|
||||
elif params["recursive"] and params["mods"]:
|
||||
print("Option --installed-mods is incompatible with --recursive")
|
||||
else:
|
||||
# Add recursivity message
|
||||
print("Running ", end='')
|
||||
if params["recursive"]:
|
||||
print("recursively ", end='')
|
||||
# Running
|
||||
if params["mods"]:
|
||||
print(f"on all locally installed modules in {os.path.abspath('~/.minetest/mods/')}")
|
||||
run_all_subfolders("~/.minetest/mods")
|
||||
elif len(params["folders"]) >= 2:
|
||||
print("on folder list:", params["folders"])
|
||||
for f in params["folders"]:
|
||||
if params["recursive"]:
|
||||
run_all_subfolders(f)
|
||||
else:
|
||||
update_folder(f)
|
||||
elif len(params["folders"]) == 1:
|
||||
print("on folder", params["folders"][0])
|
||||
if params["recursive"]:
|
||||
run_all_subfolders(params["folders"][0])
|
||||
else:
|
||||
update_folder(params["folders"][0])
|
||||
else:
|
||||
print("on folder", os.path.abspath("./"))
|
||||
if params["recursive"]:
|
||||
run_all_subfolders(os.path.abspath("./"))
|
||||
else:
|
||||
update_folder(os.path.abspath("./"))
|
||||
|
||||
#group 2 will be the string, groups 1 and 3 will be the delimiters (" or ')
|
||||
#See https://stackoverflow.com/questions/46967465/regex-match-text-in-either-single-or-double-quote
|
||||
pattern_lua = re.compile(r'[\.=^\t,{\(\s]N?S\(\s*(["\'])((?:\\\1|(?:(?!\1)).)*)(\1)[\s,\)]', re.DOTALL)
|
||||
pattern_lua_bracketed = re.compile(r'[\.=^\t,{\(\s]N?S\(\s*\[\[(.*?)\]\][\s,\)]', re.DOTALL)
|
||||
|
||||
# Handles "concatenation" .. " of strings"
|
||||
pattern_concat = re.compile(r'["\'][\s]*\.\.[\s]*["\']', re.DOTALL)
|
||||
|
||||
pattern_tr = re.compile(r'(.+?[^@])=(.*)')
|
||||
pattern_name = re.compile(r'^name[ ]*=[ ]*([^ \n]*)')
|
||||
pattern_tr_filename = re.compile(r'\.tr$')
|
||||
pattern_po_language_code = re.compile(r'(.*)\.po$')
|
||||
|
||||
#attempt to read the mod's name from the mod.conf file. Returns None on failure
|
||||
def get_modname(folder):
|
||||
try:
|
||||
with open(os.path.join(folder, "mod.conf"), "r", encoding='utf-8') as mod_conf:
|
||||
for line in mod_conf:
|
||||
match = pattern_name.match(line)
|
||||
if match:
|
||||
return match.group(1)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
return None
|
||||
|
||||
#If there are already .tr files in /locale, returns a list of their names
|
||||
def get_existing_tr_files(folder):
|
||||
out = []
|
||||
for root, dirs, files in os.walk(os.path.join(folder, 'locale/')):
|
||||
for name in files:
|
||||
if pattern_tr_filename.search(name):
|
||||
out.append(name)
|
||||
return out
|
||||
|
||||
# A series of search and replaces that massage a .po file's contents into
|
||||
# a .tr file's equivalent
|
||||
def process_po_file(text):
|
||||
# The first three items are for unused matches
|
||||
text = re.sub(r'#~ msgid "', "", text)
|
||||
text = re.sub(r'"\n#~ msgstr ""\n"', "=", text)
|
||||
text = re.sub(r'"\n#~ msgstr "', "=", text)
|
||||
# comment lines
|
||||
text = re.sub(r'#.*\n', "", text)
|
||||
# converting msg pairs into "=" pairs
|
||||
text = re.sub(r'msgid "', "", text)
|
||||
text = re.sub(r'"\nmsgstr ""\n"', "=", text)
|
||||
text = re.sub(r'"\nmsgstr "', "=", text)
|
||||
# various line breaks and escape codes
|
||||
text = re.sub(r'"\n"', "", text)
|
||||
text = re.sub(r'"\n', "\n", text)
|
||||
text = re.sub(r'\\"', '"', text)
|
||||
text = re.sub(r'\\n', '@n', text)
|
||||
# remove header text
|
||||
text = re.sub(r'=Project-Id-Version:.*\n', "", text)
|
||||
# remove double-spaced lines
|
||||
text = re.sub(r'\n\n', '\n', text)
|
||||
return text
|
||||
|
||||
# Go through existing .po files and, if a .tr file for that language
|
||||
# *doesn't* exist, convert it and create it.
|
||||
# The .tr file that results will subsequently be reprocessed so
|
||||
# any "no longer used" strings will be preserved.
|
||||
# Note that "fuzzy" tags will be lost in this process.
|
||||
def process_po_files(folder, modname):
|
||||
for root, dirs, files in os.walk(os.path.join(folder, 'locale/')):
|
||||
for name in files:
|
||||
code_match = pattern_po_language_code.match(name)
|
||||
if code_match == None:
|
||||
continue
|
||||
language_code = code_match.group(1)
|
||||
tr_name = modname + "." + language_code + ".tr"
|
||||
tr_file = os.path.join(root, tr_name)
|
||||
if os.path.exists(tr_file):
|
||||
if params["verbose"]:
|
||||
print(f"{tr_name} already exists, ignoring {name}")
|
||||
continue
|
||||
fname = os.path.join(root, name)
|
||||
with open(fname, "r", encoding='utf-8') as po_file:
|
||||
if params["verbose"]:
|
||||
print(f"Importing translations from {name}")
|
||||
text = process_po_file(po_file.read())
|
||||
with open(tr_file, "wt", encoding='utf-8') as tr_out:
|
||||
tr_out.write(text)
|
||||
|
||||
# from https://stackoverflow.com/questions/600268/mkdir-p-functionality-in-python/600612#600612
|
||||
# Creates a directory if it doesn't exist, silently does
|
||||
# nothing if it already exists
|
||||
def mkdir_p(path):
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except OSError as exc: # Python >2.5
|
||||
if exc.errno == errno.EEXIST and os.path.isdir(path):
|
||||
pass
|
||||
else: raise
|
||||
|
||||
# Converts the template dictionary to a text to be written as a file
|
||||
# dKeyStrings is a dictionary of localized string to source file sets
|
||||
# dOld is a dictionary of existing translations and comments from
|
||||
# the previous version of this text
|
||||
def strings_to_text(dkeyStrings, dOld, mod_name):
|
||||
lOut = [f"# textdomain: {mod_name}\n"]
|
||||
|
||||
dGroupedBySource = {}
|
||||
|
||||
for key in dkeyStrings:
|
||||
sourceList = list(dkeyStrings[key])
|
||||
sourceList.sort()
|
||||
sourceString = "\n".join(sourceList)
|
||||
listForSource = dGroupedBySource.get(sourceString, [])
|
||||
listForSource.append(key)
|
||||
dGroupedBySource[sourceString] = listForSource
|
||||
|
||||
lSourceKeys = list(dGroupedBySource.keys())
|
||||
lSourceKeys.sort()
|
||||
for source in lSourceKeys:
|
||||
localizedStrings = dGroupedBySource[source]
|
||||
localizedStrings.sort()
|
||||
lOut.append("")
|
||||
lOut.append(source)
|
||||
lOut.append("")
|
||||
for localizedString in localizedStrings:
|
||||
val = dOld.get(localizedString, {})
|
||||
translation = val.get("translation", "")
|
||||
comment = val.get("comment")
|
||||
if len(localizedString) > doublespace_threshold and not lOut[-1] == "":
|
||||
lOut.append("")
|
||||
if comment != None:
|
||||
lOut.append(comment)
|
||||
lOut.append(f"{localizedString}={translation}")
|
||||
if len(localizedString) > doublespace_threshold:
|
||||
lOut.append("")
|
||||
|
||||
|
||||
unusedExist = False
|
||||
for key in dOld:
|
||||
if key not in dkeyStrings:
|
||||
val = dOld[key]
|
||||
translation = val.get("translation")
|
||||
comment = val.get("comment")
|
||||
# only keep an unused translation if there was translated
|
||||
# text or a comment associated with it
|
||||
if translation != None and (translation != "" or comment):
|
||||
if not unusedExist:
|
||||
unusedExist = True
|
||||
lOut.append("\n\n##### not used anymore #####\n")
|
||||
if len(key) > doublespace_threshold and not lOut[-1] == "":
|
||||
lOut.append("")
|
||||
if comment != None:
|
||||
lOut.append(comment)
|
||||
lOut.append(f"{key}={translation}")
|
||||
if len(key) > doublespace_threshold:
|
||||
lOut.append("")
|
||||
return "\n".join(lOut) + '\n'
|
||||
|
||||
# Writes a template.txt file
|
||||
# dkeyStrings is the dictionary returned by generate_template
|
||||
def write_template(templ_file, dkeyStrings, mod_name):
|
||||
# read existing template file to preserve comments
|
||||
existing_template = import_tr_file(templ_file)
|
||||
|
||||
text = strings_to_text(dkeyStrings, existing_template[0], mod_name)
|
||||
mkdir_p(os.path.dirname(templ_file))
|
||||
with open(templ_file, "wt", encoding='utf-8') as template_file:
|
||||
template_file.write(text)
|
||||
|
||||
|
||||
# Gets all translatable strings from a lua file
|
||||
def read_lua_file_strings(lua_file):
|
||||
lOut = []
|
||||
with open(lua_file, encoding='utf-8') as text_file:
|
||||
text = text_file.read()
|
||||
#TODO remove comments here
|
||||
|
||||
text = re.sub(pattern_concat, "", text)
|
||||
|
||||
strings = []
|
||||
for s in pattern_lua.findall(text):
|
||||
strings.append(s[1])
|
||||
for s in pattern_lua_bracketed.findall(text):
|
||||
strings.append(s)
|
||||
|
||||
for s in strings:
|
||||
s = re.sub(r'"\.\.\s+"', "", s)
|
||||
s = re.sub("@[^@=0-9]", "@@", s)
|
||||
s = s.replace('\\"', '"')
|
||||
s = s.replace("\\'", "'")
|
||||
s = s.replace("\n", "@n")
|
||||
s = s.replace("\\n", "@n")
|
||||
s = s.replace("=", "@=")
|
||||
lOut.append(s)
|
||||
return lOut
|
||||
|
||||
# Gets strings from an existing translation file
|
||||
# returns both a dictionary of translations
|
||||
# and the full original source text so that the new text
|
||||
# can be compared to it for changes.
|
||||
def import_tr_file(tr_file):
|
||||
dOut = {}
|
||||
text = None
|
||||
if os.path.exists(tr_file):
|
||||
with open(tr_file, "r", encoding='utf-8') as existing_file :
|
||||
# save the full text to allow for comparison
|
||||
# of the old version with the new output
|
||||
text = existing_file.read()
|
||||
existing_file.seek(0)
|
||||
# a running record of the current comment block
|
||||
# we're inside, to allow preceeding multi-line comments
|
||||
# to be retained for a translation line
|
||||
latest_comment_block = None
|
||||
for line in existing_file.readlines():
|
||||
line = line.rstrip('\n')
|
||||
if line[:3] == "###":
|
||||
# Reset comment block if we hit a header
|
||||
latest_comment_block = None
|
||||
continue
|
||||
if line[:1] == "#":
|
||||
# Save the comment we're inside
|
||||
if not latest_comment_block:
|
||||
latest_comment_block = line
|
||||
else:
|
||||
latest_comment_block = latest_comment_block + "\n" + line
|
||||
continue
|
||||
match = pattern_tr.match(line)
|
||||
if match:
|
||||
# this line is a translated line
|
||||
outval = {}
|
||||
outval["translation"] = match.group(2)
|
||||
if latest_comment_block:
|
||||
# if there was a comment, record that.
|
||||
outval["comment"] = latest_comment_block
|
||||
latest_comment_block = None
|
||||
dOut[match.group(1)] = outval
|
||||
return (dOut, text)
|
||||
|
||||
# Walks all lua files in the mod folder, collects translatable strings,
|
||||
# and writes it to a template.txt file
|
||||
# Returns a dictionary of localized strings to source file sets
|
||||
# that can be used with the strings_to_text function.
|
||||
def generate_template(folder, mod_name):
|
||||
dOut = {}
|
||||
for root, dirs, files in os.walk(folder):
|
||||
for name in files:
|
||||
if fnmatch.fnmatch(name, "*.lua"):
|
||||
fname = os.path.join(root, name)
|
||||
found = read_lua_file_strings(fname)
|
||||
if params["verbose"]:
|
||||
print(f"{fname}: {str(len(found))} translatable strings")
|
||||
|
||||
for s in found:
|
||||
sources = dOut.get(s, set())
|
||||
sources.add(f"### {os.path.basename(fname)} ###")
|
||||
dOut[s] = sources
|
||||
|
||||
if len(dOut) == 0:
|
||||
return None
|
||||
templ_file = os.path.join(folder, "locale/template.txt")
|
||||
write_template(templ_file, dOut, mod_name)
|
||||
return dOut
|
||||
|
||||
# Updates an existing .tr file, copying the old one to a ".old" file
|
||||
# if any changes have happened
|
||||
# dNew is the data used to generate the template, it has all the
|
||||
# currently-existing localized strings
|
||||
def update_tr_file(dNew, mod_name, tr_file):
|
||||
if params["verbose"]:
|
||||
print(f"updating {tr_file}")
|
||||
|
||||
tr_import = import_tr_file(tr_file)
|
||||
dOld = tr_import[0]
|
||||
textOld = tr_import[1]
|
||||
|
||||
textNew = strings_to_text(dNew, dOld, mod_name)
|
||||
|
||||
if textOld and textOld != textNew:
|
||||
print(f"{tr_file} has changed.")
|
||||
shutil.copyfile(tr_file, f"{tr_file}.old")
|
||||
|
||||
with open(tr_file, "w", encoding='utf-8') as new_tr_file:
|
||||
new_tr_file.write(textNew)
|
||||
|
||||
# Updates translation files for the mod in the given folder
|
||||
def update_mod(folder):
|
||||
modname = get_modname(folder)
|
||||
if modname is not None:
|
||||
process_po_files(folder, modname)
|
||||
print(f"Updating translations for {modname}")
|
||||
data = generate_template(folder, modname)
|
||||
if data == None:
|
||||
print(f"No translatable strings found in {modname}")
|
||||
else:
|
||||
for tr_file in get_existing_tr_files(folder):
|
||||
update_tr_file(data, modname, os.path.join(folder, "locale/", tr_file))
|
||||
else:
|
||||
print("Unable to find modname in folder " + folder)
|
||||
|
||||
# Determines if the folder being pointed to is a mod or a mod pack
|
||||
# and then runs update_mod accordingly
|
||||
def update_folder(folder):
|
||||
is_modpack = os.path.exists(os.path.join(folder, "modpack.txt")) or os.path.exists(os.path.join(folder, "modpack.conf"))
|
||||
if is_modpack:
|
||||
subfolders = [f.path for f in os.scandir(folder) if f.is_dir()]
|
||||
for subfolder in subfolders:
|
||||
update_mod(subfolder + "/")
|
||||
else:
|
||||
update_mod(folder)
|
||||
print("Done.")
|
||||
|
||||
def run_all_subfolders(folder):
|
||||
for modfolder in [f.path for f in os.scandir(folder) if f.is_dir()]:
|
||||
update_folder(modfolder + "/")
|
||||
|
||||
|
||||
main()
|
@ -4,9 +4,8 @@ minetest.register_alias("castle:light", "castle_lighting:light")
|
||||
minetest.register_alias("castle:chandelier", "castle_lighting:chandelier")
|
||||
minetest.register_alias("castle:chandelier_chain", "castle_lighting:chandelier_chain")
|
||||
|
||||
-- internationalization boilerplate
|
||||
local MP = minetest.get_modpath(minetest.get_current_modname())
|
||||
local S, NS = dofile(MP.."/intllib.lua")
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
castle_lighting = {}
|
||||
|
||||
|
@ -1,45 +0,0 @@
|
||||
|
||||
-- Fallback functions for when `intllib` is not installed.
|
||||
-- Code released under Unlicense <http://unlicense.org>.
|
||||
|
||||
-- Get the latest version of this file at:
|
||||
-- https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua
|
||||
|
||||
local function format(str, ...)
|
||||
local args = { ... }
|
||||
local function repl(escape, open, num, close)
|
||||
if escape == "" then
|
||||
local replacement = tostring(args[tonumber(num)])
|
||||
if open == "" then
|
||||
replacement = replacement..close
|
||||
end
|
||||
return replacement
|
||||
else
|
||||
return "@"..open..num..close
|
||||
end
|
||||
end
|
||||
return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl))
|
||||
end
|
||||
|
||||
local gettext, ngettext
|
||||
if minetest.get_modpath("intllib") then
|
||||
if intllib.make_gettext_pair then
|
||||
-- New method using gettext.
|
||||
gettext, ngettext = intllib.make_gettext_pair()
|
||||
else
|
||||
-- Old method using text files.
|
||||
gettext = intllib.Getter()
|
||||
end
|
||||
end
|
||||
|
||||
-- Fill in missing functions.
|
||||
|
||||
gettext = gettext or function(msgid, ...)
|
||||
return format(msgid, ...)
|
||||
end
|
||||
|
||||
ngettext = ngettext or function(msgid, msgid_plural, n, ...)
|
||||
return format(n==1 and msgid or msgid_plural, ...)
|
||||
end
|
||||
|
||||
return gettext, ngettext
|
18
castle_lighting/locale/castle_lighting.es.tr
Normal file
@ -0,0 +1,18 @@
|
||||
# textdomain: castle_lighting
|
||||
|
||||
|
||||
### brasier.lua ###
|
||||
|
||||
@1 Brasier=Brasero de @1
|
||||
A brasier for producing copious amounts of light and heat.=Un brasero para producir grandes cantidades de luz y calor.
|
||||
Floor Brasier=Brasero con Patas
|
||||
Stonebrick=Ladrillo de piedra
|
||||
|
||||
To ignite the brasier place a flammable fuel in its inventory slot. A lump of coal will burn for about half an hour.=Para encender el brasero coloque un combustible inflamable en su ranura de inventario. Un trozo de carbón arderá durante media hora.
|
||||
|
||||
|
||||
### init.lua ###
|
||||
|
||||
Chandelier=Candelero
|
||||
Chandelier Chain=Colgante de Candelero
|
||||
Light Block=Bloque de luz
|
18
castle_lighting/locale/castle_lighting.it.tr
Normal file
@ -0,0 +1,18 @@
|
||||
# textdomain: castle_lighting
|
||||
|
||||
|
||||
### brasier.lua ###
|
||||
|
||||
@1 Brasier=Braciere di @1
|
||||
A brasier for producing copious amounts of light and heat.=Un braciere per produrre grandi quantità di luce e calore.
|
||||
Floor Brasier=Braciere da pavimento
|
||||
Stonebrick=Mattoni di pietra
|
||||
|
||||
To ignite the brasier place a flammable fuel in its inventory slot. A lump of coal will burn for about half an hour.=Per accendere il braciere mettete del combustibile nella sua casella di inventario. Un grumo di carbone brucerà per circa mezz'ora.
|
||||
|
||||
|
||||
### init.lua ###
|
||||
|
||||
Chandelier=Candeliere
|
||||
Chandelier Chain=Catena per candeliere
|
||||
Light Block=Lampada
|
@ -1,54 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-03-01 23:52-0700\n"
|
||||
"PO-Revision-Date: 2017-04-28 12:40-0400\n"
|
||||
"Last-Translator: Carlos Barraza\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: Español\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: brasier.lua:7
|
||||
msgid "A brasier for producing copious amounts of light and heat."
|
||||
msgstr "Un brasero para producir grandes cantidades de luz y calor."
|
||||
|
||||
#: brasier.lua:8
|
||||
msgid ""
|
||||
"To ignite the brasier place a flammable fuel in its inventory slot. A lump "
|
||||
"of coal will burn for about half an hour."
|
||||
msgstr ""
|
||||
"Para encender el brasero coloque un combustible inflamable en su ranura de "
|
||||
"inventario. Un trozo de carbón arderá durante media hora."
|
||||
|
||||
#: brasier.lua:107
|
||||
msgid "Floor Brasier"
|
||||
msgstr "Brasero con Patas"
|
||||
|
||||
#: brasier.lua:156
|
||||
msgid "Stonebrick"
|
||||
msgstr "Ladrillo de piedra"
|
||||
|
||||
#: brasier.lua:228
|
||||
msgid "@1 Brasier"
|
||||
msgstr "Brasero de @1"
|
||||
|
||||
#: init.lua:17
|
||||
msgid "Light Block"
|
||||
msgstr "Bloque de luz"
|
||||
|
||||
#: init.lua:37
|
||||
msgid "Chandelier"
|
||||
msgstr "Candelero"
|
||||
|
||||
#: init.lua:76
|
||||
msgid "Chandelier Chain"
|
||||
msgstr "Colgante de Candelero"
|
@ -1,55 +0,0 @@
|
||||
# ITALIAN LOCALE FILE FOR THE CASTLE LIGHTING MODULE
|
||||
# Copyright (C) 2017 Philipbenr And DanDuncombe
|
||||
# This file is distributed under the same license as the CASTLE LIGHTING package.
|
||||
# Hamlet <h4mlet@riseup.net>, 2017.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Castle Lighting\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-03-01 23:52-0700\n"
|
||||
"PO-Revision-Date: 2017-09-10 22:00+0100\n"
|
||||
"Last-Translator: H4mlet <h4mlet@riseup.net>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: it\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Poedit 1.6.10\n"
|
||||
|
||||
#: brasier.lua:7
|
||||
msgid "A brasier for producing copious amounts of light and heat."
|
||||
msgstr "Un braciere per produrre grandi quantità di luce e calore."
|
||||
|
||||
#: brasier.lua:8
|
||||
msgid ""
|
||||
"To ignite the brasier place a flammable fuel in its inventory slot. A lump "
|
||||
"of coal will burn for about half an hour."
|
||||
msgstr ""
|
||||
"Per accendere il braciere mettete del combustibile nella sua casella di "
|
||||
"inventario. Un grumo di carbone brucerà per circa mezz'ora."
|
||||
|
||||
#: brasier.lua:107
|
||||
msgid "Floor Brasier"
|
||||
msgstr "Braciere da pavimento"
|
||||
|
||||
#: brasier.lua:156
|
||||
msgid "Stonebrick"
|
||||
msgstr "Mattoni di pietra"
|
||||
|
||||
#: brasier.lua:228
|
||||
msgid "@1 Brasier"
|
||||
msgstr "Braciere di @1"
|
||||
|
||||
#: init.lua:17
|
||||
msgid "Light Block"
|
||||
msgstr "Lampada"
|
||||
|
||||
#: init.lua:37
|
||||
msgid "Chandelier"
|
||||
msgstr "Candeliere"
|
||||
|
||||
#: init.lua:76
|
||||
msgid "Chandelier Chain"
|
||||
msgstr "Catena per candeliere"
|
@ -1,52 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-03-01 23:52-0700\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: brasier.lua:7
|
||||
msgid "A brasier for producing copious amounts of light and heat."
|
||||
msgstr ""
|
||||
|
||||
#: brasier.lua:8
|
||||
msgid ""
|
||||
"To ignite the brasier place a flammable fuel in its inventory slot. A lump "
|
||||
"of coal will burn for about half an hour."
|
||||
msgstr ""
|
||||
|
||||
#: brasier.lua:107
|
||||
msgid "Floor Brasier"
|
||||
msgstr ""
|
||||
|
||||
#: brasier.lua:156
|
||||
msgid "Stonebrick"
|
||||
msgstr ""
|
||||
|
||||
#: brasier.lua:228
|
||||
msgid "@1 Brasier"
|
||||
msgstr ""
|
||||
|
||||
#: init.lua:17
|
||||
msgid "Light Block"
|
||||
msgstr ""
|
||||
|
||||
#: init.lua:37
|
||||
msgid "Chandelier"
|
||||
msgstr ""
|
||||
|
||||
#: init.lua:76
|
||||
msgid "Chandelier Chain"
|
||||
msgstr ""
|
18
castle_lighting/locale/template.txt
Normal file
@ -0,0 +1,18 @@
|
||||
# textdomain: castle_lighting
|
||||
|
||||
|
||||
### brasier.lua ###
|
||||
|
||||
@1 Brasier=
|
||||
A brasier for producing copious amounts of light and heat.=
|
||||
Floor Brasier=
|
||||
Stonebrick=
|
||||
|
||||
To ignite the brasier place a flammable fuel in its inventory slot. A lump of coal will burn for about half an hour.=
|
||||
|
||||
|
||||
### init.lua ###
|
||||
|
||||
Chandelier=
|
||||
Chandelier Chain=
|
||||
Light Block=
|
@ -1 +1,4 @@
|
||||
name = castle_lighting
|
||||
depends = default
|
||||
optional_depends = fire, castle_masonry, hopper, doc
|
||||
description = This mod contains medieval castle lighting solutions
|
||||
|
Before Width: | Height: | Size: 360 B After Width: | Height: | Size: 347 B |
Before Width: | Height: | Size: 169 B After Width: | Height: | Size: 157 B |
Before Width: | Height: | Size: 316 B After Width: | Height: | Size: 311 B |
Before Width: | Height: | Size: 771 B After Width: | Height: | Size: 755 B |
Before Width: | Height: | Size: 214 B After Width: | Height: | Size: 207 B |
Before Width: | Height: | Size: 465 B After Width: | Height: | Size: 460 B |
@ -1,9 +1,7 @@
|
||||
minetest.register_alias("darkage:box", "castle_storage:crate")
|
||||
minetest.register_alias("castle:crate", "castle_storage:crate")
|
||||
|
||||
-- internationalization boilerplate
|
||||
local MP = minetest.get_modpath(minetest.get_current_modname())
|
||||
local S, NS = dofile(MP.."/intllib.lua")
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
minetest.register_node("castle_storage:crate", {
|
||||
description = S("Crate"),
|
||||
|
@ -1,3 +1,2 @@
|
||||
default
|
||||
intllib?
|
||||
hopper?
|
||||
|
418
castle_storage/i18n.py
Normal file
@ -0,0 +1,418 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Script to generate the template file and update the translation files.
|
||||
# Copy the script into the mod or modpack root folder and run it there.
|
||||
#
|
||||
# Copyright (C) 2019 Joachim Stolberg, 2020 FaceDeer, 2020 Louis Royer
|
||||
# LGPLv2.1+
|
||||
|
||||
from __future__ import print_function
|
||||
import os, fnmatch, re, shutil, errno
|
||||
from sys import argv as _argv
|
||||
|
||||
# Running params
|
||||
params = {"recursive": False,
|
||||
"help": False,
|
||||
"mods": False,
|
||||
"verbose": False,
|
||||
"folders": []
|
||||
}
|
||||
# Available CLI options
|
||||
options = {"recursive": ['--recursive', '-r'],
|
||||
"help": ['--help', '-h'],
|
||||
"mods": ['--installed-mods'],
|
||||
"verbose": ['--verbose', '-v']
|
||||
}
|
||||
|
||||
# Strings longer than this will have extra space added between
|
||||
# them in the translation files to make it easier to distinguish their
|
||||
# beginnings and endings at a glance
|
||||
doublespace_threshold = 60
|
||||
|
||||
def set_params_folders(tab: list):
|
||||
'''Initialize params["folders"] from CLI arguments.'''
|
||||
# Discarding argument 0 (tool name)
|
||||
for param in tab[1:]:
|
||||
stop_param = False
|
||||
for option in options:
|
||||
if param in options[option]:
|
||||
stop_param = True
|
||||
break
|
||||
if not stop_param:
|
||||
params["folders"].append(os.path.abspath(param))
|
||||
|
||||
def set_params(tab: list):
|
||||
'''Initialize params from CLI arguments.'''
|
||||
for option in options:
|
||||
for option_name in options[option]:
|
||||
if option_name in tab:
|
||||
params[option] = True
|
||||
break
|
||||
|
||||
def print_help(name):
|
||||
'''Prints some help message.'''
|
||||
print(f'''SYNOPSIS
|
||||
{name} [OPTIONS] [PATHS...]
|
||||
DESCRIPTION
|
||||
{', '.join(options["help"])}
|
||||
prints this help message
|
||||
{', '.join(options["recursive"])}
|
||||
run on all subfolders of paths given
|
||||
{', '.join(options["mods"])}
|
||||
run on locally installed modules
|
||||
{', '.join(options["verbose"])}
|
||||
add output information
|
||||
''')
|
||||
|
||||
|
||||
def main():
|
||||
'''Main function'''
|
||||
set_params(_argv)
|
||||
set_params_folders(_argv)
|
||||
if params["help"]:
|
||||
print_help(_argv[0])
|
||||
elif params["recursive"] and params["mods"]:
|
||||
print("Option --installed-mods is incompatible with --recursive")
|
||||
else:
|
||||
# Add recursivity message
|
||||
print("Running ", end='')
|
||||
if params["recursive"]:
|
||||
print("recursively ", end='')
|
||||
# Running
|
||||
if params["mods"]:
|
||||
print(f"on all locally installed modules in {os.path.abspath('~/.minetest/mods/')}")
|
||||
run_all_subfolders("~/.minetest/mods")
|
||||
elif len(params["folders"]) >= 2:
|
||||
print("on folder list:", params["folders"])
|
||||
for f in params["folders"]:
|
||||
if params["recursive"]:
|
||||
run_all_subfolders(f)
|
||||
else:
|
||||
update_folder(f)
|
||||
elif len(params["folders"]) == 1:
|
||||
print("on folder", params["folders"][0])
|
||||
if params["recursive"]:
|
||||
run_all_subfolders(params["folders"][0])
|
||||
else:
|
||||
update_folder(params["folders"][0])
|
||||
else:
|
||||
print("on folder", os.path.abspath("./"))
|
||||
if params["recursive"]:
|
||||
run_all_subfolders(os.path.abspath("./"))
|
||||
else:
|
||||
update_folder(os.path.abspath("./"))
|
||||
|
||||
#group 2 will be the string, groups 1 and 3 will be the delimiters (" or ')
|
||||
#See https://stackoverflow.com/questions/46967465/regex-match-text-in-either-single-or-double-quote
|
||||
pattern_lua = re.compile(r'[\.=^\t,{\(\s]N?S\(\s*(["\'])((?:\\\1|(?:(?!\1)).)*)(\1)[\s,\)]', re.DOTALL)
|
||||
pattern_lua_bracketed = re.compile(r'[\.=^\t,{\(\s]N?S\(\s*\[\[(.*?)\]\][\s,\)]', re.DOTALL)
|
||||
|
||||
# Handles "concatenation" .. " of strings"
|
||||
pattern_concat = re.compile(r'["\'][\s]*\.\.[\s]*["\']', re.DOTALL)
|
||||
|
||||
pattern_tr = re.compile(r'(.+?[^@])=(.*)')
|
||||
pattern_name = re.compile(r'^name[ ]*=[ ]*([^ \n]*)')
|
||||
pattern_tr_filename = re.compile(r'\.tr$')
|
||||
pattern_po_language_code = re.compile(r'(.*)\.po$')
|
||||
|
||||
#attempt to read the mod's name from the mod.conf file. Returns None on failure
|
||||
def get_modname(folder):
|
||||
try:
|
||||
with open(os.path.join(folder, "mod.conf"), "r", encoding='utf-8') as mod_conf:
|
||||
for line in mod_conf:
|
||||
match = pattern_name.match(line)
|
||||
if match:
|
||||
return match.group(1)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
return None
|
||||
|
||||
#If there are already .tr files in /locale, returns a list of their names
|
||||
def get_existing_tr_files(folder):
|
||||
out = []
|
||||
for root, dirs, files in os.walk(os.path.join(folder, 'locale/')):
|
||||
for name in files:
|
||||
if pattern_tr_filename.search(name):
|
||||
out.append(name)
|
||||
return out
|
||||
|
||||
# A series of search and replaces that massage a .po file's contents into
|
||||
# a .tr file's equivalent
|
||||
def process_po_file(text):
|
||||
# The first three items are for unused matches
|
||||
text = re.sub(r'#~ msgid "', "", text)
|
||||
text = re.sub(r'"\n#~ msgstr ""\n"', "=", text)
|
||||
text = re.sub(r'"\n#~ msgstr "', "=", text)
|
||||
# comment lines
|
||||
text = re.sub(r'#.*\n', "", text)
|
||||
# converting msg pairs into "=" pairs
|
||||
text = re.sub(r'msgid "', "", text)
|
||||
text = re.sub(r'"\nmsgstr ""\n"', "=", text)
|
||||
text = re.sub(r'"\nmsgstr "', "=", text)
|
||||
# various line breaks and escape codes
|
||||
text = re.sub(r'"\n"', "", text)
|
||||
text = re.sub(r'"\n', "\n", text)
|
||||
text = re.sub(r'\\"', '"', text)
|
||||
text = re.sub(r'\\n', '@n', text)
|
||||
# remove header text
|
||||
text = re.sub(r'=Project-Id-Version:.*\n', "", text)
|
||||
# remove double-spaced lines
|
||||
text = re.sub(r'\n\n', '\n', text)
|
||||
return text
|
||||
|
||||
# Go through existing .po files and, if a .tr file for that language
|
||||
# *doesn't* exist, convert it and create it.
|
||||
# The .tr file that results will subsequently be reprocessed so
|
||||
# any "no longer used" strings will be preserved.
|
||||
# Note that "fuzzy" tags will be lost in this process.
|
||||
def process_po_files(folder, modname):
|
||||
for root, dirs, files in os.walk(os.path.join(folder, 'locale/')):
|
||||
for name in files:
|
||||
code_match = pattern_po_language_code.match(name)
|
||||
if code_match == None:
|
||||
continue
|
||||
language_code = code_match.group(1)
|
||||
tr_name = modname + "." + language_code + ".tr"
|
||||
tr_file = os.path.join(root, tr_name)
|
||||
if os.path.exists(tr_file):
|
||||
if params["verbose"]:
|
||||
print(f"{tr_name} already exists, ignoring {name}")
|
||||
continue
|
||||
fname = os.path.join(root, name)
|
||||
with open(fname, "r", encoding='utf-8') as po_file:
|
||||
if params["verbose"]:
|
||||
print(f"Importing translations from {name}")
|
||||
text = process_po_file(po_file.read())
|
||||
with open(tr_file, "wt", encoding='utf-8') as tr_out:
|
||||
tr_out.write(text)
|
||||
|
||||
# from https://stackoverflow.com/questions/600268/mkdir-p-functionality-in-python/600612#600612
|
||||
# Creates a directory if it doesn't exist, silently does
|
||||
# nothing if it already exists
|
||||
def mkdir_p(path):
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except OSError as exc: # Python >2.5
|
||||
if exc.errno == errno.EEXIST and os.path.isdir(path):
|
||||
pass
|
||||
else: raise
|
||||
|
||||
# Converts the template dictionary to a text to be written as a file
|
||||
# dKeyStrings is a dictionary of localized string to source file sets
|
||||
# dOld is a dictionary of existing translations and comments from
|
||||
# the previous version of this text
|
||||
def strings_to_text(dkeyStrings, dOld, mod_name):
|
||||
lOut = [f"# textdomain: {mod_name}\n"]
|
||||
|
||||
dGroupedBySource = {}
|
||||
|
||||
for key in dkeyStrings:
|
||||
sourceList = list(dkeyStrings[key])
|
||||
sourceList.sort()
|
||||
sourceString = "\n".join(sourceList)
|
||||
listForSource = dGroupedBySource.get(sourceString, [])
|
||||
listForSource.append(key)
|
||||
dGroupedBySource[sourceString] = listForSource
|
||||
|
||||
lSourceKeys = list(dGroupedBySource.keys())
|
||||
lSourceKeys.sort()
|
||||
for source in lSourceKeys:
|
||||
localizedStrings = dGroupedBySource[source]
|
||||
localizedStrings.sort()
|
||||
lOut.append("")
|
||||
lOut.append(source)
|
||||
lOut.append("")
|
||||
for localizedString in localizedStrings:
|
||||
val = dOld.get(localizedString, {})
|
||||
translation = val.get("translation", "")
|
||||
comment = val.get("comment")
|
||||
if len(localizedString) > doublespace_threshold and not lOut[-1] == "":
|
||||
lOut.append("")
|
||||
if comment != None:
|
||||
lOut.append(comment)
|
||||
lOut.append(f"{localizedString}={translation}")
|
||||
if len(localizedString) > doublespace_threshold:
|
||||
lOut.append("")
|
||||
|
||||
|
||||
unusedExist = False
|
||||
for key in dOld:
|
||||
if key not in dkeyStrings:
|
||||
val = dOld[key]
|
||||
translation = val.get("translation")
|
||||
comment = val.get("comment")
|
||||
# only keep an unused translation if there was translated
|
||||
# text or a comment associated with it
|
||||
if translation != None and (translation != "" or comment):
|
||||
if not unusedExist:
|
||||
unusedExist = True
|
||||
lOut.append("\n\n##### not used anymore #####\n")
|
||||
if len(key) > doublespace_threshold and not lOut[-1] == "":
|
||||
lOut.append("")
|
||||
if comment != None:
|
||||
lOut.append(comment)
|
||||
lOut.append(f"{key}={translation}")
|
||||
if len(key) > doublespace_threshold:
|
||||
lOut.append("")
|
||||
return "\n".join(lOut) + '\n'
|
||||
|
||||
# Writes a template.txt file
|
||||
# dkeyStrings is the dictionary returned by generate_template
|
||||
def write_template(templ_file, dkeyStrings, mod_name):
|
||||
# read existing template file to preserve comments
|
||||
existing_template = import_tr_file(templ_file)
|
||||
|
||||
text = strings_to_text(dkeyStrings, existing_template[0], mod_name)
|
||||
mkdir_p(os.path.dirname(templ_file))
|
||||
with open(templ_file, "wt", encoding='utf-8') as template_file:
|
||||
template_file.write(text)
|
||||
|
||||
|
||||
# Gets all translatable strings from a lua file
|
||||
def read_lua_file_strings(lua_file):
|
||||
lOut = []
|
||||
with open(lua_file, encoding='utf-8') as text_file:
|
||||
text = text_file.read()
|
||||
#TODO remove comments here
|
||||
|
||||
text = re.sub(pattern_concat, "", text)
|
||||
|
||||
strings = []
|
||||
for s in pattern_lua.findall(text):
|
||||
strings.append(s[1])
|
||||
for s in pattern_lua_bracketed.findall(text):
|
||||
strings.append(s)
|
||||
|
||||
for s in strings:
|
||||
s = re.sub(r'"\.\.\s+"', "", s)
|
||||
s = re.sub("@[^@=0-9]", "@@", s)
|
||||
s = s.replace('\\"', '"')
|
||||
s = s.replace("\\'", "'")
|
||||
s = s.replace("\n", "@n")
|
||||
s = s.replace("\\n", "@n")
|
||||
s = s.replace("=", "@=")
|
||||
lOut.append(s)
|
||||
return lOut
|
||||
|
||||
# Gets strings from an existing translation file
|
||||
# returns both a dictionary of translations
|
||||
# and the full original source text so that the new text
|
||||
# can be compared to it for changes.
|
||||
def import_tr_file(tr_file):
|
||||
dOut = {}
|
||||
text = None
|
||||
if os.path.exists(tr_file):
|
||||
with open(tr_file, "r", encoding='utf-8') as existing_file :
|
||||
# save the full text to allow for comparison
|
||||
# of the old version with the new output
|
||||
text = existing_file.read()
|
||||
existing_file.seek(0)
|
||||
# a running record of the current comment block
|
||||
# we're inside, to allow preceeding multi-line comments
|
||||
# to be retained for a translation line
|
||||
latest_comment_block = None
|
||||
for line in existing_file.readlines():
|
||||
line = line.rstrip('\n')
|
||||
if line[:3] == "###":
|
||||
# Reset comment block if we hit a header
|
||||
latest_comment_block = None
|
||||
continue
|
||||
if line[:1] == "#":
|
||||
# Save the comment we're inside
|
||||
if not latest_comment_block:
|
||||
latest_comment_block = line
|
||||
else:
|
||||
latest_comment_block = latest_comment_block + "\n" + line
|
||||
continue
|
||||
match = pattern_tr.match(line)
|
||||
if match:
|
||||
# this line is a translated line
|
||||
outval = {}
|
||||
outval["translation"] = match.group(2)
|
||||
if latest_comment_block:
|
||||
# if there was a comment, record that.
|
||||
outval["comment"] = latest_comment_block
|
||||
latest_comment_block = None
|
||||
dOut[match.group(1)] = outval
|
||||
return (dOut, text)
|
||||
|
||||
# Walks all lua files in the mod folder, collects translatable strings,
|
||||
# and writes it to a template.txt file
|
||||
# Returns a dictionary of localized strings to source file sets
|
||||
# that can be used with the strings_to_text function.
|
||||
def generate_template(folder, mod_name):
|
||||
dOut = {}
|
||||
for root, dirs, files in os.walk(folder):
|
||||
for name in files:
|
||||
if fnmatch.fnmatch(name, "*.lua"):
|
||||
fname = os.path.join(root, name)
|
||||
found = read_lua_file_strings(fname)
|
||||
if params["verbose"]:
|
||||
print(f"{fname}: {str(len(found))} translatable strings")
|
||||
|
||||
for s in found:
|
||||
sources = dOut.get(s, set())
|
||||
sources.add(f"### {os.path.basename(fname)} ###")
|
||||
dOut[s] = sources
|
||||
|
||||
if len(dOut) == 0:
|
||||
return None
|
||||
templ_file = os.path.join(folder, "locale/template.txt")
|
||||
write_template(templ_file, dOut, mod_name)
|
||||
return dOut
|
||||
|
||||
# Updates an existing .tr file, copying the old one to a ".old" file
|
||||
# if any changes have happened
|
||||
# dNew is the data used to generate the template, it has all the
|
||||
# currently-existing localized strings
|
||||
def update_tr_file(dNew, mod_name, tr_file):
|
||||
if params["verbose"]:
|
||||
print(f"updating {tr_file}")
|
||||
|
||||
tr_import = import_tr_file(tr_file)
|
||||
dOld = tr_import[0]
|
||||
textOld = tr_import[1]
|
||||
|
||||
textNew = strings_to_text(dNew, dOld, mod_name)
|
||||
|
||||
if textOld and textOld != textNew:
|
||||
print(f"{tr_file} has changed.")
|
||||
shutil.copyfile(tr_file, f"{tr_file}.old")
|
||||
|
||||
with open(tr_file, "w", encoding='utf-8') as new_tr_file:
|
||||
new_tr_file.write(textNew)
|
||||
|
||||
# Updates translation files for the mod in the given folder
|
||||
def update_mod(folder):
|
||||
modname = get_modname(folder)
|
||||
if modname is not None:
|
||||
process_po_files(folder, modname)
|
||||
print(f"Updating translations for {modname}")
|
||||
data = generate_template(folder, modname)
|
||||
if data == None:
|
||||
print(f"No translatable strings found in {modname}")
|
||||
else:
|
||||
for tr_file in get_existing_tr_files(folder):
|
||||
update_tr_file(data, modname, os.path.join(folder, "locale/", tr_file))
|
||||
else:
|
||||
print("Unable to find modname in folder " + folder)
|
||||
|
||||
# Determines if the folder being pointed to is a mod or a mod pack
|
||||
# and then runs update_mod accordingly
|
||||
def update_folder(folder):
|
||||
is_modpack = os.path.exists(os.path.join(folder, "modpack.txt")) or os.path.exists(os.path.join(folder, "modpack.conf"))
|
||||
if is_modpack:
|
||||
subfolders = [f.path for f in os.scandir(folder) if f.is_dir()]
|
||||
for subfolder in subfolders:
|
||||
update_mod(subfolder + "/")
|
||||
else:
|
||||
update_mod(folder)
|
||||
print("Done.")
|
||||
|
||||
def run_all_subfolders(folder):
|
||||
for modfolder in [f.path for f in os.scandir(folder) if f.is_dir()]:
|
||||
update_folder(modfolder + "/")
|
||||
|
||||
|
||||
main()
|
@ -1,45 +0,0 @@
|
||||
|
||||
-- Fallback functions for when `intllib` is not installed.
|
||||
-- Code released under Unlicense <http://unlicense.org>.
|
||||
|
||||
-- Get the latest version of this file at:
|
||||
-- https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua
|
||||
|
||||
local function format(str, ...)
|
||||
local args = { ... }
|
||||
local function repl(escape, open, num, close)
|
||||
if escape == "" then
|
||||
local replacement = tostring(args[tonumber(num)])
|
||||
if open == "" then
|
||||
replacement = replacement..close
|
||||
end
|
||||
return replacement
|
||||
else
|
||||
return "@"..open..num..close
|
||||
end
|
||||
end
|
||||
return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl))
|
||||
end
|
||||
|
||||
local gettext, ngettext
|
||||
if minetest.get_modpath("intllib") then
|
||||
if intllib.make_gettext_pair then
|
||||
-- New method using gettext.
|
||||
gettext, ngettext = intllib.make_gettext_pair()
|
||||
else
|
||||
-- Old method using text files.
|
||||
gettext = intllib.Getter()
|
||||
end
|
||||
end
|
||||
|
||||
-- Fill in missing functions.
|
||||
|
||||
gettext = gettext or function(msgid, ...)
|
||||
return format(msgid, ...)
|
||||
end
|
||||
|
||||
ngettext = ngettext or function(msgid, msgid_plural, n, ...)
|
||||
return format(n==1 and msgid or msgid_plural, ...)
|
||||
end
|
||||
|
||||
return gettext, ngettext
|
@ -1,8 +1,6 @@
|
||||
minetest.register_alias("castle:ironbound_chest", "castle_storage:ironbound_chest")
|
||||
|
||||
-- internationalization boilerplate
|
||||
local MP = minetest.get_modpath(minetest.get_current_modname())
|
||||
local S, NS = dofile(MP.."/intllib.lua")
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
local get_ironbound_chest_formspec = function(pos)
|
||||
local spos = pos.x .. "," .. pos.y .. "," ..pos.z
|
||||
|
21
castle_storage/locale/castle_storage.it.tr
Normal file
@ -0,0 +1,21 @@
|
||||
# textdomain: castle_storage
|
||||
|
||||
|
||||
### crate.lua ###
|
||||
|
||||
@1 moves stuff in crate at @2=@1 mette delle cose nella cassa alle coordinate @2
|
||||
@1 moves stuff to crate at @2=@1 prende delle cose dalla cassa alle coordinate @2
|
||||
Crate=Cassa
|
||||
|
||||
### crate.lua ###
|
||||
### ironbound_chest.lua ###
|
||||
|
||||
@1 takes stuff from locked chest at @2=@1 prende delle cose dal baule chiuso a chiave alle coordinate @2
|
||||
|
||||
### ironbound_chest.lua ###
|
||||
|
||||
@1 moves stuff in locked chest at @2=@1 sposta delle cose nel baule chiuso a chiave alle coordinate @2
|
||||
@1 moves stuff to locked chest at @2=@1 mette delle cose nel baule chiuso a chiave alle coordinate @2
|
||||
@1 tried to access a locked chest belonging to @2 at @3=@1 ha tentato di aprire un baule chiuso a chiave di @2 alle coordinate @3
|
||||
Ironbound Chest=Baule rinforzato col ferro
|
||||
Ironbound Chest (owned by @1)=Baule rinforzato col ferro (di @1)
|
@ -1,56 +0,0 @@
|
||||
# ITALIAN LOCALE FILE FOR THE CASTLE STORAGE MODULE
|
||||
# Copyright (C) 2017 Philipbenr And DanDuncombe
|
||||
# This file is distributed under the same license as the CASTLE STORAGE package.
|
||||
# Hamlet <h4mlet@riseup.net>, 2017.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Castle Storage\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-02-25 19:18-0700\n"
|
||||
"PO-Revision-Date: 2017-09-10 22:46+0100\n"
|
||||
"Last-Translator: H4mlet <h4mlet@riseup.net>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"Language: it\n"
|
||||
"X-Generator: Poedit 1.6.10\n"
|
||||
|
||||
#: crate.lua:9 crate.lua:24
|
||||
msgid "Crate"
|
||||
msgstr "Cassa"
|
||||
|
||||
#: crate.lua:34
|
||||
msgid "@1 moves stuff in crate at @2"
|
||||
msgstr "@1 mette delle cose nella cassa alle coordinate @2"
|
||||
|
||||
#: crate.lua:37
|
||||
msgid "@1 moves stuff to crate at @2"
|
||||
msgstr "@1 prende delle cose dalla cassa alle coordinate @2"
|
||||
|
||||
#: crate.lua:40 ironbound_chest.lua:113
|
||||
msgid "@1 takes stuff from locked chest at @2"
|
||||
msgstr "@1 prende delle cose dal baule chiuso a chiave alle coordinate @2"
|
||||
|
||||
#: ironbound_chest.lua:35 ironbound_chest.lua:69
|
||||
msgid "Ironbound Chest"
|
||||
msgstr "Baule rinforzato col ferro"
|
||||
|
||||
#: ironbound_chest.lua:65
|
||||
msgid "Ironbound Chest (owned by @1)"
|
||||
msgstr "Baule rinforzato col ferro (di @1)"
|
||||
|
||||
#: ironbound_chest.lua:82 ironbound_chest.lua:91 ironbound_chest.lua:100
|
||||
msgid "@1 tried to access a locked chest belonging to @2 at @3"
|
||||
msgstr ""
|
||||
"@1 ha tentato di aprire un baule chiuso a chiave di @2 alle coordinate @3"
|
||||
|
||||
#: ironbound_chest.lua:107
|
||||
msgid "@1 moves stuff in locked chest at @2"
|
||||
msgstr "@1 sposta delle cose nel baule chiuso a chiave alle coordinate @2"
|
||||
|
||||
#: ironbound_chest.lua:110
|
||||
msgid "@1 moves stuff to locked chest at @2"
|
||||
msgstr "@1 mette delle cose nel baule chiuso a chiave alle coordinate @2"
|
@ -1,53 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-02-25 19:18-0700\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: crate.lua:9 crate.lua:24
|
||||
msgid "Crate"
|
||||
msgstr ""
|
||||
|
||||
#: crate.lua:34
|
||||
msgid "@1 moves stuff in crate at @2"
|
||||
msgstr ""
|
||||
|
||||
#: crate.lua:37
|
||||
msgid "@1 moves stuff to crate at @2"
|
||||
msgstr ""
|
||||
|
||||
#: crate.lua:40 ironbound_chest.lua:113
|
||||
msgid "@1 takes stuff from locked chest at @2"
|
||||
msgstr ""
|
||||
|
||||
#: ironbound_chest.lua:35 ironbound_chest.lua:69
|
||||
msgid "Ironbound Chest"
|
||||
msgstr ""
|
||||
|
||||
#: ironbound_chest.lua:65
|
||||
msgid "Ironbound Chest (owned by @1)"
|
||||
msgstr ""
|
||||
|
||||
#: ironbound_chest.lua:82 ironbound_chest.lua:91 ironbound_chest.lua:100
|
||||
msgid "@1 tried to access a locked chest belonging to @2 at @3"
|
||||
msgstr ""
|
||||
|
||||
#: ironbound_chest.lua:107
|
||||
msgid "@1 moves stuff in locked chest at @2"
|
||||
msgstr ""
|
||||
|
||||
#: ironbound_chest.lua:110
|
||||
msgid "@1 moves stuff to locked chest at @2"
|
||||
msgstr ""
|
21
castle_storage/locale/template.txt
Normal file
@ -0,0 +1,21 @@
|
||||
# textdomain: castle_storage
|
||||
|
||||
|
||||
### crate.lua ###
|
||||
|
||||
@1 moves stuff in crate at @2=
|
||||
@1 moves stuff to crate at @2=
|
||||
Crate=
|
||||
|
||||
### crate.lua ###
|
||||
### ironbound_chest.lua ###
|
||||
|
||||
@1 takes stuff from locked chest at @2=
|
||||
|
||||
### ironbound_chest.lua ###
|
||||
|
||||
@1 moves stuff in locked chest at @2=
|
||||
@1 moves stuff to locked chest at @2=
|
||||
@1 tried to access a locked chest belonging to @2 at @3=
|
||||
Ironbound Chest=
|
||||
Ironbound Chest (owned by @1)=
|
@ -1 +1,4 @@
|
||||
name = castle_storage
|
||||
name = castle_storage
|
||||
depends = default
|
||||
optional_depends = hopper
|
||||
description = This mod contains storage containers one might find contained in a castle.
|
||||
|
Before Width: | Height: | Size: 374 B After Width: | Height: | Size: 365 B |
@ -1,6 +1,7 @@
|
||||
-- internationalization boilerplate
|
||||
local MP = minetest.get_modpath(minetest.get_current_modname())
|
||||
local S, NS = dofile(MP.."/intllib.lua")
|
||||
|
||||
-- Used for localization, choose either built-in or intllib.
|
||||
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
minetest.register_alias("castle:battleaxe", "castle_weapons:battleaxe")
|
||||
|
||||
|
@ -18,9 +18,7 @@ minetest.register_alias("castle:bolt", "castle_weapons:crossbow_bolt")
|
||||
minetest.register_alias("castle:crossbow_bolt", "castle_weapons:crossbow_bolt")
|
||||
minetest.register_alias("castle:crossbow_loaded", "castle_weapons:crossbow_loaded")
|
||||
|
||||
-- internationalization boilerplate
|
||||
local MP = minetest.get_modpath(minetest.get_current_modname())
|
||||
local S, NS = dofile(MP.."/intllib.lua")
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
local crossbow={}
|
||||
|
||||
@ -458,4 +456,4 @@ minetest.register_craft({
|
||||
recipe = {
|
||||
{'default:stick', 'default:stick', 'default:steel_ingot'},
|
||||
}
|
||||
})
|
||||
})
|
||||
|
418
castle_weapons/i18n.py
Normal file
@ -0,0 +1,418 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Script to generate the template file and update the translation files.
|
||||
# Copy the script into the mod or modpack root folder and run it there.
|
||||
#
|
||||
# Copyright (C) 2019 Joachim Stolberg, 2020 FaceDeer, 2020 Louis Royer
|
||||
# LGPLv2.1+
|
||||
|
||||
from __future__ import print_function
|
||||
import os, fnmatch, re, shutil, errno
|
||||
from sys import argv as _argv
|
||||
|
||||
# Running params
|
||||
params = {"recursive": False,
|
||||
"help": False,
|
||||
"mods": False,
|
||||
"verbose": False,
|
||||
"folders": []
|
||||
}
|
||||
# Available CLI options
|
||||
options = {"recursive": ['--recursive', '-r'],
|
||||
"help": ['--help', '-h'],
|
||||
"mods": ['--installed-mods'],
|
||||
"verbose": ['--verbose', '-v']
|
||||
}
|
||||
|
||||
# Strings longer than this will have extra space added between
|
||||
# them in the translation files to make it easier to distinguish their
|
||||
# beginnings and endings at a glance
|
||||
doublespace_threshold = 60
|
||||
|
||||
def set_params_folders(tab: list):
|
||||
'''Initialize params["folders"] from CLI arguments.'''
|
||||
# Discarding argument 0 (tool name)
|
||||
for param in tab[1:]:
|
||||
stop_param = False
|
||||
for option in options:
|
||||
if param in options[option]:
|
||||
stop_param = True
|
||||
break
|
||||
if not stop_param:
|
||||
params["folders"].append(os.path.abspath(param))
|
||||
|
||||
def set_params(tab: list):
|
||||
'''Initialize params from CLI arguments.'''
|
||||
for option in options:
|
||||
for option_name in options[option]:
|
||||
if option_name in tab:
|
||||
params[option] = True
|
||||
break
|
||||
|
||||
def print_help(name):
|
||||
'''Prints some help message.'''
|
||||
print(f'''SYNOPSIS
|
||||
{name} [OPTIONS] [PATHS...]
|
||||
DESCRIPTION
|
||||
{', '.join(options["help"])}
|
||||
prints this help message
|
||||
{', '.join(options["recursive"])}
|
||||
run on all subfolders of paths given
|
||||
{', '.join(options["mods"])}
|
||||
run on locally installed modules
|
||||
{', '.join(options["verbose"])}
|
||||
add output information
|
||||
''')
|
||||
|
||||
|
||||
def main():
|
||||
'''Main function'''
|
||||
set_params(_argv)
|
||||
set_params_folders(_argv)
|
||||
if params["help"]:
|
||||
print_help(_argv[0])
|
||||
elif params["recursive"] and params["mods"]:
|
||||
print("Option --installed-mods is incompatible with --recursive")
|
||||
else:
|
||||
# Add recursivity message
|
||||
print("Running ", end='')
|
||||
if params["recursive"]:
|
||||
print("recursively ", end='')
|
||||
# Running
|
||||
if params["mods"]:
|
||||
print(f"on all locally installed modules in {os.path.abspath('~/.minetest/mods/')}")
|
||||
run_all_subfolders("~/.minetest/mods")
|
||||
elif len(params["folders"]) >= 2:
|
||||
print("on folder list:", params["folders"])
|
||||
for f in params["folders"]:
|
||||
if params["recursive"]:
|
||||
run_all_subfolders(f)
|
||||
else:
|
||||
update_folder(f)
|
||||
elif len(params["folders"]) == 1:
|
||||
print("on folder", params["folders"][0])
|
||||
if params["recursive"]:
|
||||
run_all_subfolders(params["folders"][0])
|
||||
else:
|
||||
update_folder(params["folders"][0])
|
||||
else:
|
||||
print("on folder", os.path.abspath("./"))
|
||||
if params["recursive"]:
|
||||
run_all_subfolders(os.path.abspath("./"))
|
||||
else:
|
||||
update_folder(os.path.abspath("./"))
|
||||
|
||||
#group 2 will be the string, groups 1 and 3 will be the delimiters (" or ')
|
||||
#See https://stackoverflow.com/questions/46967465/regex-match-text-in-either-single-or-double-quote
|
||||
pattern_lua = re.compile(r'[\.=^\t,{\(\s]N?S\(\s*(["\'])((?:\\\1|(?:(?!\1)).)*)(\1)[\s,\)]', re.DOTALL)
|
||||
pattern_lua_bracketed = re.compile(r'[\.=^\t,{\(\s]N?S\(\s*\[\[(.*?)\]\][\s,\)]', re.DOTALL)
|
||||
|
||||
# Handles "concatenation" .. " of strings"
|
||||
pattern_concat = re.compile(r'["\'][\s]*\.\.[\s]*["\']', re.DOTALL)
|
||||
|
||||
pattern_tr = re.compile(r'(.+?[^@])=(.*)')
|
||||
pattern_name = re.compile(r'^name[ ]*=[ ]*([^ \n]*)')
|
||||
pattern_tr_filename = re.compile(r'\.tr$')
|
||||
pattern_po_language_code = re.compile(r'(.*)\.po$')
|
||||
|
||||
#attempt to read the mod's name from the mod.conf file. Returns None on failure
|
||||
def get_modname(folder):
|
||||
try:
|
||||
with open(os.path.join(folder, "mod.conf"), "r", encoding='utf-8') as mod_conf:
|
||||
for line in mod_conf:
|
||||
match = pattern_name.match(line)
|
||||
if match:
|
||||
return match.group(1)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
return None
|
||||
|
||||
#If there are already .tr files in /locale, returns a list of their names
|
||||
def get_existing_tr_files(folder):
|
||||
out = []
|
||||
for root, dirs, files in os.walk(os.path.join(folder, 'locale/')):
|
||||
for name in files:
|
||||
if pattern_tr_filename.search(name):
|
||||
out.append(name)
|
||||
return out
|
||||
|
||||
# A series of search and replaces that massage a .po file's contents into
|
||||
# a .tr file's equivalent
|
||||
def process_po_file(text):
|
||||
# The first three items are for unused matches
|
||||
text = re.sub(r'#~ msgid "', "", text)
|
||||
text = re.sub(r'"\n#~ msgstr ""\n"', "=", text)
|
||||
text = re.sub(r'"\n#~ msgstr "', "=", text)
|
||||
# comment lines
|
||||
text = re.sub(r'#.*\n', "", text)
|
||||
# converting msg pairs into "=" pairs
|
||||
text = re.sub(r'msgid "', "", text)
|
||||
text = re.sub(r'"\nmsgstr ""\n"', "=", text)
|
||||
text = re.sub(r'"\nmsgstr "', "=", text)
|
||||
# various line breaks and escape codes
|
||||
text = re.sub(r'"\n"', "", text)
|
||||
text = re.sub(r'"\n', "\n", text)
|
||||
text = re.sub(r'\\"', '"', text)
|
||||
text = re.sub(r'\\n', '@n', text)
|
||||
# remove header text
|
||||
text = re.sub(r'=Project-Id-Version:.*\n', "", text)
|
||||
# remove double-spaced lines
|
||||
text = re.sub(r'\n\n', '\n', text)
|
||||
return text
|
||||
|
||||
# Go through existing .po files and, if a .tr file for that language
|
||||
# *doesn't* exist, convert it and create it.
|
||||
# The .tr file that results will subsequently be reprocessed so
|
||||
# any "no longer used" strings will be preserved.
|
||||
# Note that "fuzzy" tags will be lost in this process.
|
||||
def process_po_files(folder, modname):
|
||||
for root, dirs, files in os.walk(os.path.join(folder, 'locale/')):
|
||||
for name in files:
|
||||
code_match = pattern_po_language_code.match(name)
|
||||
if code_match == None:
|
||||
continue
|
||||
language_code = code_match.group(1)
|
||||
tr_name = modname + "." + language_code + ".tr"
|
||||
tr_file = os.path.join(root, tr_name)
|
||||
if os.path.exists(tr_file):
|
||||
if params["verbose"]:
|
||||
print(f"{tr_name} already exists, ignoring {name}")
|
||||
continue
|
||||
fname = os.path.join(root, name)
|
||||
with open(fname, "r", encoding='utf-8') as po_file:
|
||||
if params["verbose"]:
|
||||
print(f"Importing translations from {name}")
|
||||
text = process_po_file(po_file.read())
|
||||
with open(tr_file, "wt", encoding='utf-8') as tr_out:
|
||||
tr_out.write(text)
|
||||
|
||||
# from https://stackoverflow.com/questions/600268/mkdir-p-functionality-in-python/600612#600612
|
||||
# Creates a directory if it doesn't exist, silently does
|
||||
# nothing if it already exists
|
||||
def mkdir_p(path):
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except OSError as exc: # Python >2.5
|
||||
if exc.errno == errno.EEXIST and os.path.isdir(path):
|
||||
pass
|
||||
else: raise
|
||||
|
||||
# Converts the template dictionary to a text to be written as a file
|
||||
# dKeyStrings is a dictionary of localized string to source file sets
|
||||
# dOld is a dictionary of existing translations and comments from
|
||||
# the previous version of this text
|
||||
def strings_to_text(dkeyStrings, dOld, mod_name):
|
||||
lOut = [f"# textdomain: {mod_name}\n"]
|
||||
|
||||
dGroupedBySource = {}
|
||||
|
||||
for key in dkeyStrings:
|
||||
sourceList = list(dkeyStrings[key])
|
||||
sourceList.sort()
|
||||
sourceString = "\n".join(sourceList)
|
||||
listForSource = dGroupedBySource.get(sourceString, [])
|
||||
listForSource.append(key)
|
||||
dGroupedBySource[sourceString] = listForSource
|
||||
|
||||
lSourceKeys = list(dGroupedBySource.keys())
|
||||
lSourceKeys.sort()
|
||||
for source in lSourceKeys:
|
||||
localizedStrings = dGroupedBySource[source]
|
||||
localizedStrings.sort()
|
||||
lOut.append("")
|
||||
lOut.append(source)
|
||||
lOut.append("")
|
||||
for localizedString in localizedStrings:
|
||||
val = dOld.get(localizedString, {})
|
||||
translation = val.get("translation", "")
|
||||
comment = val.get("comment")
|
||||
if len(localizedString) > doublespace_threshold and not lOut[-1] == "":
|
||||
lOut.append("")
|
||||
if comment != None:
|
||||
lOut.append(comment)
|
||||
lOut.append(f"{localizedString}={translation}")
|
||||
if len(localizedString) > doublespace_threshold:
|
||||
lOut.append("")
|
||||
|
||||
|
||||
unusedExist = False
|
||||
for key in dOld:
|
||||
if key not in dkeyStrings:
|
||||
val = dOld[key]
|
||||
translation = val.get("translation")
|
||||
comment = val.get("comment")
|
||||
# only keep an unused translation if there was translated
|
||||
# text or a comment associated with it
|
||||
if translation != None and (translation != "" or comment):
|
||||
if not unusedExist:
|
||||
unusedExist = True
|
||||
lOut.append("\n\n##### not used anymore #####\n")
|
||||
if len(key) > doublespace_threshold and not lOut[-1] == "":
|
||||
lOut.append("")
|
||||
if comment != None:
|
||||
lOut.append(comment)
|
||||
lOut.append(f"{key}={translation}")
|
||||
if len(key) > doublespace_threshold:
|
||||
lOut.append("")
|
||||
return "\n".join(lOut) + '\n'
|
||||
|
||||
# Writes a template.txt file
|
||||
# dkeyStrings is the dictionary returned by generate_template
|
||||
def write_template(templ_file, dkeyStrings, mod_name):
|
||||
# read existing template file to preserve comments
|
||||
existing_template = import_tr_file(templ_file)
|
||||
|
||||
text = strings_to_text(dkeyStrings, existing_template[0], mod_name)
|
||||
mkdir_p(os.path.dirname(templ_file))
|
||||
with open(templ_file, "wt", encoding='utf-8') as template_file:
|
||||
template_file.write(text)
|
||||
|
||||
|
||||
# Gets all translatable strings from a lua file
|
||||
def read_lua_file_strings(lua_file):
|
||||
lOut = []
|
||||
with open(lua_file, encoding='utf-8') as text_file:
|
||||
text = text_file.read()
|
||||
#TODO remove comments here
|
||||
|
||||
text = re.sub(pattern_concat, "", text)
|
||||
|
||||
strings = []
|
||||
for s in pattern_lua.findall(text):
|
||||
strings.append(s[1])
|
||||
for s in pattern_lua_bracketed.findall(text):
|
||||
strings.append(s)
|
||||
|
||||
for s in strings:
|
||||
s = re.sub(r'"\.\.\s+"', "", s)
|
||||
s = re.sub("@[^@=0-9]", "@@", s)
|
||||
s = s.replace('\\"', '"')
|
||||
s = s.replace("\\'", "'")
|
||||
s = s.replace("\n", "@n")
|
||||
s = s.replace("\\n", "@n")
|
||||
s = s.replace("=", "@=")
|
||||
lOut.append(s)
|
||||
return lOut
|
||||
|
||||
# Gets strings from an existing translation file
|
||||
# returns both a dictionary of translations
|
||||
# and the full original source text so that the new text
|
||||
# can be compared to it for changes.
|
||||
def import_tr_file(tr_file):
|
||||
dOut = {}
|
||||
text = None
|
||||
if os.path.exists(tr_file):
|
||||
with open(tr_file, "r", encoding='utf-8') as existing_file :
|
||||
# save the full text to allow for comparison
|
||||
# of the old version with the new output
|
||||
text = existing_file.read()
|
||||
existing_file.seek(0)
|
||||
# a running record of the current comment block
|
||||
# we're inside, to allow preceeding multi-line comments
|
||||
# to be retained for a translation line
|
||||
latest_comment_block = None
|
||||
for line in existing_file.readlines():
|
||||
line = line.rstrip('\n')
|
||||
if line[:3] == "###":
|
||||
# Reset comment block if we hit a header
|
||||
latest_comment_block = None
|
||||
continue
|
||||
if line[:1] == "#":
|
||||
# Save the comment we're inside
|
||||
if not latest_comment_block:
|
||||
latest_comment_block = line
|
||||
else:
|
||||
latest_comment_block = latest_comment_block + "\n" + line
|
||||
continue
|
||||
match = pattern_tr.match(line)
|
||||
if match:
|
||||
# this line is a translated line
|
||||
outval = {}
|
||||
outval["translation"] = match.group(2)
|
||||
if latest_comment_block:
|
||||
# if there was a comment, record that.
|
||||
outval["comment"] = latest_comment_block
|
||||
latest_comment_block = None
|
||||
dOut[match.group(1)] = outval
|
||||
return (dOut, text)
|
||||
|
||||
# Walks all lua files in the mod folder, collects translatable strings,
|
||||
# and writes it to a template.txt file
|
||||
# Returns a dictionary of localized strings to source file sets
|
||||
# that can be used with the strings_to_text function.
|
||||
def generate_template(folder, mod_name):
|
||||
dOut = {}
|
||||
for root, dirs, files in os.walk(folder):
|
||||
for name in files:
|
||||
if fnmatch.fnmatch(name, "*.lua"):
|
||||
fname = os.path.join(root, name)
|
||||
found = read_lua_file_strings(fname)
|
||||
if params["verbose"]:
|
||||
print(f"{fname}: {str(len(found))} translatable strings")
|
||||
|
||||
for s in found:
|
||||
sources = dOut.get(s, set())
|
||||
sources.add(f"### {os.path.basename(fname)} ###")
|
||||
dOut[s] = sources
|
||||
|
||||
if len(dOut) == 0:
|
||||
return None
|
||||
templ_file = os.path.join(folder, "locale/template.txt")
|
||||
write_template(templ_file, dOut, mod_name)
|
||||
return dOut
|
||||
|
||||
# Updates an existing .tr file, copying the old one to a ".old" file
|
||||
# if any changes have happened
|
||||
# dNew is the data used to generate the template, it has all the
|
||||
# currently-existing localized strings
|
||||
def update_tr_file(dNew, mod_name, tr_file):
|
||||
if params["verbose"]:
|
||||
print(f"updating {tr_file}")
|
||||
|
||||
tr_import = import_tr_file(tr_file)
|
||||
dOld = tr_import[0]
|
||||
textOld = tr_import[1]
|
||||
|
||||
textNew = strings_to_text(dNew, dOld, mod_name)
|
||||
|
||||
if textOld and textOld != textNew:
|
||||
print(f"{tr_file} has changed.")
|
||||
shutil.copyfile(tr_file, f"{tr_file}.old")
|
||||
|
||||
with open(tr_file, "w", encoding='utf-8') as new_tr_file:
|
||||
new_tr_file.write(textNew)
|
||||
|
||||
# Updates translation files for the mod in the given folder
|
||||
def update_mod(folder):
|
||||
modname = get_modname(folder)
|
||||
if modname is not None:
|
||||
process_po_files(folder, modname)
|
||||
print(f"Updating translations for {modname}")
|
||||
data = generate_template(folder, modname)
|
||||
if data == None:
|
||||
print(f"No translatable strings found in {modname}")
|
||||
else:
|
||||
for tr_file in get_existing_tr_files(folder):
|
||||
update_tr_file(data, modname, os.path.join(folder, "locale/", tr_file))
|
||||
else:
|
||||
print("Unable to find modname in folder " + folder)
|
||||
|
||||
# Determines if the folder being pointed to is a mod or a mod pack
|
||||
# and then runs update_mod accordingly
|
||||
def update_folder(folder):
|
||||
is_modpack = os.path.exists(os.path.join(folder, "modpack.txt")) or os.path.exists(os.path.join(folder, "modpack.conf"))
|
||||
if is_modpack:
|
||||
subfolders = [f.path for f in os.scandir(folder) if f.is_dir()]
|
||||
for subfolder in subfolders:
|
||||
update_mod(subfolder + "/")
|
||||
else:
|
||||
update_mod(folder)
|
||||
print("Done.")
|
||||
|
||||
def run_all_subfolders(folder):
|
||||
for modfolder in [f.path for f in os.scandir(folder) if f.is_dir()]:
|
||||
update_folder(modfolder + "/")
|
||||
|
||||
|
||||
main()
|
@ -1,45 +0,0 @@
|
||||
|
||||
-- Fallback functions for when `intllib` is not installed.
|
||||
-- Code released under Unlicense <http://unlicense.org>.
|
||||
|
||||
-- Get the latest version of this file at:
|
||||
-- https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua
|
||||
|
||||
local function format(str, ...)
|
||||
local args = { ... }
|
||||
local function repl(escape, open, num, close)
|
||||
if escape == "" then
|
||||
local replacement = tostring(args[tonumber(num)])
|
||||
if open == "" then
|
||||
replacement = replacement..close
|
||||
end
|
||||
return replacement
|
||||
else
|
||||
return "@"..open..num..close
|
||||
end
|
||||
end
|
||||
return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl))
|
||||
end
|
||||
|
||||
local gettext, ngettext
|
||||
if minetest.get_modpath("intllib") then
|
||||
if intllib.make_gettext_pair then
|
||||
-- New method using gettext.
|
||||
gettext, ngettext = intllib.make_gettext_pair()
|
||||
else
|
||||
-- Old method using text files.
|
||||
gettext = intllib.Getter()
|
||||
end
|
||||
end
|
||||
|
||||
-- Fill in missing functions.
|
||||
|
||||
gettext = gettext or function(msgid, ...)
|
||||
return format(msgid, ...)
|
||||
end
|
||||
|
||||
ngettext = ngettext or function(msgid, msgid_plural, n, ...)
|
||||
return format(n==1 and msgid or msgid_plural, ...)
|
||||
end
|
||||
|
||||
return gettext, ngettext
|
12
castle_weapons/locale/castle_weapons.it.tr
Normal file
@ -0,0 +1,12 @@
|
||||
# textdomain: castle_weapons
|
||||
|
||||
|
||||
### battleaxe.lua ###
|
||||
|
||||
# textdomain:castle_weapons
|
||||
Battleaxe=Ascia da guerra
|
||||
|
||||
### crossbow.lua ###
|
||||
|
||||
Bolt=Quadrello
|
||||
Crossbow=Balestra
|
@ -1,31 +0,0 @@
|
||||
# ITALIAN LOCALE FILE FOR THE CASTLE WEAPONS MODULE
|
||||
# Copyright (C) 2017 Philipbenr And DanDuncombe
|
||||
# This file is distributed under the same license as the CASTLE WEAPONS package.
|
||||
# Hamlet <h4mlet@riseup.net>, 2017.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Castle Weapons\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-02-25 19:35-0700\n"
|
||||
"PO-Revision-Date: 2017-09-10 22:49+0100\n"
|
||||
"Last-Translator: H4mlet <h4mlet@riseup.net>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"Language: it\n"
|
||||
"X-Generator: Poedit 1.6.10\n"
|
||||
|
||||
#: battleaxe.lua:8
|
||||
msgid "Battleaxe"
|
||||
msgstr "Ascia da guerra"
|
||||
|
||||
#: crossbow.lua:244
|
||||
msgid "Bolt"
|
||||
msgstr "Quadrello"
|
||||
|
||||
#: crossbow.lua:357 crossbow.lua:416
|
||||
msgid "Crossbow"
|
||||
msgstr "Balestra"
|
@ -1,29 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-02-25 19:35-0700\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: battleaxe.lua:8
|
||||
msgid "Battleaxe"
|
||||
msgstr ""
|
||||
|
||||
#: crossbow.lua:244
|
||||
msgid "Bolt"
|
||||
msgstr ""
|
||||
|
||||
#: crossbow.lua:357 crossbow.lua:416
|
||||
msgid "Crossbow"
|
||||
msgstr ""
|
12
castle_weapons/locale/template.txt
Normal file
@ -0,0 +1,12 @@
|
||||
# textdomain: castle_weapons
|
||||
|
||||
|
||||
### battleaxe.lua ###
|
||||
|
||||
# textdomain:castle_weapons
|
||||
Battleaxe=
|
||||
|
||||
### crossbow.lua ###
|
||||
|
||||
Bolt=
|
||||
Crossbow=
|
@ -1 +1,3 @@
|
||||
name = castle_weapons
|
||||
description = Provides several medieval weapons for use around castles
|
||||
depends = default
|
||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 358 B After Width: | Height: | Size: 225 B |
Before Width: | Height: | Size: 280 B After Width: | Height: | Size: 274 B |
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 282 B |
@ -1,4 +0,0 @@
|
||||
default
|
||||
intllib?
|
||||
hopper?
|
||||
doc?
|
@ -1 +0,0 @@
|
||||
An auto-crafting bench
|
421
crafting_bench/i18n.py
Normal file
@ -0,0 +1,421 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Script to generate the template file and update the translation files.
|
||||
# Copy the script into the mod or modpack root folder and run it there.
|
||||
#
|
||||
# Copyright (C) 2019 Joachim Stolberg, 2020 FaceDeer, 2020 Louis Royer
|
||||
# LGPLv2.1+
|
||||
#
|
||||
# See https://github.com/minetest-tools/update_translations for
|
||||
# potential future updates to this script.
|
||||
|
||||
from __future__ import print_function
|
||||
import os, fnmatch, re, shutil, errno
|
||||
from sys import argv as _argv
|
||||
|
||||
# Running params
|
||||
params = {"recursive": False,
|
||||
"help": False,
|
||||
"mods": False,
|
||||
"verbose": False,
|
||||
"folders": []
|
||||
}
|
||||
# Available CLI options
|
||||
options = {"recursive": ['--recursive', '-r'],
|
||||
"help": ['--help', '-h'],
|
||||
"mods": ['--installed-mods'],
|
||||
"verbose": ['--verbose', '-v']
|
||||
}
|
||||
|
||||
# Strings longer than this will have extra space added between
|
||||
# them in the translation files to make it easier to distinguish their
|
||||
# beginnings and endings at a glance
|
||||
doublespace_threshold = 60
|
||||
|
||||
def set_params_folders(tab: list):
|
||||
'''Initialize params["folders"] from CLI arguments.'''
|
||||
# Discarding argument 0 (tool name)
|
||||
for param in tab[1:]:
|
||||
stop_param = False
|
||||
for option in options:
|
||||
if param in options[option]:
|
||||
stop_param = True
|
||||
break
|
||||
if not stop_param:
|
||||
params["folders"].append(os.path.abspath(param))
|
||||
|
||||
def set_params(tab: list):
|
||||
'''Initialize params from CLI arguments.'''
|
||||
for option in options:
|
||||
for option_name in options[option]:
|
||||
if option_name in tab:
|
||||
params[option] = True
|
||||
break
|
||||
|
||||
def print_help(name):
|
||||
'''Prints some help message.'''
|
||||
print(f'''SYNOPSIS
|
||||
{name} [OPTIONS] [PATHS...]
|
||||
DESCRIPTION
|
||||
{', '.join(options["help"])}
|
||||
prints this help message
|
||||
{', '.join(options["recursive"])}
|
||||
run on all subfolders of paths given
|
||||
{', '.join(options["mods"])}
|
||||
run on locally installed modules
|
||||
{', '.join(options["verbose"])}
|
||||
add output information
|
||||
''')
|
||||
|
||||
|
||||
def main():
|
||||
'''Main function'''
|
||||
set_params(_argv)
|
||||
set_params_folders(_argv)
|
||||
if params["help"]:
|
||||
print_help(_argv[0])
|
||||
elif params["recursive"] and params["mods"]:
|
||||
print("Option --installed-mods is incompatible with --recursive")
|
||||
else:
|
||||
# Add recursivity message
|
||||
print("Running ", end='')
|
||||
if params["recursive"]:
|
||||
print("recursively ", end='')
|
||||
# Running
|
||||
if params["mods"]:
|
||||
print(f"on all locally installed modules in {os.path.abspath('~/.minetest/mods/')}")
|
||||
run_all_subfolders("~/.minetest/mods")
|
||||
elif len(params["folders"]) >= 2:
|
||||
print("on folder list:", params["folders"])
|
||||
for f in params["folders"]:
|
||||
if params["recursive"]:
|
||||
run_all_subfolders(f)
|
||||
else:
|
||||
update_folder(f)
|
||||
elif len(params["folders"]) == 1:
|
||||
print("on folder", params["folders"][0])
|
||||
if params["recursive"]:
|
||||
run_all_subfolders(params["folders"][0])
|
||||
else:
|
||||
update_folder(params["folders"][0])
|
||||
else:
|
||||
print("on folder", os.path.abspath("./"))
|
||||
if params["recursive"]:
|
||||
run_all_subfolders(os.path.abspath("./"))
|
||||
else:
|
||||
update_folder(os.path.abspath("./"))
|
||||
|
||||
#group 2 will be the string, groups 1 and 3 will be the delimiters (" or ')
|
||||
#See https://stackoverflow.com/questions/46967465/regex-match-text-in-either-single-or-double-quote
|
||||
pattern_lua = re.compile(r'[\.=^\t,{\(\s]N?S\(\s*(["\'])((?:\\\1|(?:(?!\1)).)*)(\1)[\s,\)]', re.DOTALL)
|
||||
pattern_lua_bracketed = re.compile(r'[\.=^\t,{\(\s]N?S\(\s*\[\[(.*?)\]\][\s,\)]', re.DOTALL)
|
||||
|
||||
# Handles "concatenation" .. " of strings"
|
||||
pattern_concat = re.compile(r'["\'][\s]*\.\.[\s]*["\']', re.DOTALL)
|
||||
|
||||
pattern_tr = re.compile(r'(.+?[^@])=(.*)')
|
||||
pattern_name = re.compile(r'^name[ ]*=[ ]*([^ \n]*)')
|
||||
pattern_tr_filename = re.compile(r'\.tr$')
|
||||
pattern_po_language_code = re.compile(r'(.*)\.po$')
|
||||
|
||||
#attempt to read the mod's name from the mod.conf file. Returns None on failure
|
||||
def get_modname(folder):
|
||||
try:
|
||||
with open(os.path.join(folder, "mod.conf"), "r", encoding='utf-8') as mod_conf:
|
||||
for line in mod_conf:
|
||||
match = pattern_name.match(line)
|
||||
if match:
|
||||
return match.group(1)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
return None
|
||||
|
||||
#If there are already .tr files in /locale, returns a list of their names
|
||||
def get_existing_tr_files(folder):
|
||||
out = []
|
||||
for root, dirs, files in os.walk(os.path.join(folder, 'locale/')):
|
||||
for name in files:
|
||||
if pattern_tr_filename.search(name):
|
||||
out.append(name)
|
||||
return out
|
||||
|
||||
# A series of search and replaces that massage a .po file's contents into
|
||||
# a .tr file's equivalent
|
||||
def process_po_file(text):
|
||||
# The first three items are for unused matches
|
||||
text = re.sub(r'#~ msgid "', "", text)
|
||||
text = re.sub(r'"\n#~ msgstr ""\n"', "=", text)
|
||||
text = re.sub(r'"\n#~ msgstr "', "=", text)
|
||||
# comment lines
|
||||
text = re.sub(r'#.*\n', "", text)
|
||||
# converting msg pairs into "=" pairs
|
||||
text = re.sub(r'msgid "', "", text)
|
||||
text = re.sub(r'"\nmsgstr ""\n"', "=", text)
|
||||
text = re.sub(r'"\nmsgstr "', "=", text)
|
||||
# various line breaks and escape codes
|
||||
text = re.sub(r'"\n"', "", text)
|
||||
text = re.sub(r'"\n', "\n", text)
|
||||
text = re.sub(r'\\"', '"', text)
|
||||
text = re.sub(r'\\n', '@n', text)
|
||||
# remove header text
|
||||
text = re.sub(r'=Project-Id-Version:.*\n', "", text)
|
||||
# remove double-spaced lines
|
||||
text = re.sub(r'\n\n', '\n', text)
|
||||
return text
|
||||
|
||||
# Go through existing .po files and, if a .tr file for that language
|
||||
# *doesn't* exist, convert it and create it.
|
||||
# The .tr file that results will subsequently be reprocessed so
|
||||
# any "no longer used" strings will be preserved.
|
||||
# Note that "fuzzy" tags will be lost in this process.
|
||||
def process_po_files(folder, modname):
|
||||
for root, dirs, files in os.walk(os.path.join(folder, 'locale/')):
|
||||
for name in files:
|
||||
code_match = pattern_po_language_code.match(name)
|
||||
if code_match == None:
|
||||
continue
|
||||
language_code = code_match.group(1)
|
||||
tr_name = modname + "." + language_code + ".tr"
|
||||
tr_file = os.path.join(root, tr_name)
|
||||
if os.path.exists(tr_file):
|
||||
if params["verbose"]:
|
||||
print(f"{tr_name} already exists, ignoring {name}")
|
||||
continue
|
||||
fname = os.path.join(root, name)
|
||||
with open(fname, "r", encoding='utf-8') as po_file:
|
||||
if params["verbose"]:
|
||||
print(f"Importing translations from {name}")
|
||||
text = process_po_file(po_file.read())
|
||||
with open(tr_file, "wt", encoding='utf-8') as tr_out:
|
||||
tr_out.write(text)
|
||||
|
||||
# from https://stackoverflow.com/questions/600268/mkdir-p-functionality-in-python/600612#600612
|
||||
# Creates a directory if it doesn't exist, silently does
|
||||
# nothing if it already exists
|
||||
def mkdir_p(path):
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except OSError as exc: # Python >2.5
|
||||
if exc.errno == errno.EEXIST and os.path.isdir(path):
|
||||
pass
|
||||
else: raise
|
||||
|
||||
# Converts the template dictionary to a text to be written as a file
|
||||
# dKeyStrings is a dictionary of localized string to source file sets
|
||||
# dOld is a dictionary of existing translations and comments from
|
||||
# the previous version of this text
|
||||
def strings_to_text(dkeyStrings, dOld, mod_name):
|
||||
lOut = [f"# textdomain: {mod_name}\n"]
|
||||
|
||||
dGroupedBySource = {}
|
||||
|
||||
for key in dkeyStrings:
|
||||
sourceList = list(dkeyStrings[key])
|
||||
sourceList.sort()
|
||||
sourceString = "\n".join(sourceList)
|
||||
listForSource = dGroupedBySource.get(sourceString, [])
|
||||
listForSource.append(key)
|
||||
dGroupedBySource[sourceString] = listForSource
|
||||
|
||||
lSourceKeys = list(dGroupedBySource.keys())
|
||||
lSourceKeys.sort()
|
||||
for source in lSourceKeys:
|
||||
localizedStrings = dGroupedBySource[source]
|
||||
localizedStrings.sort()
|
||||
lOut.append("")
|
||||
lOut.append(source)
|
||||
lOut.append("")
|
||||
for localizedString in localizedStrings:
|
||||
val = dOld.get(localizedString, {})
|
||||
translation = val.get("translation", "")
|
||||
comment = val.get("comment")
|
||||
if len(localizedString) > doublespace_threshold and not lOut[-1] == "":
|
||||
lOut.append("")
|
||||
if comment != None:
|
||||
lOut.append(comment)
|
||||
lOut.append(f"{localizedString}={translation}")
|
||||
if len(localizedString) > doublespace_threshold:
|
||||
lOut.append("")
|
||||
|
||||
|
||||
unusedExist = False
|
||||
for key in dOld:
|
||||
if key not in dkeyStrings:
|
||||
val = dOld[key]
|
||||
translation = val.get("translation")
|
||||
comment = val.get("comment")
|
||||
# only keep an unused translation if there was translated
|
||||
# text or a comment associated with it
|
||||
if translation != None and (translation != "" or comment):
|
||||
if not unusedExist:
|
||||
unusedExist = True
|
||||
lOut.append("\n\n##### not used anymore #####\n")
|
||||
if len(key) > doublespace_threshold and not lOut[-1] == "":
|
||||
lOut.append("")
|
||||
if comment != None:
|
||||
lOut.append(comment)
|
||||
lOut.append(f"{key}={translation}")
|
||||
if len(key) > doublespace_threshold:
|
||||
lOut.append("")
|
||||
return "\n".join(lOut) + '\n'
|
||||
|
||||
# Writes a template.txt file
|
||||
# dkeyStrings is the dictionary returned by generate_template
|
||||
def write_template(templ_file, dkeyStrings, mod_name):
|
||||
# read existing template file to preserve comments
|
||||
existing_template = import_tr_file(templ_file)
|
||||
|
||||
text = strings_to_text(dkeyStrings, existing_template[0], mod_name)
|
||||
mkdir_p(os.path.dirname(templ_file))
|
||||
with open(templ_file, "wt", encoding='utf-8') as template_file:
|
||||
template_file.write(text)
|
||||
|
||||
|
||||
# Gets all translatable strings from a lua file
|
||||
def read_lua_file_strings(lua_file):
|
||||
lOut = []
|
||||
with open(lua_file, encoding='utf-8') as text_file:
|
||||
text = text_file.read()
|
||||
#TODO remove comments here
|
||||
|
||||
text = re.sub(pattern_concat, "", text)
|
||||
|
||||
strings = []
|
||||
for s in pattern_lua.findall(text):
|
||||
strings.append(s[1])
|
||||
for s in pattern_lua_bracketed.findall(text):
|
||||
strings.append(s)
|
||||
|
||||
for s in strings:
|
||||
s = re.sub(r'"\.\.\s+"', "", s)
|
||||
s = re.sub("@[^@=0-9]", "@@", s)
|
||||
s = s.replace('\\"', '"')
|
||||
s = s.replace("\\'", "'")
|
||||
s = s.replace("\n", "@n")
|
||||
s = s.replace("\\n", "@n")
|
||||
s = s.replace("=", "@=")
|
||||
lOut.append(s)
|
||||
return lOut
|
||||
|
||||
# Gets strings from an existing translation file
|
||||
# returns both a dictionary of translations
|
||||
# and the full original source text so that the new text
|
||||
# can be compared to it for changes.
|
||||
def import_tr_file(tr_file):
|
||||
dOut = {}
|
||||
text = None
|
||||
if os.path.exists(tr_file):
|
||||
with open(tr_file, "r", encoding='utf-8') as existing_file :
|
||||
# save the full text to allow for comparison
|
||||
# of the old version with the new output
|
||||
text = existing_file.read()
|
||||
existing_file.seek(0)
|
||||
# a running record of the current comment block
|
||||
# we're inside, to allow preceeding multi-line comments
|
||||
# to be retained for a translation line
|
||||
latest_comment_block = None
|
||||
for line in existing_file.readlines():
|
||||
line = line.rstrip('\n')
|
||||
if line[:3] == "###":
|
||||
# Reset comment block if we hit a header
|
||||
latest_comment_block = None
|
||||
continue
|
||||
if line[:1] == "#":
|
||||
# Save the comment we're inside
|
||||
if not latest_comment_block:
|
||||
latest_comment_block = line
|
||||
else:
|
||||
latest_comment_block = latest_comment_block + "\n" + line
|
||||
continue
|
||||
match = pattern_tr.match(line)
|
||||
if match:
|
||||
# this line is a translated line
|
||||
outval = {}
|
||||
outval["translation"] = match.group(2)
|
||||
if latest_comment_block:
|
||||
# if there was a comment, record that.
|
||||
outval["comment"] = latest_comment_block
|
||||
latest_comment_block = None
|
||||
dOut[match.group(1)] = outval
|
||||
return (dOut, text)
|
||||
|
||||
# Walks all lua files in the mod folder, collects translatable strings,
|
||||
# and writes it to a template.txt file
|
||||
# Returns a dictionary of localized strings to source file sets
|
||||
# that can be used with the strings_to_text function.
|
||||
def generate_template(folder, mod_name):
|
||||
dOut = {}
|
||||
for root, dirs, files in os.walk(folder):
|
||||
for name in files:
|
||||
if fnmatch.fnmatch(name, "*.lua"):
|
||||
fname = os.path.join(root, name)
|
||||
found = read_lua_file_strings(fname)
|
||||
if params["verbose"]:
|
||||
print(f"{fname}: {str(len(found))} translatable strings")
|
||||
|
||||
for s in found:
|
||||
sources = dOut.get(s, set())
|
||||
sources.add(f"### {os.path.basename(fname)} ###")
|
||||
dOut[s] = sources
|
||||
|
||||
if len(dOut) == 0:
|
||||
return None
|
||||
templ_file = os.path.join(folder, "locale/template.txt")
|
||||
write_template(templ_file, dOut, mod_name)
|
||||
return dOut
|
||||
|
||||
# Updates an existing .tr file, copying the old one to a ".old" file
|
||||
# if any changes have happened
|
||||
# dNew is the data used to generate the template, it has all the
|
||||
# currently-existing localized strings
|
||||
def update_tr_file(dNew, mod_name, tr_file):
|
||||
if params["verbose"]:
|
||||
print(f"updating {tr_file}")
|
||||
|
||||
tr_import = import_tr_file(tr_file)
|
||||
dOld = tr_import[0]
|
||||
textOld = tr_import[1]
|
||||
|
||||
textNew = strings_to_text(dNew, dOld, mod_name)
|
||||
|
||||
if textOld and textOld != textNew:
|
||||
print(f"{tr_file} has changed.")
|
||||
shutil.copyfile(tr_file, f"{tr_file}.old")
|
||||
|
||||
with open(tr_file, "w", encoding='utf-8') as new_tr_file:
|
||||
new_tr_file.write(textNew)
|
||||
|
||||
# Updates translation files for the mod in the given folder
|
||||
def update_mod(folder):
|
||||
modname = get_modname(folder)
|
||||
if modname is not None:
|
||||
process_po_files(folder, modname)
|
||||
print(f"Updating translations for {modname}")
|
||||
data = generate_template(folder, modname)
|
||||
if data == None:
|
||||
print(f"No translatable strings found in {modname}")
|
||||
else:
|
||||
for tr_file in get_existing_tr_files(folder):
|
||||
update_tr_file(data, modname, os.path.join(folder, "locale/", tr_file))
|
||||
else:
|
||||
print("Unable to find modname in folder " + folder)
|
||||
|
||||
# Determines if the folder being pointed to is a mod or a mod pack
|
||||
# and then runs update_mod accordingly
|
||||
def update_folder(folder):
|
||||
is_modpack = os.path.exists(os.path.join(folder, "modpack.txt")) or os.path.exists(os.path.join(folder, "modpack.conf"))
|
||||
if is_modpack:
|
||||
subfolders = [f.path for f in os.scandir(folder) if f.is_dir()]
|
||||
for subfolder in subfolders:
|
||||
update_mod(subfolder + "/")
|
||||
else:
|
||||
update_mod(folder)
|
||||
print("Done.")
|
||||
|
||||
def run_all_subfolders(folder):
|
||||
for modfolder in [f.path for f in os.scandir(folder) if f.is_dir()]:
|
||||
update_folder(modfolder + "/")
|
||||
|
||||
|
||||
main()
|
@ -1,6 +1,4 @@
|
||||
-- internationalization boilerplate
|
||||
local MP = minetest.get_modpath(minetest.get_current_modname())
|
||||
local S, NS = dofile(MP.."/intllib.lua")
|
||||
local S = minetest.get_translator("crafting_bench")
|
||||
|
||||
minetest.register_alias("castle:workbench", "crafting_bench:workbench")
|
||||
|
||||
@ -17,7 +15,7 @@ if crafting_rate == nil then crafting_rate = 5 end
|
||||
|
||||
minetest.register_node("crafting_bench:workbench",{
|
||||
description = S("Workbench"),
|
||||
_doc_items_longdesc = string.format(S("A workbench that does work for you. Set a crafting recipe and provide raw materials and items will magically craft themselves once every %i seconds."), crafting_rate),
|
||||
_doc_items_longdesc = S("A workbench that does work for you. Set a crafting recipe and provide raw materials and items will magically craft themselves once every @1 seconds.", crafting_rate),
|
||||
_doc_items_usagehelp = usage_help,
|
||||
tiles = {
|
||||
"crafting_bench_workbench_top.png",
|
||||
@ -58,13 +56,13 @@ minetest.register_node("crafting_bench:workbench",{
|
||||
return inv:is_empty("main")
|
||||
end,
|
||||
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
minetest.log("action", S("@1 moves stuff in workbench at @2", player:get_player_name(), minetest.pos_to_string(pos)))
|
||||
minetest.log("action", player:get_player_name().." moves stuff in workbench at "..minetest.pos_to_string(pos))
|
||||
end,
|
||||
on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
minetest.log("action", S("@1 moves stuff to workbench at @2", player:get_player_name(), minetest.pos_to_string(pos)))
|
||||
minetest.log("action", player:get_player_name().." moves stuff to workbench at "..minetest.pos_to_string(pos))
|
||||
end,
|
||||
on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||
minetest.log("action", S("@1 takes stuff from workbench at @2", player:get_player_name(), minetest.pos_to_string(pos)))
|
||||
minetest.log("action", player:get_player_name().." takes stuff from workbench at "..minetest.pos_to_string(pos))
|
||||
end,
|
||||
})
|
||||
local get_recipe = function ( inv )
|
||||
|
@ -1,45 +0,0 @@
|
||||
|
||||
-- Fallback functions for when `intllib` is not installed.
|
||||
-- Code released under Unlicense <http://unlicense.org>.
|
||||
|
||||
-- Get the latest version of this file at:
|
||||
-- https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua
|
||||
|
||||
local function format(str, ...)
|
||||
local args = { ... }
|
||||
local function repl(escape, open, num, close)
|
||||
if escape == "" then
|
||||
local replacement = tostring(args[tonumber(num)])
|
||||
if open == "" then
|
||||
replacement = replacement..close
|
||||
end
|
||||
return replacement
|
||||
else
|
||||
return "@"..open..num..close
|
||||
end
|
||||
end
|
||||
return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl))
|
||||
end
|
||||
|
||||
local gettext, ngettext
|
||||
if minetest.get_modpath("intllib") then
|
||||
if intllib.make_gettext_pair then
|
||||
-- New method using gettext.
|
||||
gettext, ngettext = intllib.make_gettext_pair()
|
||||
else
|
||||
-- Old method using text files.
|
||||
gettext = intllib.Getter()
|
||||
end
|
||||
end
|
||||
|
||||
-- Fill in missing functions.
|
||||
|
||||
gettext = gettext or function(msgid, ...)
|
||||
return format(msgid, ...)
|
||||
end
|
||||
|
||||
ngettext = ngettext or function(msgid, msgid_plural, n, ...)
|
||||
return format(n==1 and msgid or msgid_plural, ...)
|
||||
end
|
||||
|
||||
return gettext, ngettext
|
16
crafting_bench/locale/crafting_bench.fr.tr
Normal file
@ -0,0 +1,16 @@
|
||||
# textdomain: crafting_bench
|
||||
|
||||
|
||||
### init.lua ###
|
||||
|
||||
A workbench that does work for you. Set a crafting recipe and provide raw materials and items will magically craft themselves once every @1 seconds.=Un établi qui travaille pour vous. Définissez une recette de fabrication et fournissez les matériaux, et le résultat se fabriquera par magie toutes les @1 secondes.
|
||||
|
||||
Craft Output=Produits finis
|
||||
Recipe to Use=Recette à utiliser
|
||||
Source Material=Matériaux à utiliser
|
||||
|
||||
The inventory on the left is for raw materials, the inventory on the right holds finished products. The crafting grid in the center defines what recipe this workbench will make use of; place raw materials into it in the crafting pattern corresponding to what you want to build.=L’inventaire de gauche est pour les matériaux à utiliser, l’inventaire de droite contient les produits finis. La grille de fabrication au centre définit la recette que l’établi utilisera ; placez des matériaux dans la grille en suivant le pattern qui correspond à ce que vous voulez fabriquer.
|
||||
|
||||
This workbench is compatible with hoppers. Hoppers will insert into the raw material inventory and remove items from the finished goods inventory.=Cet établi est compatible avec les entonnoirs. Les entonoirs peuvent insérer des matériaux à utiliser et retirer les produits finis depuis les bons inventaires.
|
||||
|
||||
Workbench=Établi
|
@ -1,67 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-02-28 21:08-0700\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: init.lua:7
|
||||
msgid ""
|
||||
"The inventory on the left is for raw materials, the inventory on the right "
|
||||
"holds finished products. The crafting grid in the center defines what recipe "
|
||||
"this workbench will make use of; place raw materials into it in the crafting "
|
||||
"pattern corresponding to what you want to build."
|
||||
msgstr ""
|
||||
|
||||
#: init.lua:10
|
||||
msgid ""
|
||||
"This workbench is compatible with hoppers. Hoppers will insert into the raw "
|
||||
"material inventory and remove items from the finished goods inventory."
|
||||
msgstr ""
|
||||
|
||||
#: init.lua:19 init.lua:49
|
||||
msgid "Workbench"
|
||||
msgstr ""
|
||||
|
||||
#: init.lua:20
|
||||
#, lua-format
|
||||
msgid ""
|
||||
"A workbench that does work for you. Set a crafting recipe and provide raw "
|
||||
"materials and items will magically craft themselves once every %i seconds."
|
||||
msgstr ""
|
||||
|
||||
#: init.lua:42
|
||||
msgid "Source Material"
|
||||
msgstr ""
|
||||
|
||||
#: init.lua:44
|
||||
msgid "Recipe to Use"
|
||||
msgstr ""
|
||||
|
||||
#: init.lua:46
|
||||
msgid "Craft Output"
|
||||
msgstr ""
|
||||
|
||||
#: init.lua:61
|
||||
msgid "@1 moves stuff in workbench at @2"
|
||||
msgstr ""
|
||||
|
||||
#: init.lua:64
|
||||
msgid "@1 moves stuff to workbench at @2"
|
||||
msgstr ""
|
||||
|
||||
#: init.lua:67
|
||||
msgid "@1 takes stuff from workbench at @2"
|
||||
msgstr ""
|
16
crafting_bench/locale/template.txt
Normal file
@ -0,0 +1,16 @@
|
||||
# textdomain: crafting_bench
|
||||
|
||||
|
||||
### init.lua ###
|
||||
|
||||
A workbench that does work for you. Set a crafting recipe and provide raw materials and items will magically craft themselves once every @1 seconds.=
|
||||
|
||||
Craft Output=
|
||||
Recipe to Use=
|
||||
Source Material=
|
||||
|
||||
The inventory on the left is for raw materials, the inventory on the right holds finished products. The crafting grid in the center defines what recipe this workbench will make use of; place raw materials into it in the crafting pattern corresponding to what you want to build.=
|
||||
|
||||
This workbench is compatible with hoppers. Hoppers will insert into the raw material inventory and remove items from the finished goods inventory.=
|
||||
|
||||
Workbench=
|
@ -1 +1,4 @@
|
||||
name = crafting_bench
|
||||
description = An auto-crafting bench
|
||||
depends = default
|
||||
optional_depends = hopper, doc
|
||||
|
@ -1,8 +1,6 @@
|
||||
barter = {}
|
||||
|
||||
-- internationalization boilerplate
|
||||
local MP = minetest.get_modpath(minetest.get_current_modname())
|
||||
local S, NS = dofile(MP.."/intllib.lua")
|
||||
local S = minetest.get_translator("currency")
|
||||
|
||||
barter.chest = {}
|
||||
barter.chest.expire_after = tonumber(minetest.settings:get('barter.chest.expireafter')) or 15 * 60
|
||||
@ -12,20 +10,20 @@ barter.chest.formspec = {
|
||||
"list[current_name;pl2;5,0;3,4;]"..
|
||||
"list[current_player;main;0,5;8,4;]",
|
||||
pl1 = {
|
||||
start = "button[3,1;1,1;pl1_start;" .. S("Start") .. "]",
|
||||
player = function(name) return "label[3,0;"..name.."]" end,
|
||||
accept1 = "button[3,1;1,1;pl1_accept1;" .. S("Confirm") .. "]"..
|
||||
"button[3,2;1,1;pl1_cancel;" .. S("Cancel") .. "]",
|
||||
accept2 = "button[3,1;1,1;pl1_accept2;" .. S("Exchange") .. "]"..
|
||||
"button[3,2;1,1;pl1_cancel;" .. S("Cancel") .. "]",
|
||||
start = "button[0,4;3,1;pl1_start;" .. S("Start") .. "]",
|
||||
player = function(name) return "label[0,4;"..name.."]" end,
|
||||
accept1 = "button[2.9,1;1.2,1;pl1_accept1;" .. S("Confirm") .. "]"..
|
||||
"button[2.9,2;1.2,1;pl1_cancel;" .. S("Cancel") .. "]",
|
||||
accept2 = "button[2.9,1;1.2,1;pl1_accept2;" .. S("Exchange") .. "]"..
|
||||
"button[2.9,2;1.2,1;pl1_cancel;" .. S("Cancel") .. "]",
|
||||
},
|
||||
pl2 = {
|
||||
start = "button[4,1;1,1;pl2_start;" .. S("Start") .. "]",
|
||||
player = function(name) return "label[4,0;"..name.."]" end,
|
||||
accept1 = "button[4,1;1,1;pl2_accept1;" .. S("Confirm") .. "]"..
|
||||
"button[4,2;1,1;pl2_cancel;" .. S("Cancel") .. "]",
|
||||
accept2 = "button[4,1;1,1;pl2_accept2;" .. S("Exchange") .. "]"..
|
||||
"button[4,2;1,1;pl2_cancel;" .. S("Cancel") .. "]",
|
||||
start = "button[5,4;3,1;pl2_start;" .. S("Start") .. "]",
|
||||
player = function(name) return "label[5,4;"..name.."]" end,
|
||||
accept1 = "button[3.9,1;1.2,1;pl2_accept1;" .. S("Confirm") .. "]"..
|
||||
"button[3.9,2;1.2,1;pl2_cancel;" .. S("Cancel") .. "]",
|
||||
accept2 = "button[3.9,1;1.2,1;pl2_accept2;" .. S("Exchange") .. "]"..
|
||||
"button[3.9,2;1.2,1;pl2_cancel;" .. S("Cancel") .. "]",
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -1,58 +1,56 @@
|
||||
-- internationalization boilerplate
|
||||
local MP = minetest.get_modpath(minetest.get_current_modname())
|
||||
local S, NS = dofile(MP.."/intllib.lua")
|
||||
local S = minetest.get_translator("currency")
|
||||
|
||||
minetest.register_craftitem("currency:minegeld_cent_5", {
|
||||
description = S("5 Minegeld cent coin"),
|
||||
description = S("@1 Minegeld cent coin", "5"),
|
||||
inventory_image = "minegeld_cent_5.png",
|
||||
stack_max = 1000,
|
||||
groups = {minegeld = 1}
|
||||
})
|
||||
|
||||
minetest.register_craftitem("currency:minegeld_cent_10", {
|
||||
description = S("10 Minegeld cent coin"),
|
||||
description = S("@1 Minegeld cent coin", "10"),
|
||||
inventory_image = "minegeld_cent_10.png",
|
||||
stack_max = 1000,
|
||||
groups = {minegeld = 1}
|
||||
})
|
||||
|
||||
minetest.register_craftitem("currency:minegeld_cent_25", {
|
||||
description = S("25 Minegeld cent coin"),
|
||||
description = S("@1 Minegeld cent coin", "25"),
|
||||
inventory_image = "minegeld_cent_25.png",
|
||||
stack_max = 1000,
|
||||
groups = {minegeld = 1}
|
||||
})
|
||||
|
||||
minetest.register_craftitem("currency:minegeld", {
|
||||
description = S("1 Minegeld Note"),
|
||||
description = S("@1 Minegeld Note", "1"),
|
||||
inventory_image = "minegeld.png",
|
||||
stack_max = 65535,
|
||||
groups = {minegeld = 1}
|
||||
})
|
||||
|
||||
minetest.register_craftitem("currency:minegeld_5", {
|
||||
description = S("5 Minegeld Note"),
|
||||
description = S("@1 Minegeld Note", "5"),
|
||||
inventory_image = "minegeld_5.png",
|
||||
stack_max = 65535,
|
||||
groups = {minegeld = 1}
|
||||
})
|
||||
|
||||
minetest.register_craftitem("currency:minegeld_10", {
|
||||
description = S("10 Minegeld Note"),
|
||||
description = S("@1 Minegeld Note", "10"),
|
||||
inventory_image = "minegeld_10.png",
|
||||
stack_max = 65535,
|
||||
groups = {minegeld = 1}
|
||||
})
|
||||
|
||||
minetest.register_craftitem("currency:minegeld_50", {
|
||||
description = S("50 Minegeld Note"),
|
||||
description = S("@1 Minegeld Note", "50"),
|
||||
inventory_image = "minegeld_50.png",
|
||||
stack_max = 65535,
|
||||
groups = {minegeld = 1}
|
||||
})
|
||||
|
||||
minetest.register_craftitem("currency:minegeld_100", {
|
||||
description = S("100 Minegeld Note"),
|
||||
description = S("@1 Minegeld Note", "100"),
|
||||
inventory_image = "minegeld_100.png",
|
||||
stack_max = 65535,
|
||||
groups = {minegeld = 1}
|
||||
|
@ -1,4 +0,0 @@
|
||||
default
|
||||
intllib?
|
||||
loot?
|
||||
pipeworks?
|
@ -1 +0,0 @@
|
||||
Provides shops, barter tables, safes, and multiple denominations of currency, called "Minegeld".
|
@ -1,9 +1,5 @@
|
||||
local players_income = {}
|
||||
|
||||
-- internationalization boilerplate
|
||||
local MP = minetest.get_modpath(minetest.get_current_modname())
|
||||
local S, NS = dofile(MP.."/intllib.lua")
|
||||
|
||||
local income_enabled = minetest.settings:get_bool("currency.income_enabled", true)
|
||||
local income_item = minetest.settings:get("currency.income_item") or "currency:minegeld_10"
|
||||
local income_count = tonumber(minetest.settings:get("currency.income_count")) or 1
|
||||
@ -18,7 +14,7 @@ if income_enabled then
|
||||
for _, player in ipairs(minetest.get_connected_players()) do
|
||||
local name = player:get_player_name()
|
||||
players_income[name] = income_count
|
||||
minetest.log("info", "[Currency] "..S("basic income for @1", name))
|
||||
minetest.log("info", "[Currency] basic income for "..name)
|
||||
end
|
||||
end
|
||||
end)
|
||||
@ -32,7 +28,7 @@ if income_enabled then
|
||||
local inv = player:get_inventory()
|
||||
inv:add_item("main", {name=income_item, count=income_count})
|
||||
players_income[name] = nil
|
||||
minetest.log("info", "[Currency] "..S("added basic income for @1 to inventory", name))
|
||||
minetest.log("info", "[Currency] added basic income for "..name.." to inventory")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,24 +1,21 @@
|
||||
local modpath = minetest.get_modpath("currency")
|
||||
|
||||
-- internationalization boilerplate
|
||||
local S, NS = dofile(modpath.."/intllib.lua")
|
||||
|
||||
minetest.log("info", S("Currency mod loading..."))
|
||||
minetest.log("info", "Currency mod loading...")
|
||||
|
||||
dofile(modpath.."/craftitems.lua")
|
||||
minetest.log("info", "[Currency] "..S("Craft_items Loaded!"))
|
||||
minetest.log("info", "[Currency] Craft_items Loaded!")
|
||||
dofile(modpath.."/shop.lua")
|
||||
minetest.log("info", "[Currency] "..S("Shop Loaded!"))
|
||||
minetest.log("info", "[Currency] Shop Loaded!")
|
||||
dofile(modpath.."/barter.lua")
|
||||
minetest.log("info", "[Currency] "..S("Barter Loaded!"))
|
||||
minetest.log("info", "[Currency] Barter Loaded!")
|
||||
dofile(modpath.."/safe.lua")
|
||||
minetest.log("info", "[Currency] "..S("Safe Loaded!"))
|
||||
minetest.log("info", "[Currency] Safe Loaded!")
|
||||
dofile(modpath.."/crafting.lua")
|
||||
minetest.log("info", "[Currency] "..S("Crafting Loaded!"))
|
||||
minetest.log("info", "[Currency] Crafting Loaded!")
|
||||
|
||||
if minetest.settings:get_bool("creative_mode") then
|
||||
minetest.log("info", "[Currency] "..S("Creative mode in use, skipping basic income."))
|
||||
minetest.log("info", "[Currency] Creative mode in use, skipping basic income.")
|
||||
else
|
||||
dofile(modpath.."/income.lua")
|
||||
minetest.log("info", "[Currency] "..S("Income Loaded!"))
|
||||
minetest.log("info", "[Currency] Income Loaded!")
|
||||
end
|
||||
|
@ -1,45 +0,0 @@
|
||||
|
||||
-- Fallback functions for when `intllib` is not installed.
|
||||
-- Code released under Unlicense <http://unlicense.org>.
|
||||
|
||||
-- Get the latest version of this file at:
|
||||
-- https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua
|
||||
|
||||
local function format(str, ...)
|
||||
local args = { ... }
|
||||
local function repl(escape, open, num, close)
|
||||
if escape == "" then
|
||||
local replacement = tostring(args[tonumber(num)])
|
||||
if open == "" then
|
||||
replacement = replacement..close
|
||||
end
|
||||
return replacement
|
||||
else
|
||||
return "@"..open..num..close
|
||||
end
|
||||
end
|
||||
return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl))
|
||||
end
|
||||
|
||||
local gettext, ngettext
|
||||
if minetest.get_modpath("intllib") then
|
||||
if intllib.make_gettext_pair then
|
||||
-- New method using gettext.
|
||||
gettext, ngettext = intllib.make_gettext_pair()
|
||||
else
|
||||
-- Old method using text files.
|
||||
gettext = intllib.Getter()
|
||||
end
|
||||
end
|
||||
|
||||
-- Fill in missing functions.
|
||||
|
||||
gettext = gettext or function(msgid, ...)
|
||||
return format(msgid, ...)
|
||||
end
|
||||
|
||||
ngettext = ngettext or function(msgid, msgid_plural, n, ...)
|
||||
return format(n==1 and msgid or msgid_plural, ...)
|
||||
end
|
||||
|
||||
return gettext, ngettext
|
46
currency/locale/currency.de.tr
Normal file
@ -0,0 +1,46 @@
|
||||
# textdomain: currency
|
||||
# A.C.M. <undertakers_help@yahoo.com>, 2018
|
||||
|
||||
### barter.lua ###
|
||||
|
||||
Barter Table=Tausch Tisch
|
||||
Cancel=Abbruch
|
||||
Confirm=Bestätigen
|
||||
Start=Start
|
||||
|
||||
### shop.lua ###
|
||||
|
||||
Exchange=Tausch
|
||||
|
||||
### craftitems.lua ###
|
||||
|
||||
@1 Minegeld Note=@1 Minegeld Banknote
|
||||
@1 Minegeld cent coin=
|
||||
Bundle of random Minegeld notes=Bündel von verschiedenen Minegeld Banknoten
|
||||
|
||||
### safe.lua ###
|
||||
|
||||
Safe=Safe
|
||||
Safe (owned by @1)=Safe (gehört @1)
|
||||
|
||||
### shop.lua ###
|
||||
|
||||
Customer gets:=Kunde bekommt:
|
||||
Customer gives (pay here!)=Kunde gibt (bezahl hier!)
|
||||
Customers gave:=Kunde gab:
|
||||
Exchange can not be done, check if you put all items!=Tausch kann nicht abgeschlossen werden, prüfe nochmal alles was du hinein gelegt hast!
|
||||
Exchange can not be done, contact the shop owner.=Tausch kann nicht abgeschlossen werden, benachrichtige den Geschäftsinhaber.
|
||||
Exchange shop (owned by @1)=Tauschgeschäft (gehört @1)
|
||||
Exchanged!=Getauscht!
|
||||
In exchange, you give:=Im Tausch, du gibst:
|
||||
Owner gives:=Inhaber gibt:
|
||||
Owner wants:=Inhaber will:
|
||||
|
||||
Owner, Use (E)+Place (right mouse button) for customer interface=Inhaber, Benutze (E)+Platziere (rechte Maustaste) für Kunde ...
|
||||
|
||||
Shop=Geschäft
|
||||
This is your own shop, you can't exchange to yourself!=Das ist dein eigenes Geschäft, du kannst nicht mit dir selbst tauschen!
|
||||
You want:=Du willst:
|
||||
Your stock:=Dein Lager:
|
||||
|
||||
|
47
currency/locale/currency.fr.tr
Normal file
@ -0,0 +1,47 @@
|
||||
# textdomain: currency
|
||||
# Papou30, 2018.
|
||||
# Louis Royer, 2020.
|
||||
|
||||
### barter.lua ###
|
||||
|
||||
Barter Table=Table de troc
|
||||
Cancel=Annuler
|
||||
Confirm=Valider
|
||||
Start=Commencer
|
||||
|
||||
### shop.lua ###
|
||||
|
||||
Exchange=Troquer
|
||||
|
||||
### craftitems.lua ###
|
||||
|
||||
@1 Minegeld Note=@1 MineGeld
|
||||
@1 Minegeld cent coin=Pièce de @1 centimes de MineGeld
|
||||
Bundle of random Minegeld notes=Liasse de Minegeld de diverses valeurs
|
||||
|
||||
### safe.lua ###
|
||||
|
||||
Safe=Coffre-fort
|
||||
Safe (owned by @1)=Coffre-fort (appartenant à @1)
|
||||
|
||||
### shop.lua ###
|
||||
|
||||
Customer gets:=Client obtient:
|
||||
Customer gives (pay here!)=Client donne (payer ici!)
|
||||
Customers gave:=Le client a donné:
|
||||
Exchange can not be done, check if you put all items!=L'echange ne peut pas être fait, vérifiez que vous avez placé tous les articles!
|
||||
Exchange can not be done, contact the shop owner.=L'échange ne peut être fait, contactez le propriétaire du magasin.
|
||||
Exchange shop (owned by @1)=Boutique d'échange (appartenant à @1)
|
||||
Exchanged!=Échangé!
|
||||
In exchange, you give:=En échange, vous donnez :
|
||||
Owner gives:=Le propriétaire donne :
|
||||
Owner wants:=Le propriétaire veut :
|
||||
|
||||
Owner, Use (E)+Place (right mouse button) for customer interface=Propriétaire, utilisez Spécial+clic droit pour l'interface client
|
||||
|
||||
Shop=Boutique
|
||||
This is your own shop, you can't exchange to yourself!=C'est votre propre boutique, vous ne pouvez pas échanger avec vous-même!
|
||||
You want:=Vous voulez :
|
||||
Your stock:=Votre stock :
|
||||
|
||||
|
46
currency/locale/currency.ms.tr
Normal file
@ -0,0 +1,46 @@
|
||||
# textdomain: currency
|
||||
|
||||
|
||||
### barter.lua ###
|
||||
|
||||
Barter Table=Meja Barter
|
||||
Cancel=Batal
|
||||
Confirm=Sah
|
||||
Start=Mula
|
||||
|
||||
### shop.lua ###
|
||||
|
||||
Exchange=Tukar
|
||||
|
||||
### craftitems.lua ###
|
||||
|
||||
@1 Minegeld Note=Wang @1 MineGeld
|
||||
@1 Minegeld cent coin=
|
||||
Bundle of random Minegeld notes=Seberkas wang Minegeld rawak
|
||||
|
||||
### safe.lua ###
|
||||
|
||||
Safe=Peti besi
|
||||
Safe (owned by @1)=Peti besi (pemilik: @1)
|
||||
|
||||
### shop.lua ###
|
||||
|
||||
Customer gets:=Pelanggan dapat:
|
||||
Customer gives (pay here!)=Pelanggan beri (bayar sini!)
|
||||
Customers gave:=Pelanggan berikan:
|
||||
Exchange can not be done, check if you put all items!=Tak boleh jual, pastikan anda ada apa yang penjual mahukan!
|
||||
Exchange can not be done, contact the shop owner.=Tak boleh jual, hubungi penjual.
|
||||
Exchange shop (owned by @1)=Kedai (pemilik: @1)
|
||||
Exchanged!=Jual!
|
||||
In exchange, you give:=Anda berikan:
|
||||
Owner gives:=Penjual berikan:
|
||||
Owner wants:=Penjual inginkan:
|
||||
|
||||
Owner, Use (E)+Place (right mouse button) for customer interface=Penjual, Gunakan (E) + Letak (butang tetikus kanan) untuk antaramuka pelanggan
|
||||
|
||||
Shop=Kedai
|
||||
This is your own shop, you can't exchange to yourself!=Ini kedai anda, anda tidak boleh menjual kepada diri sendiri!
|
||||
You want:=Anda mahukan:
|
||||
Your stock:=Stok anda:
|
||||
|
||||
|
46
currency/locale/currency.ru.tr
Normal file
@ -0,0 +1,46 @@
|
||||
# textdomain: currency
|
||||
|
||||
|
||||
### barter.lua ###
|
||||
|
||||
Barter Table=Таблица бартера
|
||||
Cancel=Отмена
|
||||
Confirm=Подтверждение
|
||||
Start=Старт
|
||||
|
||||
### shop.lua ###
|
||||
|
||||
Exchange=Обмен
|
||||
|
||||
### craftitems.lua ###
|
||||
|
||||
@1 Minegeld Note=Банкнота в @1 MineGeld
|
||||
@1 Minegeld cent coin=
|
||||
Bundle of random Minegeld notes=Пачка случайных банкнот Minegeld
|
||||
|
||||
### safe.lua ###
|
||||
|
||||
Safe=Сейф
|
||||
Safe (owned by @1)=Сейф (принадлежит @1)
|
||||
|
||||
### shop.lua ###
|
||||
|
||||
Customer gets:=Покупатель получает:
|
||||
Customer gives (pay here!)=Покупатель отдаёт (здесь оплата!)
|
||||
Customers gave:=Покупатель отдал:
|
||||
Exchange can not be done, check if you put all items!=Обмен невозможен, проверьте, что вы положили все предметы!
|
||||
Exchange can not be done, contact the shop owner.=Обмен невозможен, свяжитесь с владельцем магазина.
|
||||
Exchange shop (owned by @1)=Пункт обмена (принадлежит @1)
|
||||
Exchanged!=Обмен произведён!
|
||||
In exchange, you give:=Взамен вы даёте:
|
||||
Owner gives:=Владелец отдаёт:
|
||||
Owner wants:=Владелец хочет:
|
||||
|
||||
Owner, Use (E)+Place (right mouse button) for customer interface=Владелец, используйте (E)+Разместить (правая кнопка мыши) для открытия интерфейса покупателя
|
||||
|
||||
Shop=Магазин
|
||||
This is your own shop, you can't exchange to yourself!=Это ваш собственный магазин, вы не можете обмениваться с самим собой!
|
||||
You want:=Вы хотите:
|
||||
Your stock:=Ваш запас:
|
||||
|
||||
|
@ -1,183 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2018-05-24 22:01+0200\n"
|
||||
"PO-Revision-Date: 2018-05-24 22:48+0200\n"
|
||||
"Last-Translator: A.C.M. <undertakers_help@yahoo.com>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.0.7\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: barter.lua
|
||||
msgid "Start"
|
||||
msgstr "Start"
|
||||
|
||||
#: barter.lua
|
||||
msgid "Confirm"
|
||||
msgstr "Bestätigen"
|
||||
|
||||
#: barter.lua
|
||||
msgid "Cancel"
|
||||
msgstr "Abbruch"
|
||||
|
||||
#: barter.lua shop.lua
|
||||
msgid "Exchange"
|
||||
msgstr "Tausch"
|
||||
|
||||
#: barter.lua
|
||||
msgid "Barter Table"
|
||||
msgstr "Tausch Tisch"
|
||||
|
||||
#: craftitems.lua
|
||||
msgid "1 MineGeld Note"
|
||||
msgstr "1 Minegeld Banknote"
|
||||
|
||||
#: craftitems.lua
|
||||
msgid "5 MineGeld Note"
|
||||
msgstr "5 Minegeld Banknote"
|
||||
|
||||
#: craftitems.lua
|
||||
msgid "10 MineGeld Note"
|
||||
msgstr "10 Minegeld Banknote"
|
||||
|
||||
#: craftitems.lua
|
||||
msgid "50 MineGeld Note"
|
||||
msgstr "50 Minegeld Banknote"
|
||||
|
||||
#: craftitems.lua
|
||||
msgid "Bundle of random Minegeld notes"
|
||||
msgstr "Bündel von verschiedenen Minegeld Banknoten"
|
||||
|
||||
#: income.lua
|
||||
msgid "basic income for @1"
|
||||
msgstr "Grundeinkommen für @1"
|
||||
|
||||
#: income.lua
|
||||
msgid "added basic income for @1 to inventory"
|
||||
msgstr "Grundeinkommen für @1 ins Inventar gelegt"
|
||||
|
||||
#: init.lua
|
||||
msgid "Currency mod loading..."
|
||||
msgstr "Currency mod lädt..."
|
||||
|
||||
#: init.lua
|
||||
msgid "Craft_items Loaded!"
|
||||
msgstr "Craft_items geladen!"
|
||||
|
||||
#: init.lua
|
||||
msgid "Shop Loaded!"
|
||||
msgstr "Geschäft geladen!"
|
||||
|
||||
#: init.lua
|
||||
msgid "Barter Loaded!"
|
||||
msgstr "Tauschtisch geladen!"
|
||||
|
||||
#: init.lua
|
||||
msgid "Safe Loaded!"
|
||||
msgstr "Safe geladen!"
|
||||
|
||||
#: init.lua
|
||||
msgid "Crafting Loaded!"
|
||||
msgstr "Crafting geladen!"
|
||||
|
||||
#: init.lua
|
||||
msgid "Creative mode in use, skipping basic income."
|
||||
msgstr "Kreativmodus eingeschalten, überspringe Grundeinkommen."
|
||||
|
||||
#: init.lua
|
||||
msgid "Income Loaded!"
|
||||
msgstr "Income geladen!"
|
||||
|
||||
#: safe.lua
|
||||
msgid "Safe"
|
||||
msgstr "Safe"
|
||||
|
||||
#: safe.lua
|
||||
msgid "Safe (owned by @1)"
|
||||
msgstr "Safe (gehört @1)"
|
||||
|
||||
#: safe.lua
|
||||
msgid "@1 tried to access a safe belonging to @2 at @3"
|
||||
msgstr "@1 versuchte den Zugriff auf Safe von @2 bei @3"
|
||||
|
||||
#: safe.lua
|
||||
msgid "@1 moves stuff in safe at @2"
|
||||
msgstr "@1 verschiebt Gegenstände in den Safe bei @2"
|
||||
|
||||
#: safe.lua
|
||||
msgid "@1 moves stuff to safe at @2"
|
||||
msgstr "@1 verschiebt Gegenstände nach Safe bei @2"
|
||||
|
||||
#: safe.lua
|
||||
msgid "@1 takes stuff from safe at @2"
|
||||
msgstr "@1 nimmt Gegenstände aus Safe bei @2"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Customer gives (pay here!)"
|
||||
msgstr "Kunde gibt (bezahl hier!)"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Customer gets:"
|
||||
msgstr "Kunde bekommt:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Owner wants:"
|
||||
msgstr "Inhaber will:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Owner gives:"
|
||||
msgstr "Inhaber gibt:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Customers gave:"
|
||||
msgstr "Kunde gab:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Your stock:"
|
||||
msgstr "Dein Lager:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "You want:"
|
||||
msgstr "Du willst:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "In exchange, you give:"
|
||||
msgstr "Im Tausch, du gibst:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Owner, Use (E)+Place (right mouse button) for customer interface"
|
||||
msgstr "Inhaber, Benutze (E)+Platziere (rechte Maustaste) für Kunde ..."
|
||||
|
||||
#: shop.lua
|
||||
msgid "Shop"
|
||||
msgstr "Geschäft"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Exchange shop (owned by @1)"
|
||||
msgstr "Tauschgeschäft (gehört @1)"
|
||||
|
||||
#: shop.lua
|
||||
msgid "This is your own shop, you can't exchange to yourself!"
|
||||
msgstr "Das ist dein eigenes Geschäft, du kannst nicht mit dir selbst tauschen!"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Exchanged!"
|
||||
msgstr "Getauscht!"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Exchange can not be done, contact the shop owner."
|
||||
msgstr "Tausch kann nicht abgeschlossen werden, benachrichtige den Geschäftsinhaber."
|
||||
|
||||
#: shop.lua
|
||||
msgid "Exchange can not be done, check if you put all items!"
|
||||
msgstr "Tausch kann nicht abgeschlossen werden, prüfe nochmal alles was du hinein gelegt hast!"
|
@ -1,187 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2018-05-24 23:06+0200\n"
|
||||
"PO-Revision-Date: 2018-05-12 14:55+0200\n"
|
||||
"Last-Translator: Papou30\n"
|
||||
"Language-Team: \n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.0.7\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: barter.lua
|
||||
msgid "Start"
|
||||
msgstr "Début"
|
||||
|
||||
#: barter.lua
|
||||
msgid "Confirm"
|
||||
msgstr "Confirmer"
|
||||
|
||||
#: barter.lua
|
||||
msgid "Cancel"
|
||||
msgstr "Annuler"
|
||||
|
||||
#: barter.lua shop.lua
|
||||
msgid "Exchange"
|
||||
msgstr "Échange"
|
||||
|
||||
#: barter.lua
|
||||
msgid "Barter Table"
|
||||
msgstr "Table de troc"
|
||||
|
||||
#: craftitems.lua
|
||||
msgid "1 MineGeld Note"
|
||||
msgstr "1 MineGeld"
|
||||
|
||||
#: craftitems.lua
|
||||
msgid "5 MineGeld Note"
|
||||
msgstr "5 MineGeld"
|
||||
|
||||
#: craftitems.lua
|
||||
msgid "10 MineGeld Note"
|
||||
msgstr "10 MineGeld"
|
||||
|
||||
#: craftitems.lua
|
||||
#, fuzzy
|
||||
msgid "50 MineGeld Note"
|
||||
msgstr "5 MineGeld"
|
||||
|
||||
#: craftitems.lua
|
||||
msgid "Bundle of random Minegeld notes"
|
||||
msgstr "Liasse de Minegeld aléatoire"
|
||||
|
||||
#: income.lua
|
||||
msgid "basic income for @1"
|
||||
msgstr "revenu de base pour @1"
|
||||
|
||||
#: income.lua
|
||||
msgid "added basic income for @1 to inventory"
|
||||
msgstr "revenu de base ajouté pour @1 à l'inventaire"
|
||||
|
||||
#: init.lua
|
||||
msgid "Currency mod loading..."
|
||||
msgstr "Chargement du mod Currency..."
|
||||
|
||||
#: init.lua
|
||||
msgid "Craft_items Loaded!"
|
||||
msgstr "Fabrication d'objets (Craft_items) chargé!"
|
||||
|
||||
#: init.lua
|
||||
msgid "Shop Loaded!"
|
||||
msgstr "Boutique (Shop) chargée!"
|
||||
|
||||
#: init.lua
|
||||
msgid "Barter Loaded!"
|
||||
msgstr "Troc (Barter) chargé!"
|
||||
|
||||
#: init.lua
|
||||
msgid "Safe Loaded!"
|
||||
msgstr "Coffre-fort (Safe) chargé!"
|
||||
|
||||
#: init.lua
|
||||
msgid "Crafting Loaded!"
|
||||
msgstr "Artisanat (Crafting) chargé!"
|
||||
|
||||
#: init.lua
|
||||
msgid "Creative mode in use, skipping basic income."
|
||||
msgstr "Mod créatif en cours d'utilisation, ignoré le revenu de base."
|
||||
|
||||
#: init.lua
|
||||
msgid "Income Loaded!"
|
||||
msgstr "Revenu de base (Income) chargé!"
|
||||
|
||||
#: safe.lua
|
||||
msgid "Safe"
|
||||
msgstr "Coffre-fort"
|
||||
|
||||
#: safe.lua
|
||||
msgid "Safe (owned by @1)"
|
||||
msgstr "Coffre-fort (appartenant à @1)"
|
||||
|
||||
#: safe.lua
|
||||
msgid "@1 tried to access a safe belonging to @2 at @3"
|
||||
msgstr "@1 a tenté d'accéder à un coffre-fort appartenant à @2 à @3"
|
||||
|
||||
#: safe.lua
|
||||
msgid "@1 moves stuff in safe at @2"
|
||||
msgstr "@1 déplace le matériel dans coffre-fort à @2"
|
||||
|
||||
#: safe.lua
|
||||
msgid "@1 moves stuff to safe at @2"
|
||||
msgstr "@1 déplace le matériel vers coffre-fort à @2"
|
||||
|
||||
#: safe.lua
|
||||
msgid "@1 takes stuff from safe at @2"
|
||||
msgstr "@1 prend le matériel dans le coffre-fort à @2"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Customer gives (pay here!)"
|
||||
msgstr "Client donne (payer ici!)"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Customer gets:"
|
||||
msgstr "Client obtient:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Owner wants:"
|
||||
msgstr "Le propriétaire veut:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Owner gives:"
|
||||
msgstr "Propriétaire donne:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Customers gave:"
|
||||
msgstr "Le client a donné:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Your stock:"
|
||||
msgstr "Votre stock:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "You want:"
|
||||
msgstr "Vous voulez:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "In exchange, you give:"
|
||||
msgstr "En échange, vous donnez:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Owner, Use (E)+Place (right mouse button) for customer interface"
|
||||
msgstr ""
|
||||
"Propriétaire, utilisez (E) + place (bouton droit de la souris) pour "
|
||||
"l'interface client"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Shop"
|
||||
msgstr "Boutique"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Exchange shop (owned by @1)"
|
||||
msgstr "Boutique d'échange (détenue par @1)"
|
||||
|
||||
#: shop.lua
|
||||
msgid "This is your own shop, you can't exchange to yourself!"
|
||||
msgstr "C'est ta propre boutique, tu ne peux pas échanger avec toi-même!"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Exchanged!"
|
||||
msgstr "Échangé!"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Exchange can not be done, contact the shop owner."
|
||||
msgstr "L'échange ne peut être fait, contactez le propriétaire du magasin."
|
||||
|
||||
#: shop.lua
|
||||
msgid "Exchange can not be done, check if you put all items!"
|
||||
msgstr ""
|
||||
"L'echange ne peut pas etre fait, verifiez si vous mettez tous les articles!"
|
@ -1,186 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2018-05-24 23:06+0200\n"
|
||||
"PO-Revision-Date: 2017-10-17 02:03+0800\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: ms\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.0.4\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: barter.lua
|
||||
msgid "Start"
|
||||
msgstr "Mula"
|
||||
|
||||
#: barter.lua
|
||||
msgid "Confirm"
|
||||
msgstr "Sah"
|
||||
|
||||
#: barter.lua
|
||||
msgid "Cancel"
|
||||
msgstr "Batal"
|
||||
|
||||
#: barter.lua shop.lua
|
||||
msgid "Exchange"
|
||||
msgstr "Tukar"
|
||||
|
||||
#: barter.lua
|
||||
msgid "Barter Table"
|
||||
msgstr "Meja Barter"
|
||||
|
||||
#: craftitems.lua
|
||||
msgid "1 MineGeld Note"
|
||||
msgstr "Wang 1 MineGeld"
|
||||
|
||||
#: craftitems.lua
|
||||
msgid "5 MineGeld Note"
|
||||
msgstr "Wang 5 MineGeld"
|
||||
|
||||
#: craftitems.lua
|
||||
msgid "10 MineGeld Note"
|
||||
msgstr "Wang 10 MineGeld"
|
||||
|
||||
#: craftitems.lua
|
||||
#, fuzzy
|
||||
msgid "50 MineGeld Note"
|
||||
msgstr "Wang 5 MineGeld"
|
||||
|
||||
#: craftitems.lua
|
||||
msgid "Bundle of random Minegeld notes"
|
||||
msgstr "Seberkas wang Minegeld rawak"
|
||||
|
||||
#: income.lua
|
||||
msgid "basic income for @1"
|
||||
msgstr "pendapatan asas untuk @1"
|
||||
|
||||
#: income.lua
|
||||
msgid "added basic income for @1 to inventory"
|
||||
msgstr "pendapatan asas untuk @1 ditambah masuk ke dalam inventori"
|
||||
|
||||
#: init.lua
|
||||
msgid "Currency mod loading..."
|
||||
msgstr "Memuatkan mods Currency..."
|
||||
|
||||
#: init.lua
|
||||
msgid "Craft_items Loaded!"
|
||||
msgstr "Item pertukangan dimuatkan!"
|
||||
|
||||
#: init.lua
|
||||
msgid "Shop Loaded!"
|
||||
msgstr "Kedai dimuatkan!"
|
||||
|
||||
#: init.lua
|
||||
msgid "Barter Loaded!"
|
||||
msgstr "Meja barter dimuatkan!"
|
||||
|
||||
#: init.lua
|
||||
msgid "Safe Loaded!"
|
||||
msgstr "Peti besi dimuatkan!"
|
||||
|
||||
#: init.lua
|
||||
msgid "Crafting Loaded!"
|
||||
msgstr "Pertukangan dimuatkan!"
|
||||
|
||||
#: init.lua
|
||||
msgid "Creative mode in use, skipping basic income."
|
||||
msgstr "Dalam mod kreatif, pendapatan asas diabaikan."
|
||||
|
||||
#: init.lua
|
||||
msgid "Income Loaded!"
|
||||
msgstr "Pendapatan dimuatkan!"
|
||||
|
||||
#: safe.lua
|
||||
msgid "Safe"
|
||||
msgstr "Peti besi"
|
||||
|
||||
#: safe.lua
|
||||
msgid "Safe (owned by @1)"
|
||||
msgstr "Peti besi (pemilik: @1)"
|
||||
|
||||
#: safe.lua
|
||||
msgid "@1 tried to access a safe belonging to @2 at @3"
|
||||
msgstr "@1 cuba untuk mengakses peti besi milik @2 di @3"
|
||||
|
||||
#: safe.lua
|
||||
msgid "@1 moves stuff in safe at @2"
|
||||
msgstr "@1 pindahkan barang dalam peti besi di @2"
|
||||
|
||||
#: safe.lua
|
||||
msgid "@1 moves stuff to safe at @2"
|
||||
msgstr "@1 masukkan barang dalam peti besi di @2"
|
||||
|
||||
#: safe.lua
|
||||
msgid "@1 takes stuff from safe at @2"
|
||||
msgstr "@1 keluarkan barang dari peti besi di @2"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Customer gives (pay here!)"
|
||||
msgstr "Pelanggan beri (bayar sini!)"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Customer gets:"
|
||||
msgstr "Pelanggan dapat:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Owner wants:"
|
||||
msgstr "Penjual inginkan:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Owner gives:"
|
||||
msgstr "Penjual berikan:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Customers gave:"
|
||||
msgstr "Pelanggan berikan:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Your stock:"
|
||||
msgstr "Stok anda:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "You want:"
|
||||
msgstr "Anda mahukan:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "In exchange, you give:"
|
||||
msgstr "Anda berikan:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Owner, Use (E)+Place (right mouse button) for customer interface"
|
||||
msgstr ""
|
||||
"Penjual, Gunakan (E) + Letak (butang tetikus kanan) untuk antaramuka "
|
||||
"pelanggan"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Shop"
|
||||
msgstr "Kedai"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Exchange shop (owned by @1)"
|
||||
msgstr "Kedai (pemilik: @1)"
|
||||
|
||||
#: shop.lua
|
||||
msgid "This is your own shop, you can't exchange to yourself!"
|
||||
msgstr "Ini kedai anda, anda tidak boleh menjual kepada diri sendiri!"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Exchanged!"
|
||||
msgstr "Jual!"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Exchange can not be done, contact the shop owner."
|
||||
msgstr "Tak boleh jual, hubungi penjual."
|
||||
|
||||
#: shop.lua
|
||||
msgid "Exchange can not be done, check if you put all items!"
|
||||
msgstr "Tak boleh jual, pastikan anda ada apa yang penjual mahukan!"
|
@ -1,187 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2018-05-24 23:06+0200\n"
|
||||
"PO-Revision-Date: 2017-08-11 19:03+0300\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: ru\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.0.3\n"
|
||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
|
||||
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
||||
|
||||
#: barter.lua
|
||||
msgid "Start"
|
||||
msgstr "Старт"
|
||||
|
||||
#: barter.lua
|
||||
msgid "Confirm"
|
||||
msgstr "Подтверждение"
|
||||
|
||||
#: barter.lua
|
||||
msgid "Cancel"
|
||||
msgstr "Отмена"
|
||||
|
||||
#: barter.lua shop.lua
|
||||
msgid "Exchange"
|
||||
msgstr "Обмен"
|
||||
|
||||
#: barter.lua
|
||||
msgid "Barter Table"
|
||||
msgstr "Таблица бартера"
|
||||
|
||||
#: craftitems.lua
|
||||
msgid "1 MineGeld Note"
|
||||
msgstr "Банкнота в 1 MineGeld"
|
||||
|
||||
#: craftitems.lua
|
||||
msgid "5 MineGeld Note"
|
||||
msgstr "Банкнота в 5 MineGeld"
|
||||
|
||||
#: craftitems.lua
|
||||
msgid "10 MineGeld Note"
|
||||
msgstr "Банкнота в 10 MineGeld"
|
||||
|
||||
#: craftitems.lua
|
||||
#, fuzzy
|
||||
msgid "50 MineGeld Note"
|
||||
msgstr "Банкнота в 5 MineGeld"
|
||||
|
||||
#: craftitems.lua
|
||||
msgid "Bundle of random Minegeld notes"
|
||||
msgstr "Пачка случайных банкнот Minegeld"
|
||||
|
||||
#: income.lua
|
||||
msgid "basic income for @1"
|
||||
msgstr "базовая прибыль для @1"
|
||||
|
||||
#: income.lua
|
||||
msgid "added basic income for @1 to inventory"
|
||||
msgstr "базовая прибыль для @1 добавлена в инвентарь"
|
||||
|
||||
#: init.lua
|
||||
msgid "Currency mod loading..."
|
||||
msgstr "Загружается мод Currency..."
|
||||
|
||||
#: init.lua
|
||||
msgid "Craft_items Loaded!"
|
||||
msgstr "Предметы для сборки загружены!"
|
||||
|
||||
#: init.lua
|
||||
msgid "Shop Loaded!"
|
||||
msgstr "Магазин загружен!"
|
||||
|
||||
#: init.lua
|
||||
msgid "Barter Loaded!"
|
||||
msgstr "Бартер загружен!"
|
||||
|
||||
#: init.lua
|
||||
msgid "Safe Loaded!"
|
||||
msgstr "Сейф загружен!"
|
||||
|
||||
#: init.lua
|
||||
msgid "Crafting Loaded!"
|
||||
msgstr "Механизм сборки загружен!"
|
||||
|
||||
#: init.lua
|
||||
msgid "Creative mode in use, skipping basic income."
|
||||
msgstr "Используется режим творчества, пропускаем базовую прибыль."
|
||||
|
||||
#: init.lua
|
||||
msgid "Income Loaded!"
|
||||
msgstr "Прибыль загружена!"
|
||||
|
||||
#: safe.lua
|
||||
msgid "Safe"
|
||||
msgstr "Сейф"
|
||||
|
||||
#: safe.lua
|
||||
msgid "Safe (owned by @1)"
|
||||
msgstr "Сейф (принадлежит @1)"
|
||||
|
||||
#: safe.lua
|
||||
msgid "@1 tried to access a safe belonging to @2 at @3"
|
||||
msgstr "@1 попробовал открыть сейф, принадлежащий @2 в @3"
|
||||
|
||||
#: safe.lua
|
||||
msgid "@1 moves stuff in safe at @2"
|
||||
msgstr "@1 перемещает вещи в сейфе в @2"
|
||||
|
||||
#: safe.lua
|
||||
msgid "@1 moves stuff to safe at @2"
|
||||
msgstr "@1 кладёт вещи в сейф в @2"
|
||||
|
||||
#: safe.lua
|
||||
msgid "@1 takes stuff from safe at @2"
|
||||
msgstr "@1 забирает вещи из сейфа в @2"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Customer gives (pay here!)"
|
||||
msgstr "Покупатель отдаёт (здесь оплата!)"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Customer gets:"
|
||||
msgstr "Покупатель получает:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Owner wants:"
|
||||
msgstr "Владелец хочет:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Owner gives:"
|
||||
msgstr "Владелец отдаёт:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Customers gave:"
|
||||
msgstr "Покупатель отдал:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Your stock:"
|
||||
msgstr "Ваш запас:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "You want:"
|
||||
msgstr "Вы хотите:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "In exchange, you give:"
|
||||
msgstr "Взамен вы даёте:"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Owner, Use (E)+Place (right mouse button) for customer interface"
|
||||
msgstr ""
|
||||
"Владелец, используйте (E)+Разместить (правая кнопка мыши) для открытия "
|
||||
"интерфейса покупателя"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Shop"
|
||||
msgstr "Магазин"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Exchange shop (owned by @1)"
|
||||
msgstr "Пункт обмена (принадлежит @1)"
|
||||
|
||||
#: shop.lua
|
||||
msgid "This is your own shop, you can't exchange to yourself!"
|
||||
msgstr "Это ваш собственный магазин, вы не можете обмениваться с самим собой!"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Exchanged!"
|
||||
msgstr "Обмен произведён!"
|
||||
|
||||
#: shop.lua
|
||||
msgid "Exchange can not be done, contact the shop owner."
|
||||
msgstr "Обмен невозможен, свяжитесь с владельцем магазина."
|
||||
|
||||
#: shop.lua
|
||||
msgid "Exchange can not be done, check if you put all items!"
|
||||
msgstr "Обмен невозможен, проверьте, что вы положили все предметы!"
|
@ -1,182 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2018-05-24 23:06+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: barter.lua
|
||||
msgid "Start"
|
||||
msgstr ""
|
||||
|
||||
#: barter.lua
|
||||
msgid "Confirm"
|
||||
msgstr ""
|
||||
|
||||
#: barter.lua
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: barter.lua shop.lua
|
||||
msgid "Exchange"
|
||||
msgstr ""
|
||||
|
||||
#: barter.lua
|
||||
msgid "Barter Table"
|
||||
msgstr ""
|
||||
|
||||
#: craftitems.lua
|
||||
msgid "1 MineGeld Note"
|
||||
msgstr ""
|
||||
|
||||
#: craftitems.lua
|
||||
msgid "5 MineGeld Note"
|
||||
msgstr ""
|
||||
|
||||
#: craftitems.lua
|
||||
msgid "10 MineGeld Note"
|
||||
msgstr ""
|
||||
|
||||
#: craftitems.lua
|
||||
msgid "50 MineGeld Note"
|
||||
msgstr ""
|
||||
|
||||
#: craftitems.lua
|
||||
msgid "Bundle of random Minegeld notes"
|
||||
msgstr ""
|
||||
|
||||
#: income.lua
|
||||
msgid "basic income for @1"
|
||||
msgstr ""
|
||||
|
||||
#: income.lua
|
||||
msgid "added basic income for @1 to inventory"
|
||||
msgstr ""
|
||||
|
||||
#: init.lua
|
||||
msgid "Currency mod loading..."
|
||||
msgstr ""
|
||||
|
||||
#: init.lua
|
||||
msgid "Craft_items Loaded!"
|
||||
msgstr ""
|
||||
|
||||
#: init.lua
|
||||
msgid "Shop Loaded!"
|
||||
msgstr ""
|
||||
|
||||
#: init.lua
|
||||
msgid "Barter Loaded!"
|
||||
msgstr ""
|
||||
|
||||
#: init.lua
|
||||
msgid "Safe Loaded!"
|
||||
msgstr ""
|
||||
|
||||
#: init.lua
|
||||
msgid "Crafting Loaded!"
|
||||
msgstr ""
|
||||
|
||||
#: init.lua
|
||||
msgid "Creative mode in use, skipping basic income."
|
||||
msgstr ""
|
||||
|
||||
#: init.lua
|
||||
msgid "Income Loaded!"
|
||||
msgstr ""
|
||||
|
||||
#: safe.lua
|
||||
msgid "Safe"
|
||||
msgstr ""
|
||||
|
||||
#: safe.lua
|
||||
msgid "Safe (owned by @1)"
|
||||
msgstr ""
|
||||
|
||||
#: safe.lua
|
||||
msgid "@1 tried to access a safe belonging to @2 at @3"
|
||||
msgstr ""
|
||||
|
||||
#: safe.lua
|
||||
msgid "@1 moves stuff in safe at @2"
|
||||
msgstr ""
|
||||
|
||||
#: safe.lua
|
||||
msgid "@1 moves stuff to safe at @2"
|
||||
msgstr ""
|
||||
|
||||
#: safe.lua
|
||||
msgid "@1 takes stuff from safe at @2"
|
||||
msgstr ""
|
||||
|
||||
#: shop.lua
|
||||
msgid "Customer gives (pay here!)"
|
||||
msgstr ""
|
||||
|
||||
#: shop.lua
|
||||
msgid "Customer gets:"
|
||||
msgstr ""
|
||||
|
||||
#: shop.lua
|
||||
msgid "Owner wants:"
|
||||
msgstr ""
|
||||
|
||||
#: shop.lua
|
||||
msgid "Owner gives:"
|
||||
msgstr ""
|
||||
|
||||
#: shop.lua
|
||||
msgid "Customers gave:"
|
||||
msgstr ""
|
||||
|
||||
#: shop.lua
|
||||
msgid "Your stock:"
|
||||
msgstr ""
|
||||
|
||||
#: shop.lua
|
||||
msgid "You want:"
|
||||
msgstr ""
|
||||
|
||||
#: shop.lua
|
||||
msgid "In exchange, you give:"
|
||||
msgstr ""
|
||||
|
||||
#: shop.lua
|
||||
msgid "Owner, Use (E)+Place (right mouse button) for customer interface"
|
||||
msgstr ""
|
||||
|
||||
#: shop.lua
|
||||
msgid "Shop"
|
||||
msgstr ""
|
||||
|
||||
#: shop.lua
|
||||
msgid "Exchange shop (owned by @1)"
|
||||
msgstr ""
|
||||
|
||||
#: shop.lua
|
||||
msgid "This is your own shop, you can't exchange to yourself!"
|
||||
msgstr ""
|
||||
|
||||
#: shop.lua
|
||||
msgid "Exchanged!"
|
||||
msgstr ""
|
||||
|
||||
#: shop.lua
|
||||
msgid "Exchange can not be done, contact the shop owner."
|
||||
msgstr ""
|
||||
|
||||
#: shop.lua
|
||||
msgid "Exchange can not be done, check if you put all items!"
|
||||
msgstr ""
|
44
currency/locale/template.txt
Normal file
@ -0,0 +1,44 @@
|
||||
# textdomain: currency
|
||||
|
||||
|
||||
### barter.lua ###
|
||||
|
||||
Barter Table=
|
||||
Cancel=
|
||||
Confirm=
|
||||
Start=
|
||||
|
||||
### shop.lua ###
|
||||
|
||||
Exchange=
|
||||
|
||||
### craftitems.lua ###
|
||||
|
||||
@1 Minegeld Note=
|
||||
@1 Minegeld cent coin=
|
||||
Bundle of random Minegeld notes=
|
||||
|
||||
### safe.lua ###
|
||||
|
||||
Safe=
|
||||
Safe (owned by @1)=
|
||||
|
||||
### shop.lua ###
|
||||
|
||||
Customer gets:=
|
||||
Customer gives (pay here!)=
|
||||
Customers gave:=
|
||||
Exchange can not be done, check if you put all items!=
|
||||
Exchange can not be done, contact the shop owner.=
|
||||
Exchange shop (owned by @1)=
|
||||
Exchanged!=
|
||||
In exchange, you give:=
|
||||
Owner gives:=
|
||||
Owner wants:=
|
||||
|
||||
Owner, Use (E)+Place (right mouse button) for customer interface=
|
||||
|
||||
Shop=
|
||||
This is your own shop, you can't exchange to yourself!=
|
||||
You want:=
|
||||
Your stock:=
|
@ -1,3 +1,4 @@
|
||||
name = currency
|
||||
depends = default
|
||||
optional_depends = intllib,loot,pipeworks
|
||||
optional_depends = loot, pipeworks
|
||||
description = Provides shops, barter tables, safes, and multiple denominations of currency, called "Minegeld".
|
||||
|
@ -1,6 +1,4 @@
|
||||
-- internationalization boilerplate
|
||||
local MP = minetest.get_modpath(minetest.get_current_modname())
|
||||
local S, NS = dofile(MP.."/intllib.lua")
|
||||
local S = minetest.get_translator("currency")
|
||||
|
||||
function default.get_safe_formspec(pos)
|
||||
local spos = pos.x .. "," .. pos.y .. "," ..pos.z
|
||||
@ -60,8 +58,9 @@ minetest.register_node("currency:safe", {
|
||||
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if not has_safe_privilege(meta, player) then
|
||||
minetest.log("action", S("@1 tried to access a safe belonging to @2 at @3",
|
||||
player:get_player_name(), meta:get_string("owner"), minetest.pos_to_string(pos)))
|
||||
minetest.log("action", player:get_player_name().." tried to access a safe belonging to "
|
||||
..meta:get_string("owner").." at "
|
||||
..minetest.pos_to_string(pos))
|
||||
return 0
|
||||
end
|
||||
return count
|
||||
@ -69,8 +68,9 @@ minetest.register_node("currency:safe", {
|
||||
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if not has_safe_privilege(meta, player) then
|
||||
minetest.log("action", S("@1 tried to access a safe belonging to @2 at @3",
|
||||
player:get_player_name(), meta:get_string("owner"), minetest.pos_to_string(pos)))
|
||||
minetest.log("action", player:get_player_name().." tried to access a safe belonging to "
|
||||
..meta:get_string("owner").." at "
|
||||
..minetest.pos_to_string(pos))
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
@ -78,20 +78,21 @@ minetest.register_node("currency:safe", {
|
||||
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if not has_safe_privilege(meta, player) then
|
||||
minetest.log("action", S("@1 tried to access a safe belonging to @2 at @3",
|
||||
player:get_player_name(), meta:get_string("owner"), minetest.pos_to_string(pos)))
|
||||
minetest.log("action", player:get_player_name().." tried to access a safe belonging to "
|
||||
..meta:get_string("owner").." at "
|
||||
..minetest.pos_to_string(pos))
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end,
|
||||
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
minetest.log("action", S("@1 moves stuff in safe at @2", player:get_player_name(), minetest.pos_to_string(pos)))
|
||||
minetest.log("action", player:get_player_name().." moves stuff in safe at "..minetest.pos_to_string(pos))
|
||||
end,
|
||||
on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
minetest.log("action", S("@1 moves stuff to safe at @2", player:get_player_name(), minetest.pos_to_string(pos)))
|
||||
minetest.log("action", player:get_player_name().." moves stuff to safe at "..minetest.pos_to_string(pos))
|
||||
end,
|
||||
on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||
minetest.log("action", S("@1 takes stuff from safe at @2", player:get_player_name(), minetest.pos_to_string(pos)))
|
||||
minetest.log("action", player:get_player_name().." takes stuff from safe at "..minetest.pos_to_string(pos))
|
||||
end,
|
||||
on_rightclick = function(pos, node, clicker)
|
||||
local meta = minetest.get_meta(pos)
|
||||
|
@ -1,6 +1,4 @@
|
||||
-- internationalization boilerplate
|
||||
local MP = minetest.get_modpath(minetest.get_current_modname())
|
||||
local S, NS = dofile(MP.."/intllib.lua")
|
||||
local S = minetest.get_translator("currency")
|
||||
|
||||
default.shop = {}
|
||||
default.shop.current_shop = {}
|
||||
@ -27,10 +25,10 @@ default.shop.formspec = {
|
||||
"list["..list_name..";customers_gave;0,0.5;3,2;]"..
|
||||
"label[0,2.5;" .. S("Your stock:") .. "]"..
|
||||
"list["..list_name..";stock;0,3;3,2;]"..
|
||||
"label[5,0;" .. S("You want:") .. "]"..
|
||||
"list["..list_name..";owner_wants;5,0.5;3,2;]"..
|
||||
"label[5,2.5;" .. S("In exchange, you give:") .. "]"..
|
||||
"list["..list_name..";owner_gives;5,3;3,2;]"..
|
||||
"label[4,0;" .. S("You want:") .. "]"..
|
||||
"list["..list_name..";owner_wants;4,0.5;3,2;]"..
|
||||
"label[4,2.5;" .. S("In exchange, you give:") .. "]"..
|
||||
"list["..list_name..";owner_gives;4,3;3,2;]"..
|
||||
"label[0,5;" .. S("Owner, Use (E)+Place (right mouse button) for customer interface") .. "]"..
|
||||
"list[current_player;main;0,5.5;8,4;]"
|
||||
return formspec
|
||||
@ -102,7 +100,7 @@ minetest.register_node("currency:shop", {
|
||||
local owner = placer:get_player_name()
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", S("Exchange shop (owned by @1)", owner))
|
||||
meta:set_string("owner",owner)
|
||||
meta:set_string("owner", owner)
|
||||
--[[meta:set_string("pl1","")
|
||||
meta:set_string("pl2","")]]
|
||||
local inv = meta:get_inventory()
|
||||
@ -166,7 +164,7 @@ minetest.register_on_player_receive_fields(function(sender, formname, fields)
|
||||
local pos = default.shop.current_shop[name]
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_string("owner") == name then
|
||||
minetest.chat_send_player(name,S("This is your own shop, you can't exchange to yourself!"))
|
||||
minetest.chat_send_player(name, S("This is your own shop, you can't exchange to yourself!"))
|
||||
else
|
||||
local minv = meta:get_inventory()
|
||||
local pinv = sender:get_inventory()
|
||||
@ -203,12 +201,12 @@ minetest.register_on_player_receive_fields(function(sender, formname, fields)
|
||||
minv:remove_item("stock",item)
|
||||
pinv:add_item("customer_gets",item)
|
||||
end
|
||||
minetest.chat_send_player(name,S("Exchanged!"))
|
||||
minetest.chat_send_player(name, S("Exchanged!"))
|
||||
else
|
||||
if owners_fault then
|
||||
minetest.chat_send_player(name,S("Exchange can not be done, contact the shop owner."))
|
||||
minetest.chat_send_player(name, S("Exchange can not be done, contact the shop owner."))
|
||||
else
|
||||
minetest.chat_send_player(name,S("Exchange can not be done, check if you put all items!"))
|
||||
minetest.chat_send_player(name, S("Exchange can not be done, check if you put all items!"))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -71,3 +71,12 @@ As in, [digiline][junction box][dirt][junction box][digiline] will work to trans
|
||||
How to use the I/O expander:
|
||||
After setting a channel, send a table (same format as a Luacontroller's "port" table) to set the output states.
|
||||
A table in this same format will be sent back whenever an input changes or you manually poll it by sending a "GET" message.
|
||||
|
||||
How to use the card reader:
|
||||
After setting a channel, swiping a card (punch the reader with the card to swipe) will send a message in the following format:
|
||||
{event = "read",data = "The data that was on the card"}
|
||||
To write a card, send a command in the following format:
|
||||
{command = "write",data = "The data to put on the card",description = "A description of what the card is for"}
|
||||
After sending the write command, swipe the card to be written and the reader will send back the following message:
|
||||
{event = "write"}
|
||||
Both blank and previously written cards can be written to. If the card was not blank, it will be overwritten.
|
||||
|