diff --git a/binaries/data/mods/public/globalscripts/l10n.js b/binaries/data/mods/public/globalscripts/l10n.js new file mode 100644 index 0000000000..5ac4b388d6 --- /dev/null +++ b/binaries/data/mods/public/globalscripts/l10n.js @@ -0,0 +1,154 @@ +var g_translations = {}; +var g_pluralTranslations = {}; +var g_translationsWithContext = {}; +var g_pluralTranslationsWithContext = {}; + +// Translates the specified English message into the current language. +// +// This function relies on the g_translations cache when possible. You should use this function instead of +// Engine.Translate() whenever you can to minimize the number of C++ calls and string conversions involved. +function translate(message) +{ + var translation = g_translations[message]; + if (!translation) + return g_translations[message] = Engine.Translate(message); + return translation; +} + + +// Translates the specified English message into the current language for the specified number. +// +// This function relies on the g_pluralTranslations cache when possible. You should use this function instead of +// Engine.TranslatePlural() whenever you can to minimize the number of C++ calls and string conversions involved. +function translatePlural(singularMessage, pluralMessage, number) +{ + var translation = g_pluralTranslations[singularMessage]; + if (!translation) + g_pluralTranslations[singularMessage] = {}; + + var pluralTranslation = g_pluralTranslations[singularMessage][number]; + if (!pluralTranslation) + return g_pluralTranslations[singularMessage][number] = Engine.TranslatePlural(singularMessage, pluralMessage, number); + + return pluralTranslation; +} + + +// Translates the specified English message into the current language for the specified context. +// +// This function relies on the g_translationsWithContext cache when possible. You should use this function instead of +// Engine.TranslateWithContext() whenever you can to minimize the number of C++ calls and string conversions involved. +function translateWithContext(context, message) +{ + var translationContext = g_translationsWithContext[context]; + if (!translationContext) + g_translationsWithContext[context] = {} + + var translationWithContext = g_translationsWithContext[context][message]; + if (!translationWithContext) + return g_translationsWithContext[context][message] = Engine.TranslateWithContext(context, message); + + return translationWithContext; +} + + +// Translates the specified English message into the current language for the specified context and number. +// +// This function relies on the g_pluralTranslationsWithContext cache when possible. You should use this function instead of +// Engine.TranslatePluralWithContext() whenever you can to minimize the number of C++ calls and string conversions involved. +function translatePluralWithContext(context, singularMessage, pluralMessage, number) +{ + var translationContext = g_pluralTranslationsWithContext[context]; + if (!translationContext) + g_pluralTranslationsWithContext[context] = {}; + + var translationWithContext = g_pluralTranslationsWithContext[context][singularMessage]; + if (!translationWithContext) + g_pluralTranslationsWithContext[context][singularMessage] = {}; + + var pluralTranslationWithContext = g_pluralTranslationsWithContext[context][singularMessage][number]; + if (!pluralTranslationWithContext) + return g_pluralTranslationsWithContext[context][singularMessage][number] = Engine.TranslatePluralWithContext(context, singularMessage, pluralMessage, number); + + return pluralTranslationWithContext; +} + +/** + * Translates any string value in the specified JavaScript object + * that is associated with a key included in the specified keys array. + * + * it accepts an object in the form of + * + * { + * translatedString1: "my first message", + * unTranslatedString1: "some English string", + * ignoredObject: { + * translatedString2: "my second message", + * unTranslatedString2: "some English string" + * }, + * translatedObject1: { + * message: "my third singular message", + * context: "message context", + * }, + * translatedObject2: { + * list: ["list", "of", "strings"], + * context: "message context", + * }, + * } + * + * Together with a keys list to translate the strings and objects + * ["translatedString1", "translatedString2", "translatedObject1", + * "translatedObject2"] + * + * The result will be (f.e. in Dutch) + * { + * translatedString1: "mijn eerste bericht", + * unTranslatedString1: "some English string", + * ignoredObject: { + * translatedString2: "mijn tweede bericht", + * unTranslatedString2: "some English string" + * }, + * translatedObject1: "mijn derde bericht", + * translatedObject2: "lijst, van, teksten", + * } + * + * So you see that the keys array can also contain lower-level keys, + * And that you can include objects in the keys array to translate + * them with a context, or to join a list of translations. + */ +function translateObjectKeys(object, keys) { + for (var property in object) + { + if (keys.indexOf(property) > -1) + { + if (typeof object[property] == "string") + object[property] = translate(object[property]); + else if (object[property] instanceof Object) + { + // the translation function + var trans = translate; + if (object[property].context) + trans = function(msg) { return translateWithContext(object[property].context, msg);}; + + if (object[property].message) + object[property] = trans(object[property].message); + else if (object[property].list) + { + var translatedList = object[property].list.map(trans); + object[property] = translatedList.join(translateWithContext("enumeration", ", ")); + } + } + } + else if (object[property] instanceof Object) + translateObjectKeys(object[property], keys); + } +} + +function markForTranslation(message) { + return message; +} + +function markForTranslationWithContext(context, message) { + return message; +} + diff --git a/binaries/data/mods/public/globalscripts/sprintf.js b/binaries/data/mods/public/globalscripts/sprintf.js new file mode 100644 index 0000000000..69035cec6e --- /dev/null +++ b/binaries/data/mods/public/globalscripts/sprintf.js @@ -0,0 +1,183 @@ +/** +sprintf() for JavaScript 0.7-beta1 +http://www.diveintojavascript.com/projects/javascript-sprintf + +Copyright (c) Alexandru Marasteanu +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of sprintf() for JavaScript nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL Alexandru Marasteanu BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Changelog: +2010.09.06 - 0.7-beta1 + - features: vsprintf, support for named placeholders + - enhancements: format cache, reduced global namespace pollution + +2010.05.22 - 0.6: + - reverted to 0.4 and fixed the bug regarding the sign of the number 0 + Note: + Thanks to Raphael Pigulla (http://www.n3rd.org/) + who warned me about a bug in 0.5, I discovered that the last update was + a regress. I appologize for that. + +2010.05.09 - 0.5: + - bug fix: 0 is now preceeded with a + sign + - bug fix: the sign was not at the right position on padded results (Kamal Abdali) + - switched from GPL to BSD license + +2007.10.21 - 0.4: + - unit test and patch (David Baird) + +2007.09.17 - 0.3: + - bug fix: no longer throws exception on empty paramenters (Hans Pufal) + +2007.09.11 - 0.2: + - feature: added argument swapping + +2007.04.03 - 0.1: + - initial release +**/ + +var sprintf = (function() { + function get_type(variable) { + return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase(); + } + function str_repeat(input, multiplier) { + for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */} + return output.join(''); + } + + var str_format = function() { + if (!str_format.cache.hasOwnProperty(arguments[0])) { + str_format.cache[arguments[0]] = str_format.parse(arguments[0]); + } + return str_format.format.call(null, str_format.cache[arguments[0]], arguments); + }; + + str_format.format = function(parse_tree, argv) { + var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length; + for (i = 0; i < tree_length; i++) { + node_type = get_type(parse_tree[i]); + if (node_type === 'string') { + output.push(parse_tree[i]); + } + else if (node_type === 'array') { + match = parse_tree[i]; // convenience purposes only + if (match[2]) { // keyword argument + arg = argv[cursor]; + for (k = 0; k < match[2].length; k++) { + if (!arg.hasOwnProperty(match[2][k])) { + throw(sprintf(Engine.Translate('[sprintf] property "%s" does not exist'), match[2][k])); + } + arg = arg[match[2][k]]; + } + } + else if (match[1]) { // positional argument (explicit) + arg = argv[match[1]]; + } + else { // positional argument (implicit) + arg = argv[cursor++]; + } + + if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) { + throw(sprintf(Engine.Translate('[sprintf] expecting number but found %s'), get_type(arg))); + } + switch (match[8]) { + case 'b': arg = arg.toString(2); break; + case 'c': arg = String.fromCharCode(arg); break; + case 'd': arg = parseInt(arg, 10); break; + case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break; + case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break; + case 'o': arg = arg.toString(8); break; + case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break; + case 'u': arg = Math.abs(arg); break; + case 'x': arg = arg.toString(16); break; + case 'X': arg = arg.toString(16).toUpperCase(); break; + } + arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg); + pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' '; + pad_length = match[6] - String(arg).length; + pad = match[6] ? str_repeat(pad_character, pad_length) : ''; + output.push(match[5] ? arg + pad : pad + arg); + } + } + return output.join(''); + }; + + str_format.cache = {}; + + str_format.parse = function(fmt) { + var _fmt = fmt, match = [], parse_tree = [], arg_names = 0; + while (_fmt) { + if ((match = /^[^\x25]+/.exec(_fmt)) !== null) { + parse_tree.push(match[0]); + } + else if ((match = /^\x25{2}/.exec(_fmt)) !== null) { + parse_tree.push('%'); + } + else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) { + if (match[2]) { + arg_names |= 1; + var field_list = [], replacement_field = match[2], field_match = []; + if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') { + if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + } + else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + } + else { + throw(Engine.Translate('[sprintf] huh?')); + } + } + } + else { + throw(Engine.Translate('[sprintf] huh?')); + } + match[2] = field_list; + } + else { + arg_names |= 2; + } + if (arg_names === 3) { + throw(Engine.Translate('[sprintf] mixing positional and named placeholders is not (yet) supported')); + } + parse_tree.push(match); + } + else { + throw(sprintf(Engine.Translate('[sprintf] No placeholder found in the ‘%(formatString)s’ format string. Maybe you used an incorrect syntax for your placeholder?'), { formatString: _fmt } )); + } + _fmt = _fmt.substring(match[0].length); + } + return parse_tree; + }; + + return str_format; +})(); + +var vsprintf = function(fmt, argv) { + argv.unshift(fmt); + return sprintf.apply(null, argv); +}; diff --git a/binaries/data/mods/public/gui/aiconfig/aiconfig.js b/binaries/data/mods/public/gui/aiconfig/aiconfig.js index 331c48d154..ce5a7624b4 100644 --- a/binaries/data/mods/public/gui/aiconfig/aiconfig.js +++ b/binaries/data/mods/public/gui/aiconfig/aiconfig.js @@ -4,12 +4,14 @@ var g_PlayerSlot; function init(settings) { g_PlayerSlot = settings.playerSlot; + + translateObjectKeys(settings.ais, ["name", "description"]); g_AIs = [ - {id: "", data: {name: "None", description: "AI will be disabled for this player."}} + {id: "", data: {name: translateWithContext("ai", "None"), description: translate("AI will be disabled for this player.")}} ].concat(settings.ais); var aiSelection = Engine.GetGUIObjectByName("aiSelection"); - aiSelection.list = [ ai.data.name for each (ai in g_AIs) ]; + aiSelection.list = [ translate(ai.data.name) for each (ai in g_AIs) ]; var selected = 0; for (var i = 0; i < g_AIs.length; ++i) @@ -23,7 +25,7 @@ function init(settings) aiSelection.selected = selected; var aiDiff = Engine.GetGUIObjectByName("aiDifficulty"); - aiDiff.list = [ "Sandbox", "Easy", "Medium", "Hard", "Very Hard" ]; + aiDiff.list = [translate("Sandbox"), translate("Easy"), translate("Medium"), translate("Hard"), translate("Very Hard")]; aiDiff.selected = settings.difficulty; } diff --git a/binaries/data/mods/public/gui/aiconfig/aiconfig.xml b/binaries/data/mods/public/gui/aiconfig/aiconfig.xml index 8387d02509..1ad3a39b52 100644 --- a/binaries/data/mods/public/gui/aiconfig/aiconfig.xml +++ b/binaries/data/mods/public/gui/aiconfig/aiconfig.xml @@ -9,11 +9,13 @@ - AI Configuration + + AI Configuration + - AI Player + AI Player @@ -21,7 +23,7 @@ - AI Difficulty + AI Difficulty @@ -37,12 +39,12 @@ - OK + OK returnAI(); - Cancel + Cancel Engine.PopGuiPage(); diff --git a/binaries/data/mods/public/gui/civinfo/civinfo.js b/binaries/data/mods/public/gui/civinfo/civinfo.js index 60f2bce350..4826fb6730 100644 --- a/binaries/data/mods/public/gui/civinfo/civinfo.js +++ b/binaries/data/mods/public/gui/civinfo/civinfo.js @@ -80,37 +80,41 @@ function heading(string, size) // Called when user selects civ from dropdown function selectCiv(code) { + var escapeChars = function(str) + { + return str.replace(/\[/g, "[").replace(/\]/g, "]").replace(/"/g, """); + }; + var civInfo = g_CivData[code]; if(!civInfo) - error("Error loading civ data for \""+code+"\""); + error(sprintf("Error loading civ data for \"%(code)s\"", { code: code })); // Update civ gameplay display - Engine.GetGUIObjectByName("civGameplayHeading").caption = heading(civInfo.Name+" Gameplay", 16); - + Engine.GetGUIObjectByName("civGameplayHeading").caption = heading(sprintf(translate("%(civilization)s Gameplay"), { civilization: civInfo.Name }), 16); // Bonuses - var bonusCaption = heading("Civilization Bonus"+(civInfo.CivBonuses.length == 1 ? "" : "es"), 12) + '\n'; + var bonusCaption = heading(translatePlural("Civilization Bonus", "Civilization Bonuses", civInfo.CivBonuses.length), 12) + '\n'; for(var i = 0; i < civInfo.CivBonuses.length; ++i) { bonusCaption += '[color="' + TEXTCOLOR + '"][font="serif-bold-14"]' + civInfo.CivBonuses[i].Name + '[/font] [icon="iconInfo" tooltip="' - + civInfo.CivBonuses[i].History + '" tooltip_style="civInfoTooltip"]\n ' + civInfo.CivBonuses[i].Description + '\n[/color]'; + + escapeChars(civInfo.CivBonuses[i].History) + '" tooltip_style="civInfoTooltip"]\n ' + civInfo.CivBonuses[i].Description + '\n[/color]'; } - bonusCaption += heading("Team Bonus"+(civInfo.TeamBonuses.length == 1 ? "" : "es"), 12) + '\n'; + bonusCaption += heading(translatePlural("Team Bonus", "Team Bonuses", civInfo.TeamBonuses.length), 12) + '\n'; for(var i = 0; i < civInfo.TeamBonuses.length; ++i) { bonusCaption += '[color="' + TEXTCOLOR + '"][font="serif-bold-14"]' + civInfo.TeamBonuses[i].Name + '[/font] [icon="iconInfo" tooltip="' - + civInfo.TeamBonuses[i].History + '" tooltip_style="civInfoTooltip"]\n ' + civInfo.TeamBonuses[i].Description + '\n[/color]'; + + escapeChars(civInfo.TeamBonuses[i].History) + '" tooltip_style="civInfoTooltip"]\n ' + civInfo.TeamBonuses[i].Description + '\n[/color]'; } Engine.GetGUIObjectByName("civBonuses").caption = bonusCaption; // Special techs / buildings - var techCaption = heading("Special Technologies", 12) + '\n'; + var techCaption = heading(translate("Special Technologies"), 12) + '\n'; for(var i = 0; i < civInfo.Factions.length; ++i) { @@ -118,23 +122,23 @@ function selectCiv(code) for(var j = 0; j < faction.Technologies.length; ++j) { techCaption += '[color="' + TEXTCOLOR + '"][font="serif-bold-14"]' + faction.Technologies[j].Name + '[/font] [icon="iconInfo" tooltip="' - + faction.Technologies[j].History + '" tooltip_style="civInfoTooltip"]\n ' + faction.Technologies[j].Description + '\n[/color]'; + + escapeChars(faction.Technologies[j].History) + '" tooltip_style="civInfoTooltip"]\n ' + faction.Technologies[j].Description + '\n[/color]'; } } - techCaption += heading("Special Building"+(civInfo.Structures.length == 1 ? "" : "s"), 12) + '\n'; + techCaption += heading(translatePlural("Special Building", "Special Buildings", civInfo.Structures.length), 12) + '\n'; for(var i = 0; i < civInfo.Structures.length; ++i) { techCaption += '[color="' + TEXTCOLOR + '"][font="serif-bold-14"]' + civInfo.Structures[i].Name + '[/font][/color] [icon="iconInfo" tooltip="' - + civInfo.Structures[i].History + '" tooltip_style="civInfoTooltip"]\n'; + + escapeChars(civInfo.Structures[i].History) + '" tooltip_style="civInfoTooltip"]\n'; } Engine.GetGUIObjectByName("civTechs").caption = techCaption; // Heroes - var heroCaption = heading("Heroes", 12) + '\n'; + var heroCaption = heading(translate("Heroes"), 12) + '\n'; for(var i = 0; i < civInfo.Factions.length; ++i) { @@ -142,7 +146,7 @@ function selectCiv(code) for(var j = 0; j < faction.Heroes.length; ++j) { heroCaption += '[color="' + TEXTCOLOR + '"][font="serif-bold-14"]' + faction.Heroes[j].Name + '[/font][/color] [icon="iconInfo" tooltip="' - + faction.Heroes[j].History + '" tooltip_style="civInfoTooltip"]\n'; + + escapeChars(faction.Heroes[j].History) + '" tooltip_style="civInfoTooltip"]\n'; } heroCaption += '\n'; } @@ -151,6 +155,6 @@ function selectCiv(code) // Update civ history display - Engine.GetGUIObjectByName("civHistoryHeading").caption = heading("History of the " + civInfo.Name, 16); + Engine.GetGUIObjectByName("civHistoryHeading").caption = heading(sprintf(translate("History of the %(civilization)s"), { civilization: civInfo.Name }), 16); Engine.GetGUIObjectByName("civHistoryText").caption = civInfo.History; } diff --git a/binaries/data/mods/public/gui/civinfo/civinfo.xml b/binaries/data/mods/public/gui/civinfo/civinfo.xml index 87743faf3c..ded0cc5129 100644 --- a/binaries/data/mods/public/gui/civinfo/civinfo.xml +++ b/binaries/data/mods/public/gui/civinfo/civinfo.xml @@ -10,9 +10,11 @@ - + - Civilizations + + Civilizations + @@ -22,8 +24,8 @@ font="serif-bold-20" textcolor="white" text_align="left" - size="50%-320 10 50%-96 48"> - Civilization Selection + size="50%-420 10 50%-96 48"> + Civilization Selection @@ -112,7 +114,8 @@ type="button" style="StoneButton" size="100%-164 100%-52 100%-24 100%-24" - >Close + > + Close = 0) ? team+1 : "-"; @@ -1229,7 +1238,7 @@ function onGameAttributesChange() } } - Engine.GetGUIObjectByName("mapInfoDescription").caption = playerString + description; + Engine.GetGUIObjectByName("mapInfoDescription").caption = playerString; g_IsInGuiUpdate = false; @@ -1310,12 +1319,12 @@ function updatePlayerList() } // Give AI a different color so it stands out aiAssignments[ai.id] = hostNameList.length; - hostNameList.push("[color=\"70 150 70 255\"]AI: " + ai.data.name); + hostNameList.push("[color=\"70 150 70 255\"]" + sprintf(translate("AI: %(ai)s"), { ai: translate(ai.data.name) })); hostGuidList.push("ai:" + ai.id); } noAssignment = hostNameList.length; - hostNameList.push("[color=\"140 140 140 255\"]Unassigned"); + hostNameList.push("[color=\"140 140 140 255\"]" + translate("Unassigned")); hostGuidList.push(""); for (var i = 0; i < MAX_PLAYERS; ++i) @@ -1342,7 +1351,7 @@ function updatePlayerList() if (aiId in aiAssignments) selection = aiAssignments[aiId]; else - warn("AI \""+aiId+"\" not present. Defaulting to unassigned."); + warn(sprintf("AI \"%(id)s\" not present. Defaulting to unassigned.", { id: aiId })); } if (!selection) @@ -1507,19 +1516,23 @@ function addChatMessage(msg) switch (msg.type) { case "connect": - formatted = '[font="serif-bold-13"][color="'+ color +'"]' + username + '[/color][/font] [color="gold"]has joined[/color]'; + var formattedUsername = '[font="serif-bold-13"][color="'+ color +'"]' + username + '[/color][/font][color="gold"]' + formatted = '[color="gold"]' + sprintf(translate("%(username)s has joined"), { username: formattedUsername }); break; case "disconnect": - formatted = '[font="serif-bold-13"][color="'+ color +'"]' + username + '[/color][/font] [color="gold"]has left[/color]'; + var formattedUsername = '[font="serif-bold-13"][color="'+ color +'"]' + username + '[/color][/font][color="gold"]' + formatted = '[color="gold"]' + sprintf(translate("%(username)s has left"), { username: formattedUsername }); break; case "message": - formatted = '[font="serif-bold-13"]<[color="'+ color +'"]' + username + '[/color]>[/font] ' + message; + var formattedUsername = '[color="'+ color +'"]' + username + '[/color]' + var formattedUsernamePrefix = '[font="serif-bold-13"]' + sprintf(translate("<%(username)s>"), { username: formattedUsername }) + '[/font]' + formatted = sprintf(translate("%(username)s %(message)s"), { username: formattedUsernamePrefix, message: message }); break; default: - error("Invalid chat message '" + uneval(msg) + "'"); + error(sprintf("Invalid chat message '%(message)s'", { message: uneval(msg) })); return; } @@ -1538,11 +1551,12 @@ function toggleMoreOptions() // Basic map filters API // Add a new map list filter -function addFilter(name, filterFunc) +function addFilter(id, name, filterFunc) { if (filterFunc instanceof Object) { // Basic validity test var newFilter = {}; + newFilter.id = id; newFilter.name = name; newFilter.filter = filterFunc; @@ -1550,12 +1564,22 @@ function addFilter(name, filterFunc) } else { - error("Invalid map filter: "+name); + error(sprintf("Invalid map filter: %(name)s", { name: name })); } } +// Get array of map filter IDs +function getFilterIds() +{ + var filters = []; + for (var i = 0; i < g_MapFilters.length; ++i) + filters.push(g_MapFilters[i].id); + + return filters; +} + // Get array of map filter names -function getFilters() +function getFilterNames() { var filters = []; for (var i = 0; i < g_MapFilters.length; ++i) @@ -1565,13 +1589,13 @@ function getFilters() } // Test map filter on given map settings object -function testFilter(name, mapSettings) +function testFilter(id, mapSettings) { for (var i = 0; i < g_MapFilters.length; ++i) - if (g_MapFilters[i].name == name) + if (g_MapFilters[i].id == id) return g_MapFilters[i].filter(mapSettings); - error("Invalid map filter: "+name); + error(sprintf("Invalid map filter: %(id)s", { id: id })); return false; } diff --git a/binaries/data/mods/public/gui/gamesetup/gamesetup.xml b/binaries/data/mods/public/gui/gamesetup/gamesetup.xml index 0a1bc8d857..d0b83483a4 100644 --- a/binaries/data/mods/public/gui/gamesetup/gamesetup.xml +++ b/binaries/data/mods/public/gui/gamesetup/gamesetup.xml @@ -12,17 +12,17 @@ - Match Setup + Match Setup - Loading + Loading - Loading map data. Please wait... + Loading map data. Please wait... @@ -38,7 +38,9 @@ - Number of players: + + Number of players: + @@ -48,8 +50,8 @@ type="dropdown" style="ModernDropDown" size="0 0 100% 28" - tooltip_style="onscreenToolTip" - tooltip="Select number of players."> + tooltip_style="onscreenToolTip"> + Select number of players. selectNumPlayers(this.list_data[this.selected]); @@ -59,37 +61,53 @@ - Player Name - Player Placement - Civilization + + Player Name + + + Player Placement + + + Civilization + + View civilization info - Team + + Team +