Merge lp:~gunchleoc/widelands/i18n-20140307 into lp:widelands

Proposed by GunChleoc
Status: Merged
Merged at revision: 6866
Proposed branch: lp:~gunchleoc/widelands/i18n-20140307
Merge into: lp:widelands
Diff against target: 616 lines (+90/-70)
23 files modified
maps/MP Scenarios/Island Hopping.wmf/scripting/multiplayer_init.lua (+1/-0)
maps/MP Scenarios/Smugglers.wmf/scripting/texts.lua (+6/-6)
maps/Plateau.wmf/scripting/texts.lua (+1/-1)
scripting/win_conditions/02_collectors.lua (+8/-6)
scripting/win_conditions/04_wood_gnome.lua (+4/-4)
src/editor/ui_menus/editor_main_menu_load_map.cc (+1/-0)
src/editor/ui_menus/editor_main_menu_save_map.cc (+1/-0)
src/logic/production_program.cc (+29/-21)
src/logic/soldier.cc (+2/-4)
src/network/nethost.cc (+3/-3)
src/ui_fsmenu/editor_mapselect.cc (+1/-0)
src/ui_fsmenu/launchMPG.cc (+1/-0)
src/wui/encyclopedia_window.cc (+1/-1)
src/wui/game_main_menu_save_game.cc (+6/-2)
src/wui/playerdescrgroup.cc (+1/-1)
tribes/atlanteans/scripting/sc01_castle_village.lua (+4/-4)
tribes/barbarians/coalmine/help.lua (+3/-2)
tribes/barbarians/conf (+1/-1)
tribes/barbarians/deep_coalmine/help.lua (+3/-2)
tribes/barbarians/deeper_coalmine/help.lua (+3/-2)
tribes/barbarians/scripting/sc01_citadel_village.lua (+4/-4)
tribes/empire/scripting/sc01_castle_village.lua (+4/-4)
txts/README.lua (+2/-2)
To merge this branch: bzr merge lp:~gunchleoc/widelands/i18n-20140307
Reviewer Review Type Date Requested Status
SirVer Needs Information
Review via email: mp+210046@code.launchpad.net

Description of the change

Some more i18n fixes.

Catalogs and translations will need rebuilding.

To post a comment you must log in.
Revision history for this message
SirVer (sirver) wrote :

I have a question about the changes made to for example the wood gnome win condition.

having quotes for each line makes it really inconvenient to type those texts (in the source). I.e.

[[Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.]]

is much better than

[[Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod ]] ..
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, ]] ..
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo ]] ..
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse ]] ..
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non ]] ..
proident, sunt in culpa qui officia deserunt mollit anim id est laborum. ]] ..

Why are those changes necessary?

review: Needs Information
Revision history for this message
SirVer (sirver) wrote :

weird line breaks come from launchpad ....

Revision history for this message
GunChleoc (gunchleoc) wrote :

> I have a question about the changes made to for example the wood gnome win
> condition.
>
> having quotes for each line makes it really inconvenient to type those texts
> (in the source). I.e.
>
> [snip]
> Why are those changes necessary?

I am adding those because semantically empty line breaks are confusing for translators, thus creating extra work for them + head scratching.

Could you please have a look at game_main_menu_save_game.cc for me? I can't get it to work like I want and I can't find the problem. Look for the comment: // TODO: This should be ngettext(" %i player" etc. with boost::format, but it refuses to work, line 140 + 180. If I use boost::format on these with proper numbering, the number isn't displayed properly.

Revision history for this message
SirVer (sirver) wrote :

> I am adding those because semantically empty line breaks are confusing for translators, thus creating extra work for them + head scratching.

Can we find another way? How about introducing a 'texts' secion in each file where we do not care about the length of lines? We could do one sentence per translated unit or so. I think that makes it pretty easy to work with - it also means that diffs are more meaningful as each change is a change per sentence.

// TODO: This should be ngettext(" %i player" etc. with

not sure what the problem is here. I'll need to investigate a bit more. I put it onto my list.

I saw in some other places that you had trouble with segfaults. The reason is that only boost::format understands std::string directly. Everything else needs .c_str() like so:

std::string a = "Hello"
snprintf(..."%s", a.c_str())

as those are old apis that can only deal with plain old c strings, not with classes.

Revision history for this message
GunChleoc (gunchleoc) wrote :

> > I am adding those because semantically empty line breaks are confusing for
> translators, thus creating extra work for them + head scratching.
>
> Can we find another way? How about introducing a 'texts' secion in each file
> where we do not care about the length of lines? We could do one sentence per
> translated unit or so. I think that makes it pretty easy to work with - it
> also means that diffs are more meaningful as each change is a change per
> sentence.

OK, I will do that in the future. Most of the long texts are in scenarios as well.

I have created strings like that all over the place, maybe leave them for now and only change the code when we need to fix a string?

> // TODO: This should be ngettext(" %i player" etc. with
>
> not sure what the problem is here. I'll need to investigate a bit more. I put
> it onto my list.
>
> I saw in some other places that you had trouble with segfaults. The reason is
> that only boost::format understands std::string directly. Everything else
> needs .c_str() like so:

I copy/pasted code that is working from somewhere else, so the problem must be in turning the number into a string somehow. I tried both %u and %i, something like this:

(format(ngettext("%u player", "%u players, player_no)) % player_no).str().c_str()
Maybe it's a stupid error with the brackets or something.

Revision history for this message
SirVer (sirver) wrote :

I merged this now and fixed the issue you had with boost::format. The problem here was that player_no was defined to be a [u]int_8 which is the same as unsigned char on most systems. boost now does not understand that this is not a single character, but indeed a small integer value. I got around this by defining player_no to be a simple int (i.e. 4 byte integer). You could also cast in the future:

(format(ngettext("%u player", "%u players, player_no)) % static_cast<int>(player_no)).str().c_str()

Revision history for this message
GunChleoc (gunchleoc) wrote :

Thanks!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'maps/MP Scenarios/Island Hopping.wmf/scripting/multiplayer_init.lua'
--- maps/MP Scenarios/Island Hopping.wmf/scripting/multiplayer_init.lua 2014-03-05 18:47:03 +0000
+++ maps/MP Scenarios/Island Hopping.wmf/scripting/multiplayer_init.lua 2014-03-08 16:14:22 +0000
@@ -129,6 +129,7 @@
129 elseif resource == "goldore" then129 elseif resource == "goldore" then
130 return ngettext("%s Gold Ore","%s Gold Ore",count):bformat(count)130 return ngettext("%s Gold Ore","%s Gold Ore",count):bformat(count)
131 else131 else
132 -- TRANSLATORS: number + resource name, e.g. '1 stone'
132 return (_"%1$i %2$s"):bformat(count, resource)133 return (_"%1$i %2$s"):bformat(count, resource)
133 end134 end
134end135end
135136
=== modified file 'maps/MP Scenarios/Smugglers.wmf/scripting/texts.lua'
--- maps/MP Scenarios/Smugglers.wmf/scripting/texts.lua 2014-03-03 20:50:30 +0000
+++ maps/MP Scenarios/Smugglers.wmf/scripting/texts.lua 2014-03-08 16:14:22 +0000
@@ -11,7 +11,7 @@
11[[To establish a smuggling route, you need to build a warehouse on a sending/receiving spot ]] ..11[[To establish a smuggling route, you need to build a warehouse on a sending/receiving spot ]] ..
12[[while your team mate has to build one on the corresponding receiving/sending spot. ]] ..12[[while your team mate has to build one on the corresponding receiving/sending spot. ]] ..
13[[A ware is then transported every 10 seconds. ]]) ..13[[A ware is then transported every 10 seconds. ]]) ..
14-- TRANSLATORS: %s = "<number> points"14-- TRANSLATORS: %s = '<number> points'
15_([[For harder to defend smuggling routes, you get 2 or 3 points per ware smuggled. The first team to collect %s wins.]]15_([[For harder to defend smuggling routes, you get 2 or 3 points per ware smuggled. The first team to collect %s wins.]]
16)) ..16)) ..
17 rt("image=map:send_spot.png", p(_"A sending spot")) ..17 rt("image=map:send_spot.png", p(_"A sending spot")) ..
@@ -25,30 +25,30 @@
25[[You can see the number of wares traded at any time in the general statistics menu. Good luck!]]25[[You can see the number of wares traded at any time in the general statistics menu. Good luck!]]
26)))26)))
2727
28-- TRANSLATORS: the first 2 parameters are player names, the last parameter is "<number> points"28-- TRANSLATORS: the first 2 parameters are player names, the last parameter is '<number> points'
29smuggling_route_established_other_team = rt(p(_(29smuggling_route_established_other_team = rt(p(_(
30[[A new smuggling route from %1$s to %2$s has been established! ]] ..30[[A new smuggling route from %1$s to %2$s has been established! ]] ..
31[[Every ware they smuggle there is worth %3$s.]]31[[Every ware they smuggle there is worth %3$s.]]
32)))32)))
33-- TRANSLATORS: %s = "<number> points"33-- TRANSLATORS: %s = '<number> points'
34smuggling_route_established_sender = rt(p(_(34smuggling_route_established_sender = rt(p(_(
35[[Your team has established a new smuggling route. You have the sending warehouse. ]] ..35[[Your team has established a new smuggling route. You have the sending warehouse. ]] ..
36[[Every ware smuggled here is worth %s.]]36[[Every ware smuggled here is worth %s.]]
37)))37)))
38-- TRANSLATORS: %s = "<number> points"38-- TRANSLATORS: %s = '<number> points'
39smuggling_route_established_receiver = rt(p(_(39smuggling_route_established_receiver = rt(p(_(
40[[Your team has established a new smuggling route. You have the receiving warehouse. ]] ..40[[Your team has established a new smuggling route. You have the receiving warehouse. ]] ..
41[[Every ware smuggled here is worth %s.]]41[[Every ware smuggled here is worth %s.]]
42)))42)))
4343
44-- TRANSLATORS: the first parameter is "<number> points", the last 2 parameters are player names44-- TRANSLATORS: the first parameter is '<number> points', the last 2 parameters are player names
45smuggling_route_broken = rt(p(_45smuggling_route_broken = rt(p(_
46[[The smuggling route worth %1$s from %2$s to %3$s has been broken!]]46[[The smuggling route worth %1$s from %2$s to %3$s has been broken!]]
47))47))
4848
49game_over = rt(49game_over = rt(
50 h1("Game over!") ..50 h1("Game over!") ..
51-- TRANSLATORS: the first 4 parameters are player names, the last parameter is "<number> points"51-- TRANSLATORS: the first 4 parameters are player names, the last parameter is '<number> points'
52 p(_52 p(_
53[[Game over! %1$s and %2$s have won the game! %3$s and %4$s only managed to collect %5$s.]]53[[Game over! %1$s and %2$s have won the game! %3$s and %4$s only managed to collect %5$s.]]
54)54)
5555
=== modified file 'maps/Plateau.wmf/scripting/texts.lua'
--- maps/Plateau.wmf/scripting/texts.lua 2014-02-26 16:52:26 +0000
+++ maps/Plateau.wmf/scripting/texts.lua 2014-03-08 16:14:22 +0000
@@ -53,7 +53,7 @@
53 "<rt><p line-spacing=3 font-size=12>" .. reflow(text)53 "<rt><p line-spacing=3 font-size=12>" .. reflow(text)
54 objs = {...}54 objs = {...}
55 if #objs > 0 then55 if #objs > 0 then
56 s = s .. "<br><br></p></rt>" .. rt(h2(_"New Objectives")) .. "<rt><p line-spacing=3 font-size=12>"56 s = s .. "<br><br></p></rt>" .. rt(h2(_"New Objective")) .. "<rt><p line-spacing=3 font-size=12>"
57 local i = 157 local i = 1
58 while i < #objs do58 while i < #objs do
59 s = s .. reflow(objs[i].body) .. "<br>"59 s = s .. reflow(objs[i].body) .. "<br>"
6060
=== modified file 'scripting/win_conditions/02_collectors.lua'
--- scripting/win_conditions/02_collectors.lua 2014-02-24 17:19:30 +0000
+++ scripting/win_conditions/02_collectors.lua 2014-03-08 16:14:22 +0000
@@ -4,6 +4,7 @@
44
5use("aux", "coroutine") -- for sleep5use("aux", "coroutine") -- for sleep
6use("aux", "table")6use("aux", "table")
7use("aux", "formatting")
7use("aux", "win_condition_functions")8use("aux", "win_condition_functions")
89
9set_textdomain("win_conditions")10set_textdomain("win_conditions")
@@ -92,7 +93,7 @@
92 )93 )
9394
94 local points = 095 local points = 0
95 local descr = { (_"Status for %s"):format(plr.name) .. "<br>"}96 local descr = { "</p>" .. h2((_"Status for %s"):format(plr.name)) .. "<p line-spacing=3 font-size=12>"}
96 for idx, ware in ipairs(point_table[plr.tribe_name .. "_order"]) do97 for idx, ware in ipairs(point_table[plr.tribe_name .. "_order"]) do
97 local value = point_table[plr.tribe_name][ware]98 local value = point_table[plr.tribe_name][ware]
98 local count = 099 local count = 0
@@ -101,12 +102,13 @@
101 end102 end
102 local lpoints = count * value103 local lpoints = count * value
103 points = points + lpoints104 points = points + lpoints
104 -- TRANSLATORS: For example: "gold (3 P) x 4 = 12 P", P meaning "Points"105 -- TRANSLATORS: For example: 'gold (3 P) x 4 = 12 P", P meaning "Points'
105 descr[#descr+1] = (_" %1$s (%2$i P) x %3$i = %4$i P<br>"):bformat(106 descr[#descr+1] = [[• ]] .. (_" %1$s (%2$i P) x %3$i = %4$i P"):bformat(
106 ware, value, count, lpoints107 ware, value, count, lpoints
107 )108 ) .. "<br>"
108 end109 end
109 descr[#descr+1] = (ngettext("Total: %i point", "Total: %i points", points)):format(points)110 descr[#descr+1] = "</p>" .. h3(ngettext("Total: %i point", "Total: %i points", points)):format(points)
111 .. "<p line-spacing=3 font-size=12>"
110 return points, p(table.concat(descr, "\n"))112 return points, p(table.concat(descr, "\n"))
111end113end
112114
@@ -117,7 +119,7 @@
117 local m = remaining_time % 60119 local m = remaining_time % 60
118 local time = ""120 local time = ""
119 if h > 0 then121 if h > 0 then
120 -- TRANSLATORS: Context: "The game will end in %s."122 -- TRANSLATORS: Context: 'The game will end in %s.'
121 time = (_"%1$ih%2$02im"):bformat(h,m)123 time = (_"%1$ih%2$02im"):bformat(h,m)
122 else124 else
123 time = (ngettext("%i minute", "%i minutes", m)):format(m)125 time = (ngettext("%i minute", "%i minutes", m)):format(m)
124126
=== modified file 'scripting/win_conditions/04_wood_gnome.lua'
--- scripting/win_conditions/04_wood_gnome.lua 2014-03-03 20:50:30 +0000
+++ scripting/win_conditions/04_wood_gnome.lua 2014-03-08 16:14:22 +0000
@@ -12,10 +12,10 @@
1212
13local wc_name = _ "Wood Gnome"13local wc_name = _ "Wood Gnome"
14local wc_version = 214local wc_version = 2
15local wc_desc = _15local wc_desc = _(
16[[As wood gnome you like big forests, so your task is to have more trees on16[[As wood gnome you like big forests, so your task is to have more trees on ]] ..
17your territory than any other player. The game will end after 4 hours of17[[your territory than any other player. The game will end after 4 hours of ]] ..
18playing. The one with the most trees at that point will win the game.]]18[[playing. The one with the most trees at that point will win the game.]])
19local wc_trees_owned = _"Trees owned"19local wc_trees_owned = _"Trees owned"
20return {20return {
21 name = wc_name,21 name = wc_name,
2222
=== modified file 'src/editor/ui_menus/editor_main_menu_load_map.cc'
--- src/editor/ui_menus/editor_main_menu_load_map.cc 2014-03-05 11:59:09 +0000
+++ src/editor/ui_menus/editor_main_menu_load_map.cc 2014-03-08 16:14:22 +0000
@@ -221,6 +221,7 @@
221 m_parentdir = m_curdir.substr(0, m_curdir.rfind('\\'));221 m_parentdir = m_curdir.substr(0, m_curdir.rfind('\\'));
222#endif222#endif
223 std::string parent_string =223 std::string parent_string =
224 /** TRANSLATORS: Parent directory */
224 (boost::format("\\<%s\\>") % _("parent")).str();225 (boost::format("\\<%s\\>") % _("parent")).str();
225 m_ls->add226 m_ls->add
226 (parent_string.c_str(),227 (parent_string.c_str(),
227228
=== modified file 'src/editor/ui_menus/editor_main_menu_save_map.cc'
--- src/editor/ui_menus/editor_main_menu_save_map.cc 2014-03-05 11:59:09 +0000
+++ src/editor/ui_menus/editor_main_menu_save_map.cc 2014-03-08 16:14:22 +0000
@@ -294,6 +294,7 @@
294 m_parentdir = m_curdir.substr(0, m_curdir.rfind('\\'));294 m_parentdir = m_curdir.substr(0, m_curdir.rfind('\\'));
295#endif295#endif
296 std::string parent_string =296 std::string parent_string =
297 /** TRANSLATORS: Parent directory */
297 (boost::format("\\<%s\\>") % _("parent")).str();298 (boost::format("\\<%s\\>") % _("parent")).str();
298 m_ls->add299 m_ls->add
299 (parent_string.c_str(),300 (parent_string.c_str(),
300301
=== modified file 'src/logic/production_program.cc'
--- src/logic/production_program.cc 2014-03-04 13:24:58 +0000
+++ src/logic/production_program.cc 2014-03-08 16:14:22 +0000
@@ -151,7 +151,7 @@
151std::string ProductionProgram::ActReturn::Negation::description151std::string ProductionProgram::ActReturn::Negation::description
152 (const Tribe_Descr & tribe) const152 (const Tribe_Descr & tribe) const
153{153{
154 /** TRANSLATORS: %s = e.g. "economy needs ..." Context: "and/or not %s" */154 /** TRANSLATORS: %s = e.g. 'economy needs ...' Context: 'and/or not %s' */
155 return (boost::format(_("not %s")) % operand->description(tribe)).str();155 return (boost::format(_("not %s")) % operand->description(tribe)).str();
156}156}
157157
@@ -174,7 +174,7 @@
174std::string ProductionProgram::ActReturn::Economy_Needs_Ware::description174std::string ProductionProgram::ActReturn::Economy_Needs_Ware::description
175 (const Tribe_Descr & tribe) const175 (const Tribe_Descr & tribe) const
176{176{
177 /** TRANSLATORS: e.g. "economy needs water" Context: "and/or (not) economy needs %s" */177 /** TRANSLATORS: e.g. 'economy needs water' Context: 'and/or (not) economy needs %s' */
178 return (boost::format(_("economy needs %s")) % tribe.get_ware_descr(ware_type)->descname()).str();178 return (boost::format(_("economy needs %s")) % tribe.get_ware_descr(ware_type)->descname()).str();
179}179}
180180
@@ -196,7 +196,7 @@
196std::string ProductionProgram::ActReturn::Economy_Needs_Worker::description196std::string ProductionProgram::ActReturn::Economy_Needs_Worker::description
197 (const Tribe_Descr & tribe) const197 (const Tribe_Descr & tribe) const
198{198{
199 /** TRANSLATORS: e.g. "economy needs worker" Context: "and/or (not) economy needs %s" */199 /** TRANSLATORS: e.g. 'economy needs worker' Context: 'and/or (not) economy needs %s' */
200 return (boost::format(_("economy needs %s")) % tribe.get_ware_descr(worker_type)->descname()).str();200 return (boost::format(_("economy needs %s")) % tribe.get_ware_descr(worker_type)->descname()).str();
201}201}
202202
@@ -229,10 +229,10 @@
229 std::string condition = "";229 std::string condition = "";
230 container_iterate_const(std::set<Ware_Index>, group.first, i) {230 container_iterate_const(std::set<Ware_Index>, group.first, i) {
231 condition =231 condition =
232 /** TRANSLATORS: Adds a ware to list of wares in "Failed/Skipped ..." messages. */232 /** TRANSLATORS: Adds a ware to list of wares in 'Failed/Skipped ...' messages. */
233 (boost::format(_("%1$s %2$s")) % condition % tribe.get_ware_descr(*i.current)->descname())233 (boost::format(_("%1$s %2$s")) % condition % tribe.get_ware_descr(*i.current)->descname())
234 .str();234 .str();
235 /** TRANSLATORS: Separator for list of wares in "Failed/Skipped ..." messages. */235 /** TRANSLATORS: Separator for list of wares in 'Failed/Skipped ...' messages. */
236 condition = (boost::format(_("%s,")) % condition).str();236 condition = (boost::format(_("%s,")) % condition).str();
237 }237 }
238 if (1 < group.second) {238 if (1 < group.second) {
@@ -257,6 +257,7 @@
257std::string ProductionProgram::ActReturn::Workers_Need_Experience::description257std::string ProductionProgram::ActReturn::Workers_Need_Experience::description
258 (const Tribe_Descr &) const258 (const Tribe_Descr &) const
259{259{
260 /** TRANSLATORS: 'Failed/Skipped ... because: workers need experience'. */
260 return _("workers need experience");261 return _("workers need experience");
261}262}
262263
@@ -423,16 +424,16 @@
423 (Game & game, ProductionSite & ps) const424 (Game & game, ProductionSite & ps) const
424{425{
425 std::string statistics_string =426 std::string statistics_string =
426 /** TRANSLATORS: "Failed %s because (not): %s {and/or %s}" */427 /** TRANSLATORS: 'Failed %s because (not): %s {and/or %s}' */
427 m_result == Failed ? (boost::format(_("Failed %s")) % ps.top_state().program->descname()).str() :428 m_result == Failed ? (boost::format(_("Failed %s")) % ps.top_state().program->descname()).str() :
428 /** TRANSLATORS: "Completed %s because (not): %s {and/or %s}" */429 /** TRANSLATORS: 'Completed %s because (not): %s {and/or %s}' */
429 m_result == Completed ? (boost::format(_("Completed %s")) % ps.top_state().program->descname()).str() :430 m_result == Completed ? (boost::format(_("Completed %s")) % ps.top_state().program->descname()).str() :
430 /** TRANSLATORS: "Skipped %s because (not): %s {and/or %s}" */431 /** TRANSLATORS: 'Skipped %s because (not): %s {and/or %s}' */
431 (boost::format(_("Skipped %s")) % ps.top_state().program->descname()).str();432 (boost::format(_("Skipped %s")) % ps.top_state().program->descname()).str();
432433
433 if (!m_conditions.empty()) {434 if (!m_conditions.empty()) {
434 std::string result_string = statistics_string;435 std::string result_string = statistics_string;
435 if (m_is_when) { // "when a and b and ..." (all conditions must be true)436 if (m_is_when) { // 'when a and b and ...' (all conditions must be true)
436 std::string condition_string = "";437 std::string condition_string = "";
437 for (wl_const_range<Conditions> i(m_conditions); i;)438 for (wl_const_range<Conditions> i(m_conditions); i;)
438 {439 {
@@ -443,11 +444,11 @@
443 if (i.advance().empty())444 if (i.advance().empty())
444 break;445 break;
445 // TODO Would prefer "%1$s and %2$s" but getting segfaults, so leaving this for now446 // TODO Would prefer "%1$s and %2$s" but getting segfaults, so leaving this for now
446 /** TRANSLATORS: "Failed/Completed/Skipped %s because: %s {and %s}" */447 /** TRANSLATORS: 'Failed/Completed/Skipped %s because: %s {and %s}' */
447 condition_string = (boost::format(_("%s and ")) % condition_string).str();448 condition_string = (boost::format(_("%s and ")) % condition_string).str();
448 }449 }
449 result_string =450 result_string =
450 /** TRANSLATORS: "Failed/Completed/Skipped %s because: %s {and %s}" */451 /** TRANSLATORS: 'Failed/Completed/Skipped %s because: %s {and %s}' */
451 (boost::format(_("%1$s because: %2$s")) % statistics_string % condition_string).str();452 (boost::format(_("%1$s because: %2$s")) % statistics_string % condition_string).str();
452 } else { // "unless a or b or ..." (all conditions must be false)453 } else { // "unless a or b or ..." (all conditions must be false)
453 std::string condition_string = "";454 std::string condition_string = "";
@@ -459,12 +460,12 @@
459 condition_string += i.front()->description(ps.owner().tribe());460 condition_string += i.front()->description(ps.owner().tribe());
460 if (i.advance().empty())461 if (i.advance().empty())
461 break;462 break;
462 // TODO Would prefer "%1$s or %2$s" but getting segfaults, so leaving this for now463 // TODO Would prefer '%1$s or %2$s' but getting segfaults, so leaving this for now
463 /** TRANSLATORS: "Failed/Completed/Skipped %s because not: %s {or %s}" */464 /** TRANSLATORS: 'Failed/Completed/Skipped %s because not: %s {or %s}' */
464 condition_string = (boost::format(_("%s or ")) % condition_string).str();465 condition_string = (boost::format(_("%s or ")) % condition_string).str();
465 }466 }
466 result_string =467 result_string =
467 /** TRANSLATORS: "Failed/Completed/Skipped %s because not: %s {or %s}" */468 /** TRANSLATORS: 'Failed/Completed/Skipped %s because not: %s {or %s}' */
468 (boost::format(_("%1$s because not: %2$s")) % statistics_string % condition_string).str();469 (boost::format(_("%1$s because not: %2$s")) % statistics_string % condition_string).str();
469 }470 }
470 snprintf471 snprintf
@@ -828,7 +829,7 @@
828 if (uint8_t const nr_missing_groups = l_groups.size()) {829 if (uint8_t const nr_missing_groups = l_groups.size()) {
829 const Tribe_Descr & tribe = ps.owner().tribe();830 const Tribe_Descr & tribe = ps.owner().tribe();
830 std::string result_string =831 std::string result_string =
831 /** TRANSLATORS: e.g. "Failed work because: water, wheat (2) are missing" */832 /** TRANSLATORS: e.g. 'Failed work because: water, wheat (2) are missing' */
832 (boost::format(_("Failed %s because:")) % ps.top_state().program->descname()).str();833 (boost::format(_("Failed %s because:")) % ps.top_state().program->descname()).str();
833834
834 for (wl_const_range<Groups> i(l_groups); i;)835 for (wl_const_range<Groups> i(l_groups); i;)
@@ -837,13 +838,13 @@
837 for (wl_const_range<std::set<Ware_Index> > j(i.current->first); j;)838 for (wl_const_range<std::set<Ware_Index> > j(i.current->first); j;)
838 {839 {
839 result_string =840 result_string =
840 /** TRANSLATORS: Adds a ware to list of wares in "Failed/Skipped ..." messages. */841 /** TRANSLATORS: Adds a ware to list of wares in 'Failed/Skipped ...' messages. */
841 (boost::format(_("%1$s %2$s")) % result_string842 (boost::format(_("%1$s %2$s")) % result_string
842 % tribe.get_ware_descr(j.front())->descname())843 % tribe.get_ware_descr(j.front())->descname())
843 .str();844 .str();
844 if (j.advance().empty())845 if (j.advance().empty())
845 break;846 break;
846 /** TRANSLATORS: Separator for list of wares in "Failed/Skipped ..." messages. */847 /** TRANSLATORS: Separator for list of wares in 'Failed/Skipped ...' messages. */
847 result_string = (boost::format(_("%s,")) % result_string).str();848 result_string = (boost::format(_("%s,")) % result_string).str();
848 }849 }
849 {850 {
@@ -851,7 +852,7 @@
851 if (1 < count) {852 if (1 < count) {
852 // TODO this should be done with ngettext853 // TODO this should be done with ngettext
853 result_string =854 result_string =
854 /** TRANSLATORS: e.g. "Failed work because: water, wheat (2) are missing" */855 /** TRANSLATORS: e.g. 'Failed work because: water, wheat (2) are missing' */
855 (boost::format(_("%1$s (%2$i)")) % result_string856 (boost::format(_("%1$s (%2$i)")) % result_string
856 % static_cast<unsigned int>(count))857 % static_cast<unsigned int>(count))
857 .str();858 .str();
@@ -862,8 +863,9 @@
862 result_string = (boost::format(_("%s and")) % result_string).str();863 result_string = (boost::format(_("%s and")) % result_string).str();
863 }864 }
864 result_string =865 result_string =
865 /** TRANSLATORS: e.g. "Failed work because: water, wheat (2) are missing" */866 /** TRANSLATORS: e.g. %1$s = 'Failed work because: water, wheat (2)' %2$s = 'are missing' */
866 (boost::format(_("%1$s %2$s")) % result_string867 (boost::format(_("%1$s %2$s")) % result_string
868 /** TRANSLATORS: e.g. 'Failed work because: water, wheat (2) are missing' */
867 % ngettext(" is missing", " are missing", nr_missing_groups))869 % ngettext(" is missing", " are missing", nr_missing_groups))
868 .str();870 .str();
869871
@@ -958,6 +960,7 @@
958 uint8_t const count = i.current->second;960 uint8_t const count = i.current->second;
959 if (1 < count) {961 if (1 < count) {
960 char buffer[5];962 char buffer[5];
963 /** TRANSLATORS: Number used in list of wares */
961 sprintf(buffer, _("%u "), count);964 sprintf(buffer, _("%u "), count);
962 result_string += buffer;965 result_string += buffer;
963 }966 }
@@ -965,9 +968,11 @@
965 result_string += tribe.get_ware_descr(i.current->first)->descname();968 result_string += tribe.get_ware_descr(i.current->first)->descname();
966 if (i.advance().empty())969 if (i.advance().empty())
967 break;970 break;
971 /** TRANSLATORS: Separator for list of wares */
968 result_string += _(", ");972 result_string += _(", ");
969 }973 }
970 // Keep translateability in mind!974 // Keep translateability in mind!
975 /** TRANSLATORS: %s is a list of wares */
971 result_string = str(format(_("Produced %s")) % result_string);976 result_string = str(format(_("Produced %s")) % result_string);
972 snprintf977 snprintf
973 (ps.m_result_buffer, sizeof(ps.m_result_buffer),978 (ps.m_result_buffer, sizeof(ps.m_result_buffer),
@@ -1054,6 +1059,7 @@
1054 uint8_t const count = i.current->second;1059 uint8_t const count = i.current->second;
1055 if (1 < count) {1060 if (1 < count) {
1056 char buffer[5];1061 char buffer[5];
1062 /** TRANSLATORS: Number used in list of workers */
1057 sprintf(buffer, _("%u "), count);1063 sprintf(buffer, _("%u "), count);
1058 unit_string += buffer;1064 unit_string += buffer;
1059 }1065 }
@@ -1061,9 +1067,11 @@
1061 unit_string += tribe.get_worker_descr(i.current->first)->descname();1067 unit_string += tribe.get_worker_descr(i.current->first)->descname();
1062 if (i.advance().empty())1068 if (i.advance().empty())
1063 break;1069 break;
1070 /** TRANSLATORS: Separator for list of workers */
1064 unit_string += _(", ");1071 unit_string += _(", ");
1065 }1072 }
1066 std::string result_string = (boost::format(_("Recruited %s?")) % unit_string).str();1073 /** TRANSLATORS: %s is a lost of workers */
1074 std::string result_string = (boost::format(_("Recruited %s")) % unit_string).str();
1067 snprintf1075 snprintf
1068 (ps.m_result_buffer, sizeof(ps.m_result_buffer),1076 (ps.m_result_buffer, sizeof(ps.m_result_buffer),
1069 "%s", result_string.c_str());1077 "%s", result_string.c_str());
@@ -1119,7 +1127,7 @@
1119 "percentage", parameters);1127 "percentage", parameters);
1120 }1128 }
1121 std::string description =1129 std::string description =
1122 /** TRANSLATORS: %1$s = name, %2$s = production program, %3$s = resource*/1130 /** TRANSLATORS: %1$s = production site name, %2$s = production program name, %3$s = resource */
1123 (boost::format(_("%1$s %2$s mine %3$s")) % descr.descname() % production_program_name1131 (boost::format(_("%1$s %2$s mine %3$s")) % descr.descname() % production_program_name
1124 % world.get_resource(m_resource)->descname())1132 % world.get_resource(m_resource)->descname())
1125 .str();1133 .str();
11261134
=== modified file 'src/logic/soldier.cc'
--- src/logic/soldier.cc 2014-03-05 11:59:09 +0000
+++ src/logic/soldier.cc 2014-03-08 16:14:22 +0000
@@ -1557,14 +1557,12 @@
1557 descname().c_str(), serial(), owner().player_number(),1557 descname().c_str(), serial(), owner().player_number(),
1558 get_position().x, get_position().y,1558 get_position().x, get_position().y,
1559 immovable_position ?1559 immovable_position ?
1560 /** TRANSLATORS this is followed by "immovable" in the source string */1560 immovable_position->descr().descname().c_str() : ("no"),
1561 immovable_position->descr().descname().c_str() : _("no"),
1562 opponent.descname().c_str(), opponent.serial(),1561 opponent.descname().c_str(), opponent.serial(),
1563 opponent.owner().player_number(),1562 opponent.owner().player_number(),
1564 dest.x, dest.y,1563 dest.x, dest.y,
1565 immovable_dest ?1564 immovable_dest ?
1566 /** TRANSLATORS this is followed by "immovable" in the source string */1565 immovable_dest->descr().descname().c_str() : ("no"),
1567 immovable_dest->descr().descname().c_str() : _("no"),
1568 descname().c_str());1566 descname().c_str());
1569 owner().add_message1567 owner().add_message
1570 (game,1568 (game,
15711569
=== modified file 'src/network/nethost.cc'
--- src/network/nethost.cc 2014-03-06 12:52:12 +0000
+++ src/network/nethost.cc 2014-03-08 16:14:22 +0000
@@ -212,7 +212,7 @@
212 h->setPlayerState(number, newstate, true);212 h->setPlayerState(number, newstate, true);
213 }213 }
214214
215 virtual void setPlayerTribe215 virtual void setPlayerTribe
216 (uint8_t const number, const std::string & tribe, bool const random_tribe) override216 (uint8_t const number, const std::string & tribe, bool const random_tribe) override
217 {217 {
218 if (number >= h->settings().players.size())218 if (number >= h->settings().players.size())
@@ -444,8 +444,8 @@
444 c.msg = (format(_("The client %s could not be found.")) % arg1).str();444 c.msg = (format(_("The client %s could not be found.")) % arg1).str();
445 else {445 else {
446 kickClient = num;446 kickClient = num;
447 c.msg = (format(_("Are you sure you want to kick %s?<br>")) % arg1).str();447 c.msg = (format(_("Are you sure you want to kick %s?")) % arg1).str() + "<br>";
448 c.msg += (format(_("The stated reason was: %s<br>")) % kickReason).str();448 c.msg += (format(_("The stated reason was: %s")) % kickReason).str() + "<br>";
449 c.msg += (format(_("If yes, type: /ack_kick %s")) % arg1).str();449 c.msg += (format(_("If yes, type: /ack_kick %s")) % arg1).str();
450 }450 }
451 }451 }
452452
=== modified file 'src/ui_fsmenu/editor_mapselect.cc'
--- src/ui_fsmenu/editor_mapselect.cc 2014-02-22 18:04:02 +0000
+++ src/ui_fsmenu/editor_mapselect.cc 2014-03-08 16:14:22 +0000
@@ -227,6 +227,7 @@
227 m_parentdir = m_curdir.substr(0, m_curdir.rfind('\\'));227 m_parentdir = m_curdir.substr(0, m_curdir.rfind('\\'));
228#endif228#endif
229 std::string parent_string =229 std::string parent_string =
230 /** TRANSLATORS: Parent directory */
230 (boost::format("\\<%s\\>") % _("parent")).str();231 (boost::format("\\<%s\\>") % _("parent")).str();
231 m_list.add232 m_list.add
232 (parent_string.c_str(),233 (parent_string.c_str(),
233234
=== modified file 'src/ui_fsmenu/launchMPG.cc'
--- src/ui_fsmenu/launchMPG.cc 2014-03-05 11:59:09 +0000
+++ src/ui_fsmenu/launchMPG.cc 2014-03-08 16:14:22 +0000
@@ -49,6 +49,7 @@
49 (UI::Panel * parent, GameController * gc, uint32_t w, uint32_t h,49 (UI::Panel * parent, GameController * gc, uint32_t w, uint32_t h,
50 UI::Font * font)50 UI::Font * font)
51 :51 :
52 /** TRANSLATORS: Dialog box title for selecting between map or saved game for new multiplayer game */
52 Window(parent, "selection_window", 0, 0, w, h, _("Please select")),53 Window(parent, "selection_window", 0, 0, w, h, _("Please select")),
53 m_ctrl(gc)54 m_ctrl(gc)
54 {55 {
5556
=== modified file 'src/wui/encyclopedia_window.cc'
--- src/wui/encyclopedia_window.cc 2014-03-05 11:59:09 +0000
+++ src/wui/encyclopedia_window.cc 2014-03-08 16:14:22 +0000
@@ -191,7 +191,7 @@
191 tribe.get_ware_descr(*k)->descname();191 tribe.get_ware_descr(*k)->descname();
192 if (k.advance().empty())192 if (k.advance().empty())
193 break;193 break;
194 /** TRANSLATORS: List or wares, e.g. "Fish or Meat" */194 /** TRANSLATORS: List of wares, e.g. "Fish or Meat" */
195 ware_type_names += _(" or ");195 ware_type_names += _(" or ");
196 }196 }
197197
198198
=== modified file 'src/wui/game_main_menu_save_game.cc'
--- src/wui/game_main_menu_save_game.cc 2014-03-05 11:59:09 +0000
+++ src/wui/game_main_menu_save_game.cc 2014-03-08 16:14:22 +0000
@@ -137,7 +137,9 @@
137137
138 char buf[200];138 char buf[200];
139 uint8_t player_nr = parent.game().player_manager()->get_number_of_players();139 uint8_t player_nr = parent.game().player_manager()->get_number_of_players();
140 sprintf(buf, "%i %s", player_nr, ngettext(_("player"), _("players"), player_nr));140 // TODO: This should be ngettext(" %i player" etc. with boost::format, but it refuses to work
141 /** TRANSLATORS: This is preceded by a number */
142 sprintf(buf, "%i %s", player_nr, ngettext("player", "players", player_nr));
141 m_players_label.set_text(buf);143 m_players_label.set_text(buf);
142 m_win_condition.set_text(parent.game().get_win_condition_displayname());144 m_win_condition.set_text(parent.game().get_win_condition_displayname());
143 }145 }
@@ -175,7 +177,9 @@
175 char buf[200];177 char buf[200];
176 sprintf178 sprintf
177 (buf, "%i %s", gpdp.get_number_of_players(),179 (buf, "%i %s", gpdp.get_number_of_players(),
178 ngettext(_("player"), _("players"), gpdp.get_number_of_players()));180 // TODO: This should be ngettext(" %i player" etc. with boost::format, but it refuses to work
181 /** TRANSLATORS: This is preceded by a number */
182 ngettext("player", "players", gpdp.get_number_of_players()));
179 m_players_label.set_text(buf);183 m_players_label.set_text(buf);
180 } else {184 } else {
181 // Keep label empty185 // Keep label empty
182186
=== modified file 'src/wui/playerdescrgroup.cc'
--- src/wui/playerdescrgroup.cc 2014-03-05 11:59:09 +0000
+++ src/wui/playerdescrgroup.cc 2014-03-08 16:14:22 +0000
@@ -174,7 +174,7 @@
174 if (player.random_ai) {174 if (player.random_ai) {
175 title += _("AI: Random");175 title += _("AI: Random");
176 } else {176 } else {
177 /** TRANSLATORS %s = AI type, e.g. "Agressive" */177 /** TRANSLATORS %s = AI type, e.g. 'Agressive' */
178 title += (boost::format(_("AI: %s")) % _(player.ai)).str();178 title += (boost::format(_("AI: %s")) % _(player.ai)).str();
179 }179 }
180 }180 }
181181
=== modified file 'tribes/atlanteans/scripting/sc01_castle_village.lua'
--- tribes/atlanteans/scripting/sc01_castle_village.lua 2014-02-25 14:45:19 +0000
+++ tribes/atlanteans/scripting/sc01_castle_village.lua 2014-03-08 16:14:22 +0000
@@ -98,10 +98,10 @@
98 wares = { trunk = 1 }98 wares = { trunk = 1 }
99 })99 })
100 end) then100 end) then
101 plr:send_message(_"Not enough space", _101 plr:send_message(_"Not enough space", _(
102[[Some of your starting buildings didn’t have enough room and102[[Some of your starting buildings didn’t have enough room and ]] ..
103weren’t built. You are at a disadvantage with this; consider restarting103[[weren’t built. You are at a disadvantage with this; consider restarting ]] ..
104this map with a fair starting condition.]], {popup=true}104[[this map with a fair starting condition.]]), {popup=true}
105 )105 )
106 end106 end
107107
108108
=== modified file 'tribes/barbarians/coalmine/help.lua'
--- tribes/barbarians/coalmine/help.lua 2014-03-05 18:47:03 +0000
+++ tribes/barbarians/coalmine/help.lua 2014-03-08 16:14:22 +0000
@@ -9,8 +9,9 @@
9 --Lore Section9 --Lore Section
10 rt(h2(_"Lore")) ..10 rt(h2(_"Lore")) ..
11 rt("image=tribes/barbarians/coalmine/coalmine_i_00.png", p(11 rt("image=tribes/barbarians/coalmine/coalmine_i_00.png", p(
12 _[[Ages ago, the Barbarians learned to delve into mountainsides for that black material that feeds their furnaces. <br>12 _([[Ages ago, the Barbarians learned to delve into mountainsides for that black material that feeds their furnaces.<br>
13 Wood may serve for a household fire and to keep you warm, but when it comes to working with iron or gold, there is no way around coal.]]13]] ..
14 [[Wood may serve for a household fire and to keep you warm, but when it comes to working with iron or gold, there is no way around coal.]])
14 )) ..15 )) ..
15 --General Section16 --General Section
16 rt(h2(_"General")) ..17 rt(h2(_"General")) ..
1718
=== modified file 'tribes/barbarians/conf'
--- tribes/barbarians/conf 2014-03-05 18:47:03 +0000
+++ tribes/barbarians/conf 2014-03-08 16:14:22 +0000
@@ -105,7 +105,7 @@
105strongbeer=_Strong Beer105strongbeer=_Strong Beer
106thatchreed=_Thatch Reed106thatchreed=_Thatch Reed
107trunk=_Log107trunk=_Log
108warhelmet=_War Helm108warhelmet=_Warhelm
109warriorsaxe=_Warrior’s Ax109warriorsaxe=_Warrior’s Ax
110water=_Water110water=_Water
111wheat=_Wheat111wheat=_Wheat
112112
=== modified file 'tribes/barbarians/deep_coalmine/help.lua'
--- tribes/barbarians/deep_coalmine/help.lua 2014-03-05 18:47:03 +0000
+++ tribes/barbarians/deep_coalmine/help.lua 2014-03-08 16:14:22 +0000
@@ -9,8 +9,9 @@
9 --Lore Section9 --Lore Section
10 rt(h2(_"Lore")) ..10 rt(h2(_"Lore")) ..
11 rt("image=tribes/barbarians/deep_coalmine/deep_coalmine_i_00.png", p(--text identical to coalmine11 rt("image=tribes/barbarians/deep_coalmine/deep_coalmine_i_00.png", p(--text identical to coalmine
12 _[[Ages ago, the Barbarians learned to delve into mountainsides for that black material that feeds their furnaces. <br>12 _([[Ages ago, the Barbarians learned to delve into mountainsides for that black material that feeds their furnaces.<br>
13 Wood may serve for a household fire and to keep you warm, but when it comes to working with iron or gold, there is no way around coal.]]13]] ..
14 [[Wood may serve for a household fire and to keep you warm, but when it comes to working with iron or gold, there is no way around coal.]])
14 )) ..15 )) ..
15 --General Section16 --General Section
16 rt(h2(_"General")) ..17 rt(h2(_"General")) ..
1718
=== modified file 'tribes/barbarians/deeper_coalmine/help.lua'
--- tribes/barbarians/deeper_coalmine/help.lua 2014-03-05 18:47:03 +0000
+++ tribes/barbarians/deeper_coalmine/help.lua 2014-03-08 16:14:22 +0000
@@ -9,8 +9,9 @@
9 --Lore Section9 --Lore Section
10 rt(h2(_"Lore")) ..10 rt(h2(_"Lore")) ..
11 rt("image=tribes/barbarians/deeper_coalmine/deeper_coalmine_i_00.png", p(--text identical to coalmine11 rt("image=tribes/barbarians/deeper_coalmine/deeper_coalmine_i_00.png", p(--text identical to coalmine
12 _[[Ages ago, the Barbarians learned to delve into mountainsides for that black material that feeds their furnaces. <br>12 _([[Ages ago, the Barbarians learned to delve into mountainsides for that black material that feeds their furnaces.<br>
13 Wood may serve for a household fire and to keep you warm, but when it comes to working with iron or gold, there is no way around coal.]]13]] ..
14 [[Wood may serve for a household fire and to keep you warm, but when it comes to working with iron or gold, there is no way around coal.]])
14 )) ..15 )) ..
15 --General Section16 --General Section
16 rt(h2(_"General")) ..17 rt(h2(_"General")) ..
1718
=== modified file 'tribes/barbarians/scripting/sc01_citadel_village.lua'
--- tribes/barbarians/scripting/sc01_citadel_village.lua 2014-02-25 14:45:19 +0000
+++ tribes/barbarians/scripting/sc01_citadel_village.lua 2014-03-08 16:14:22 +0000
@@ -91,10 +91,10 @@
91 wares = { raw_stone = 6, coal = 3 },91 wares = { raw_stone = 6, coal = 3 },
92 })92 })
93 end) then93 end) then
94 plr:send_message(_"Not enough space", _ 94 plr:send_message(_"Not enough space", _(
95[[Some of your starting buildings didn’t have enough room and 95[[Some of your starting buildings didn’t have enough room and ]] ..
96weren’t built. You are at a disadvantage with this; consider restarting 96[[weren’t built. You are at a disadvantage with this; consider restarting ]] ..
97this map with a fair starting condition.]], {popup=true}97[[this map with a fair starting condition.]]), {popup=true}
98 )98 )
99 end99 end
100end,100end,
101101
=== modified file 'tribes/empire/scripting/sc01_castle_village.lua'
--- tribes/empire/scripting/sc01_castle_village.lua 2014-02-25 14:45:19 +0000
+++ tribes/empire/scripting/sc01_castle_village.lua 2014-03-08 16:14:22 +0000
@@ -116,10 +116,10 @@
116116
117 place_building_in_region(plr, "stonemasons_house", sf:region(11))117 place_building_in_region(plr, "stonemasons_house", sf:region(11))
118 end) then118 end) then
119 plr:send_message(_"Not enough space", _ 119 plr:send_message(_"Not enough space", _(
120[[Some of your starting buildings didn’t have enough room and 120[[Some of your starting buildings didn’t have enough room and ]] ..
121weren’t built. You are at a disadvantage with this; consider restarting 121[[weren’t built. You are at a disadvantage with this; consider restarting ]] ..
122this map with a fair starting condition.]], {popup=true}122[[this map with a fair starting condition.]]), {popup=true}
123 )123 )
124 end124 end
125end125end
126126
=== modified file 'txts/README.lua'
--- txts/README.lua 2014-03-03 20:50:30 +0000
+++ txts/README.lua 2014-03-08 16:14:22 +0000
@@ -58,8 +58,8 @@
58 ) .. h2(_58 ) .. h2(_
59[[Keyboard shortcuts (in-game)]]59[[Keyboard shortcuts (in-game)]]
60 ) .. p(60 ) .. p(
61_"PAGEUP: increases games peed" .. "<br>"61_"PAGEUP: increases game speed" .. "<br>"
62.. _"PAGEDOWN: decreases games peed" .. "<br>"62.. _"PAGEDOWN: decreases game speed" .. "<br>"
63.. _"PAUSE: pauses the game" .. "<br>"63.. _"PAUSE: pauses the game" .. "<br>"
64.. _"SPACE: toggles if building spaces are shown" .. "<br>"64.. _"SPACE: toggles if building spaces are shown" .. "<br>"
65.. _"M: toggles minimap" .. "<br>"65.. _"M: toggles minimap" .. "<br>"

Subscribers

People subscribed via source and target branches

to status/vote changes: