diff --git a/.luacheckrc b/.luacheckrc
new file mode 100644
index 0000000..952672d
--- /dev/null
+++ b/.luacheckrc
@@ -0,0 +1,26 @@
+std = "lua51+minetest"
+unused_args = false
+allow_defined_top = true
+max_line_length = 999
+
+stds.minetest = {
+	read_globals = {
+		"minetest",
+		"VoxelManip",
+		"VoxelArea",
+		"PseudoRandom",
+		"ItemStack",
+		"default",
+		table = {
+			fields = {
+				"copy",
+			},
+		},
+	}
+}
+
+read_globals = {
+	"toolranks",
+	"toolranks_extras",
+	"wielded_light",
+}
diff --git a/README.md b/README.md
index 81837d9..007394c 100644
--- a/README.md
+++ b/README.md
@@ -36,15 +36,15 @@ throwing.toolranks = true
 
 By default, the trajectory of the arrow is a simple parabola. You can set the vertical acceleration (acceleration of gravity) using `throwing.vertical_acceleration`.
 
-If you want a more realistic trajectory that uses a first-order modelling of air friction, you can set `throwing.realistic_trajectory` to true. In this mode, `throwing.frictional_coefficient` indicates the ratio between the friction force on the arrow and its velocity. It should be negative. The acceleration of the arrow is subsequently determined by dividing the force by the "mass" of the arrow, the reference mass of 1 being the mass of a simple steel arrow. Generally, the frictional coefficient should be quite small; a value of -1 will already drastically shorten the range of the arrow. The default is -0.5.
+If you want a more realistic trajectory that uses a first-order modelling of air friction, you can set `throwing.realistic_trajectory` to true. In this mode, `throwing.frictional_coefficient` indicates the ratio between the friction force on the arrow and its velocity. It should be negative. The acceleration of the arrow is subsequently determined by dividing the force by the "mass" of the arrow, the reference mass of 1 being the mass of the steel arrow in `throwing_arrows`. Generally, the frictional coefficient should be quite small; a value of -1 will already drastically shorten the range of the arrow. The default is -0.5.
 
 ### Initial velocity computation
 
-The mod provides three modes to compute the initial speed of an arrow: simple, strength or strengthmass.
+The mod provides three modes to compute the initial velocity of an arrow after it is shot: simple, strength and momentum.
 
-In simple mode, the initial velocity of the arrow is always the same. The `throwing.velocity_factor` contains the value of this velocity.
+In simple mode, the initial velocity of the arrow is always the same. The value of this velocity is controlled by the `throwing.velocity_factor` setting, which defaults to 19.
 
-In strength mode (the default), the initial velocity of the arrow only depends on the bow that is used---the more expensive the bow, the faster the arrow. The arrow strength is multiplied by the velocity factor to compute the speed of the arrow, an arrow strength of 1 is about the strength of the steel bow in `throwing_arrows`.
+In strength mode (the default), the initial velocity of the arrow only depends on the bow that is used---the more expensive the bow, the faster the arrow. The bow strength is multiplied by the velocity factor to compute the speed of the arrow. For reference, the steel bow in `throwing_arrows` has a strength of about 1.
 
 Finally, momentum mode is the most realistic. It computes the velocity of the arrow based on the bow strength, as in the strength mode, and on the mass of the arrow: the heavier the arrow, the slower it will be shot. It is called the momentum mode because, in this mode, the strength of a bow indicates the initial momentum of the arrow rather than its initial speed.
 
@@ -76,6 +76,7 @@ Definition: definition table, containing:
   * sound: sound to be played when the bow is used
   * delay: delay before throwing the arrow
   * no_toolranks: If true, toolranks support is disabled for this item. Defaults to false.
+  * strength: strength of the bow, see above. Defaults to 1.
 ]]
 
 -- Example:
@@ -93,6 +94,7 @@ Definition: definition table, containing:
   * tiles (essential): tiles of the arrow.
   * target (optional, defaulting to throwing.target_both): what the arrow is able to hit (throwing.target_node, throwing.target_object, throwing.target_both).
   * allow_protected (optional, defaulting to false): whether the arrow can be throw in a protected area
+  * mass (optional, defaulting to 1): the mass of the arrow (see above)
   * on_hit_sound (optional): sound played when the arrow hits a node or an object.
   * on_hit(self, pos, last_pos, node, object, hitter, data) (optional but very useful): callback function:
     - pos: the position of the hit node or object.
diff --git a/init.lua b/init.lua
index 4656126..a257473 100644
--- a/init.lua
+++ b/init.lua
@@ -7,6 +7,7 @@ throwing.target_node = 2
 throwing.target_both = 3
 
 throwing.modname = minetest.get_current_modname()
+local S = minetest.get_translator("throwing")
 local use_toolranks = minetest.get_modpath("toolranks") and minetest.settings:get_bool("throwing.toolranks", true)
 
 --------- Arrows functions ---------
@@ -24,7 +25,7 @@ function throwing.spawn_arrow_entity(pos, arrow, player)
 			return minetest.registered_items[arrow].throwing_entity(pos, player)
 		end
 	else
-		obj = minetest.add_entity(pos, "__builtin:item", arrow)
+		return minetest.add_entity(pos, "__builtin:item", arrow)
 	end
 end
 
@@ -109,13 +110,7 @@ local function shoot_arrow(def, toolranks_data, player, bow_index, throw_itself,
 	end
 
 	if not minetest.settings:get_bool("creative_mode") then
-		if new_stack then
-			inventory:set_stack("main", arrrow_index, new_stack)
-		else
-			local stack = inventory:get_stack("main", arrow_index)
-			stack:take_item()
-			inventory:set_stack("main", arrow_index, stack)
-		end
+		inventory:set_stack("main", arrow_index, new_stack)
 	end
 
 	return true
@@ -135,7 +130,7 @@ function throwing.arrow_step(self, dtime)
 		minetest.log(level or "action", "[throwing] Arrow "..(self.item or self.name).." throwed by player "..self.player.." "..tostring(self.timer).."s ago "..message)
 	end
 
-	local hit = function(pos, node, obj)
+	local hit = function(pos1, node1, obj)
 		if obj then
 			if obj:is_player() then
 				if obj:get_player_name() == self.player then -- Avoid hitting the hitter
@@ -154,7 +149,7 @@ function throwing.arrow_step(self, dtime)
 				player:get_inventory():add_item("main", self.item)
 			end
 			if self.on_hit_fails then
-				self:on_hit_fails(pos, player, self.data)
+				self:on_hit_fails(pos1, player, self.data)
 			end
 		end
 
@@ -164,14 +159,14 @@ function throwing.arrow_step(self, dtime)
 			return
 		end
 
-		if node and minetest.is_protected(pos, self.player) and not self.allow_protected then -- Forbid hitting nodes in protected areas
-			minetest.record_protection_violation(pos, self.player)
+		if node1 and minetest.is_protected(pos1, self.player) and not self.allow_protected then -- Forbid hitting nodes in protected areas
+			minetest.record_protection_violation(pos1, self.player)
 			logging("hitted a node into a protected area")
 			return
 		end
 
 		if self.on_hit then
-			local ret, reason = self:on_hit(pos, self.last_pos, node, obj, player, self.data)
+			local ret, reason = self:on_hit(pos1, self.last_pos, node1, obj, player, self.data)
 			if ret == false then
 				if reason then
 					logging(": on_hit function failed for reason: "..reason)
@@ -185,26 +180,32 @@ function throwing.arrow_step(self, dtime)
 		end
 
 		if self.on_hit_sound then
-			minetest.sound_play(self.on_hit_sound, {pos = pos, gain = 0.8})
+			minetest.sound_play(self.on_hit_sound, {pos = pos1, gain = 0.8})
 		end
-		if node then
-			logging("collided with node "..node.name.." at ("..pos.x..","..pos.y..","..pos.z..")")
+
+		local identifier
+		if node1 then
+			identifier = "node " .. node1.name
 		elseif obj then
 			if obj:get_luaentity() then
-				logging("collided with luaentity "..obj:get_luaentity().name.." at ("..pos.x..","..pos.y..","..pos.z..")")
+				identifier = "luaentity " .. obj:get_luaentity().name
 			elseif obj:is_player() then
-				logging("collided with player "..obj:get_player_name().." at ("..pos.x..","..pos.y..","..pos.z..")")
+				identifier = "player " .. obj:get_player_name()
 			else
-				logging("collided with object at ("..pos.x..","..pos.y..","..pos.z..")")
+				identifier = "unknown object"
 			end
 		end
+		if identifier then
+			logging("collided with " .. identifier .. " at " .. minetest.pos_to_string(pos1) .. ")")
+		end
 
 		-- Toolranks support: update bow uses
 		if self.toolranks then
 			local inventory = player:get_inventory()
 			-- Check that the player did not move the bow
-			if inventory:get_stack("main", self.toolranks.index):get_name() == self.toolranks.itemstack:get_name() then
-				local new_itemstack = toolranks.new_afteruse(self.toolranks.itemstack, player, nil, {wear = self.toolranks.wear})
+			local current_stack = inventory:get_stack("main", self.toolranks.index)
+			if current_stack:get_name() == self.toolranks.name then
+				local new_itemstack = toolranks.new_afteruse(current_stack, player, nil, {wear = self.toolranks.wear})
 				inventory:set_stack("main", self.toolranks.index, new_itemstack)
 			end
 		end
@@ -295,12 +296,12 @@ function throwing.register_arrow(name, def)
 		if minetest.settings:get_bool("throwing.allow_arrow_placing") and pointed_thing.above then
 			local playername = placer:get_player_name()
 			if not minetest.is_protected(pointed_thing.above, playername) then
-				minetest.log("action", "Player "..playername.." placed arrow "..name.." at ("..pointed_thing.above.x..","..pointed_thing.above.y..","..pointed_thing.above.z..")")
+				minetest.log("action", "Player "..playername.." placed arrow "..name.." at "..minetest.pos_to_string(pointed_thing.above))
 				minetest.set_node(pointed_thing.above, {name = name})
 				itemstack:take_item()
 				return itemstack
 			else
-				minetest.log("warning", "Player "..playername.." tried to place arrow "..name.." into a protected area at ("..pointed_thing.above.x..","..pointed_thing.above.y..","..pointed_thing.above.z..")")
+				minetest.log("warning", "Player "..playername.." tried to place arrow "..name.." into a protected area at "..minetest.pos_to_string(pointed_thing.above))
 				minetest.record_protection_violation(pointed_thing.above, playername)
 				return itemstack
 			end
@@ -353,6 +354,10 @@ end
 
 
 ---------- Bows -----------
+if use_toolranks and minetest.get_modpath("toolranks_extras") and toolranks_extras.register_tool_type then
+	toolranks_extras.register_tool_type("bow", S("bow"), S("Arrows thrown"))
+end
+
 function throwing.register_bow(name, def)
 	local enable_toolranks = use_toolranks and not def.no_toolranks
 
@@ -401,12 +406,20 @@ function throwing.register_bow(name, def)
 		minetest.after(def.delay or 0, function()
 			-- Re-check that the arrow can be thrown. Overwrite the new_stack
 			local old_new_stack = new_stack
-			res, new_stack = def.allow_shot(user, user:get_inventory():get_stack("main", arrow_index), arrow_index, true)
+
+			local arrow_stack = user:get_inventory():get_stack("main", arrow_index)
+
+			res, new_stack = def.allow_shot(user, arrow_stack, arrow_index, true)
+			if not res then
+				return
+			end
+
 			if not new_stack then
 				new_stack = old_new_stack
 			end
-			if not res then
-				return
+			if not new_stack then
+				arrow_stack:take_item()
+				new_stack = arrow_stack
 			end
 
 			-- Shoot arrow
@@ -414,7 +427,7 @@ function throwing.register_bow(name, def)
 			local toolranks_data
 			if enable_toolranks then
 				toolranks_data = {
-					itemstack = itemstack,
+					name = itemstack:get_name(),
 					index = bow_index,
 					wear = uses
 				}
@@ -428,7 +441,7 @@ function throwing.register_bow(name, def)
 
 			if def.throw_itself then
 				-- This is a bug. If we return ItemStack(nil), the player punches the entity,
-				-- and if the entity if a __builtin:item, it gets back to his inventory.
+				-- and if the entity is a __builtin:item, it gets back to his inventory.
 				minetest.after(0.1, function()
 					user:get_inventory():remove_item("main", itemstack)
 				end)
@@ -442,7 +455,7 @@ function throwing.register_bow(name, def)
 
 	if enable_toolranks then
 		def.original_description = def.original_description or def.description
-		def.description = toolranks.create_description(def.description, 0, 1)
+		def.description = toolranks.create_description(def.description)
 	end
 
 	minetest.register_tool(name, def)
diff --git a/locale/template.txt b/locale/template.txt
new file mode 100644
index 0000000..d46b065
--- /dev/null
+++ b/locale/template.txt
@@ -0,0 +1,7 @@
+# textdomain: throwing
+
+
+### init.lua ###
+
+Arrows thrown=
+bow=
diff --git a/locale/throwing.fr.tr b/locale/throwing.fr.tr
new file mode 100644
index 0000000..c42ecdb
--- /dev/null
+++ b/locale/throwing.fr.tr
@@ -0,0 +1,7 @@
+# textdomain: throwing
+
+
+### init.lua ###
+
+Arrows thrown=Flèches lancées
+bow=arc
diff --git a/mod.conf b/mod.conf
index 8bc0a97..8cbd9e3 100644
--- a/mod.conf
+++ b/mod.conf
@@ -1,3 +1,3 @@
 name = throwing
-optional_depends = wielded_light, toolranks
+optional_depends = wielded_light, toolranks, toolranks_extras
 description = Throwing library: provides an API for registering throwing and throwable things